"""Blue-team evidence files attached to a `mission_test`.""" from __future__ import annotations import uuid from datetime import datetime from typing import TYPE_CHECKING from sqlalchemy import BigInteger, DateTime, ForeignKey, Index, String, Text, Uuid, func from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.base import Base from app.db.mixins import SoftDeleteMixin, TimestampMixin, UuidPkMixin if TYPE_CHECKING: from app.models.auth import User class EvidenceFile(Base, UuidPkMixin, TimestampMixin, SoftDeleteMixin): __tablename__ = "evidence_files" mission_test_id: Mapped[uuid.UUID] = mapped_column( Uuid(as_uuid=True), ForeignKey("mission_tests.id", ondelete="CASCADE"), nullable=False, ) sha256: Mapped[str] = mapped_column(String(64), nullable=False) mime: Mapped[str] = mapped_column(String(127), nullable=False) size_bytes: Mapped[int] = mapped_column(BigInteger, nullable=False) storage_path: Mapped[str] = mapped_column(Text, nullable=False) original_filename: Mapped[str] = mapped_column(String(255), nullable=False) uploaded_by_user_id: Mapped[uuid.UUID | None] = mapped_column( Uuid(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True, ) uploaded_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False ) uploaded_by: Mapped["User | None"] = relationship(back_populates="uploaded_evidence") __table_args__ = ( Index("ix_evidence_files_mission_test", "mission_test_id"), Index("ix_evidence_files_sha256", "sha256"), Index( "ix_evidence_files_active", "deleted_at", postgresql_where="deleted_at IS NULL", ), )