Files
meijiaka-zy/python-api/app/schemas/auth.py
T
小鱼开发 923ff63a3d feat: 密码登录功能(验证码/密码双模式 + 忘记密码 + 设置密码)
后端:
- security.py: 新增 bcrypt 密码哈希/校验工具
- auth_service.py: 新增 login_with_password、reset_password_with_sms
- auth.py: 新增 /login-password、/has-password、/set-password、/reset-password 接口
- schemas/auth.py: 新增 PasswordLoginRequest、SetPasswordRequest、ResetPasswordRequest、CheckPasswordResponse
- crud/user.py: 新增 update_password

前端:
- Login.tsx: 支持验证码/密码切换登录,密码模式下显示忘记密码入口
- Login.css: 新增登录方式切换标签、密码输入框样式
- authStore.ts: 新增 loginWithPassword
- Settings.tsx: 新增账号安全区块,显示密码状态,打开设置/修改密码弹窗
- SetPasswordModal.tsx: 设置/修改密码弹窗(旧密码校验、密码显示切换、表单验证)
- ResetPasswordModal.tsx: 忘记密码弹窗(手机号+验证码+新密码重置)

兼容:
- 零数据库迁移,password_hash 字段已存在(nullable)
- 现有接口不变,完全向后兼容旧版本
2026-06-09 23:26:50 +08:00

81 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
认证相关 Schema
===============
"""
from pydantic import BaseModel, Field
from app.schemas.user import UserInfo
class MobileLoginRequest(BaseModel):
"""手机号验证码登录请求"""
mobile: str = Field(..., description="手机号", min_length=11, max_length=20)
code: str = Field(..., description="短信验证码", min_length=4, max_length=10)
device_id: str = Field(..., description="设备唯一标识")
device_name: str | None = Field(None, description="设备名称")
os_info: str | None = Field(None, description="操作系统信息")
app_version: str | None = Field(None, description="应用版本号")
class PasswordLoginRequest(BaseModel):
"""手机号密码登录请求"""
mobile: str = Field(..., description="手机号", min_length=11, max_length=20)
password: str = Field(..., description="密码", min_length=6, max_length=128)
device_id: str = Field(..., description="设备唯一标识")
device_name: str | None = Field(None, description="设备名称")
os_info: str | None = Field(None, description="操作系统信息")
app_version: str | None = Field(None, description="应用版本号")
class SendSmsCodeRequest(BaseModel):
"""发送短信验证码请求"""
mobile: str = Field(..., description="手机号", min_length=11, max_length=20)
class SetPasswordRequest(BaseModel):
"""设置/修改密码请求"""
old_password: str | None = Field(None, description="旧密码(修改时必填)", max_length=128)
new_password: str = Field(..., description="新密码", min_length=6, max_length=128)
class ResetPasswordRequest(BaseModel):
"""短信验证码重置密码请求"""
mobile: str = Field(..., description="手机号", min_length=11, max_length=20)
code: str = Field(..., description="短信验证码", min_length=4, max_length=10)
new_password: str = Field(..., description="新密码", min_length=6, max_length=128)
class RefreshTokenRequest(BaseModel):
"""刷新 Token 请求"""
refresh_token: str = Field(..., description="Refresh Token")
class TokenResponse(BaseModel):
"""Token 响应(登录/刷新共用)"""
access_token: str = Field(..., description="Access Token30 分钟有效)")
refresh_token: str = Field(..., description="Refresh Token30 天有效)")
user: UserInfo = Field(..., description="用户信息")
class CheckPasswordResponse(BaseModel):
"""检查是否设置过密码响应"""
has_password: bool = Field(..., description="是否已设置密码")
class TokenPayload(BaseModel):
"""Token 载荷"""
sub: str | None = Field(None, description="用户 ID")
type: str | None = Field(None, description="Token 类型:access / refresh")
jti: str | None = Field(None, description="JWT 唯一标识(Refresh Token 用)")
exp: int | None = Field(None, description="过期时间戳")