from sqlalchemy import Index, Integer, Text from sqlalchemy.orm import Mapped, mapped_column from scribe.models import Base from scribe.models.base import CreatedAtMixin class User(Base, CreatedAtMixin): __tablename__ = "users" id: Mapped[int] = mapped_column(primary_key=True) username: Mapped[str] = mapped_column(Text, unique=True, nullable=False) email: Mapped[str | None] = mapped_column(Text, nullable=True) password_hash: Mapped[str | None] = mapped_column(Text, nullable=True) oauth_sub: Mapped[str | None] = mapped_column(Text, unique=True, nullable=True) role: Mapped[str] = mapped_column(Text, nullable=False, default="user") session_version: Mapped[int] = mapped_column(Integer, nullable=False, default=1) __table_args__ = ( Index("ix_users_username", "username"), ) def to_dict(self) -> dict: return { "id": self.id, "username": self.username, "email": self.email, "role": self.role, "created_at": self.created_at.isoformat(), "has_password": self.password_hash is not None, }