127 lines
4.8 KiB
Python
127 lines
4.8 KiB
Python
|
|
# =============================================================================
|
||
|
|
# 企微IT智能服务台 — 扫码登录 Pydantic Schema
|
||
|
|
# =============================================================================
|
||
|
|
# 说明:定义扫码登录的请求/响应数据结构
|
||
|
|
# 涵盖 4 个端点的入参/出参:
|
||
|
|
# 1. POST /api/auth_qrcode/create — 创建扫码登录票据
|
||
|
|
# 2. GET /api/auth_qrcode/poll/{ticket} — 前端轮询扫码状态
|
||
|
|
# 3. POST /api/auth_qrcode/scan — 企微用户扫码后 OAuth code 回调
|
||
|
|
# 4. POST /api/auth_qrcode/confirm — 当前已登录用户确认授权
|
||
|
|
# =============================================================================
|
||
|
|
|
||
|
|
from datetime import datetime
|
||
|
|
from typing import List, Optional
|
||
|
|
|
||
|
|
from pydantic import BaseModel, Field
|
||
|
|
|
||
|
|
|
||
|
|
# --------------------------------------------------------------------------
|
||
|
|
# POST /api/auth_qrcode/create — 创建扫码登录票据
|
||
|
|
# --------------------------------------------------------------------------
|
||
|
|
class QrcodeCreateResponse(BaseModel):
|
||
|
|
"""扫码登录票据创建响应。
|
||
|
|
|
||
|
|
Attributes:
|
||
|
|
ticket: 票据 UUID,前端用此票据轮询状态
|
||
|
|
qrcode_url: 企微 OAuth2 授权 URL(前端渲染二维码)
|
||
|
|
expires_in: 票据有效期(秒),默认 120
|
||
|
|
expires_at: 票据过期时间(ISO 8601 字符串)
|
||
|
|
"""
|
||
|
|
|
||
|
|
ticket: str = Field(..., description="票据 UUID")
|
||
|
|
qrcode_url: str = Field(..., description="企微 OAuth2 授权 URL")
|
||
|
|
expires_in: int = Field(120, description="有效期(秒)")
|
||
|
|
expires_at: datetime = Field(..., description="过期时间(ISO 8601)")
|
||
|
|
|
||
|
|
|
||
|
|
# --------------------------------------------------------------------------
|
||
|
|
# GET /api/auth_qrcode/poll/{ticket} — 轮询扫码状态
|
||
|
|
# --------------------------------------------------------------------------
|
||
|
|
class QrcodePollResponse(BaseModel):
|
||
|
|
"""扫码登录票据轮询响应。
|
||
|
|
|
||
|
|
status 取值:
|
||
|
|
- waiting: 票据有效,等待扫码
|
||
|
|
- scanned: 已扫码,等待确认
|
||
|
|
- confirmed: 已确认登录成功,附带 token
|
||
|
|
- expired: 票据过期/不存在
|
||
|
|
|
||
|
|
Attributes:
|
||
|
|
status: 扫码状态
|
||
|
|
employee_id: 企微用户 ID(scanned/confirmed 时返回)
|
||
|
|
name: 企微用户姓名(scanned/confirmed 时返回)
|
||
|
|
token: 登录 Token(confirmed 时返回,前端存 localStorage)
|
||
|
|
"""
|
||
|
|
|
||
|
|
status: str = Field(..., description="等待/已扫码/已确认/已过期")
|
||
|
|
employee_id: Optional[str] = Field(None, description="企微用户 ID")
|
||
|
|
name: Optional[str] = Field(None, description="企微用户姓名")
|
||
|
|
token: Optional[str] = Field(None, description="登录 Token")
|
||
|
|
|
||
|
|
|
||
|
|
# --------------------------------------------------------------------------
|
||
|
|
# POST /api/auth_qrcode/scan — 企微 OAuth code 回调
|
||
|
|
# --------------------------------------------------------------------------
|
||
|
|
class QrcodeScanRequest(BaseModel):
|
||
|
|
"""扫码登录扫码请求体。
|
||
|
|
|
||
|
|
Attributes:
|
||
|
|
ticket: 扫码登录票据(UUID)
|
||
|
|
code: 企微 OAuth2 授权回调 code
|
||
|
|
"""
|
||
|
|
|
||
|
|
ticket: str = Field(..., min_length=1, description="扫码登录票据")
|
||
|
|
code: str = Field(..., min_length=1, description="企微 OAuth2 授权 code")
|
||
|
|
|
||
|
|
|
||
|
|
class QrcodeScanResponse(BaseModel):
|
||
|
|
"""扫码登录扫码响应。
|
||
|
|
|
||
|
|
Attributes:
|
||
|
|
success: 是否成功
|
||
|
|
message: 提示消息
|
||
|
|
"""
|
||
|
|
|
||
|
|
success: bool = Field(..., description="是否成功")
|
||
|
|
message: str = Field(..., description="提示消息")
|
||
|
|
|
||
|
|
|
||
|
|
# --------------------------------------------------------------------------
|
||
|
|
# POST /api/auth_qrcode/confirm — 当前已登录用户确认授权
|
||
|
|
# --------------------------------------------------------------------------
|
||
|
|
class QrcodeConfirmRequest(BaseModel):
|
||
|
|
"""扫码登录确认请求体。
|
||
|
|
|
||
|
|
Attributes:
|
||
|
|
ticket: 扫码登录票据(UUID)
|
||
|
|
otp_code: OTP 动态码(管理员场景下可选,普通坐席可空)
|
||
|
|
"""
|
||
|
|
|
||
|
|
ticket: str = Field(..., min_length=1, description="扫码登录票据")
|
||
|
|
otp_code: Optional[str] = Field(
|
||
|
|
None,
|
||
|
|
min_length=6,
|
||
|
|
max_length=6,
|
||
|
|
description="OTP 动态码(管理员可选,普通坐席留空)",
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
class QrcodeConfirmResponse(BaseModel):
|
||
|
|
"""扫码登录确认响应。
|
||
|
|
|
||
|
|
Attributes:
|
||
|
|
token: 登录 Token(scanned 用户换发的新 token)
|
||
|
|
employee_id: 企微用户 ID
|
||
|
|
name: 用户姓名
|
||
|
|
roles: 用户角色列表
|
||
|
|
require_otp: 是否需要 OTP 二次验证(预留,本任务不强制)
|
||
|
|
"""
|
||
|
|
|
||
|
|
token: str = Field(..., description="登录 Token")
|
||
|
|
employee_id: str = Field(..., description="企微用户 ID")
|
||
|
|
name: str = Field(..., description="用户姓名")
|
||
|
|
roles: List[str] = Field(default_factory=list, description="用户角色列表")
|
||
|
|
require_otp: Optional[bool] = Field(
|
||
|
|
None,
|
||
|
|
description="是否需要 OTP 二次验证(预留字段,Phase 2.1 实现)",
|
||
|
|
)
|