From cbc01f8b3951db4f9073e1f098a2b40349526870 Mon Sep 17 00:00:00 2001 From: chengma Date: Sun, 9 Aug 2026 13:51:34 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=BD=92=E6=A1=A3=E4=BB=BB=E5=8A=A1=20?= =?UTF-8?q?#51?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/task/51-admin-采购员账号管理.md | 88 ++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs/task/51-admin-采购员账号管理.md diff --git a/docs/task/51-admin-采购员账号管理.md b/docs/task/51-admin-采购员账号管理.md new file mode 100644 index 0000000..eee2fb8 --- /dev/null +++ b/docs/task/51-admin-采购员账号管理.md @@ -0,0 +1,88 @@ +# 51 Admin:实现采购员账号管理 + +- 类型:需求 +- 父级大工单:#14 +- 所属 MVP / 版本:#15 / MVP +- 状态:已完成 +- 日期:2026-08-09 +- Gitea 工单: + +## 背景与目标 + +#50 建立了首次管理员和网页登录,但管理员还不能维护采购员账号。本任务增加最小 +账号管理闭环:管理员可以搜索、新增、启停和重置采购员;采购员继续使用现有业务 +页面,但不能进入用户管理;影响登录安全的修改会立即撤销目标账号全部 Session。 + +## 最终方案 + +- 新增 `/users` 管理页,沿用全站每页 20 条、SQL 分页、越界兜底和筛选条件保留; + 支持用户名字面量搜索和启用/禁用状态筛选。 +- 新建账号固定为 `purchaser` 和 `active`,不提供公开注册、第二管理员或角色选择; + 用户名继续由 v6 的 `NOCASE UNIQUE` 约束做并发下的最终防重。 +- `/users` 路由先经过 #50 的登录认证,再叠加管理员角色中间件。采购员访问返回 + `403`,但访问蝦皮、PDD、顺运宝、任务和客户端等现有业务页面不受影响。 +- 启停账号与 Session 撤销处于同一个写事务;重置 bcrypt 密码哈希与 Session + 撤销也处于同一个事务。失败时整体回滚,不留下“状态已改但旧登录仍有效”的中间态。 +- 禁用有效管理员前在事务内统计有效管理员,最后一个有效管理员不能被禁用;页面 + 同时将唯一管理员的禁用按钮置灰,服务端仍做最终保护。 +- 新增采购员、启停和重置密码均使用 POST + CSRF。启停和重置前二次确认;密码 + 不进入 URL、列表或日志,校验失败时只保留用户名并清空密码。 +- 导航只有管理员显示“用户管理”。页面使用可见标签、文字状态和共享弹窗;一个 + 重置弹窗通过用户编号定位目标,前端不承担权限或 Session 业务逻辑。 + +实际实现与工单方案一致,没有新增数据库迁移、API Key、Client 登录、物理删除或 +细粒度业务页权限。 + +## 改了哪些 + +- `admin/repository/user.go`:用户搜索分页、采购员写入、状态与密码事务、Session 撤销、 + 最后管理员保护。 +- `admin/service/user.go`、`admin/service/auth.go`:管理员权限、采购员业务、共享用户名和 + 密码校验,以及安全区分表单错误和内部错误。 +- `admin/handler/web/user.go`、`admin/handler/web/web.go`:管理员中间件和用户管理路由。 +- `admin/templates/user/list.html`、`admin/templates/partials/header.html`:用户表格、筛选、 + 新增/重置弹窗、管理员导航和行内启停。 +- `admin/static/js/app.js`、`admin/static/css/app.css`:敏感操作确认、共享重置弹窗、状态 + 标签和操作区样式。 +- `admin/service/user_test.go`、`admin/user_integration_test.go`:角色、唯一性、筛选、事务、 + Session 撤销、HTTP 权限和页面泄密回归测试。 + +## 验收结果 + +| 验收标准 | 结果 | +|---|---| +| 管理员可创建用户名大小写不敏感且唯一的采购员 | 通过 | +| 管理员可搜索并按状态筛选采购员 | 通过 | +| 管理员可启用和禁用采购员 | 通过 | +| 管理员可重置采购员密码,旧密码失效 | 通过 | +| 禁用或重置密码在同一事务撤销全部 Session | 通过 | +| 采购员可访问业务页但 `/users` 返回 403 | 通过 | +| 不提供公开注册、第二管理员和物理删除入口 | 通过 | +| 最后一个有效管理员不能被禁用 | 通过 | +| 写操作使用 POST、CSRF 和二次确认 | 通过 | +| 页面不泄露密码、哈希和 Session | 通过 | +| 1366×768 用户表格及弹窗可用 | 通过 | +| Go 1.23.0 构建、测试和 vet | 通过 | + +## 测试 + +- 执行的命令: + + ```powershell + cd D:\chengma\cmautobuy\admin + gofmt -l . + go vet ./... + go build ./... + go test ./... -count=1 + ``` + +- 结果:全部通过;`gofmt -l .` 无输出。 +- 浏览器验证:使用隔离的临时数据库,在 1366×768 以管理员进入 `/users`,打开 + 新增弹窗、创建采购员并打开该账号的重置密码弹窗;导航、筛选、表格、焦点、 + 目标用户名和操作按钮均正常。 +- **没验证到的部分**:没有在真实多人同时操作的浏览器环境做人工竞态测试,唯一性、 + 最后管理员保护和 Session 原子撤销由 SQLite 集成测试覆盖;没有触发真实采购。 + +## 相关提交 + +- `eea0d65` feat: 实现 Admin 采购员账号管理 (#51)