inital commit

This commit is contained in:
2026-06-08 15:57:11 +02:00
parent aaf8729663
commit d9ca48addc
114 changed files with 12172 additions and 1 deletions

View File

@@ -0,0 +1,91 @@
from __future__ import annotations
from typing import Any
from sqlalchemy.orm import Session
from app.auth.dependencies import ApiPrincipal
from app.db.models import AuditLog
SENSITIVE_DETAIL_KEYS = {
"password",
"smtp_password",
"imap_password",
"secret",
"api_key",
"token",
}
def _sanitize_details(value: Any) -> Any:
if isinstance(value, dict):
sanitized: dict[str, Any] = {}
for key, item in value.items():
if str(key).lower() in SENSITIVE_DETAIL_KEYS:
sanitized[key] = "<redacted>"
else:
sanitized[key] = _sanitize_details(item)
return sanitized
if isinstance(value, list):
return [_sanitize_details(item) for item in value]
return value
def audit_event(
session: Session,
*,
tenant_id: str | None,
action: str,
user_id: str | None = None,
api_key_id: str | None = None,
object_type: str | None = None,
object_id: str | None = None,
details: dict[str, Any] | None = None,
commit: bool = False,
) -> AuditLog:
"""Persist one audit event.
The function deliberately accepts primitive IDs so it can be used from API
handlers, CLI commands and worker code without coupling the lower-level
services to FastAPI request objects.
"""
item = AuditLog(
tenant_id=tenant_id,
user_id=user_id,
api_key_id=api_key_id,
action=action,
object_type=object_type,
object_id=object_id,
details=_sanitize_details(details or {}),
)
session.add(item)
if commit:
session.commit()
else:
session.flush()
return item
def audit_from_principal(
session: Session,
principal: ApiPrincipal,
*,
action: str,
object_type: str | None = None,
object_id: str | None = None,
details: dict[str, Any] | None = None,
commit: bool = False,
) -> AuditLog:
return audit_event(
session,
tenant_id=principal.tenant_id,
user_id=principal.user.id,
api_key_id=principal.api_key.id,
action=action,
object_type=object_type,
object_id=object_id,
details=details,
commit=commit,
)