主题
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 错误码大全。
实现步骤建议
- 数据层:在
SchemaPatch增加ensureSubuserTable()(参考ensureRealnamePending的建表写法,幂等)。 - 服务层:新增
SubUserService(邀请、绑定、权限读写、effectiveOwnerId解析)。 - 鉴权层:扩展
AuthServicepayload + 新增SubUserScope中间件,注册到 home 应用。 - 控制器:新增
app/home/controller/Subuser.php;改造Console/Invoice/Order/Ticket的归属过滤。 - 前端:
frontend/home会员中心新增「团队/子用户」页与权限勾选 UI。 - 后台:可选地在客户详情展示其子用户树。
兼容性与风险
- 所有归属查询统一走
effectiveOwnerId(),避免子用户看到他人数据; - 余额扣款仅作用于
owner,子用户invoice.pay必须显式授权; - 实名认证沿用各自
kd_users记录,不在子用户间共享证件信息; - 迁移工具(魔方/V10)如带 Contacts 数据,可在
MigrationService增加映射到本表。
下一篇:23 全站开发文档