"""用户相关 Pydantic v2 Schema(请求/响应)。""" import re from pydantic import BaseModel, EmailStr, Field, field_validator _USERNAME_RE = re.compile(r"^[A-Za-z0-9_\-一-鿿]{2,32}$") class RegisterRequest(BaseModel): username: str = Field(min_length=2, max_length=32) email: str = Field(min_length=5, max_length=255) password: str = Field(min_length=8, max_length=128) @field_validator("username") @classmethod def validate_username(cls, v: str) -> str: if not _USERNAME_RE.match(v): raise ValueError("用户名只能包含字母、数字、下划线、短横线和中文,长度 2-32。") return v @field_validator("email") @classmethod def validate_email(cls, v: str) -> str: # 简单格式校验(不引入 email-validator 重依赖) if "@" not in v or "." not in v.split("@")[-1]: raise ValueError("邮箱格式不正确。") return v.lower().strip() @field_validator("password") @classmethod def validate_password(cls, v: str) -> str: if len(v) < 8: raise ValueError("密码长度不能少于 8 位。") return v class LoginRequest(BaseModel): username_or_email: str = Field(min_length=2, max_length=255) password: str = Field(min_length=1, max_length=128) class UserResponse(BaseModel): id: str username: str email: str status: str storage_used: int storage_quota: int created_at: str model_config = {"from_attributes": True} class MeResponse(BaseModel): id: str username: str email: str status: str storage_used: int storage_quota: int created_at: str model_config = {"from_attributes": True} class StorageInfoResponse(BaseModel): storage_used: int storage_quota: int storage_used_mb: float storage_quota_mb: float class UpdateMeRequest(BaseModel): password: str | None = Field(default=None, min_length=8, max_length=128) @field_validator("password") @classmethod def validate_password(cls, v: str | None) -> str | None: if v is not None and len(v) < 8: raise ValueError("密码长度不能少于 8 位。") return v