from __future__ import annotations import uuid from datetime import datetime from sqlalchemy import CheckConstraint, DateTime, ForeignKey, Text, func from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column from . import Base class Share(Base): """An additional access grant on one resource (identified by type + id). A resource's OWNER is tracked on the resource row itself (its owner_id column); this table records grants BEYOND the owner — to a single user or to a whole group. It is polymorphic (resource_type + resource_id) so every future shareable entity (notes first, in M1) reuses one table and one ACL predicate. Exactly one of shared_with_user_id / shared_with_group_id is set. """ __tablename__ = "shares" __table_args__ = ( CheckConstraint( "(shared_with_user_id IS NOT NULL) <> (shared_with_group_id IS NOT NULL)", name="ck_shares_one_target", ), ) id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) resource_type: Mapped[str] = mapped_column(Text(), nullable=False) resource_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), nullable=False) shared_with_user_id: Mapped[uuid.UUID | None] = mapped_column( UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=True ) shared_with_group_id: Mapped[uuid.UUID | None] = mapped_column( UUID(as_uuid=True), ForeignKey("groups.id", ondelete="CASCADE"), nullable=True ) permission: Mapped[str] = mapped_column(Text(), nullable=False, server_default="view") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())