from datetime import datetime from typing import Optional from pydantic import BaseModel, EmailStr, Field, ConfigDict from app.domain.models.role import UserRole # ============================================ # Request Schemas (输入) # ============================================ class UserCreate(BaseModel): """用户注册""" username: str = Field(..., min_length=3, max_length=50, description="用户名,3-50个字符") email: EmailStr = Field(..., description="邮箱地址") password: str = Field(..., min_length=6, max_length=100, description="密码,至少6个字符") role: UserRole = Field(default=UserRole.USER, description="用户角色") class UserLogin(BaseModel): """用户登录""" username: str = Field(..., description="用户名或邮箱") password: str = Field(..., description="密码") class UserUpdate(BaseModel): """用户信息更新""" email: Optional[EmailStr] = None password: Optional[str] = Field(None, min_length=6, max_length=100) role: Optional[UserRole] = None is_active: Optional[bool] = None # ============================================ # Response Schemas (输出) # ============================================ class UserResponse(BaseModel): """用户信息响应(不含密码)""" id: int username: str email: str role: UserRole is_active: bool is_superuser: bool created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class UserInDB(UserResponse): """数据库中的用户(含密码哈希)""" hashed_password: str # ============================================ # Token Schemas # ============================================ class Token(BaseModel): """JWT Token 响应""" access_token: str refresh_token: Optional[str] = None token_type: str = "bearer" expires_in: int = Field(..., description="过期时间(秒)") class TokenPayload(BaseModel): """JWT Token Payload""" sub: str = Field(..., description="用户ID或用户名") exp: Optional[int] = None iat: Optional[int] = None type: str = Field(default="access", description="token类型: access 或 refresh")