liuyun d793d34cfc
Some checks are pending
CI / backend (push) Waiting to run
CI / frontend (push) Waiting to run
feat(auth): 平台超管租户切换(子模块 + openspec change)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-12 00:02:52 +08:00

2.2 KiB
Raw Blame History

Context

JWT 载荷为 { sub, tenantCode, username, ver, sid };RequestContext 由 token 派生,resolveAuth/buildContext/getMenus 在当前租户内解析角色与 isSuper;checkUserActive 在当前租户内查用户。多租户隔离使平台超管(touyun)看不到 demo 租户数据。动机见 proposal.md - Why。

Goals / Non-Goals

Goals:

  • 平台超管切入任意租户,数据按目标租户过滤、权限超管绕过、审计归属保留真实超管。

Non-Goals:

  • 不做普通用户/业务租户管理员的跨租户切换。
  • 不做「切回上一个租户」的历史记录(重新选择即可)。

Decisions

D1 — 身份保留 + super 标志

JWT 增加 super?: boolean(仅切换接口签发 true)。sub 始终是平台超管真实 userId,tenantCode 为切入租户。切回 = 再次切换(切到 touyun)。

  • 为什么不用「冒充目标租户管理员」:会丢失超管真实身份,切回需重新登录,审计归属也错。

D2 — POST /auth/switch-tenant

仅登录态;校验 isPlatformSuperAdmin(userId)(查 touyun 的 user_role 是否含 super_admin)+ 目标租户存在且 enabled;签发 super:true 新 token(沿用超管 ver,新 sid);记审计 auth/switch-tenant。

D3 — isSuper 解析改为「平台租户为准」

isPlatformSuperAdmin(userId) = 平台租户 user_role 含 super_admin。resolveAuth/buildContext/getMenus 的 isSuper = 当前租户含 super_admin || isPlatformSuperAdmin(userId)。checkUserActive 对 super token 在平台租户查用户(因超管 userId 在 touyun 而非目标租户)。

D4 — 前端顶栏切换

permissionStore.super 为真时显示「切换租户」下拉(列 GET /tenants);切换后 auth store 换 token、reset 菜单/字典/权限/页签,刷新进入目标租户上下文。

Risks / Trade-offs

  • [super 标志被篡改] → JWT 签名防篡改,且仅 switch 接口签发 super:true。
  • [切换后超管自身待改密] → super token 仍走 checkUserActive,超管待改密时需先改密(可接受)。

Migration Plan

无数据迁移;纯后端 + 前端。回滚即撤销。

Open Questions

无。