77 lines
2.8 KiB
Python
77 lines
2.8 KiB
Python
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() |