From 0281d6ed5b5d5190d416b724095a7b24e81bb9b2 Mon Sep 17 00:00:00 2001 From: zichun Date: Wed, 13 May 2026 17:46:43 +0800 Subject: [PATCH] feat(usr): V2 种子超管 + USR 权限分类 REQ-USR-001 --- backend/src/main/resources/application.yml | 2 +- backend/src/test/java/com/xly/test4/ApplicationContextIT.java | 28 ++++++++++++++++++++++++++++ docs/03-数据库设计文档.md | 25 +++++++++++++++++++++++++ sql/migrations/V2__seed_admin_and_permissions.sql | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 sql/migrations/V2__seed_admin_and_permissions.sql diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 91e40a0..ab4abec 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -6,7 +6,7 @@ spring: config: import: optional:file:../.env.local[.properties] datasource: - url: jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_SCHEMA}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false + url: jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_SCHEMA}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false&tinyInt1isBit=false username: ${DB_USER} password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/backend/src/test/java/com/xly/test4/ApplicationContextIT.java b/backend/src/test/java/com/xly/test4/ApplicationContextIT.java index 513c284..f8a9397 100644 --- a/backend/src/test/java/com/xly/test4/ApplicationContextIT.java +++ b/backend/src/test/java/com/xly/test4/ApplicationContextIT.java @@ -1,9 +1,12 @@ package com.xly.test4; +import java.util.Map; + import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; +import org.springframework.jdbc.core.JdbcTemplate; import static org.assertj.core.api.Assertions.assertThat; @@ -13,9 +16,34 @@ class ApplicationContextIT { @Autowired private ApplicationContext context; + @Autowired + private JdbcTemplate jdbcTemplate; + @Test void contextLoads() { assertThat(context).isNotNull(); assertThat(context.getBean(Application.class)).isNotNull(); } + + @Test + void flywayMigrationsApplied_seedDataPresent() { + Integer permCount = jdbcTemplate.queryForObject( + "SELECT COUNT(*) FROM tPermission WHERE sCategory IN " + + "('usr:user:create','usr:user:update','usr:user:list','usr:user:assign-role')", + Integer.class); + assertThat(permCount).isEqualTo(4); + + Map admin = jdbcTemplate.queryForMap( + "SELECT sUserType, sBrandsId, sSubsidiaryId, iIsDisabled FROM tUser WHERE sUserName = 'admin'"); + assertThat(admin.get("sUserType")).isEqualTo("ADMIN"); + assertThat(admin.get("sBrandsId")).isEqualTo("BR-DEFAULT"); + assertThat(admin.get("sSubsidiaryId")).isEqualTo("SUB-DEFAULT"); + assertThat(((Number) admin.get("iIsDisabled")).intValue()).isEqualTo(0); + + Integer authCount = jdbcTemplate.queryForObject( + "SELECT COUNT(*) FROM tUserPermission WHERE iUserId = " + + "(SELECT iIncrement FROM tUser WHERE sUserName = 'admin')", + Integer.class); + assertThat(authCount).isEqualTo(4); + } } diff --git a/docs/03-数据库设计文档.md b/docs/03-数据库设计文档.md index 4034a9d..f630836 100644 --- a/docs/03-数据库设计文档.md +++ b/docs/03-数据库设计文档.md @@ -229,3 +229,28 @@ tUser ──────────────────────── - 字典表,提供 REQ-USR-004 登录页「版本」下拉数据。 - 不与 `tUser` 建外键:账号可在多公司 / 多版本之间复用;登录时仅用作上下文选择,由应用层校验"用户是否被允许进入该公司版本"。 - 当 `sEdition` 的取值集合稳定后,可改为受控字典并迁移到 `tDictionary` 类公共字典表;当前阶段独立维护。 + +--- + +## 种子数据(V2 migration) + +由 `sql/migrations/V2__seed_admin_and_permissions.sql` 写入,REQ-USR-001 配套。 + +### `tPermission` + +| sCategory | sCategoryName | 用途 | +|---|---|---| +| `usr:user:create` | 新增用户 | REQ-USR-001 接口 `@PreAuthorize` | +| `usr:user:update` | 修改用户 | REQ-USR-002 接口 `@PreAuthorize` | +| `usr:user:list` | 查询用户 | REQ-USR-003 接口 `@PreAuthorize` | +| `usr:user:assign-role` | 分配用户角色 | REQ-USR-002 修改 `userType` 子权限 | + +### `tUser` — 超级管理员 + +| sUserCode | sUserName | sUserType | sLanguage | sBrandsId | sSubsidiaryId | 明文密码 | +|---|---|---|---|---|---|---| +| ADMIN001 | admin | ADMIN | zh-CN | BR-DEFAULT | SUB-DEFAULT | `admin`(BCrypt $2y$10$ 哈希存入) | + +### `tUserPermission` + +admin × 上述 4 个权限分类,全部授权(`sGrantedBy='system'`)。 diff --git a/sql/migrations/V2__seed_admin_and_permissions.sql b/sql/migrations/V2__seed_admin_and_permissions.sql new file mode 100644 index 0000000..545d0b7 --- /dev/null +++ b/sql/migrations/V2__seed_admin_and_permissions.sql @@ -0,0 +1,32 @@ +-- V2__seed_admin_and_permissions.sql +-- REQ-USR-001 配套种子:USR 模块权限分类 + 超级管理员账号 +-- +-- 来源:docs/superpowers/specs/2026-05-13-REQ-USR-001.md § 附带基础设施 / Migration +-- 密码哈希算法:BCrypt($2y$10$,等价于 $2a$10$,Spring Security BCryptPasswordEncoder 兼容) +-- 明文密码:admin(仅本地开发/测试用,生产环境 admin 账号上线后必须立即改密) + +-- 种子权限分类(覆盖 USR 模块全部 REQ 所需) +INSERT INTO tPermission (sCategory, sCategoryName, sDescription, iIsDisabled) +VALUES + ('usr:user:create', '新增用户', 'REQ-USR-001 增加用户', 0), + ('usr:user:update', '修改用户', 'REQ-USR-002 修改用户', 0), + ('usr:user:list', '查询用户', 'REQ-USR-003 查询用户', 0), + ('usr:user:assign-role', '分配用户角色', '修改用户类型 NORMAL/ADMIN 用', 0); + +-- 种子超级管理员 +INSERT INTO tUser + (sUserCode, sUserName, iEmployeeId, sUserType, sLanguage, iCanEditDoc, + sPasswordHash, iIsDisabled, iLoginFailCount, + sBrandsId, sSubsidiaryId, sCreatedBy) +VALUES + ('ADMIN001', 'admin', NULL, 'ADMIN', 'zh-CN', 1, + '$2y$10$Diskv9jfPWYxJGof9IazgeKj2CFCztxuxH0WQ1TDJRwlizKXi1h.2', 0, 0, + 'BR-DEFAULT', 'SUB-DEFAULT', 'system'); + +-- 给 admin 授权全部 4 个权限分类 +INSERT INTO tUserPermission (iUserId, iPermissionId, sGrantedBy, sBrandsId, sSubsidiaryId) +SELECT u.iIncrement, p.iIncrement, 'system', 'BR-DEFAULT', 'SUB-DEFAULT' +FROM tUser u +CROSS JOIN tPermission p +WHERE u.sUserName = 'admin' + AND p.sCategory IN ('usr:user:create','usr:user:update','usr:user:list','usr:user:assign-role'); -- libgit2 0.22.2