from pydantic import BaseModel, EmailStr, Field, validator from typing import Optional class RegisterRequest(BaseModel): name: str = Field(..., min_length=2, max_length=50) email: EmailStr password: str = Field(..., min_length=8) phone: Optional[str] = None @validator("password") def validate_password(cls, v): if len(v) < 8: raise ValueError("Password must be at least 8 characters") if not any(c.isupper() for c in v): raise ValueError("Password must contain at least one uppercase letter") if not any(c.islower() for c in v): raise ValueError("Password must contain at least one lowercase letter") if not any(c.isdigit() for c in v): raise ValueError("Password must contain at least one number") return v @validator("phone") def validate_phone(cls, v): if v and not v.isdigit() or (v and len(v) not in [10, 11]): raise ValueError("Phone must be 10-11 digits") return v class LoginRequest(BaseModel): email: EmailStr password: str rememberMe: Optional[bool] = False mfaToken: Optional[str] = None class RefreshTokenRequest(BaseModel): refreshToken: Optional[str] = None class ForgotPasswordRequest(BaseModel): email: EmailStr class ResetPasswordRequest(BaseModel): token: str password: str = Field(..., min_length=8) @validator("password") def validate_password(cls, v): if len(v) < 8: raise ValueError("Password must be at least 8 characters") if not any(c.isupper() for c in v): raise ValueError("Password must contain at least one uppercase letter") if not any(c.islower() for c in v): raise ValueError("Password must contain at least one lowercase letter") if not any(c.isdigit() for c in v): raise ValueError("Password must contain at least one number") return v class UserResponse(BaseModel): id: int name: str email: str phone: Optional[str] role: str createdAt: Optional[str] updatedAt: Optional[str] class Config: from_attributes = True class AuthResponse(BaseModel): user: UserResponse token: str refreshToken: Optional[str] = None class TokenResponse(BaseModel): token: str class MessageResponse(BaseModel): status: str message: str class MFAInitResponse(BaseModel): secret: str qr_code: str # Base64 data URL class EnableMFARequest(BaseModel): secret: str verification_token: str class VerifyMFARequest(BaseModel): token: str is_backup_code: Optional[bool] = False class MFAStatusResponse(BaseModel): mfa_enabled: bool backup_codes_count: int