2026-06-01-usr.md 14.6 KB

模块完成报告 — USR 用户管理(backend)

生成时间:2026-06-01 CST 模块 id:usr|阶段:后端(backend)|功能分支:module-usr(自默认分支 master 分叉) 本报告为标准化 12 节模块完成报告,供 milestone 标记前置。摘要级(不引入 diff 正文)。


① 模块概述

  • 模块名称:USR 用户管理(com.xly.erp.modules.usr)。
  • 业务范围:企业内部管理系统的用户账号全生命周期与登录认证,覆盖用户新增、修改、分页查询、登录认证 4 个后端 REQ。
  • 依赖:无(docs/08 § 二 标注「依赖: 无」),为整个 ERP 的基础模块。
  • 路径作用域backend/src/main/java/com/xly/erp/modules/usr/** + 公共基础设施 com/xly/erp/common/**(统一响应 / 异常 / 安全 / JWT / BaseEntity,本模块首次落地,供后续模块复用)。
  • 本阶段产出范围:controller / service / repository(mapper) / DTO / VO / 校验 / REST 契约实现;不触 frontend/(UI 推迟到前端阶段);本模块未新增 SQL migration(复用 A4 生成的 V1__initial_schema.sql)。

② 需求覆盖(REQ 清单 + spec 摘要)

本模块 4 个 REQ 全部完成并在 docs/08-模块任务管理.md § 二 勾选为 [x]

REQ 标题 端点 spec 摘要
REQ-USR-001 增加用户 POST /api/usr/users 管理员新建用户:用户名 3-20 位唯一、密码 BCrypt(默认 666666)、用户类型 / 语言枚举约束、可选关联职员 + 权限组授权(多对多);多表写入事务化;新建即生效(iIsVoid=0)。错误码 0/40001/40301/40901。
REQ-USR-002 修改用户 PUT /api/usr/users/{id} 管理员改用户基础信息(用户号 / 关联职员 / 用户类型 / 语言 / 单据修改权限 / 作废标志 / 权限组);sUserNamesPassword 不可改;权限组全量覆盖语义;可选字段 null = 不更新(保守不清空)。错误码 0/40001/40301/40401。
REQ-USR-003 查询用户 GET /api/usr/users 任意已认证用户的只读单条件分页查询(8 个查询字段 × 3 种匹配方式);跨表 LEFT JOIN usr_employee 取员工名 / 部门;文本模糊(LIKE 转义)/ 枚举 / 布尔 / 日期精确匹配;分页参数非法 → 42201,数据越界返回最后一页;密码绝不返回。错误码 0/40001/42201(+401 未认证)。
REQ-USR-004 登录用户 POST /api/usr/login(+ 配套 GET /api/usr/companies 用户名 + 密码 + 版本(companyId) 认证:BCrypt 比对 → 签发带 exp 的无状态 JWT + 更新 tLastLoginDate;防账号枚举(不存在/密码错误同码同提示);禁用账号 40302;进程内登录限流 42901(默认 5 次/300 秒)。配套补齐只读公司列表端点支撑登录页「版本」下拉。错误码 0/40001/40101/40302/42901(+401)。

spec 全文:docs/superpowers/specs/2026-06-01-REQ-USR-00{1,2,3,4}.md。各 spec § 8 已逐条登记自主决策(见本报告 § ⑩)。


③ 文件变更摘要(git diff --stat,master...HEAD)

  • 提交数:53 个 commit(git log master..HEAD --oneline)。
  • 变更规模:85 个文件,+8280 / -5 行。
  • 新增生产代码backend/src/main/java/com/xly/erp/,A=新增):
    • 公共基础设施 common/base/BaseEntityconfig/{MybatisPlusConfig,SecurityConfig}exception/{BusinessException,GlobalExceptionHandler}response/{Result,ResultCode,PageResult}security/{JwtUtil,JwtAuthenticationFilter,SecurityUtil}ErpApplication
    • USR 模块 modules/usr/:controller(UsrUserControllerUsrAuthController)、service(UsrUserService(+Impl)UsrAuthService(+Impl))、mapper(UsrUser/UsrCompany/UsrEmployee/UsrPermission/UsrUserPermission Mapper)、entity(UsrUser/UsrCompany/UsrEmployee/UsrPermission/UsrUserPermission)、dto(CreateUserDTO/UpdateUserDTO/UserQueryDTO/UserQueryCondition/LoginDTO)、vo(UserVO/LoginVO/CompanyOptionVO)。
    • 资源:application.ymlapplication-test.ymlmapper/usr/UsrUserMapper.xml(跨表分页查询)。
    • 构建:backend/pom.xml(Spring Boot + MyBatis-Plus + Flyway 10.10.0 + JWT,java.version=17)、backend/checkstyle.xml
  • 新增测试代码backend/src/test/java/):25 个测试类(详见 § ⑤)。
  • 流程 / 文档scripts/test.mjs(M,新增 ensureJava17())、docs/08-模块任务管理.md(M,4 个 REQ 勾选)、docs/superpowers/{specs,plans,reviews}/2026-06-01-REQ-USR-00{1..4}*.md(A)、docs/superpowers/module-reports/usr-test-gate-r1.md(A)。
  • migration:无新增(见 § ⑥)。
  • 跨模块:无(见 § ⑦)。

④ 读写的数据表

本模块涉及 5 张表,全部由 sql/migrations/V1__initial_schema.sql 建好(A4 阶段从 docs/03 翻译),本模块未做 schema 变更

操作 涉及 REQ 说明
usr_user 读 + 写 001(写) / 002(写) / 003(读) / 004(读+写 tLastLoginDate) 用户主表,主键 iIncrement,唯一索引 uk_usr_user_username
usr_user_permission 001(批量插入) / 002(全量覆盖) 用户-权限多对多关联表,唯一索引 uk_usr_user_permission(iUserId,iPermissionId)
usr_employee 001/002(存在性校验) / 003(LEFT JOIN 取员工名/部门) 职员表;与 usr_user 外键 fk_usr_user_employee ON DELETE SET NULL。
usr_permission 001/002(权限 id 存在性校验) 权限组表。
usr_company 004(版本下拉 + companyId 存在性校验) 公司/版本支撑表,与 usr_user 无外键(仅登录时选择)。

严格遵循 docs/04 § 3.4:仅经 Mapper 访问;查询不 SELECT sPassword;VO 不含密码列;SQL 参数化防注入,LIKE 通配符转义。


⑤ 测试与质量闸(test-gate)

flake 判定:无 flake。 test-gate attempt 序列仅 r1,且 r1 = GREEN(首跑即绿)。

说明:历史上曾在 JDK25 默认工具链下有 5 次 RED 记录(旧 r1–r5),其根因为 Mockito/Byte Buddy 不支持 JDK25 的 class file 版本(69),导致 UsrAuthServiceImplTestJwtUtil 整片 Mockito cannot mock 报 error(终态 88 跑 / 9 error)。该批旧证据因属过期工具链问题已在 commit 282a524 移除,并非当前 attempt 序列的一部分;工具链修复在 dbc3454scripts/test.mjs 新增 ensureJava17(),把后端测试 JVM 的 JAVA_HOME 固定到 Java 17)。本模块当前 attempt 序列从修复后重新起算,r1 首跑即绿,故不构成「red→green flake」。

本次 r1 证据docs/superpowers/module-reports/usr-test-gate-r1.md):

  • 执行命令:node scripts/test.mjs(内部 ensureJava17()/opt/homebrew/Cellar/openjdk@17/17.0.19/.../Home)。
  • 工具链确认:Spring Boot 测试日志 Starting ErpApplicationTests using Java 17.0.19;Maven 3.9.15 / Java 17.0.19。
  • 5 级闸门:1/5 setup-db ✅、2/5 build(mvn -q -B -DskipTests package) ✅、3/5 lint(mvn -q -B checkstyle:check) ✅、4/5 unit+integration(mvn -q -B test) ✅、5/5 e2e(后端无 e2e,skip)✅。
  • 退出码 0,终态 [test.mjs] GREEN
  • 测试统计(surefire-reports 汇总)Tests run: 125, Failures: 0, Errors: 0, Skipped: 0(25 个测试类)。曾整片报错的 UsrAuthServiceImplTest(含 JwtUtil mock)本次 9/9 全绿,证明根因消除。

测试类清单(25)

  • 公共:ErpApplicationTestsSecurityConfigTestGlobalExceptionHandlerTestResultTestResultCodeLoginTestPageResultTestJwtUtilTest
  • DTO 校验:CreateUserDTOValidationTestUpdateUserDTOValidationTestUserQueryDTOValidationTestLoginDTOValidationTest
  • VO 序列化:UserVOJsonTestLoginVOJsonTestCompanyOptionVOJsonTest
  • Mapper:UsrUserMapperPageTestUsrCompanyMapperTest
  • Service 单测:UsrUserServiceImplTest(24)、UsrAuthServiceImplTest(9)。
  • Controller 单测:UsrUserControllerTest(11)、UsrAuthControllerTest(6)。
  • 端到端 IT:UsrUserCreateIT(5)、UsrUserUpdateIT(6)、UsrUserQueryIT(13)、UsrLoginIT(12)、AuthLoginConfigIT(1)。

⑥ 数据库 migration

本模块未新增 migration。

  • git diff --name-only --diff-filter=A master...HEAD -- 'sql/migrations/V*.sql' 结果为空。
  • 现有唯一 migration sql/migrations/V1__initial_schema.sql 由 A4 阶段 db-initdocs/03-数据库设计文档.md(schema SSoT)翻译生成,第一行:-- Flyway migration V1 — initial schema for 小羚羊
  • 4 个 REQ 的 spec § 8 均明确决策「复用 V1,无 schema 变更」(4 张依赖表 usr_user/usr_employee/usr_permission/usr_user_permission/usr_company 结构与 docs/03 一致)。REQ-USR-004 仅对 usr_user.tLastLoginDate 做 UPDATE(DML 非 DDL)。
  • Flyway 依赖已在 pom.xml 声明(flyway-core + flyway-mysql 10.10.0),schema 由 Spring Boot / 测试启动时自动 apply(符合 CLAUDE.md Schema 演化规约)。

⑦ 跨模块改动

无跨模块改动。

  • docs/superpowers/module-reports/usr-cross-module.md 不存在(cross-module-log 未生成 = 本模块未触碰非当前模块的业务代码)。
  • 本模块新增的 common/** 公共基础设施(统一响应 / 异常 / 安全 / JWT / BaseEntity)属全局基础层首次落地,非「改动其他业务模块」,不计入跨模块改动。

⑧ 与规范 / 契约的偏离

实现层无偏离——4 个 REQ 的实现端点、请求/响应字段、错误码、分层、命名、统一响应、异常处理、事务、安全均与 docs/04 技术规范及 docs/05 API 契约一致(详见各 review 报告四维核对结论)。

仅记录 2 项对 docs/05 契约的反向同步建议(实现期已落地为代码,建议择机补入契约 SSoT,非阻塞、非违规):

  1. 新增端点 GET /api/usr/companies(REQ-USR-004 spec § 8 D1):docs/05 仅定义 POST /api/usr/login,未单列公司列表端点。为使登录链路自洽(前端需先取 companyId),后端补齐该只读放行端点。建议补入 docs/05 § REQ-USR-004。
  2. 新增限流错误码 42901(REQ-USR-004 spec § 8 D7):docs/05 未列该码,系为落地卡片「连续失败锁定/限流」要求引入。建议补入 docs/05 错误码段。

以上两项均已在 spec § 8 显式登记为「建议反向同步(非本 stage 强制)」,review 亦标为非阻塞建议。其余无任何偏离。


⑨ 评审与验证记录

每个 REQ 均有 round-1 review(裁决 approve)+ verify(证据验证)报告,路径 docs/superpowers/reviews/2026-06-01-REQ-USR-00{1..4}{,-verify}.md

REQ review 裁决 关键核对结论
REQ-USR-001 approve(issues=[]) 四维(plan-alignment / quality / architecture / docs)无 must-fix;用户名查重 + DuplicateKey 兜底并发安全;密码 BCrypt + @JsonIgnore 不外泄;多表写事务回滚验证;24/24 测试绿。
REQ-USR-002 approve 全量覆盖授权、null=不更新语义、sUserName/sPassword 不可改、审计字段只读均落地;权限差量覆盖与禁用实时生效端到端验证。
REQ-USR-003 approve 单条件 8 字段 × 3 匹配、跨表 LEFT JOIN、LIKE 转义防注入、参数非法 42201 / 数据越界返回最后一页、密码不返回均验证。
REQ-USR-004 approve 认证判定顺序(限流→查用户→验密码→判禁用→校 companyId→签发+更新时间)与 spec § 8 D3 一致;防账号枚举(同码同提示);JWT 含 exp;进程内限流 42901;安全放行 /api/usr/companies
  • 各 review 均附非阻塞口头建议(如限流计数与事务非原子、契约反向同步、冗余去重代码简化),无任何 must-fix。
  • verify 报告确认各 REQ 在通过工具链下测试全绿、验收标准(AC)逐条覆盖。
  • 模块级 test-gate(本报告 § ⑤)在锁定 JDK17 下 125/125 全绿,作为合并默认分支前的硬闸。

⑩ 自主决策汇总(decisions)

本报告渲染过程中的自主决策见文末 decisions[](test-gate 重跑判定、flake 归类等)。各 REQ 实现期的自主决策已在对应 spec § 8 逐条登记,要点汇总:

  • 语言取值锁定sLanguage ∈ {中文,英文,繁体},不取 docs/03 带审阅占位的默认值(REQ-001 D1)。
  • 管理员判定口径:以 sUserType=超级管理员 视为有写权限(无独立角色表)(REQ-001 D2 / 002 D6)。
  • 修改语义:可选字段 null = 不更新(保守不清空);权限组全量覆盖(REQ-002 D3/D4)。
  • 查询边界:单条件查询;参数非法 42201 vs 数据越界返回最后一页二分;LIKE 通配符转义(REQ-003 D1/D2/D3)。
  • 登录链路自洽:补 GET /api/usr/companies 端点;进程内限流 42901(5 次/300 秒);先验密码再判禁用防枚举;JWT 默认 2 小时(REQ-004 D1/D3/D7/D10)。
  • migration:4 个 REQ 全部复用 V1,无新增(REQ-001~004 各 Dn)。

⑪ 已知限制 / 后续事项

  1. 登录限流为进程内 MVP:当前按 sUserName 在进程内存计数(默认 5 次失败 / 锁定 300 秒),分布式部署下不共享、不随 @Transactional 回滚(极小窗口)。技术栈虽列 Redis 但当前无连接配置,留待后续平滑替换为 Redis 原子计数(REQ-004 spec § 8 D7、review 非阻塞建议)。
  2. 契约反向同步待补GET /api/usr/companies 端点与 42901 错误码建议补入 docs/05-API接口契约.md(见 § ⑧)。
  3. 多租户列兜底sBrandsId/sSubsidiaryId 由 DB 默认值 1111111111 兜底,未引入运行时多租户上下文解析(按 spec 设计,当前阶段足够)。
  4. 冗余防御代码UsrUserServiceImpl 权限去重存在一处可简化的二次去重(review 口头建议,无功能影响)。
  5. 前端未实现:FE-01~FE-04(登录页 / 主页框架 / 用户列表 / 用户单据)属前端阶段,docs/08 § 三 待办,不在本后端模块范围。

⑫ 结论

USR 用户管理后端模块 4 个 REQ(增 / 改 / 查 / 登录)全部实现并 approve,模块级硬测试闸在锁定 JDK17 工具链下 125/125 全绿(r1,无 flake),工作树干净,无新增 migration、无跨模块改动、实现层无偏离(仅 2 项非阻塞契约反向同步建议)。满足里程碑 milestone/usr 标记的全部前置条件。

证据:docs/superpowers/module-reports/usr-test-gate-r1.md(GREEN)。