itcloud/backend/src/app/domain/models.py

120 lines
4.4 KiB
Python

"""Domain models for the application."""
import enum
from datetime import datetime
from typing import Optional
from uuid import uuid4
from sqlalchemy import BigInteger, Boolean, DateTime, Enum, Float, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
from app.infra.database import Base
def generate_uuid() -> str:
"""Generate UUID as string for SQLite compatibility."""
return str(uuid4())
class AssetType(str, enum.Enum):
"""Type of media asset."""
PHOTO = "photo"
VIDEO = "video"
class AssetStatus(str, enum.Enum):
"""Status of media asset."""
UPLOADING = "uploading"
READY = "ready"
FAILED = "failed"
class User(Base):
"""User account."""
__tablename__ = "users"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=generate_uuid)
email: Mapped[str] = mapped_column(String(255), unique=True, nullable=False, index=True)
password_hash: Mapped[str] = mapped_column(String(255), nullable=False)
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False
)
class Folder(Base):
"""Folder for organizing assets."""
__tablename__ = "folders"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=generate_uuid)
user_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
parent_folder_id: Mapped[Optional[str]] = mapped_column(
String(36), nullable=True, index=True
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False
)
class Asset(Base):
"""Media asset (photo or video)."""
__tablename__ = "assets"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=generate_uuid)
user_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
folder_id: Mapped[Optional[str]] = mapped_column(String(36), nullable=True, index=True)
type: Mapped[AssetType] = mapped_column(Enum(AssetType), nullable=False)
status: Mapped[AssetStatus] = mapped_column(
Enum(AssetStatus), default=AssetStatus.UPLOADING, nullable=False, index=True
)
original_filename: Mapped[str] = mapped_column(String(512), nullable=False)
content_type: Mapped[str] = mapped_column(String(100), nullable=False)
size_bytes: Mapped[int] = mapped_column(BigInteger, nullable=False)
sha256: Mapped[Optional[str]] = mapped_column(String(64), nullable=True)
# Metadata
captured_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
width: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
height: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
duration_sec: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
# Storage
storage_key_original: Mapped[str] = mapped_column(String(512), nullable=False)
storage_key_thumb: Mapped[Optional[str]] = mapped_column(String(512), nullable=True)
# Timestamps
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False, index=True
)
class Share(Base):
"""Public share link for assets or albums."""
__tablename__ = "shares"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=generate_uuid)
owner_user_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
asset_id: Mapped[Optional[str]] = mapped_column(String(36), nullable=True, index=True)
album_id: Mapped[Optional[str]] = mapped_column(String(36), nullable=True, index=True)
token: Mapped[str] = mapped_column(String(64), unique=True, nullable=False, index=True)
expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
password_hash: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False
)
revoked_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True), nullable=True, index=True
)