from __future__ import annotations import json from fastapi import APIRouter, Request from fastapi.responses import RedirectResponse from app.core.templating import templates from app.core.db.common import CommonSessionLocal from app.core.security.csrf import get_or_create_csrf_token from app.core.security.session_auth import get_current_user from app.modules.core.audit.service import parse_details, search_audit_logs from app.modules.core.iam.scope import build_scope from app.modules.core.iam.services import paginate_list from app.modules.core.rbac.deps import get_user_permissions, get_user_roles from app.modules.core.rbac.permission_guard import require_permission router = APIRouter(prefix="/system-settings/audit-logs", tags=["audit-ui"]) def _is_system_admin(db, user) -> bool: return "System Admin" in get_user_roles(db, user.id) def _is_firm_admin(db, user) -> bool: return "Firm Admin" in get_user_roles(db, user.id) @router.get("") def logs(request: Request, q: str = "", page: int = 1, per_page: int = 20): db = CommonSessionLocal() try: user = get_current_user(request, db=db) if not user: return RedirectResponse(url="/login", status_code=303) try: require_permission(db, user, "audit.view") except Exception: return RedirectResponse(url="/system-settings", status_code=303) if not _is_system_admin(db, user) and not _is_firm_admin(db, user): return RedirectResponse(url="/system-settings", status_code=303) scope = build_scope(db, user) rows = search_audit_logs(db, scope, q=q) # Enforce final matrix explicitly: # - System Admin: all logs # - Firm Admin: own tenant logs only # - others: none if _is_firm_admin(db, user) and not _is_system_admin(db, user): rows = [r for r in rows if getattr(r, "target_tenant_id", None) == user.tenant_id] paged = paginate_list(rows, page=page, per_page=per_page) decorated = [] for row in paged.items: pretty = json.dumps(parse_details(row), indent=2, ensure_ascii=False, default=str) setattr(row, "pretty_details", pretty) decorated.append(row) return templates.TemplateResponse( "modules/core/audit/templates/logs.html", { "request": request, "current_user": user, "current_user_roles": get_user_roles(db, user.id), "current_user_permissions": get_user_permissions(db, user.id), "csrf_token": get_or_create_csrf_token(request), "title": "Audit Logs", "logs": decorated, "logs_page": paged, "filters": {"q": (q or "").strip(), "per_page": paged.per_page}, }, ) finally: db.close()