from sqlalchemy import Column, Integer, String, Boolean, TIMESTAMP, ForeignKey, Index, UniqueConstraint from sqlalchemy.sql import func from sqlalchemy.dialects.sqlite import JSON from app.core.database import Base class OAuthClient(Base): """OAuth 2.0 client registration. Attributes: client_secret: Should store a cryptographically hashed value, not plaintext. redirect_uris: JSON array of allowed redirect URIs (list of strings). grant_types: JSON array of allowed grant types (list of strings). scopes: JSON array of available scopes (list of strings). """ __tablename__ = "oauth_clients" id = Column(Integer, primary_key=True, autoincrement=True) client_id = Column(String(100), unique=True, nullable=False) client_secret = Column(String(255), nullable=False) # Hashed secret name = Column(String(200), nullable=False) redirect_uris = Column(JSON, default=list) # List of allowed redirect URIs grant_types = Column(JSON, default=list) # List of allowed grant types scopes = Column(JSON, default=list) # List of available scopes is_active = Column(Boolean, default=True) created_at = Column(TIMESTAMP, server_default=func.now()) updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now()) def __repr__(self): return f"" class OAuthToken(Base): __tablename__ = "oauth_tokens" id = Column(Integer, primary_key=True, autoincrement=True) access_token = Column(String(1000), unique=True, nullable=False) refresh_token = Column(String(1000), unique=True, nullable=True) token_type = Column(String(50), default="Bearer") expires_at = Column(TIMESTAMP, nullable=False, index=True) scopes = Column(JSON, default=list) client_id = Column(String(100), ForeignKey('oauth_clients.client_id'), nullable=False, index=True) user_id = Column(Integer, ForeignKey('oauth_users.id'), nullable=True, index=True) created_at = Column(TIMESTAMP, server_default=func.now()) updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now()) __table_args__ = ( Index('ix_oauth_tokens_client_expires', 'client_id', 'expires_at'), Index('ix_oauth_tokens_user_expires', 'user_id', 'expires_at'), ) def __repr__(self): return f"" class OAuthUser(Base): """OAuth 2.0 resource owner (user) account. Attributes: password_hash: Should store a cryptographically hashed value, not plaintext. email: Unique when provided (nullable). """ __tablename__ = "oauth_users" id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(100), unique=True, nullable=False) password_hash = Column(String(255), nullable=False) email = Column(String(255), nullable=True, unique=True) is_active = Column(Boolean, default=True) created_at = Column(TIMESTAMP, server_default=func.now()) updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now()) def __repr__(self): return f""