Backend (FastAPI): - App factory with async SQLAlchemy 2.0 + PostgreSQL - Alembic migration for users and sessions tables - JWT auth (access + refresh tokens, bcrypt passwords) - Auth endpoints: register, login, refresh, logout, me - Admin seed script, role-based access deps Frontend (React + TypeScript): - Vite + Tailwind CSS + shadcn/ui theme (health-oriented palette) - i18n with English and Russian translations - Zustand auth/UI stores with localStorage persistence - Axios client with automatic token refresh on 401 - Login/register pages, protected routing - App layout: collapsible sidebar, header with theme/language toggles - Dashboard with placeholder stats Infrastructure: - Docker Compose (postgres, backend, frontend, nginx) - Nginx reverse proxy with WebSocket support - Dev override with hot reload Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
23 lines
868 B
Python
23 lines
868 B
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import DateTime, ForeignKey, String
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.database import Base
|
|
|
|
|
|
class Session(Base):
|
|
__tablename__ = "sessions"
|
|
|
|
user_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True
|
|
)
|
|
refresh_token_hash: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
|
|
device_info: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
ip_address: Mapped[str | None] = mapped_column(String(45), nullable=True)
|
|
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
|
|
|
|
user: Mapped["User"] = relationship(back_populates="sessions") # noqa: F821
|