feat: log de actividad por usuario
- Tabla activity_log en SQLite (migración automática) - Registra: login, login_fallido, rda_enviado, rda_masivo, rda_directo, automation_run, contrato_creado, contrato_editado, contrato_toggle - Endpoint GET /logs/actividad con filtros por usuario, acción y fecha - UI /logs/actividad con badges de color por tipo de acción - Enlace "Actividad" en navegación lateral Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
8e29e2d04f
commit
c20e1a7476
@@ -2,6 +2,7 @@ from fastapi import APIRouter, Request, Form, Depends, HTTPException
|
||||
from fastapi.responses import RedirectResponse, JSONResponse
|
||||
from app.database import get_connection
|
||||
from app.auth import hash_password, verify_password, create_token, get_current_user
|
||||
from app.utils.activity import log_activity, get_ip
|
||||
|
||||
router = APIRouter(prefix="/auth", tags=["auth"])
|
||||
|
||||
@@ -62,10 +63,12 @@ async def login(
|
||||
"SELECT * FROM users WHERE username = ?", (username,)
|
||||
).fetchone()
|
||||
if not user or not verify_password(password, user["password_hash"]):
|
||||
log_activity(0, username, "login_fallido", f"Intento fallido desde {get_ip(request)}", get_ip(request))
|
||||
return request.app.state.templates.TemplateResponse("login.html", {
|
||||
"request": request, "error": "Usuario o contraseña incorrectos"
|
||||
})
|
||||
|
||||
log_activity(user["id"], user["username"], "login", f"Inicio de sesión", get_ip(request))
|
||||
token = create_token(user["id"], user["username"])
|
||||
resp = RedirectResponse("/dashboard", status_code=302)
|
||||
resp.set_cookie(key="token", value=token, httponly=True)
|
||||
|
||||
Reference in New Issue
Block a user