520be53901
- Add proper Alembic initial migration (0001_initial_schema.py) - Migrate refresh tokens from JSON file to SQLite (RefreshTokenTable) - Remove Neko-Sama provider entirely (redirects to Gupy, not a host) - Fix provider health check always showing UNKNOWN - Run check_all_health() on startup - Fix POST /providers/health/check background task bug - Add HTMX refresh after manual health check trigger - Fix anime search relevance scoring with MIN_RELEVANCE_THRESHOLD=0.5 - Replace bare 'except:' with 'except Exception:' across codebase - Add Playwright E2E test suite (12 tests, auth setup, helpers) - Fix toast container blocking clicks via pointer-events: none - Remove obsolete Jest/Vite test files and config - Clean up obsolete test_watchlist scripts - Update sonarr model comment for active providers
86 lines
2.4 KiB
Python
86 lines
2.4 KiB
Python
"""Authentication models for user management with SQLModel support"""
|
|
import uuid
|
|
from pydantic import BaseModel, EmailStr, Field as PydanticField
|
|
from typing import Optional, List
|
|
from datetime import datetime
|
|
from sqlmodel import SQLModel, Field, Relationship
|
|
|
|
|
|
class UserBase(SQLModel):
|
|
"""Base schema for user data"""
|
|
username: str = Field(index=True, unique=True, min_length=3, max_length=50)
|
|
email: Optional[str] = Field(default=None, index=True)
|
|
full_name: Optional[str] = None
|
|
is_active: bool = Field(default=True)
|
|
is_admin: bool = Field(default=False)
|
|
|
|
|
|
class UserTable(UserBase, table=True):
|
|
"""Database table for users"""
|
|
__tablename__ = "users"
|
|
|
|
id: str = Field(
|
|
default_factory=lambda: str(uuid.uuid4()),
|
|
primary_key=True,
|
|
index=True,
|
|
nullable=False
|
|
)
|
|
hashed_password: str
|
|
created_at: datetime = Field(default_factory=datetime.now)
|
|
last_login: Optional[datetime] = None
|
|
|
|
# Relationships - Using string reference to avoid circular import errors
|
|
watchlist_items: List["WatchlistItemTable"] = Relationship(back_populates="user")
|
|
|
|
|
|
class UserCreate(UserBase):
|
|
"""Schema for user registration"""
|
|
password: str = PydanticField(..., min_length=6)
|
|
email: Optional[EmailStr] = None
|
|
|
|
|
|
class UserLogin(BaseModel):
|
|
"""Schema for user login"""
|
|
username: str
|
|
password: str
|
|
|
|
|
|
class User(UserBase):
|
|
"""Schema for user data (API Response)"""
|
|
id: str
|
|
created_at: datetime
|
|
last_login: Optional[datetime] = None
|
|
|
|
|
|
class Token(BaseModel):
|
|
"""Schema for authentication token"""
|
|
access_token: str
|
|
token_type: str = "bearer"
|
|
|
|
|
|
class UserInDB(User):
|
|
"""Schema for user stored in database (with hashed password)"""
|
|
hashed_password: str
|
|
|
|
|
|
class RefreshTokenTable(SQLModel, table=True):
|
|
"""Database table for refresh tokens"""
|
|
__tablename__ = "refresh_tokens"
|
|
|
|
id: str = Field(
|
|
default_factory=lambda: str(uuid.uuid4()),
|
|
primary_key=True,
|
|
index=True,
|
|
nullable=False
|
|
)
|
|
token_id: str = Field(index=True, unique=True)
|
|
username: str = Field(index=True)
|
|
created_at: datetime = Field(default_factory=datetime.now)
|
|
expires_at: Optional[datetime] = None
|
|
revoked: bool = Field(default=False)
|
|
revoked_at: Optional[datetime] = None
|
|
|
|
|
|
# Import WatchlistItemTable here to resolve SQLModel Relationship mappings
|
|
from .watchlist import WatchlistItemTable
|