from datetime import datetime, UTC from uuid import uuid4, UUID, uuid7 from sqlalchemy import DateTime from sqlmodel import SQLModel, Field, Relationship from authlib.integrations.sqla_oauth2 import OAuth2ClientMixin, OAuth2AuthorizationCodeMixin, OAuth2TokenMixin from authentication.utils import bcrypt_sha256_hash class BaseModel(SQLModel): id: UUID | None = Field(primary_key=True, default_factory=uuid7) created: datetime = Field( default_factory=lambda: datetime.now(tz=UTC), sa_type=DateTime(timezone=True), ) updated: datetime = Field( default=None, nullable=True, sa_column_kwargs={ 'onupdate': lambda: datetime.now(tz=UTC), }, sa_type=DateTime(timezone=True), ) class User(BaseModel, table=True): username: str = Field(unique=True, index=True) password: str = Field(nullable=False) email: str def set_password(self, value): self.password = bcrypt_sha256_hash(value) class Session(BaseModel, table=True): user_id: UUID = Field(foreign_key='user.id', exclude=True) user: User = Relationship() class ClientApplication(BaseModel, OAuth2ClientMixin, table=True): name: str class AuthCode(BaseModel, OAuth2AuthorizationCodeMixin, table=True): user_id: UUID = Field(foreign_key="user.id", ondelete="CASCADE") class AuthToken(BaseModel, OAuth2TokenMixin, table=True): user_id: UUID = Field(foreign_key="user.id", ondelete="CASCADE")