from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, UniqueConstraint, func from sqlalchemy.orm import relationship import bcrypt as _bcrypt from ..database import Base class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) username = Column(String(100), unique=True, nullable=False, index=True) password_hash = Column(String(200), nullable=False) max_connections = Column(Integer, default=1, nullable=False) expiry_date = Column(DateTime(timezone=True), nullable=True) is_active = Column(Boolean, default=True, nullable=False) is_priority = Column(Boolean, default=False, nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now()) catalog_entries = relationship("UserCatalogEntry", back_populates="user", cascade="all, delete-orphan") provider_preferences = relationship("UserProviderPreference", back_populates="user", cascade="all, delete-orphan", order_by="UserProviderPreference.priority") def set_password(self, password: str) -> None: hashed = _bcrypt.hashpw(password.encode(), _bcrypt.gensalt()) self.password_hash = hashed.decode() def verify_password(self, password: str) -> bool: return _bcrypt.checkpw(password.encode(), self.password_hash.encode()) class UserCatalogEntry(Base): __tablename__ = "user_catalog_entries" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False) category_id = Column(Integer, ForeignKey("categories.id", ondelete="CASCADE"), nullable=False) user = relationship("User", back_populates="catalog_entries") category = relationship("Category", back_populates="catalog_entries") class UserCustomCatalogEntry(Base): __tablename__ = "user_custom_catalog_entries" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False) custom_category_id = Column(Integer, ForeignKey("custom_categories.id", ondelete="CASCADE"), nullable=False) __table_args__ = ( UniqueConstraint("user_id", "custom_category_id", name="uq_user_custom_cat"), ) class UserProviderPreference(Base): __tablename__ = "user_provider_preferences" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False) provider_account_id = Column(Integer, ForeignKey("provider_accounts.id", ondelete="CASCADE"), nullable=False) priority = Column(Integer, default=0, nullable=False) user = relationship("User", back_populates="provider_preferences") provider_account = relationship("ProviderAccount") __table_args__ = ( UniqueConstraint("user_id", "provider_account_id", name="uq_user_provider_pref"), )