""" AuditLog model - tracks all user actions. """ from sqlalchemy import BigInteger, ForeignKey, Integer, String from sqlalchemy.dialects.postgresql import INET, JSONB from sqlalchemy.orm import Mapped, mapped_column, relationship from app.models.base import Base class AuditLog(Base): """ Audit log model for tracking user actions. Logs every action: login, view, create, update, delete, export, etc. """ __tablename__ = "audit_logs" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) # Who user_id: Mapped[int | None] = mapped_column( ForeignKey("users.id", ondelete="SET NULL") ) user_email: Mapped[str | None] = mapped_column( String(255) ) # Cached for deleted users organization_id: Mapped[int | None] = mapped_column( ForeignKey("organizations.id", ondelete="SET NULL") ) # What action: Mapped[str] = mapped_column( String(50), nullable=False ) # login, logout, failed_login, view, create, update, delete, export, etc. resource_type: Mapped[str | None] = mapped_column( String(50) ) # device, user, location, beacon, etc. resource_id: Mapped[int | None] = mapped_column(Integer) # Details description: Mapped[str | None] = mapped_column(String) changes: Mapped[dict | None] = mapped_column(JSONB) # Before/after values # When & Where ip_address: Mapped[str | None] = mapped_column(INET) user_agent: Mapped[str | None] = mapped_column(String) # Relationships user: Mapped["User | None"] = relationship("User", back_populates="audit_logs") organization: Mapped["Organization | None"] = relationship("Organization") def __repr__(self) -> str: return f""