57 lines
1.6 KiB
Python
57 lines
1.6 KiB
Python
|
|
"""
|
||
|
|
Audit logging service.
|
||
|
|
|
||
|
|
Call `log_audit(db, ...)` from within any request handler that already holds
|
||
|
|
an open AsyncSession. The entry is added to the session — it will be
|
||
|
|
committed with the surrounding transaction.
|
||
|
|
|
||
|
|
For error logging outside a request session (e.g. exception middleware), open
|
||
|
|
a fresh session via `AsyncSessionLocal`, call `log_audit`, then `commit`.
|
||
|
|
"""
|
||
|
|
import uuid
|
||
|
|
from datetime import datetime, timezone
|
||
|
|
from typing import Optional
|
||
|
|
|
||
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
|
|
||
|
|
from app.models.audit import AuditLog
|
||
|
|
from app.services.settings import get_feature_settings_snapshot
|
||
|
|
|
||
|
|
|
||
|
|
async def log_audit(
|
||
|
|
db: AsyncSession,
|
||
|
|
*,
|
||
|
|
action_type: str,
|
||
|
|
area: str,
|
||
|
|
description: str,
|
||
|
|
member_id: Optional[uuid.UUID] = None,
|
||
|
|
member_email: Optional[str] = None,
|
||
|
|
status: str = "success",
|
||
|
|
booking_id: Optional[uuid.UUID] = None,
|
||
|
|
error_message: Optional[str] = None,
|
||
|
|
error_detail: Optional[str] = None,
|
||
|
|
ip_address: Optional[str] = None,
|
||
|
|
user_agent: Optional[str] = None,
|
||
|
|
extra: Optional[dict] = None,
|
||
|
|
) -> None:
|
||
|
|
feature_settings = await get_feature_settings_snapshot(db)
|
||
|
|
if not feature_settings.audit_history_enabled:
|
||
|
|
return
|
||
|
|
|
||
|
|
entry = AuditLog(
|
||
|
|
timestamp=datetime.now(timezone.utc),
|
||
|
|
member_id=member_id,
|
||
|
|
member_email=member_email,
|
||
|
|
action_type=action_type,
|
||
|
|
area=area,
|
||
|
|
description=description,
|
||
|
|
status=status,
|
||
|
|
booking_id=booking_id,
|
||
|
|
error_message=error_message,
|
||
|
|
error_detail=error_detail,
|
||
|
|
ip_address=ip_address,
|
||
|
|
user_agent=user_agent,
|
||
|
|
extra=extra,
|
||
|
|
)
|
||
|
|
db.add(entry)
|