Files
server-core/app/api/schemas/auth.py
T
Pine ac2df72b21 refactor(auth): 去多身份/多端口——账号单一角色,删 user_identities/select-identity/多端口路由
- 删 UserIdentity 模型/IdentityRepository/db.identities,账号统一单一角色(users.role)
- auth.py 去 select-identity/_identity_summaries,登录恒返回 identities=[];_login_response_for_user 按单角色签发
- 删多端口路由 rbac_government/investor/developer 及其 main 挂载
- seed 去多身份回填(_migrate_identities/_ensure_port_agents/多端身份/端口标签映射)
- dependencies: require_port 去端口隔离(单角色放宽)、optional_current_user 修 identity_id 多余参数
- user_admin_service create_user 不再建端口身份;schemas 去 SelectIdentityRequest
- 新增迁移 0014_drop_user_identities(drop user_identities 表)
- 测试改写为单角色契约(登录空 identities、无 select-identity、账号级智能体)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-26 19:15:51 +08:00

165 lines
5.5 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.
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 # 是否已绑手机(小程序「已绑定手机」徽标/绑定门槛)
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 = "service"
account_type_label: str = "服务方"
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)
class ProfileResponse(UserProfile):
"""update-profile 成功后的响应;修改凭据时附带新令牌。"""
token: str = ""
identities: list[IdentityInfo] = Field(default_factory=list)
# ---------------------------------------------------------------------------
# 统一登录(手机验证码 / 微信)—— 六端登录归一
# ---------------------------------------------------------------------------
class SendCodeRequest(BaseModel):
phone: str = Field(description="11 位手机号(作为登录账号)")
class SendCodeResponse(BaseModel):
sent: bool = True
message: str = "验证码已发送"
# 非空时表示走 stub 直发(仅开发/联调可见)
stub_code: str | None = None
class PhoneLoginRequest(BaseModel):
phone: str
code: str = Field(description="手机号接收到的 6 位验证码")
class WxLoginRequest(BaseModel):
code: str = Field(description="wx.login 返回的 code(未配置 appid 时当作 openid 直通)")
nickName: str = ""
avatarUrl: str = ""
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 管理请求/响应