| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- import re
- from datetime import datetime
- from typing import Optional
- from pydantic import BaseModel, ConfigDict, Field, model_validator, field_validator
- from sqlalchemy.ext.asyncio import AsyncSession
- from app.api.v1.module_system.user.model import UserModel
- from app.utils.sms_util import SmsTemplateEnum
- class SmsCodeSchema(BaseModel):
- # 验证手机号格式
- mobile: str = Field(..., description="手机号")
- # 短信模版
- template_name: str = Field(..., description="短信模版")
- # # 验证码
- code: Optional[str] = Field(default=None, description="验证码")
- @field_validator("mobile", mode="before")
- @classmethod
- def validate_mobile(cls, v: str) -> str:
- # 移除常见地格式化字符
- cleaned = re.sub(r'[\s\-+()()]', '', str(v))
- # 中国大陆手机号验证
- china_pattern = r'^1[3-9]\d{9}$'
- # 带国际区号的手机号
- # china_with_country_code = r'^(?:\+?86)?1[3-9]\d{9}$'
- # if not re.match(china_with_country_code, cleaned):
- # raise ValueError("手机号格式错误")
- if not re.match(china_pattern, cleaned):
- raise ValueError("手机号格式错误")
-
- # 返回清洗后的纯数字
- return cleaned.lstrip('+86')
- class AuthSchema(BaseModel):
- """权限认证模型"""
- model_config = ConfigDict(arbitrary_types_allowed=True)
- user: UserModel | None = Field(default=None, description="用户信息")
- check_data_scope: bool = Field(default=True, description="是否检查数据权限")
- db: AsyncSession = Field(description="数据库会话")
- tenant_id: int = Field(default=-1, description="租户ID")
- class JWTPayloadSchema(BaseModel):
- """JWT载荷模型"""
- sub: str = Field(..., description="用户登录信息")
- is_refresh: bool = Field(default=False, description="是否刷新token")
- exp: datetime | int = Field(..., description="过期时间")
- @model_validator(mode="after")
- def validate_fields(self):
- """
- 校验 JWT 载荷字段的基本合法性。
- 返回:
- - JWTPayloadSchema: 校验后的载荷实例。
- 异常:
- - ValueError: 必填字段为空或格式不正确时抛出。
- """
- if not self.sub or len(self.sub.strip()) == 0:
- raise ValueError("会话编号不能为空")
- return self
- class JWTOutSchema(BaseModel):
- """JWT响应模型"""
- model_config = ConfigDict(from_attributes=True)
- access_token: str = Field(..., min_length=1, description="访问token")
- refresh_token: str = Field(..., min_length=1, description="刷新token")
- token_type: str = Field(default="Bearer", description="token类型")
- expires_in: int = Field(..., gt=0, description="过期时间(秒)")
- class RefreshTokenPayloadSchema(BaseModel):
- """刷新Token载荷模型"""
- refresh_token: str = Field(..., min_length=1, description="刷新token")
- class LogoutPayloadSchema(BaseModel):
- """退出登录载荷模型"""
- token: str = Field(..., min_length=1, description="token")
- class CaptchaOutSchema(BaseModel):
- """验证码响应模型"""
- model_config = ConfigDict(from_attributes=True)
- enable: bool = Field(default=True, description="是否启用验证码")
- key: str = Field(..., min_length=1, description="验证码唯一标识")
- img_base: str = Field(..., min_length=1, description="Base64编码的验证码图片")
- class AutoLoginUserSchema(BaseModel):
- """免登录用户信息模型"""
- model_config = ConfigDict(from_attributes=True)
- id: int = Field(..., description="用户ID")
- username: str = Field(..., description="用户名")
- name: str = Field(..., description="用户姓名")
- avatar: str | None = Field(default=None, description="头像")
- class AutoLoginTokenSchema(BaseModel):
- """免登录Token响应模型"""
- model_config = ConfigDict(from_attributes=True)
- token: str = Field(..., description="免登录Token")
- user: AutoLoginUserSchema = Field(..., description="用户信息")
- class LoginMiniRequestSchema(BaseModel):
- """小程序登录请求模型"""
- model_config = ConfigDict(from_attributes=True)
- username: str = Field(..., min_length=1, description="用户名")
- password: str = Field(..., min_length=1, description="密码")
- login_type: Optional[str] = Field(default="mini", description="登录类型")
- class SmsLoginRequestSchema(SmsCodeSchema):
- code: str = Field(..., description="验证码")
|