"""用户与用户 AI 配置。""" from sqlalchemy import Boolean, ForeignKey, String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from app.models.base import new_uuid from app.db import Base, TimestampMixin class User(Base, TimestampMixin): __tablename__ = "users" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid) username: Mapped[str] = mapped_column(String(64), unique=True, index=True) email: Mapped[str | None] = mapped_column(String(255), unique=True, nullable=True) password_hash: Mapped[str] = mapped_column(String(255)) is_active: Mapped[bool] = mapped_column(Boolean, default=True) settings: Mapped["UserSettings"] = relationship( back_populates="user", uselist=False, cascade="all, delete-orphan" ) class UserSettings(Base, TimestampMixin): """每个用户可在 UI 里配置自己的 OpenAI 兼容 AI 接口。api_key 用 Fernet 加密存储。""" __tablename__ = "user_settings" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid) user_id: Mapped[str] = mapped_column( ForeignKey("users.id", ondelete="CASCADE"), unique=True, index=True ) llm_base_url: Mapped[str | None] = mapped_column(String(512), nullable=True) llm_api_key_encrypted: Mapped[str | None] = mapped_column(Text, nullable=True) llm_text_model: Mapped[str | None] = mapped_column(String(128), nullable=True) llm_vision_model: Mapped[str | None] = mapped_column(String(128), nullable=True) user: Mapped["User"] = relationship(back_populates="settings")