llm-ready-data / app /core /auth /schemas.py
light-infer-chat's picture
ok
08919be
Raw
History Blame Contribute Delete
3.84 kB
from __future__ import annotations
import re
from datetime import datetime
from typing import Any, Optional
from pydantic import BaseModel, EmailStr, Field, field_validator
def _validate_password(v: str) -> str:
if len(v) < 8:
raise ValueError("Password must be at least 8 characters")
if len(v) > 128:
raise ValueError("Password must not exceed 128 characters")
if not re.search(r"[A-Z]", v):
raise ValueError("Password must contain at least one uppercase letter")
if not re.search(r"[a-z]", v):
raise ValueError("Password must contain at least one lowercase letter")
if not re.search(r"\d", v):
raise ValueError("Password must contain at least one digit")
return v
class RegisterSchema(BaseModel):
email: EmailStr
password: str
username: Optional[str] = Field(None, min_length=2, max_length=50, pattern=r"^[a-zA-Z0-9_]+$")
full_name: Optional[str] = Field(None, min_length=1, max_length=100)
_validate_password = field_validator("password")(_validate_password)
class LoginSchema(BaseModel):
email: EmailStr
password: str
class TokenData(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
class TokenRefreshSchema(BaseModel):
refresh_token: str
class UserProfile(BaseModel):
id: str
email: str
username: Optional[str] = None
full_name: Optional[str] = None
is_active: bool
is_verified: bool
roles: list[str]
created_at: datetime
@field_validator("roles", mode="before")
@classmethod
def _extract_role_names(cls, v: Any) -> list[str]:
if not v:
return []
if isinstance(v[0], str):
return v
return [r.name for r in v]
model_config = {"from_attributes": True}
class UpdateProfileSchema(BaseModel):
username: Optional[str] = Field(None, min_length=2, max_length=50, pattern=r"^[a-zA-Z0-9_]+$")
full_name: Optional[str] = Field(None, min_length=1, max_length=100)
class ChangePasswordSchema(BaseModel):
current_password: str
new_password: str
_validate_new_password = field_validator("new_password")(_validate_password)
class ForgotPasswordSchema(BaseModel):
email: EmailStr
class ResetPasswordSchema(BaseModel):
token: str
new_password: str
_validate_new_password = field_validator("new_password")(_validate_password)
class SessionOut(BaseModel):
id: str
device_info: Optional[str] = None
ip_address: Optional[str] = None
created_at: datetime
expires_at: datetime
model_config = {"from_attributes": True}
class MessageResponse(BaseModel):
message: str
class UserSchemaField(BaseModel):
field: str
type: str
required: bool
description: str
constraints: Optional[str] = None
class UserSchemaResponse(BaseModel):
table_name: str = "users"
columns: list[UserSchemaField]
# --- Wrapped API response schemas ---
class ApiResponse(BaseModel):
success: bool = True
class DataResponse(ApiResponse):
data: dict
application_id: Optional[str] = None
warning: Optional[dict] = None
class TokenResponse(ApiResponse):
data: TokenData
application_id: Optional[str] = None
warning: Optional[dict] = None
class ProfileResponse(ApiResponse):
data: UserProfile
application_id: Optional[str] = None
warning: Optional[dict] = None
class MessageDataResponse(ApiResponse):
data: MessageResponse
application_id: Optional[str] = None
warning: Optional[dict] = None
class SchemaResponse(ApiResponse):
data: UserSchemaResponse
application_id: Optional[str] = None
warning: Optional[dict] = None
class SessionListResponse(ApiResponse):
data: list[SessionOut]
application_id: Optional[str] = None
warning: Optional[dict] = None