""" Role Models Defines domain-scoped permissions mapped from Authentik groups. Format: {domain}:{action} (e.g., control-room:admin, media:viewer) """ import uuid from typing import TYPE_CHECKING, List from sqlalchemy import String, ForeignKey from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column, relationship from src.db.database import Base if TYPE_CHECKING: from src.db.models.user import User class Role(Base): """ Role model for domain-scoped permissions Roles are seeded from configuration, not user-editable. Each role maps to an Authentik group (e.g., tatlock-control-room-admin). Domains: control-room, library, media, ai, housekeeper, developer, documents, gaming, admin Actions: viewer, user, editor, admin (hierarchical) """ __tablename__ = "roles" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) name: Mapped[str] = mapped_column( String(100), unique=True, nullable=False, index=True, comment="Role name in format domain:action (e.g., control-room:admin)", ) domain: Mapped[str] = mapped_column( String(50), nullable=False, index=True, comment="Permission domain (e.g., control-room, media, ai)", ) action: Mapped[str] = mapped_column( String(20), nullable=False, comment="Permission action (viewer, user, editor, admin)", ) authentik_group: Mapped[str | None] = mapped_column( String(255), nullable=True, unique=True, comment="Corresponding Authentik group name (e.g., tatlock-control-room-admin)", ) # Relationships users: Mapped[List["User"]] = relationship( "User", secondary="user_roles", back_populates="roles", lazy="selectin", ) def __repr__(self) -> str: return f"" class UserRole(Base): """ Association table for User-Role many-to-many relationship Synced from Authentik groups during user authentication. """ __tablename__ = "user_roles" user_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), primary_key=True, ) role_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("roles.id", ondelete="CASCADE"), primary_key=True, )