user_schema.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """
  2. 用户数据传输对象定义
  3. 定义用户相关API请求和响应的数据结构
  4. 需求: 3.4, 9.2, 9.3
  5. """
  6. from datetime import datetime, date
  7. from typing import Optional
  8. from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
  9. class UserCreate(BaseModel):
  10. """用户注册请求"""
  11. username: str = Field(..., min_length=3, max_length=50, description="用户名", examples=["testuser"])
  12. password: str = Field(..., min_length=6, max_length=100, description="密码(默认为加密密码,Swagger测试时传明文并设置encrypted=false)", examples=["password123"])
  13. nickname: str = Field(..., min_length=1, max_length=100, description="昵称", examples=["测试用户"])
  14. email: Optional[EmailStr] = Field(None, description="邮箱", examples=["test@example.com"])
  15. phone: Optional[str] = Field(None, max_length=20, description="手机号")
  16. sms_code: Optional[str] = Field(None, description="手机验证码(普通注册时必填)")
  17. email_code: Optional[str] = Field(None, description="邮箱验证码(填写邮箱时必填)")
  18. encrypted: Optional[bool] = Field(True, description="密码是否已加密(默认true,Swagger测试时设为false使用明文)")
  19. @field_validator("email", mode="before")
  20. @classmethod
  21. def normalize_email(cls, value):
  22. # Treat blank strings from external SSO providers as missing email.
  23. if value is None:
  24. return None
  25. if isinstance(value, str):
  26. normalized = value.strip()
  27. return normalized or None
  28. return value
  29. class UserLogin(BaseModel):
  30. """用户登录请求"""
  31. username: str = Field(..., description="用户名或手机号", examples=["testuser"])
  32. password: str = Field(..., description="密码(默认为加密密码,Swagger测试时传明文并设置encrypted=false)", examples=["password123"])
  33. encrypted: Optional[bool] = Field(True, description="密码是否已加密(默认true,Swagger测试时设为false使用明文)")
  34. class UserUpdate(BaseModel):
  35. """用户信息更新请求"""
  36. nickname: Optional[str] = Field(None, min_length=1, max_length=100, description="昵称")
  37. phone: Optional[str] = Field(None, max_length=20, description="手机号")
  38. email: Optional[EmailStr] = Field(None, description="邮箱")
  39. avatar: Optional[str] = Field(None, description="头像URL")
  40. apikey: Optional[str] = Field(None, max_length=255, description="API密钥")
  41. @field_validator("email", mode="before")
  42. @classmethod
  43. def normalize_email(cls, value):
  44. if value is None:
  45. return None
  46. if isinstance(value, str):
  47. normalized = value.strip()
  48. return normalized or None
  49. return value
  50. class UserVerifyRequest(BaseModel):
  51. """用户实名认证请求"""
  52. real_name: str = Field(..., min_length=2, max_length=100, description="真实姓名")
  53. id_card: str = Field(..., min_length=15, max_length=18, description="身份证号")
  54. class UserResponse(BaseModel):
  55. """用户信息响应(不包含密码)"""
  56. id: str
  57. username: Optional[str] = None
  58. nickname: str
  59. phone: Optional[str] = None
  60. email: Optional[str] = None
  61. avatar: Optional[str] = None
  62. real_name: Optional[str] = None
  63. is_verified: str = "unverified"
  64. verified_at: Optional[datetime] = None
  65. registration_date: Optional[date] = None
  66. created_at: datetime
  67. updated_at: datetime
  68. model_config = ConfigDict(from_attributes=True)
  69. class TokenResponse(BaseModel):
  70. """登录令牌响应"""
  71. access_token: str
  72. token_type: str = "bearer"
  73. user: UserResponse
  74. class TokenVerifyResponse(BaseModel):
  75. """Token验证响应"""
  76. valid: bool
  77. user: UserResponse