from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime, Boolean, ForeignKey, UniqueConstraint from sqlalchemy.orm import DeclarativeBase, sessionmaker from datetime import datetime import uuid DATABASE_URL = "sqlite:///./speechify.db" engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) class Base(DeclarativeBase): pass class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) username = Column(String(50), unique=True, nullable=False, index=True) email = Column(String(100), unique=True, nullable=False) password_hash = Column(String(255), nullable=False) role = Column(String(10), default="user") is_active = Column(Boolean, default=True) email_verified = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) class VerificationToken(Base): __tablename__ = "verification_tokens" id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) token = Column(String(64), unique=True, nullable=False, index=True) created_at = Column(DateTime, default=datetime.utcnow) class Document(Base): __tablename__ = "documents" id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) title = Column(String(500)) content = Column(Text) source_type = Column(String(20)) created_at = Column(DateTime, default=datetime.utcnow) class Progress(Base): __tablename__ = "progress" id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) document_id = Column(String(36), ForeignKey("documents.id"), nullable=False) sentence_index = Column(Integer, default=0) updated_at = Column(DateTime, default=datetime.utcnow) __table_args__ = (UniqueConstraint("user_id", "document_id", name="uq_user_doc"),) class Setting(Base): """Global admin settings (key/value)""" __tablename__ = "settings" key = Column(String(100), primary_key=True) value = Column(Text) class UserSetting(Base): """Per-user settings (key/value)""" __tablename__ = "user_settings" id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) key = Column(String(100), nullable=False) value = Column(Text) __table_args__ = (UniqueConstraint("user_id", "key", name="uq_user_setting"),) def get_db(): db = SessionLocal() try: yield db finally: db.close() def init_db(): Base.metadata.create_all(bind=engine)