Files
server-core/app/api/schemas/auth.py
T

177 lines
6.2 KiB
Python
Raw Normal View History

from pydantic import BaseModel, Field
class IdentityInfo(BaseModel):
"""账号绑定的一端口身份摘要(登录/选择身份时返回)。"""
id: str
port: str = "opc"
role: str = "opc_member"
sub_role: str | None = None
name: str = ""
org_id: str | None = None
region_id: str | None = None
org_name: str | None = None
region_name: str | None = None
status: str = "active"
class LoginRequest(BaseModel):
username: str
password: str
expires_in: int | None = Field(
default=None,
description="令牌有效期(秒),-1/0 表示永久,省略为 7 天",
)
class RegisterRequest(BaseModel):
username: str
password: str
expires_in: int | None = Field(
default=None,
description="令牌有效期(秒),-1/0 表示永久,省略为 7 天",
)
class UpdateProfileRequest(BaseModel):
"""更新资料/凭据。``current_password`` 仅在修改用户名/密码时校验。"""
current_password: str = ""
new_username: str | None = None
new_password: str | None = None
expires_in: int | None = None
# 演示用户资料字段(账户管理页可编辑)
nickname: str | None = None
# 小程序契约字段(name→nicknamestatus→opc_statustopics→JSON 列表)
name: str | None = None
status: str | None = None
topics: list[str] | None = None
account: str | None = None
company: str | None = None
room: str | None = None
avatar: str | None = None
company_avatar: str | None = None
class RevokeTokenRequest(BaseModel):
token: str | None = Field(
default=None,
description="要吊销的令牌;省略则吊销当前令牌",
)
class AuthStatusResponse(BaseModel):
enabled: bool
has_users: bool
login_modes: list[str] = ["password", "phone"] # password/phone/wechat/miniprogram(四种)
wechat_login: bool = False # 小程序扫码(code2session)
wx_qr: bool = False # 微信开放平台扫码(OAuth)
env: str = "prod" # prod | dev —— 运行环境(前端/联调可据此确认)
wxacode_env: str = "release" # release | trial | develop —— 小程序码指向的版本(体验版=trial)
class VerifyResponse(BaseModel):
valid: bool
username: str = ""
class UserProfile(BaseModel):
"""用户资料(登录/me/update-profile 均返回该结构)。"""
username: str = ""
nickname: str = ""
name: str = "" # 别名 = nickname(小程序契约:显示名 / 报名资料姓名)
phone: str = "" # 已绑定手机号
phoneBound: bool = False # 是否已绑手机(小程序「已绑定手机」徽标/绑定门槛)
wxBound: bool = False # 是否已绑定微信开放平台 openid
wxMiniBound: bool = False # 是否已绑定小程序 openid(各端口共享)
account: str = ""
company: str = ""
room: str = ""
avatar: str = ""
company_avatar: str = ""
# RBAC(登录/me 返回;update-profile 不重签时不返回权限明细)
role: str = "opc_member"
sub_role: str | None = None
# 账号类型(三种)与中文标签 —— 前端直接渲染文本,不做代码映射
account_type: str = "opc_member"
account_type_label: str = "OPC"
org_id: str | None = None
region_id: str | None = None
permissions: list[str] = Field(default_factory=list)
scope_region_ids: list[str] = Field(default_factory=list)
# 当前生效的端口身份(多身份绑定)
identity_id: str | None = None
port: str | None = None
identity_name: str = ""
class LoginResponse(UserProfile):
"""登录/注册成功后的响应:资料 + 新令牌。"""
token: str = ""
identities: list[IdentityInfo] = Field(default_factory=list)
# 登录时生成的 MQTT 连接凭证(直连 EMQX broker 用),可能为 NoneEMQX 未配置/失败)
mqtt: dict | None = None
class ProfileResponse(UserProfile):
"""update-profile 成功后的响应;修改凭据时附带新令牌。"""
token: str = ""
identities: list[IdentityInfo] = Field(default_factory=list)
# ---------------------------------------------------------------------------
# 统一登录(手机验证码 / 微信)—— 六端登录归一
# ---------------------------------------------------------------------------
class SendCodeRequest(BaseModel):
phone: str = Field(description="11 位手机号(作为登录账号)")
scene: str = Field(
default="login",
description="短信场景:login 登录 / register 注册 / notification 通知 / "
"order_status 订单状态变动 / appointment 服务预约",
)
class SendCodeResponse(BaseModel):
sent: bool = True
message: str = "验证码已发送"
# 非空时表示走 stub 直发(仅开发/联调可见)
stub_code: str | None = None
class PhoneLoginRequest(BaseModel):
phone: str
code: str = Field(description="手机号接收到的 6 位验证码")
2026-09-02 02:18:41 +08:00
inviter: str = Field(default="", description="邀请人ID或邀请码")
class WxLoginRequest(BaseModel):
code: str = Field(description="wx.login 返回的 code(未配置 appid 时当作 openid 直通)")
nickName: str = ""
avatarUrl: str = ""
2026-09-02 02:18:41 +08:00
inviter: str = Field(default="", description="邀请人ID或邀请码")
scene: str = Field(default="", description="扫码场景值")
class WxPhoneRequest(BaseModel):
openid: str
phone: str = Field(description="待补绑的手机号")
code: str = Field(description="手机号接收到的验证码")
class MpQrConfirmRequest(BaseModel):
"""小程序扫码登录确认(小程序内 wx.login 后调用)。"""
scene: str = Field(description="web/桌面端 /auth/mp-qr/start 返回的场景")
code: str = Field(description="wx.login 返回的 code")
class BindPhoneRequest(BaseModel):
"""当前账号绑定手机号(验证码;若该手机号已被其它账号占用则按手机号合并)。"""
phone: str
code: str = Field(description="发送到该手机号的验证码")
class UnbindRequest(BaseModel):
"""解除已绑定的登录方式(保留至少一种登录方式)。"""
type: str = Field(description="phone | wx | wx_mini")
# RBAC 管理请求/响应