Skip to content

22 子用户后期开发文档

状态:规划中(后期开发)。 当前代码库尚未实现子用户,kd_users 为单层客户体系。本篇是面向后续迭代的设计规格,给出数据模型、权限模型、接口与改造点,供实现时参考。

背景与目标

企业客户常需要为同一主账户下的多名成员分配独立登录与受限权限(对标魔方/WHMCS 的「子账户 / Contacts」)。目标:

  • 主账户(owner)可邀请/创建多个子用户,共享主账户的服务、账单与余额;
  • 子用户拥有独立登录凭据,但操作范围由主账户授予的权限位约束;
  • 不破坏现有单层客户的所有逻辑(向后兼容)。

数据模型设计

复用现有 kd_users 作为主账户,新增子用户关系与权限:

sql
-- 子用户关系表
CREATE TABLE `kd_user_subusers` (
  `id`            INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `owner_id`      INT UNSIGNED NOT NULL COMMENT '主账户 users.id',
  `sub_user_id`   INT UNSIGNED NOT NULL COMMENT '子用户 users.id',
  `permissions`   JSON NULL COMMENT '权限位数组',
  `status`        TINYINT NOT NULL DEFAULT 1 COMMENT '1启用 0禁用',
  `invite_email`  VARCHAR(128) NOT NULL DEFAULT '',
  `invite_token`  VARCHAR(64) NOT NULL DEFAULT '',
  `invite_expire` INT UNSIGNED NOT NULL DEFAULT 0,
  `create_time`   INT UNSIGNED NOT NULL DEFAULT 0,
  `update_time`   INT UNSIGNED NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_owner_sub` (`owner_id`,`sub_user_id`),
  KEY `idx_sub` (`sub_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='子用户关系';

设计要点:

  • 子用户本身仍是一条 kd_users 记录(复用注册/登录/实名逻辑),通过关系表挂到主账户;
  • owner_id 为空(或不存在关系)即普通主账户,完全兼容现状
  • 权限以权限位字符串数组存储,与后台 RBAC 思路一致(见下)。

权限模型

参考 AdminPermissionService 的「模块键」做法,为会员中心定义子用户权限位:

权限位含义
service.view / service.manage查看 / 操作服务实例(开通、续费、管理)
invoice.view / invoice.pay查看账单 / 支付账单(动用主账户余额)
order.create下单购买
ticket.view / ticket.manage工单查看 / 提交回复
profile.view查看主账户资料(只读)
  • 主账户默认拥有全部权限(['*']);
  • 子用户登录后,鉴权层在 UserAuth 之后追加权限位校验
  • 余额、服务、账单的归属始终是 owner_id,子用户仅是操作者。

鉴权改造点

JWT 当前 payload 为 {type:'user'|'admin', uid}(见 AuthService::issueToken)。子用户建议扩展:

json
{ "type": "user", "uid": 子用户users.id, "owner": 主账户users.id, "scope": ["service.view","invoice.pay"] }
  • AuthService::issueToken 增加可选 extra 参数写入 owner / scope
  • 新增中间件 SubUserScope:解析 token 后,把「数据归属」从 uid 重定向到 owner,并按 scope 拦截无权操作;
  • 会员中心控制器(app/home/controller/*)的「按用户过滤」改为按 effectiveOwnerId() 过滤。

接口设计(会员中心)

方法路径说明所需权限
GET/home/subuser/index子用户列表主账户
POST/home/subuser/invite邀请子用户(邮件含 token)主账户
POST/home/subuser/setPermissions设置权限位主账户
POST/home/subuser/disable / enable启停子用户主账户
POST/home/subuser/remove解除关系主账户
POST/home/auth/acceptInvite子用户凭 token 注册/绑定公开

返回结构沿用 ApiResponse,错误码见 27 错误码大全

实现步骤建议

  1. 数据层:在 SchemaPatch 增加 ensureSubuserTable()(参考 ensureRealnamePending 的建表写法,幂等)。
  2. 服务层:新增 SubUserService(邀请、绑定、权限读写、effectiveOwnerId 解析)。
  3. 鉴权层:扩展 AuthService payload + 新增 SubUserScope 中间件,注册到 home 应用。
  4. 控制器:新增 app/home/controller/Subuser.php;改造 Console/Invoice/Order/Ticket 的归属过滤。
  5. 前端frontend/home 会员中心新增「团队/子用户」页与权限勾选 UI。
  6. 后台:可选地在客户详情展示其子用户树。

兼容性与风险

  • 所有归属查询统一走 effectiveOwnerId(),避免子用户看到他人数据;
  • 余额扣款仅作用于 owner,子用户 invoice.pay 必须显式授权;
  • 实名认证沿用各自 kd_users 记录,不在子用户间共享证件信息;
  • 迁移工具(魔方/V10)如带 Contacts 数据,可在 MigrationService 增加映射到本表。

下一篇:23 全站开发文档

KeDe Finance · 纯 PHP 自研财务系统