import uuid from datetime import datetime, timezone from typing import Optional, TYPE_CHECKING from sqlalchemy import String, DateTime, ForeignKey, Boolean from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.dialects.postgresql import UUID from app.core.database import Base if TYPE_CHECKING: from app.models.tree import Tree from app.models.user import User class TreeShare(Base): __tablename__ = "tree_shares" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4 ) tree_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("trees.id", ondelete="CASCADE"), nullable=False, index=True ) share_token: Mapped[str] = mapped_column( String(64), unique=True, nullable=False, index=True, comment="URL-safe random token (48 bytes -> 64 base64 chars)" ) created_by: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True ) allow_forking: Mapped[bool] = mapped_column( Boolean, nullable=False, default=True, comment="Whether recipients can fork this tree" ) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(timezone.utc) ) expires_at: Mapped[Optional[datetime]] = mapped_column( DateTime(timezone=True), nullable=True, index=True, comment="Optional expiration for time-limited shares" ) # Relationships tree: Mapped["Tree"] = relationship("Tree", back_populates="shares") creator: Mapped["User"] = relationship("User", foreign_keys=[created_by])