import json from typing import Any from sqlalchemy import select from sqlalchemy.orm import Session from app.modules.audit.models import AuditLog from app.modules.audit.schemas import AuditLogCreate def _dump(value: Any | None) -> str | None: """Serialize audit payloads while preserving existing strings.""" if value is None: return None if isinstance(value, str): return value return json.dumps(value, ensure_ascii=False, default=str) class AuditService: """Persist and query audit log entries.""" def __init__(self, db: Session): self.db = db def log(self, payload: AuditLogCreate) -> AuditLog: record = AuditLog( actor=payload.actor, source=payload.source, action=payload.action, target_type=payload.target_type, target_id=payload.target_id, risk_level=payload.risk_level, request_payload=_dump(payload.request_payload), response_payload=_dump(payload.response_payload), status=payload.status, ) self.db.add(record) self.db.commit() self.db.refresh(record) return record def list_logs(self, limit: int = 100) -> list[AuditLog]: stmt = select(AuditLog).order_by(AuditLog.id.desc()).limit(min(limit, 500)) return list(self.db.execute(stmt).scalars())