""" Notification Log Model """ from enum import Enum from sqlalchemy import ( Column, Integer, String, DateTime, Text, ForeignKey, Enum as SQLEnum, Index ) from sqlalchemy.orm import relationship from app.models.base import Base class NotificationType(str, Enum): SLA_BREACH = "sla_breach" ASSIGNMENT = "assignment" NEW_VULNERABILITY = "new_vulnerability" MANUAL = "manual" class NotificationStatus(str, Enum): SENT = "sent" FAILED = "failed" SUPPRESSED = "suppressed" class NotificationLog(Base): __tablename__ = "notification_logs" id = Column(Integer, primary_key=True, index=True) # SET NULL, not CASCADE: the log is the record that a notification WAS # sent, and that stays true after the finding is gone. Without a rule the # database refused the delete outright — an Intune device removed upstream # could not be deleted at all once anything had been mailed about it # (ForeignKeyViolation on notification_logs_vulnerability_id_fkey). vulnerability_id = Column(Integer, ForeignKey("vulnerabilities.id", ondelete="SET NULL"), nullable=True, index=True) # SET NULL for the same reason as vulnerability_id above: the log records # that a notification WAS sent, which stays true after the asset is gone. # Without a rule this blocked asset deletion outright — the vulnerability_id # fix in migration 040 only moved the failure one constraint along. asset_id = Column(Integer, ForeignKey("assets.id", ondelete="SET NULL"), nullable=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=True, index=True) notification_type = Column(SQLEnum(NotificationType), nullable=False, index=True) sent_at = Column(DateTime, nullable=False, index=True) subject = Column(String(500), nullable=True) recipient_email = Column(String(255), nullable=True) status = Column(SQLEnum(NotificationStatus), nullable=False) message_body = Column(Text, nullable=True) error_message = Column(Text, nullable=True) # Relationships vulnerability = relationship("Vulnerability", foreign_keys=[vulnerability_id]) asset = relationship("Asset", foreign_keys=[asset_id]) user = relationship("User", foreign_keys=[user_id]) def __repr__(self): return f"" Index( 'idx_notif_vuln_type_sent', NotificationLog.vulnerability_id, NotificationLog.notification_type, NotificationLog.sent_at )