hyapp-server/server/admin/docs/permission-management.md
2026-05-09 13:36:41 +08:00

559 lines
20 KiB
Markdown
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.

# HYApp 管理后台权限管理功能文档
本文档作为后台管理系统权限管理的设计基准。以后后台相关文档统一放在 `hyapp-admin-server/docs/`
## 目标
后台权限采用 RBAC
- 用户通过角色获得权限,不直接给用户绑定权限。
- 菜单权限控制页面入口和前端路由访问。
- 按钮权限控制页面内操作按钮、批量操作、导出、状态变更等动作。
- 后端接口必须做权限校验,前端按钮隐藏或禁用只作为体验层控制。
- 权限码是前后端契约,不能只改文案或按钮,不同步后端权限码。
## 当前实现事实
当前后端已经具备基础 RBAC 表:
- `admin_users`:后台用户。
- `admin_roles`:后台角色。
- `admin_permissions`:权限定义,字段包含 `code``name``kind`
- `admin_user_roles`:用户角色关系。
- `admin_role_permissions`:角色权限关系。
- `admin_menus`:菜单定义,通过 `permission_code` 绑定菜单查看权限。
当前认证链路:
- 登录成功后,后端把用户权限码写入 access token。
- 前端 `AuthProvider` 保存 `permissions`,通过 `can(code)` 判断。
- 前端路由使用 `RequirePermission` 拦截页面。
- 后端 API 使用 `middleware.RequirePermission(code)` 校验。
当前注意点:
- 角色权限变更后,旧 access token 内的权限不会立即变化;用户重新登录或 refresh 后才会获得新权限。若后续需要立即生效,需要增加 session 失效或 token version 机制。
- `platform-admin` 当前会绑定全部权限;其他预置角色需要补默认权限绑定策略。
- `菜单权限` 页面当前只读,没有菜单、权限定义的增删改能力。
## 权限类型
权限 `kind` 使用以下值:
| kind | 用途 | 示例 |
| --- | --- | --- |
| `menu` | 页面入口、路由访问、菜单展示 | `user:view` |
| `button` | 页面按钮、批量操作、导出、状态变更 | `user:create` |
| `api` | 独立接口权限。只有当接口不能自然归属到菜单或按钮时才使用 | `search:global` |
约定:
- 普通页面查看权限统一使用 `模块:view`
- 创建使用 `模块:create`
- 编辑使用 `模块:update`
- 删除使用 `模块:delete`
- 导出使用 `模块:export`
- 状态切换使用 `模块:status`
- 批量操作如果风险高于单条操作,单独定义 `模块:batch-*`
- 不再新增过宽的 `*:manage` 权限;当前已有 `role:manage` 可兼容保留,后续应拆到按钮级权限。
## 后台基础权限矩阵
### 总览
| 权限码 | kind | 控制范围 | 后端接口 |
| --- | --- | --- | --- |
| `overview:view` | `menu` | 总览页面、总览菜单 | `GET /api/v1/dashboard/overview` |
按钮:
| 按钮 | 权限码 | 当前状态 | 目标 |
| --- | --- | --- | --- |
| 刷新 | `overview:view` | 已实现 | 查看总览即可刷新 |
| 部署服务 | `service:create` | 按钮已展示但未接动作 | 跳转或打开服务创建抽屉 |
### 服务管理
| 权限码 | kind | 控制范围 | 后端接口 |
| --- | --- | --- | --- |
| `service:view` | `menu` | 服务管理菜单、列表、详情 | `GET /api/v1/services``GET /api/v1/services/:id` |
| `service:create` | `button` | 创建服务、总览部署服务 | `POST /api/v1/services` |
| `service:update` | `button` | 编辑服务基础信息、配置 | `PATCH /api/v1/services/:id` |
| `service:operate` | `button` | 启动、停止、重启 | `PATCH /api/v1/services/:id/status``POST /api/v1/services/:id/restart` |
按钮:
| 页面 | 按钮 | 权限码 | 当前状态 | 目标 |
| --- | --- | --- | --- | --- |
| 总览 | 部署服务 | `service:create` | 缺少动作 | 接入服务创建 |
| 总览/服务管理 | 启动 | `service:operate` | 已按权限控制 | 保持 |
| 总览/服务管理 | 停止 | `service:operate` | 已按权限控制 | 保持 |
| 总览/服务管理 | 重启 | `service:operate` | 已按权限控制 | 保持 |
| 服务管理 | 创建服务 | `service:create` | 已按权限控制 | 保持 |
| 服务管理 | 编辑服务 | `service:update` | API 已有,页面未接 | 新增编辑入口 |
| 服务管理 | 更多 | 按具体动作拆分 | 当前无实际动作 | 有动作后再展示 |
### 用户管理
| 权限码 | kind | 控制范围 | 后端接口 |
| --- | --- | --- | --- |
| `user:view` | `menu` | 用户管理菜单、列表、详情 | `GET /api/v1/users``GET /api/v1/users/:id` |
| `user:create` | `button` | 新增后台用户 | `POST /api/v1/users` |
| `user:update` | `button` | 编辑后台用户姓名、团队、MFA、角色 | `PATCH /api/v1/users/:id` |
| `user:status` | `button` | 启用、停用、锁定、解锁、批量状态 | `PATCH /api/v1/users/:id/status``POST /api/v1/users/batch/status` |
| `user:reset-password` | `button` | 重置后台用户密码 | `POST /api/v1/users/:id/reset-password` |
| `user:export` | `button` | 导出后台用户 CSV | `GET /api/v1/users/export` |
按钮:
| 按钮 | 权限码 | 当前状态 | 目标 |
| --- | --- | --- | --- |
| 新增用户 | `user:create` | 已按权限控制 | 保持 |
| 编辑 | `user:update` | 已按权限控制 | 保持 |
| 锁定/解锁 | `user:status` | 已按权限控制 | 保持 |
| 启用/停用 | `user:status` | 已按权限控制 | 保持 |
| 批量启用/停用 | `user:status` | 已按权限控制 | 后续可拆 `user:batch-status` |
| 重置密码 | `user:reset-password` | 已按权限控制 | 保持 |
| 导出 | `user:export` | 当前使用 `user:view`,前端按钮未单独控制 | 拆独立导出权限 |
| 角色配置快捷入口 | `role:view` | 已按权限控制 | 保持 |
### 角色管理
当前后端使用 `role:view``role:manage`,目标需要拆细。
| 权限码 | kind | 控制范围 | 后端接口 |
| --- | --- | --- | --- |
| `role:view` | `menu` | 角色配置菜单、角色列表 | `GET /api/v1/roles` |
| `permission:view` | `menu` | 权限定义列表 | `GET /api/v1/permissions` |
| `role:create` | `button` | 新增角色 | `POST /api/v1/roles` |
| `role:update` | `button` | 编辑角色名称、编码、说明 | `PATCH /api/v1/roles/:id` |
| `role:delete` | `button` | 删除角色 | `DELETE /api/v1/roles/:id` |
| `role:permission` | `button` | 配置角色权限 | `PUT /api/v1/roles/:id/permissions` |
| `role:manage` | `button` | 兼容旧权限 | 当前已实现,后续拆分后保留迁移期 |
按钮:
| 按钮 | 权限码 | 当前状态 | 目标 |
| --- | --- | --- | --- |
| 新增角色 | `role:create` | 当前使用 `role:manage` | 拆为 `role:create` |
| 编辑角色 | `role:update` | 当前使用 `role:manage` | 拆为 `role:update` |
| 删除角色 | `role:delete` | 当前使用 `role:manage` | 拆为 `role:delete` |
| 勾选权限 | `role:permission` | 当前跟随编辑角色保存 | 拆为角色授权权限 |
### 菜单权限
当前页面只读,目标需要支持菜单树维护和权限定义查看。
| 权限码 | kind | 控制范围 | 后端接口 |
| --- | --- | --- | --- |
| `menu:view` | `menu` | 菜单权限页面、菜单树查看 | 当前用 `GET /api/v1/navigation/menus` |
| `menu:create` | `button` | 新增菜单 | 待新增 |
| `menu:update` | `button` | 编辑菜单标题、路由、图标、权限码 | 待新增 |
| `menu:delete` | `button` | 删除菜单 | 待新增 |
| `menu:sort` | `button` | 菜单排序 | 待新增 |
| `menu:visible` | `button` | 菜单显示/隐藏 | 待新增 |
| `permission:create` | `button` | 新增权限定义 | 待新增 |
| `permission:update` | `button` | 编辑权限名称、类型、说明 | 待新增 |
| `permission:delete` | `button` | 删除未绑定权限 | 待新增 |
| `permission:sync` | `button` | 从代码或配置同步权限种子 | 待新增 |
按钮:
| 按钮 | 权限码 | 当前状态 | 目标 |
| --- | --- | --- | --- |
| 新增菜单 | `menu:create` | 未实现 | 新增 |
| 编辑菜单 | `menu:update` | 未实现 | 新增 |
| 删除菜单 | `menu:delete` | 未实现 | 新增 |
| 上移/下移 | `menu:sort` | 未实现 | 新增 |
| 显示/隐藏 | `menu:visible` | 未实现 | 新增 |
| 新增权限 | `permission:create` | 未实现 | 新增 |
| 编辑权限 | `permission:update` | 未实现 | 新增 |
| 删除权限 | `permission:delete` | 未实现 | 新增 |
| 同步权限 | `permission:sync` | 未实现 | 新增 |
### 日志审计
| 权限码 | kind | 控制范围 | 后端接口 |
| --- | --- | --- | --- |
| `log:view` | `menu` | 登录日志、操作日志页面 | `GET /api/v1/logs/login``GET /api/v1/logs/operations` |
| `log:export` | `button` | 导出日志 | 待新增 |
按钮:
| 按钮 | 权限码 | 当前状态 | 目标 |
| --- | --- | --- | --- |
| 搜索 | `log:view` | 已实现 | 保持 |
| 导出 | `log:export` | 未实现 | 新增 |
| 查看详情 | `log:view` | 未实现 | 新增详情抽屉 |
### 通知中心
| 权限码 | kind | 控制范围 | 后端接口 |
| --- | --- | --- | --- |
| `notification:view` | `menu` | 通知中心页面、通知列表 | `GET /api/v1/notifications` |
| `notification:read` | `button` | 单条标记已读 | `PATCH /api/v1/notifications/:id/read` |
| `notification:read-all` | `button` | 批量已读 | 待新增 |
| `notification:delete` | `button` | 删除通知 | 待新增 |
按钮:
| 按钮 | 权限码 | 当前状态 | 目标 |
| --- | --- | --- | --- |
| 已读 | `notification:read` | 当前使用 `notification:view` | 拆独立权限 |
| 全部已读 | `notification:read-all` | 未实现 | 新增 |
| 删除 | `notification:delete` | 未实现 | 新增 |
### 个人账户
个人账户操作不走角色授权,登录用户默认可操作自己的会话和密码。
| 功能 | 权限 | 后端接口 | 当前状态 |
| --- | --- | --- | --- |
| 查看自己 | 登录态 | `GET /api/v1/auth/me` | 已实现 |
| 修改自己的密码 | 登录态 | `POST /api/v1/auth/change-password` | API 已有,前端入口未实现 |
| 退出登录 | 登录态 | `POST /api/v1/auth/logout` | 已实现 |
### 全局搜索
当前搜索接口为登录态可用:`GET /api/v1/search`
目标:
- 搜索结果必须按用户权限过滤。
- 没有 `service:view` 时不返回服务结果。
- 没有 `user:view` 时不返回用户结果。
- 没有 `role:view` 时不返回角色结果。
- 搜索结果跳转的目标页面必须有对应菜单权限。
## App 业务后台权限预留
以下权限用于 App 业务管理模块。已接入默认菜单的模块由后台种子同步菜单、权限和平台管理员授权。
### App 用户
| 权限码 | kind | 控制范围 |
| --- | --- | --- |
| `app-user:view` | `menu` | App 用户列表、详情 |
| `app-user:update` | `button` | 修改用户资料 |
| `app-user:status` | `button` | 后台封禁、解封 |
| `app-user:password` | `button` | 后台设置 App 用户密码 |
| `app-user:identity` | `button` | 短号、靓号管理 |
| `app-user:country` | `button` | 国家/区域调整 |
### 国家和区域
| 权限码 | kind | 控制范围 |
| --- | --- | --- |
| `country:view` | `menu` | 国家列表 |
| `country:create` | `button` | 新增国家 |
| `country:update` | `button` | 编辑国家 |
| `country:status` | `button` | 启用、停用国家 |
| `region:view` | `menu` | 区域列表 |
| `region:create` | `button` | 新增区域 |
| `region:update` | `button` | 编辑区域 |
| `region:status` | `button` | 停用区域 |
| `region:countries` | `button` | 维护区域国家 |
### 房间管理
| 权限码 | kind | 控制范围 |
| --- | --- | --- |
| `room:view` | `menu` | 房间列表、详情、房间状态 |
| `room:update` | `button` | 后台修改房间展示资料、模式、状态、区域 |
| `room:delete` | `button` | 后台删除房间 |
| `room:create` | `button` | 后台创建房间 |
| `room:mic` | `button` | 上下麦、换麦、锁麦 |
| `room:chat` | `button` | 公屏开关 |
| `room:admin` | `button` | 设置房间管理员 |
| `room:host-transfer` | `button` | 转移主持 |
| `room:mute` | `button` | 禁言、解除禁言 |
| `room:kick` | `button` | 踢出房间 |
| `room:unban` | `button` | 房间解封用户 |
### 文件上传
| 权限码 | kind | 控制范围 |
| --- | --- | --- |
| `upload:create` | `button` | 后台上传文件、图片到 COSobject key 使用后台独立前缀 |
### 钱包和交易
| 权限码 | kind | 控制范围 |
| --- | --- | --- |
| `wallet:view` | `menu` | 钱包概览、余额查询 |
| `wallet:transaction-view` | `menu` | 交易流水 |
| `wallet:adjust` | `button` | 后台调账 |
| `withdrawal:view` | `menu` | 提现记录 |
| `withdrawal:review` | `button` | 提现审核 |
| `withdrawal:export` | `button` | 提现导出 |
### 礼物和活动
| 权限码 | kind | 控制范围 |
| --- | --- | --- |
| `resource:view` | `menu` | 资源列表、资源详情 |
| `resource:create` | `button` | 新增资源 |
| `resource:update` | `button` | 编辑资源、启用、禁用 |
| `resource-group:view` | `menu` | 资源组列表、资源组详情 |
| `resource-group:create` | `button` | 新增资源组 |
| `resource-group:update` | `button` | 编辑资源组、替换组成员、启用、禁用 |
| `resource-grant:view` | `menu` | 资源赠送记录 |
| `resource-grant:create` | `button` | 给用户赠送资源或资源组 |
| `gift:view` | `menu` | 礼物列表 |
| `gift:create` | `button` | 从资源库选择资源新增礼物 |
| `gift:update` | `button` | 编辑礼物、资源绑定和价格 |
| `gift:status` | `button` | 上架、下架 |
| `activity:view` | `menu` | 活动列表 |
| `activity:create` | `button` | 新增活动 |
| `activity:update` | `button` | 编辑活动 |
| `activity:status` | `button` | 发布、暂停、结束 |
### 主播、公会和 BD
| 权限码 | kind | 控制范围 |
| --- | --- | --- |
| `host:view` | `menu` | 主播列表、主播资料 |
| `host:update` | `button` | 编辑主播资料 |
| `host:status` | `button` | 主播状态调整 |
| `agency:view` | `menu` | 公会列表、详情 |
| `agency:create` | `button` | 新增公会 |
| `agency:update` | `button` | 编辑公会 |
| `agency:status` | `button` | 关闭公会、开关入会 |
| `bd:view` | `menu` | BD 列表 |
| `bd:create` | `button` | 新增 BD |
| `bd:update` | `button` | 编辑 BD |
| `coin-seller:view` | `menu` | 币商列表、币商余额 |
| `coin-seller:create` | `button` | 新增币商 |
| `coin-seller:update` | `button` | 启用或禁用币商 |
| `coin-seller:stock-credit` | `button` | 币商进货、金币补偿 |
| `salary:view` | `menu` | 薪资周期、薪资明细 |
| `salary:calculate` | `button` | 计算薪资 |
| `salary:approve` | `button` | 审批薪资 |
| `salary:post` | `button` | 入账薪资 |
| `salary:void` | `button` | 作废薪资 |
| `salary:adjust` | `button` | 调整薪资项 |
## 角色预设
### 平台管理员
`platform-admin`
- 拥有全部权限。
- 能维护用户、角色、权限、菜单和所有业务模块。
### 运维管理员
`ops-admin`
建议权限:
- `overview:view`
- `service:view`
- `service:create`
- `service:update`
- `service:operate`
- `user:view`
- `user:status`
- `log:view`
- `notification:view`
- `notification:read`
### 审计员
`auditor`
建议权限:
- `overview:view`
- `log:view`
- `user:view`
- `role:view`
- `permission:view`
### 只读用户
`readonly`
建议权限:
- 所有已开放模块的 `*:view`
- 不包含创建、更新、删除、导出、状态变更、重置密码、授权等按钮权限。
## 前端落地规则
页面路由:
- 路由必须配置菜单查看权限。
- 没有菜单权限时跳转到用户有权限的第一个页面;不能固定跳到无权限页面。
菜单:
- 左侧菜单只展示当前用户拥有 `permission_code` 的菜单。
- 父菜单没有权限码时,只要存在可见子菜单即可展示。
- 父菜单没有可见子菜单时不展示。
按钮:
- 危险操作按钮没有权限时不展示。
- 表格行内操作没有权限时不展示,必要时可以禁用但必须有明确状态。
- 批量操作必须同时检查权限和选中项。
- 导出按钮必须有独立导出权限。
搜索:
- 搜索入口登录后可见。
- 搜索结果按权限过滤。
- 点击结果前仍由路由权限兜底。
## 后端落地规则
接口:
- 除登录、刷新、健康检查外,所有接口必须先通过认证。
- 每个写接口必须绑定按钮权限。
- 每个读接口必须绑定菜单查看权限或更细读权限。
- 批量、导出、重置密码、状态变更不能复用普通查看权限。
日志:
- 创建、更新、删除、授权、状态变更、密码重置、导出、批量操作必须写操作日志。
- 操作日志需要记录操作者、资源、动作、结果、详情、IP、路径。
权限变更:
- 角色权限保存后必须记录操作日志。
- 后续若要求立即生效,需要使相关用户 session 失效或提高 token version。
数据约束:
- 权限 `code` 唯一。
- 菜单 `code` 唯一。
- 删除权限前必须确认没有角色绑定、没有菜单引用。
- 删除菜单前必须确认没有子菜单,或明确采用级联删除策略。
- 删除角色前必须确认没有用户绑定,或要求先解绑。
## 需要补齐的接口
### 权限定义
| 方法 | 路径 | 权限 |
| --- | --- | --- |
| `GET` | `/api/v1/permissions` | `permission:view` |
| `POST` | `/api/v1/permissions` | `permission:create` |
| `PATCH` | `/api/v1/permissions/:id` | `permission:update` |
| `DELETE` | `/api/v1/permissions/:id` | `permission:delete` |
| `POST` | `/api/v1/permissions/sync` | `permission:sync` |
### 菜单管理
| 方法 | 路径 | 权限 |
| --- | --- | --- |
| `GET` | `/api/v1/system/menus` | `menu:view` |
| `POST` | `/api/v1/system/menus` | `menu:create` |
| `PATCH` | `/api/v1/system/menus/:id` | `menu:update` |
| `DELETE` | `/api/v1/system/menus/:id` | `menu:delete` |
| `PATCH` | `/api/v1/system/menus/:id/visible` | `menu:visible` |
| `PUT` | `/api/v1/system/menus/sort` | `menu:sort` |
说明:
- `GET /api/v1/navigation/menus` 保留为当前用户菜单接口,只返回当前用户可见菜单。
- `GET /api/v1/system/menus` 是后台菜单维护接口,返回全量菜单树。
### 角色权限
| 方法 | 路径 | 权限 |
| --- | --- | --- |
| `GET` | `/api/v1/roles` | `role:view` |
| `POST` | `/api/v1/roles` | `role:create` |
| `PATCH` | `/api/v1/roles/:id` | `role:update` |
| `DELETE` | `/api/v1/roles/:id` | `role:delete` |
| `PUT` | `/api/v1/roles/:id/permissions` | `role:permission` |
## 前端页面规划
### 角色配置页
功能:
- 角色列表。
- 新增角色。
- 编辑角色。
- 删除角色。
- 打开授权抽屉。
- 按模块、菜单、按钮分组勾选权限。
按钮权限:
- 新增角色:`role:create`
- 编辑角色:`role:update`
- 删除角色:`role:delete`
- 保存授权:`role:permission`
### 菜单权限页
功能:
- 菜单树维护。
- 菜单绑定权限码。
- 菜单排序。
- 菜单显隐。
- 权限定义列表。
- 权限同步。
按钮权限:
- 新增菜单:`menu:create`
- 编辑菜单:`menu:update`
- 删除菜单:`menu:delete`
- 排序:`menu:sort`
- 显隐:`menu:visible`
- 新增权限:`permission:create`
- 编辑权限:`permission:update`
- 删除权限:`permission:delete`
- 同步权限:`permission:sync`
### 用户管理页
功能:
- 用户列表。
- 新增后台用户。
- 编辑后台用户。
- 绑定角色。
- 启用、停用、锁定、解锁。
- 重置密码。
- 导出。
按钮权限:
- 新增用户:`user:create`
- 编辑用户:`user:update`
- 状态操作:`user:status`
- 重置密码:`user:reset-password`
- 导出:`user:export`
## 验收标准
- 无权限用户看不到对应菜单。
- 直接访问无权限路由会被拦截。
- 无按钮权限用户看不到对应操作按钮。
- 直接调用无权限接口返回 403。
- 角色授权保存后,用户重新登录或 refresh 后权限生效。
- 创建、更新、删除、授权、导出、批量和状态类操作都有操作日志。
- 全局搜索结果按当前用户权限过滤。
- `platform-admin` 拥有所有权限。
- `readonly` 只有查看权限,不能触发任何写操作。
## 实施顺序
1. 拆分并补齐权限种子:新增 `permission:*``menu:*``role:create/update/delete/permission``user:export``notification:read/read-all/delete``log:export`
2. 后端补权限定义和菜单管理接口。
3. 后端把现有接口从宽权限调整到按钮级权限。
4. 前端补角色授权抽屉和菜单权限页编辑能力。
5. 前端替换按钮权限码,导出、已读等动作不再复用查看权限。
6. 补默认角色权限绑定策略。
7. 补搜索结果权限过滤。
8. 补后端权限相关测试和前端构建验证。