mirror of
https://github.com/idrainformatica/PecFlow.git
synced 2026-06-16 12:45:42 +02:00
Audit Log
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
Router Audit Log – consultazione degli eventi di sistema.
|
||||
|
||||
Endpoint:
|
||||
GET /api/v1/audit-log – lista paginata con filtri (solo admin/super_admin)
|
||||
|
||||
Permessi:
|
||||
- admin: vede solo gli eventi del proprio tenant
|
||||
- super_admin: vede tutti i tenant (filtrabile per tenant_id)
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Query
|
||||
|
||||
from app.dependencies import AdminUser, DB
|
||||
from app.schemas.audit_log import AuditLogListResponse
|
||||
from app.services.audit_service import AuditService
|
||||
|
||||
router = APIRouter(prefix="/audit-log", tags=["Audit Log"])
|
||||
|
||||
|
||||
@router.get("", response_model=AuditLogListResponse)
|
||||
async def list_audit_log(
|
||||
current_user: AdminUser,
|
||||
db: DB,
|
||||
page: int = Query(1, ge=1, description="Numero di pagina"),
|
||||
page_size: int = Query(25, ge=1, le=100, description="Elementi per pagina"),
|
||||
action: Optional[str] = Query(None, description="Filtra per azione (es. auth.login, user.*)"),
|
||||
user_id: Optional[uuid.UUID] = Query(None, description="Filtra per utente"),
|
||||
outcome: Optional[str] = Query(None, pattern="^(success|failure)$", description="Esito: success o failure"),
|
||||
date_from: Optional[datetime] = Query(None, description="Data inizio (ISO 8601)"),
|
||||
date_to: Optional[datetime] = Query(None, description="Data fine (ISO 8601)"),
|
||||
resource_type: Optional[str] = Query(None, description="Tipo risorsa (user, mailbox, message, ...)"),
|
||||
tenant_id: Optional[uuid.UUID] = Query(None, description="Filtra per tenant (solo super_admin)"),
|
||||
) -> AuditLogListResponse:
|
||||
"""
|
||||
Restituisce la lista paginata degli eventi di audit.
|
||||
|
||||
- Admin: vede solo gli eventi del proprio tenant (tenant_id ignorato).
|
||||
- Super Admin: vede tutti i tenant, filtrabile per tenant_id.
|
||||
"""
|
||||
svc = AuditService(db)
|
||||
|
||||
# Determina il tenant_id effettivo da applicare al filtro
|
||||
if current_user.is_super_admin:
|
||||
# Super admin: usa il tenant_id passato come filtro (None = tutti)
|
||||
effective_tenant_id = tenant_id
|
||||
else:
|
||||
# Admin normale: sempre vincolato al proprio tenant
|
||||
effective_tenant_id = current_user.tenant_id
|
||||
|
||||
return await svc.list(
|
||||
tenant_id=effective_tenant_id,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
action=action,
|
||||
user_id=user_id,
|
||||
outcome=outcome,
|
||||
date_from=date_from,
|
||||
date_to=date_to,
|
||||
resource_type=resource_type,
|
||||
)
|
||||
@@ -161,13 +161,34 @@ async def totp_disable(
|
||||
summary="Cambio password utente corrente",
|
||||
)
|
||||
async def change_password(
|
||||
request: Request,
|
||||
body: PasswordChangeRequest,
|
||||
current_user: CurrentUser,
|
||||
db: DB,
|
||||
) -> None:
|
||||
from app.core.security import verify_password, hash_password
|
||||
from app.services.audit_service import log_audit
|
||||
|
||||
if not verify_password(body.current_password, current_user.password_hash):
|
||||
from app.services.audit_service import log_audit as _la
|
||||
await _la(
|
||||
db,
|
||||
"auth.password_changed",
|
||||
tenant_id=current_user.tenant_id,
|
||||
user_id=current_user.id,
|
||||
outcome="failure",
|
||||
ip_address=request.client.host if request.client else None,
|
||||
user_agent=request.headers.get("user-agent"),
|
||||
payload={"reason": "wrong_current_password"},
|
||||
)
|
||||
raise InvalidCredentialsError()
|
||||
|
||||
current_user.password_hash = hash_password(body.new_password)
|
||||
await log_audit(
|
||||
db,
|
||||
"auth.password_changed",
|
||||
tenant_id=current_user.tenant_id,
|
||||
user_id=current_user.id,
|
||||
ip_address=request.client.host if request.client else None,
|
||||
user_agent=request.headers.get("user-agent"),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user