"""Author RAG Chatbot SaaS — Pydantic Schemas for Auth.""" from typing import Literal from pydantic import BaseModel, EmailStr, Field, field_validator ClientId = Literal["author", "superadmin"] class RegisterRequest(BaseModel): """Request body for author registration.""" email: EmailStr password: str = Field(..., min_length=8, max_length=128) full_name: str = Field(..., min_length=1, max_length=255) referral_code: str | None = Field(None, max_length=50, description="Optional referral code from ?ref=") @field_validator("password") @classmethod def password_strength(cls, v: str) -> str: """Enforce password complexity: uppercase, digit, special char.""" if not any(c.isupper() for c in v): raise ValueError("Password must contain at least one uppercase letter") if not any(c.isdigit() for c in v): raise ValueError("Password must contain at least one digit") if not any(c in "!@#$%^&*()_+-=[]{}|;':\",./<>?" for c in v): raise ValueError("Password must contain at least one special character") return v class LoginRequest(BaseModel): """Request body for author/superadmin login.""" email: str = Field(..., min_length=1) # Accepts email or username password: str = Field(..., min_length=1) client_id: ClientId = "author" class RefreshRequest(BaseModel): """Request body for token refresh.""" refresh_token: str = "" client_id: ClientId = "author" class LogoutRequest(BaseModel): """Request body for scoped logout.""" client_id: ClientId = "author" class TokenResponse(BaseModel): """Response containing JWT token pair.""" access_token: str refresh_token: str token_type: str = "bearer" author_slug: str | None = None is_superadmin: bool = False role: str | None = None class UserResponse(BaseModel): """Public user profile response.""" id: str email: str full_name: str | None role: str bot_name: str timezone: str chatbot_is_active: bool model_config = {"from_attributes": True}