diff --git a/backend/app/api/auth.py b/backend/app/api/auth.py index 9061d68..bb0fc42 100644 --- a/backend/app/api/auth.py +++ b/backend/app/api/auth.py @@ -1,10 +1,11 @@ """Auth API router: login, register, refresh, logout, MFA, password change.""" -from fastapi import APIRouter, Depends +from fastapi import APIRouter, Depends, Request from sqlalchemy.orm import Session from app.core.dependencies import get_current_user from app.database import get_db +from app.services.audit_service import log_action from app.models.user import User from app.schemas.auth import ( ChangePasswordRequest, @@ -36,10 +37,19 @@ router = APIRouter() @router.post("/login", response_model=TokenResponse) -def login(data: LoginRequest, db: Session = Depends(get_db)): +def login(data: LoginRequest, request: Request, db: Session = Depends(get_db)): """Authenticate with email/password (+ optional MFA) and receive tokens.""" user = authenticate_user(db, data.email, data.password, data.mfa_code) access, refresh = create_tokens(db, user) + log_action( + db, + user_id=user.id, + action="login", + entity_type="user", + entity_id=user.id, + ip_address=request.client.host if request.client else None, + user_agent=request.headers.get("user-agent"), + ) return TokenResponse( access_token=access, refresh_token=refresh, @@ -79,11 +89,21 @@ def refresh(data: RefreshRequest, db: Session = Depends(get_db)): @router.post("/logout") def logout( data: RefreshRequest, + request: Request, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Revoke the supplied refresh token (logout).""" revoke_refresh_token(db, data.refresh_token) + log_action( + db, + user_id=current_user.id, + action="logout", + entity_type="user", + entity_id=current_user.id, + ip_address=request.client.host if request.client else None, + user_agent=request.headers.get("user-agent"), + ) return {"detail": "Logged out"} diff --git a/backend/app/api/import_router.py b/backend/app/api/import_router.py index ff52ee3..2ab5105 100644 --- a/backend/app/api/import_router.py +++ b/backend/app/api/import_router.py @@ -14,6 +14,7 @@ from app.database import get_db from app.models.audit import ImportLog from app.models.user import User from app.schemas.import_schemas import ImportPreview, ImportResult +from app.services.audit_service import log_action from app.services.csv_parser import parse_csv from app.services.icd_service import import_icd_from_xlsx from app.services.import_service import confirm_import, preview_import @@ -140,7 +141,20 @@ async def confirm_csv_import( detail=f"CSV parsing failed: {exc}", ) - return confirm_import(db, parsed, file.filename, user.id) + result = confirm_import(db, parsed, file.filename, user.id) + log_action( + db, + user_id=user.id, + action="csv_imported", + entity_type="import", + new_values={ + "filename": file.filename, + "imported": result.imported, + "skipped": result.skipped, + "updated": result.updated, + }, + ) + return result # --------------------------------------------------------------------------- @@ -194,6 +208,18 @@ async def upload_icd_xlsx( db.add(log) db.commit() + log_action( + db, + user_id=user.id, + action="icd_xlsx_imported", + entity_type="import", + new_values={ + "filename": file.filename, + "updated": result["updated"], + "errors": len(result["errors"]), + }, + ) + return ICDImportResponse(**result) diff --git a/backend/app/api/reports.py b/backend/app/api/reports.py index 523a06b..847fcd8 100644 --- a/backend/app/api/reports.py +++ b/backend/app/api/reports.py @@ -18,6 +18,7 @@ from app.schemas.report import ( ReportListResponse, ReportMeta, ) +from app.services.audit_service import log_action logger = logging.getLogger(__name__) @@ -144,6 +145,15 @@ def generate_report( db.commit() db.refresh(report) + log_action( + db, + user_id=user.id, + action="report_generated", + entity_type="report", + entity_id=report.id, + new_values={"jahr": jahr, "kw": kw, "filename": filename}, + ) + return ReportMeta.model_validate(report) except ImportError as exc: raise HTTPException(501, f"Required service not yet available: {exc}")