Files
leocrm/app/models/audit.py
T

44 lines
1.7 KiB
Python

"""AuditLog model — audit trail for all create/update/delete/login actions.
Note: DeletionLog has been merged into EntityHistory (action='delete').
DeletionLog is re-exported here as an alias for backward compatibility.
"""
from __future__ import annotations
import uuid
from datetime import datetime
from typing import Any
from sqlalchemy import DateTime, ForeignKey, String, func
from sqlalchemy.dialects.postgresql import JSONB, TSVECTOR
from sqlalchemy.dialects.postgresql import UUID as PGUUID
from sqlalchemy.orm import Mapped, mapped_column
from app.core.db import Base, TenantMixin
from app.models.owned_mixin import OwnedMixin
# Re-export EntityHistory as DeletionLog for backward compatibility.
# Tests import DeletionLog from app.models.audit and use entity_snapshot attribute.
class AuditLog(Base, TenantMixin, OwnedMixin):
"""Audit trail for all create/update/delete/login actions."""
__tablename__ = "audit_log"
search_tsv: Mapped[Any] = mapped_column(TSVECTOR, nullable=True)
id: Mapped[uuid.UUID] = mapped_column(
PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
)
user_id: Mapped[uuid.UUID | None] = mapped_column(
PGUUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True
)
action: Mapped[str] = mapped_column(String(50), nullable=False)
entity_type: Mapped[str] = mapped_column(String(50), nullable=False, index=True)
entity_id: Mapped[uuid.UUID | None] = mapped_column(PGUUID(as_uuid=True), nullable=True)
changes: Mapped[dict[str, Any] | None] = mapped_column(JSONB, nullable=True)
timestamp: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, server_default=func.now(), index=True
)