Finance-Accounts/ar-aging-app/backend/app/services/audit.py

35 lines
1.4 KiB
Python

"""
Audit trail: one append-only row per business action, attributed to the signed-in user.
`record()` only ADDS the row to the caller's ORM session — the caller's own `db.commit()`
persists it atomically with the action itself, so a failed action never leaves a phantom
audit entry (and a recorded action is never lost to a second commit failing).
"""
from __future__ import annotations
from fastapi import Request
from sqlalchemy.orm import Session as OrmSession
from ..db import models
def record(db: OrmSession, request: Request | None, action: str, detail: str = "",
session: models.Session | None = None) -> models.AuditLog:
"""Attach an audit row to the caller's transaction.
Identity comes from the verified bearer token; with auth off (dev / tests before the
first user) the row is still written with an empty username, so the trail's shape is
the same everywhere."""
from ..api.auth import current_user # late import: auth imports models too
user = current_user(request) if request is not None else None
row = models.AuditLog(
username=user.username if user else "",
display_name=user.display_name if user else "",
action=action,
session_id=session.id if session is not None else None,
session_name=session.name if session is not None else "",
detail=(detail or "")[:2000],
)
db.add(row)
return row