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 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"] # 本期:账号密码 + 手机号验证码;微信扫码预留 wechat_login: bool = False # 微信扫码(预留,本期未开放) class VerifyResponse(BaseModel): valid: bool username: str = "" class UserProfile(BaseModel): """用户资料(登录/me/update-profile 均返回该结构)。""" username: str = "" nickname: str = "" account: str = "" company: str = "" room: str = "" avatar: str = "" company_avatar: str = "" # RBAC(登录/me 返回;update-profile 不重签时不返回权限明细) role: str = "opc_member" sub_role: str | None = None 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 SelectIdentityRequest(BaseModel): """切换到指定端口身份:为新身份签发令牌。""" identity_id: str # --------------------------------------------------------------------------- # 统一登录(手机验证码 / 微信)—— 六端登录归一 # --------------------------------------------------------------------------- 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 直通)") class WxPhoneRequest(BaseModel): openid: str phone: str = Field(description="待补绑的手机号") code: str = Field(description="手机号接收到的验证码") # RBAC 管理请求/响应