From 243e66ff9b4d9fe730e36f3fa4e327f5eaf5b8ab Mon Sep 17 00:00:00 2001 From: zichun Date: Thu, 30 Apr 2026 14:42:36 +0800 Subject: [PATCH] docs(usr): review approved + check off REQ-USR-003 --- docs/08-模块任务管理.md | 2 +- docs/superpowers/reviews/2026-04-30-REQ-USR-003.md | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 docs/superpowers/reviews/2026-04-30-REQ-USR-003.md diff --git a/docs/08-模块任务管理.md b/docs/08-模块任务管理.md index f4b29f8..3c68d7e 100644 --- a/docs/08-模块任务管理.md +++ b/docs/08-模块任务管理.md @@ -72,5 +72,5 @@ - 功能: - [x] REQ-USR-001 用户新增 - [x] REQ-USR-002 用户修改 - - [ ] REQ-USR-003 用户查询 + - [x] REQ-USR-003 用户查询 - [ ] REQ-USR-004 用户登录 diff --git a/docs/superpowers/reviews/2026-04-30-REQ-USR-003.md b/docs/superpowers/reviews/2026-04-30-REQ-USR-003.md new file mode 100644 index 0000000..f00cb9f --- /dev/null +++ b/docs/superpowers/reviews/2026-04-30-REQ-USR-003.md @@ -0,0 +1,36 @@ +--- +req_id: REQ-USR-003 +date: 2026-04-30 +round: 1 +reviewer: superpower-code-reviewer +--- + +# Review: REQ-USR-003 — round 1 + +## 结论 +approve + +## Must-fix +(无) + +## Nice-to-have + +- backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java:374-389 — `getDefaults_with_jwt_returns200_andList` 未断言 records[0] 不含 `sPasswordHash`。当前由 UserListVO 字段集(11 字段)静态保证,但缺防御性 IT。建议加 `assertThat(records.get(0).has("sPasswordHash")).isFalse()`。 +- backend/src/test/java/com/xly/erp/module/usr/mapper/UserMapperIT.java:119-122 — `pageWithFilter_filtersAndJoins` 只断言 `row2.staffName == null`,未断言 `row2.department == null`。两者都是 LEFT JOIN,建议补全。 +- backend/src/main/java/com/xly/erp/module/usr/service/impl/UserServiceImpl.java:253-259 — `parseBoolean` 对非法 value(如 "abc")返回 -1,SQL `u.bDeleted = -1` → 0 结果,符合 spec line 91 "视为不命中",但缺单测固化。建议加 `listWithBooleanFieldEqualsInvalid_passesNegativeOne`。 +- backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java:374-389 — `tLastLoginDate` JSON 序列化格式无端到端断言。LocalDateTime 默认 Jackson 行为依赖 `spring.jackson.serialization.write-dates-as-timestamps`;如全局未显式 ISO 配置,可能回归出 `[2026,4,30,9,0]` 数组形式。建议加 `assertThat(records.get(0).get("tCreateDate").asText()).matches("\\d{4}-\\d{2}-\\d{2}T.*")`。 +- backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java:374-389 — 默认 ORDER BY iIncrement DESC 无显式断言。建议在 getDefaults 中加 records 中 iIncrement 单调递减的断言形成回归保护。 +- backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java — Controller IT 中 'String token = ... HttpHeaders headers = ... headers.set(Authorization,...)' 模板代码重复 ~17 次。沿用 USR-001/002 dedupe 主题。建议抽 `private HttpHeaders authedJsonHeaders(String userNo)` helper。 +- backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java:392-405 — `getKeywordContains_filtersByUsername` 只插入 1 条匹配,但断言 forEach 检查每条含'包含查询'。如果 records 为空 forEach 0 次会 vacuously pass。建议加 `assertThat(records.size()).isPositive()`。 +- Plan § 文件变更清单 line 28 明列 'Create: dto/UserListQuery.java',实际实现把 5 参直接传 service。无 DTO 反而更简洁(局部变量足够)。属于 § 通用准则 §2 Simplicity First 合理体现。建议在 module-report § ⑤ 记一笔设计抉择回顾,不需要回填 DTO。 + +## 反例 / 测试覆盖缺口 + +Spec 接受标准 19 条全部映射到测试代码(service 10 + mapperIT 1 + controllerIT 8),mvn test 129/129 全绿。 + +- **SQL 注入安全姿态**:`${field}` / `${matchOp}` 都来自 service 端 FIELD_MAP / MATCH_MAP 白名单常量;外部用户输入只用作 Map.get 的 key,不命中即 40001;用户输入 `value` 走 `#{value}` 参数化。无注入风险。 +- **field × match 兼容矩阵**(布尔/日期仅 equals)实现于 UserServiceImpl line 222,`listWithIncompatibleFieldMatch_throws40001` 覆盖。 +- **不过滤 bDeleted=0** 是 spec 显式设计抉择(作废本身是查询字段),代码与 spec 一致。 +- **计划偏离**:UserListQuery DTO 未创建(plan 列了,实现把 5 参直接传 service)—— 简化合理,无 must-fix。 + +非阻塞缺口(VO 敏感字段断言 / JSON 时间格式断言 / 排序断言 / IT dedupe / count assertion)均为健壮性补强,不阻塞 approve。 -- libgit2 0.22.2