配置 SSOT(TOML + .env) 统一错误契约 Auth 与事务边界 Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client 可观测性(OpenTelemetry + LGTM)
141 lines
4.8 KiB
Python
141 lines
4.8 KiB
Python
from typing import Literal, Optional
|
||
|
||
from pydantic import BaseModel, Field
|
||
|
||
LanguagePreference = Literal["zh", "en"]
|
||
|
||
|
||
class RegisterRequest(BaseModel):
|
||
phone: str = Field(min_length=11, max_length=11, description="手机号(11位)")
|
||
password: str = Field(min_length=6, description="密码(至少6位)")
|
||
nickname: str = Field(min_length=1, max_length=50, description="昵称")
|
||
email: Optional[str] = Field(None, description="邮箱(可选)")
|
||
agreed_to_terms: bool = Field(description="是否同意用户协议和隐私政策")
|
||
language: Optional[LanguagePreference] = Field(
|
||
None,
|
||
description="device language at signup; only used when creating a new user",
|
||
)
|
||
|
||
|
||
class LoginRequest(BaseModel):
|
||
phone: str = Field(min_length=11, max_length=11, description="手机号(11位)")
|
||
password: str = Field(min_length=1, description="密码")
|
||
agreed_to_terms: bool = Field(description="是否同意用户协议和隐私政策")
|
||
|
||
|
||
class TokenResponse(BaseModel):
|
||
access_token: str
|
||
refresh_token: str
|
||
token_type: str = "bearer"
|
||
|
||
|
||
class RefreshTokenRequest(BaseModel):
|
||
refresh_token: str = Field(description="刷新令牌")
|
||
|
||
|
||
class UserResponse(BaseModel):
|
||
id: str
|
||
phone: str
|
||
email: Optional[str] = None
|
||
nickname: str
|
||
avatar_url: Optional[str] = None
|
||
subscription_type: str
|
||
created_at: str
|
||
language_preference: LanguagePreference = "zh"
|
||
|
||
|
||
class SendSmsRequest(BaseModel):
|
||
phone: str = Field(min_length=11, max_length=11, description="手机号(11位)")
|
||
purpose: str = Field(
|
||
..., description="用途:register/login/reset_password/change_phone"
|
||
)
|
||
|
||
|
||
class SendSmsResponse(BaseModel):
|
||
success: bool
|
||
message: str
|
||
expires_in: Optional[int] = None
|
||
|
||
|
||
class SmsLoginRequest(BaseModel):
|
||
phone: str = Field(min_length=11, max_length=11, description="手机号(11位)")
|
||
code: str = Field(min_length=6, max_length=6, description="验证码(6位)")
|
||
agreed_to_terms: bool = Field(description="是否同意用户协议和隐私政策")
|
||
nickname: Optional[str] = Field(
|
||
None, max_length=50, description="昵称(注册时必填,登录时可选)"
|
||
)
|
||
language: Optional[LanguagePreference] = Field(
|
||
None,
|
||
description="device language at signup; only used when creating a new user",
|
||
)
|
||
|
||
|
||
class MockSmsLoginRequest(BaseModel):
|
||
"""开发/评测专用:与 MOCK_SMS_LOGIN_ENABLED 联用,跳过短信校验。"""
|
||
|
||
phone: str = Field(min_length=11, max_length=11, description="手机号(11位)")
|
||
agreed_to_terms: bool = Field(description="是否同意用户协议和隐私政策")
|
||
nickname: Optional[str] = Field(
|
||
None, max_length=50, description="新用户昵称(可选)"
|
||
)
|
||
language: Optional[LanguagePreference] = Field(
|
||
None,
|
||
description="device language at signup; only used when creating a new user",
|
||
)
|
||
|
||
|
||
class SmsRegisterRequest(BaseModel):
|
||
phone: str = Field(min_length=11, max_length=11, description="手机号(11位)")
|
||
code: str = Field(min_length=6, max_length=6, description="验证码(6位)")
|
||
password: str = Field(min_length=6, description="密码(至少6位)")
|
||
nickname: str = Field(min_length=1, max_length=50, description="昵称")
|
||
email: Optional[str] = Field(None, description="邮箱(可选)")
|
||
agreed_to_terms: bool = Field(description="是否同意用户协议和隐私政策")
|
||
language: Optional[LanguagePreference] = Field(
|
||
None,
|
||
description="device language at signup; only used when creating a new user",
|
||
)
|
||
|
||
|
||
class ResetPasswordRequest(BaseModel):
|
||
phone: str = Field(min_length=11, max_length=11, description="手机号(11位)")
|
||
code: str = Field(min_length=6, max_length=6, description="验证码(6位)")
|
||
new_password: str = Field(min_length=6, description="新密码(至少6位)")
|
||
|
||
|
||
class ChangePasswordRequest(BaseModel):
|
||
old_password: str = Field(min_length=1, description="旧密码")
|
||
new_password: str = Field(min_length=6, description="新密码(至少6位)")
|
||
|
||
|
||
class ChangePhoneRequest(BaseModel):
|
||
new_phone: str = Field(
|
||
..., min_length=11, max_length=11, description="新手机号(11位)"
|
||
)
|
||
code: str = Field(min_length=6, max_length=6, description="验证码(6位)")
|
||
|
||
|
||
class UpdateNicknameRequest(BaseModel):
|
||
nickname: str = Field(
|
||
..., min_length=1, max_length=50, description="昵称(1-50个字符)"
|
||
)
|
||
|
||
|
||
class AvatarUploadResponse(BaseModel):
|
||
avatar_url: str
|
||
|
||
|
||
class SetAvatarPresetRequest(BaseModel):
|
||
preset_id: str = Field(
|
||
...,
|
||
min_length=2,
|
||
max_length=2,
|
||
pattern=r"^\d{2}$",
|
||
description="预设编号,如 01–08",
|
||
)
|
||
|
||
|
||
class AvatarPresetItem(BaseModel):
|
||
id: str
|
||
url: str
|