Files

43 lines
1.8 KiB
Python

"""Users, opaque sessions and shared authentication request budgets."""
from datetime import datetime
from sqlalchemy import CheckConstraint, DateTime, ForeignKey, Integer, String, func
from sqlalchemy.orm import Mapped, mapped_column
from app.db.session import Base
class User(Base):
__tablename__ = "users"
__table_args__ = (CheckConstraint("role IN ('user', 'admin')", name="ck_users_role"),)
id: Mapped[int] = mapped_column(primary_key=True)
username: Mapped[str] = mapped_column(String(32), unique=True, nullable=False)
password_hash: Mapped[str] = mapped_column(String(255), nullable=False)
nickname: Mapped[str | None] = mapped_column(String(80))
email: Mapped[str | None] = mapped_column(String(254))
role: Mapped[str] = mapped_column(String(10), default="user", nullable=False)
credential_version: Mapped[int] = mapped_column(Integer, default=1, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
class AuthSession(Base):
__tablename__ = "auth_sessions"
token_hash: Mapped[str] = mapped_column(String(64), primary_key=True)
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), index=True)
credential_version: Mapped[int] = mapped_column(Integer, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
expires_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, index=True
)
class AuthRateLimit(Base):
__tablename__ = "auth_rate_limits"
key: Mapped[str] = mapped_column(String(64), primary_key=True)
window_start: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
attempts: Mapped[int] = mapped_column(Integer, nullable=False)