Scert/doc/user-groups.md

78 lines
6.2 KiB
Markdown
Raw Permalink 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.

# 用户分组接口与权限说明
适用项目:Scert。更新日期:2026-09-27。
## 页面入口
- 系统设置位于侧栏的系统管理区域,打开已有设置面板。
- 修改密码位于用户管理页面,修改当前登录账号的密码。
- 默认分组置顶并始终展开;命名分组初始折叠。
- 普通用户进入用户中心,只显示本人资料及修改密码,不显示分组。
## 可见范围
| 角色 | 用户读取范围 | 分组关系 | 用户新增、编辑、删除 |
|---|---|---|---|
| 超级管理员 | 全部用户和分组 | 主账号保持受保护 | 允许,主账号保护规则不变 |
| 管理员 | 自己及所属组成员的并集 | 可加入多个命名分组 | 不允许 |
| 普通用户 | 仅自己 | 最多一个命名分组 | 不允许 |
没有命名分组的账号属于默认分组。未分组管理员可见默认组成员,但不可见其他超级管理员。管理员读取多组成员时,只返回双方共同的分组,不泄露对方的其他组名。这里限定的是用户列表可见范围,不代表域名、证书、服务器资源已经实现分组隔离。
## 接口
沿用现有会话认证与同源校验。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/api/v1/users` | 按角色过滤的用户列表 |
| GET | `/api/v1/users/:id` | 查询可见用户;越权与不存在均返回 404 |
| POST | `/api/v1/users` | 超级管理员创建用户 |
| PUT | `/api/v1/users/:id` | 超级管理员更新用户 |
| DELETE | `/api/v1/users/:id` | 超级管理员删除用户 |
列表响应增加 `current_role`、`current_user_id`。用户对象的 `groups` 为字符串数组;默认组和普通用户读取时省略该字段。密码摘要不返回。
新增和更新请求支持 `groups`:省略或传 `null` 时,新增使用默认组,更新保留原关系;传 `[]` 清空命名分组、回到默认组。组名去首尾空白、去重并排序,区分大小写,长度为 1 到 32 个字符,不允许控制字符或保留名称“默认分组”。最多 32 个组,普通用户最多 1 个组。多组管理员降级为普通用户时,必须明确保留不超过一个组,否则返回 400,不会静默丢失分组。
分组名称由保存用户时创建;没有独立空组、组重命名或组删除接口。删除最后一个组内成员后,该组不再显示。
## 数据升级与验证边界
迁移版本 8 为用户表增加可空的 `groups_json` 文本字段。旧记录的空值解释为默认分组,保留原账号、角色和密码摘要。每次读取用户列表时重新读取当前账号分组,不依赖会话中缓存的分组。通过用户管理页面保存变更时,后端会撤销该用户的现有登录会话,包括仅调整分组的情况;该用户下一次请求会返回登录页面,重新登录后应用新的可见范围。不能将仓储层直接更新的单元测试解释为页面调组后无需重新登录。
SQLite 的旧版本升级与重复迁移由专项测试覆盖;MySQL 和 PostgreSQL 提供迁移文件,但本次专项测试不代表这两种数据库已完成真实环境升级验收。
## 2026年9月27日浏览器实机验收
运行版本为源码提交 `9ac222d6db61ce0daeecb846da42852778a1036c`。本轮延续已部署的 SQLite 现场,没有清库或重新初始化,也没有改变证书、DNS、部署服务器或代理配置。所有用户新增、编辑、登录、改密及删除操作均通过浏览器键鼠完成,没有直接调用实机业务接口或新增辅助测试脚本。
### 验收数据与结果
临时建立四个账号:管理员甲属于甲、乙两个组;普通成员属于甲组;管理员乙属于乙、丙两个组;另一普通成员不指定分组。所有测试账号保持用户指定的统一测试密码,文档不保存密码。
| 场景 | 本轮实机结果 |
|---|---|
| 超级管理员查看 | 默认分组置顶且展开,甲、乙、丙组默认折叠,能看到全部组及成员 |
| 管理员多组 | 管理员甲可同时加入甲、乙两组,展开后看到本人及双方共同组的成员 |
| 隐藏非共同组 | 管理员甲看不到管理员乙所属的丙组,也看不到默认组成员或主超级管理员 |
| 普通用户多组限制 | 添加第二组时明确提示先移除原分组,已有分组保持不变 |
| 多组管理员降级 | 选择普通用户后要求先移除多余分组,保存被拦截,未静默丢失原分组 |
| 回到默认分组 | 清除管理员甲的命名分组后,其旧会话失效;重新登录只看到本人及默认组普通成员,不显示其他命名组及主超级管理员 |
| 普通用户界面 | 只显示本人资料及修改密码,不显示分组、其他用户和管理员控制台 |
| 禁用账号 | 禁用管理员甲后,已有会话请求返回登录页;使用原正确密码重新登录也被拒绝 |
| 修改密码入口 | 普通用户可从用户管理打开改密弹窗;错误当前密码被拒绝,正确当前密码提交后撤销会话,重新登录成功 |
| 删除账号 | 删除已登录普通成员后,该会话下一次刷新返回登录页 |
管理员页面没有用户新增、编辑、禁用或删除控件;直接伪造越权请求的拒绝行为由本地专项测试覆盖,本轮没有通过实机接口绕过键鼠限制。改密使用与当前相同的测试密码以遵循用户的统一密码要求,不据此宣称验证了不同新旧密码的轮换流程。
### 清理与回归
- [✓] 四个临时账号均经超级管理员页面删除,命名分组随最后成员删除而消失;页面仅保留原受保护主账号。
- [✓] 通过 SQLite 只读统计补充核验:四个测试账号剩余零条、用户总数一条、命名分组关系零条;没有直接修改数据库。
- [✓] 关闭临时角色验收标签页,保留原管理页面及原始测试资源。
- [✓] Scert、Nginx 保持运行,Scert 主进程及重启计数未变,管理入口 HTTP 200、TLS 校验结果为零。
- [✓] 本地重新执行用户分组、会话失效和仓储分组专项测试通过。
本节只证明上述 SQLite 版本的用户界面与对应会话行为,不替代全新生产初始化、正式管理证书签发、邮件找回密码、其他数据库迁移或完整生产部署验收。