|
@@ -1,6 +1,6 @@
|
|
|
# 权限管理系统 (perms-system-server) — 测试报告
|
|
# 权限管理系统 (perms-system-server) — 测试报告
|
|
|
|
|
|
|
|
-> 报告日期: 2026-04-16(第七轮,Expires 字段重命名 + 含义变更验证)
|
|
|
|
|
|
|
+> 报告日期: 2026-04-16
|
|
|
> 测试范围: API (go-zero REST, 全 POST) + gRPC (status codes) + Model 层 (_gen.go 模板生成 + 自定义方法) + Logic 单元测试 + util 层 + 访问控制 + UserDetailsLoader
|
|
> 测试范围: API (go-zero REST, 全 POST) + gRPC (status codes) + Model 层 (_gen.go 模板生成 + 自定义方法) + Logic 单元测试 + util 层 + 访问控制 + UserDetailsLoader
|
|
|
> 测试用例设计详见 [test-design.md](./test-design.md)
|
|
> 测试用例设计详见 [test-design.md](./test-design.md)
|
|
|
|
|
|
|
@@ -10,63 +10,56 @@
|
|
|
|
|
|
|
|
| 指标 | 数值 |
|
|
| 指标 | 数值 |
|
|
|
| :--- | :--- |
|
|
| :--- | :--- |
|
|
|
-| 测试用例总数 (test-design.md) | 499 |
|
|
|
|
|
-| 已覆盖 TC 数 | 498 |
|
|
|
|
|
|
|
+| 测试用例总数 (test-design.md) | 510 |
|
|
|
|
|
+| 已覆盖 TC 数 | 509 |
|
|
|
| 未实现 TC 数 | 1 (TC-0189, 不可达防御分支, t.Skip) |
|
|
| 未实现 TC 数 | 1 (TC-0189, 不可达防御分支, t.Skip) |
|
|
|
-| 测试函数总数 | 662 |
|
|
|
|
|
-| 测试子用例总数 (含 table-driven) | 744 |
|
|
|
|
|
|
|
+| 测试函数总数 | 673 |
|
|
|
|
|
+| 测试子用例总数 (含 table-driven) | 755 |
|
|
|
| 测试包数量 | 23 |
|
|
| 测试包数量 | 23 |
|
|
|
-| ✅ 通过 | **743 / 744** |
|
|
|
|
|
|
|
+| ✅ 通过 | **754 / 755** |
|
|
|
| ❌ 失败 | **0** |
|
|
| ❌ 失败 | **0** |
|
|
|
| ⏭️ 跳过 | **1** (TC-0189 — 防御性不可达分支) |
|
|
| ⏭️ 跳过 | **1** (TC-0189 — 防御性不可达分支) |
|
|
|
|
|
|
|
|
-> **第七轮变更说明**:
|
|
|
|
|
->
|
|
|
|
|
-> - **Expires 字段变更** ✅:`ExpiresIn`(过期秒数) → `Expires`(过期 unix 时间戳),REST/gRPC 同步更新
|
|
|
|
|
-> - 更新了 TC-0001 (loginLogic)、TC-0013 (refreshTokenLogic)、TC-0165/TC-0172 (gRPC) 的断言逻辑
|
|
|
|
|
-> - 至此 BUG-001 ~ BUG-004 及 WARN-001 全部修复,WARN-002 / WARN-003 为设计取舍不修改
|
|
|
|
|
-> - **全部 743 个可执行测试子用例通过,0 失败**
|
|
|
|
|
-
|
|
|
|
|
### 1.1 各包测试耗时
|
|
### 1.1 各包测试耗时
|
|
|
|
|
|
|
|
| 测试包 | 状态 | 耗时 |
|
|
| 测试包 | 状态 | 耗时 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
|
-| handler/pub | ✅ ok | 2.475s |
|
|
|
|
|
-| loaders | ✅ ok | 3.104s |
|
|
|
|
|
-| logic/auth | ✅ ok | 8.033s |
|
|
|
|
|
-| logic/dept | ✅ ok | 4.314s |
|
|
|
|
|
-| logic/member | ✅ ok | 5.162s |
|
|
|
|
|
-| logic/perm | ✅ ok | 5.819s |
|
|
|
|
|
-| logic/product | ✅ ok | 6.947s |
|
|
|
|
|
-| logic/pub | ✅ ok | 6.801s |
|
|
|
|
|
-| logic/role | ✅ ok | 5.764s |
|
|
|
|
|
-| logic/user | ✅ ok | 10.236s |
|
|
|
|
|
-| middleware | ✅ ok | 8.668s |
|
|
|
|
|
-| model/dept | ✅ ok | 7.094s |
|
|
|
|
|
-| model/perm | ✅ ok | 7.932s |
|
|
|
|
|
-| model/product | ✅ ok | 10.637s |
|
|
|
|
|
-| model/productmember | ✅ ok | 12.484s |
|
|
|
|
|
-| model/role | ✅ ok | 12.569s |
|
|
|
|
|
-| model/roleperm | ✅ ok | 11.723s |
|
|
|
|
|
-| model/user | ✅ ok | 11.735s |
|
|
|
|
|
-| model/userperm | ✅ ok | 11.803s |
|
|
|
|
|
-| model/userrole | ✅ ok | 11.483s |
|
|
|
|
|
-| response | ✅ ok | 11.454s |
|
|
|
|
|
-| server | ✅ ok | 11.790s |
|
|
|
|
|
-| util | ✅ ok | 11.745s |
|
|
|
|
|
|
|
+| handler/pub | ✅ ok | 0.680s |
|
|
|
|
|
+| loaders | ✅ ok | 1.439s |
|
|
|
|
|
+| logic/auth | ✅ ok | 6.427s |
|
|
|
|
|
+| logic/dept | ✅ ok | 2.200s |
|
|
|
|
|
+| logic/member | ✅ ok | 2.819s |
|
|
|
|
|
+| logic/perm | ✅ ok | 3.275s |
|
|
|
|
|
+| logic/product | ✅ ok | 4.218s |
|
|
|
|
|
+| logic/pub | ✅ ok | 4.921s |
|
|
|
|
|
+| logic/role | ✅ ok | 5.047s |
|
|
|
|
|
+| logic/user | ✅ ok | 6.112s |
|
|
|
|
|
+| middleware | ✅ ok | 5.080s |
|
|
|
|
|
+| model/dept | ✅ ok | 5.525s |
|
|
|
|
|
+| model/perm | ✅ ok | 6.499s |
|
|
|
|
|
+| model/product | ✅ ok | 6.499s |
|
|
|
|
|
+| model/productmember | ✅ ok | 7.140s |
|
|
|
|
|
+| model/role | ✅ ok | 7.769s |
|
|
|
|
|
+| model/roleperm | ✅ ok | 7.882s |
|
|
|
|
|
+| model/user | ✅ ok | 7.827s |
|
|
|
|
|
+| model/userperm | ✅ ok | 7.935s |
|
|
|
|
|
+| model/userrole | ✅ ok | 7.545s |
|
|
|
|
|
+| response | ✅ ok | 7.080s |
|
|
|
|
|
+| server | ✅ ok | 6.574s |
|
|
|
|
|
+| util | ✅ ok | 5.796s |
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
## 二、TC 测试结果明细
|
|
## 二、TC 测试结果明细
|
|
|
|
|
|
|
|
-### 2.1 REST API (TC-0001 ~ TC-0160)
|
|
|
|
|
|
|
+### 2.1 REST API — 产品端登录 (TC-0001 ~ TC-0012)
|
|
|
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
|
-| TC-0001 | 正常登录-不带productCode | ✅ pass |
|
|
|
|
|
-| TC-0002 | 正常登录-带productCode | ✅ pass |
|
|
|
|
|
-| TC-0003 | 超管登录+productCode | ✅ pass |
|
|
|
|
|
-| TC-0004 | 超管登录-无productCode | ✅ pass |
|
|
|
|
|
|
|
+| TC-0001 | 正常登录(普通用户+productCode) | ✅ pass |
|
|
|
|
|
+| TC-0002 | 正常登录-带productCode+ADMIN成员 | ✅ pass |
|
|
|
|
|
+| TC-0003 | 超管通过产品端登录被拒绝(403) | ✅ pass |
|
|
|
|
|
+| TC-0004 | 超管无productCode被拒绝(403) | ✅ pass |
|
|
|
| TC-0005 | 用户不存在 | ✅ pass |
|
|
| TC-0005 | 用户不存在 | ✅ pass |
|
|
|
| TC-0006 | DB异常(非ErrNotFound) | ✅ pass |
|
|
| TC-0006 | DB异常(非ErrNotFound) | ✅ pass |
|
|
|
| TC-0007 | 密码错误 | ✅ pass |
|
|
| TC-0007 | 密码错误 | ✅ pass |
|
|
@@ -74,13 +67,38 @@
|
|
|
| TC-0009 | 非产品成员 | ✅ pass |
|
|
| TC-0009 | 非产品成员 | ✅ pass |
|
|
|
| TC-0010 | DEVELOPER成员 | ✅ pass |
|
|
| TC-0010 | DEVELOPER成员 | ✅ pass |
|
|
|
| TC-0011 | SQL注入 | ✅ pass |
|
|
| TC-0011 | SQL注入 | ✅ pass |
|
|
|
-| TC-0012 | 缺少必填字段 | ✅ pass |
|
|
|
|
|
|
|
+| TC-0012 | 缺少必填字段(productCode现为必填) | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.2 REST API — 管理后台登录 (TC-0500 ~ TC-0509)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
|
|
+| TC-0500 | 超管正常登录(管理后台) | ✅ pass |
|
|
|
|
|
+| TC-0501 | 普通用户正常登录(管理后台) | ✅ pass |
|
|
|
|
|
+| TC-0502 | managementKey无效 | ✅ pass |
|
|
|
|
|
+| TC-0503 | managementKey为空 | ✅ pass |
|
|
|
|
|
+| TC-0504 | 用户不存在 | ✅ pass |
|
|
|
|
|
+| TC-0505 | 密码错误 | ✅ pass |
|
|
|
|
|
+| TC-0506 | 账号冻结 | ✅ pass |
|
|
|
|
|
+| TC-0507 | 不带productCode时perms为空 | ✅ pass |
|
|
|
|
|
+| TC-0508 | 缺少必填字段(handler校验) | ✅ pass |
|
|
|
|
|
+| TC-0509 | SQL注入username | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.3 REST API — 刷新Token (TC-0013 ~ TC-0018)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0013 | 正常刷新 | ✅ pass |
|
|
| TC-0013 | 正常刷新 | ✅ pass |
|
|
|
| TC-0014 | 不带productCode(回退) | ✅ pass |
|
|
| TC-0014 | 不带productCode(回退) | ✅ pass |
|
|
|
| TC-0015 | token无效 | ✅ pass |
|
|
| TC-0015 | token无效 | ✅ pass |
|
|
|
| TC-0016 | 用户已删除 | ✅ pass |
|
|
| TC-0016 | 用户已删除 | ✅ pass |
|
|
|
| TC-0017 | 账号冻结 | ✅ pass |
|
|
| TC-0017 | 账号冻结 | ✅ pass |
|
|
|
| TC-0018 | 超管+productCode | ✅ pass |
|
|
| TC-0018 | 超管+productCode | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.4 REST API — 同步权限 (TC-0019 ~ TC-0029)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0019 | 全部新增 | ✅ pass |
|
|
| TC-0019 | 全部新增 | ✅ pass |
|
|
|
| TC-0020 | 更新已有(名称变更) | ✅ pass |
|
|
| TC-0020 | 更新已有(名称变更) | ✅ pass |
|
|
|
| TC-0021 | 无变化 | ✅ pass |
|
|
| TC-0021 | 无变化 | ✅ pass |
|
|
@@ -92,6 +110,11 @@
|
|
|
| TC-0027 | appSecret错误 | ✅ pass |
|
|
| TC-0027 | appSecret错误 | ✅ pass |
|
|
|
| TC-0028 | 产品已禁用 | ✅ pass |
|
|
| TC-0028 | 产品已禁用 | ✅ pass |
|
|
|
| TC-0029 | 大批量(1000条) | ✅ pass |
|
|
| TC-0029 | 大批量(1000条) | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.5 REST API — 用户信息 / 修改密码 (TC-0030 ~ TC-0044)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0030 | 正常获取-含productCode | ✅ pass |
|
|
| TC-0030 | 正常获取-含productCode | ✅ pass |
|
|
|
| TC-0031 | 不含productCode | ✅ pass |
|
|
| TC-0031 | 不含productCode | ✅ pass |
|
|
|
| TC-0032 | 未登录 | ✅ pass |
|
|
| TC-0032 | 未登录 | ✅ pass |
|
|
@@ -107,6 +130,11 @@
|
|
|
| TC-0042 | 新密码恰好72字符 | ✅ pass |
|
|
| TC-0042 | 新密码恰好72字符 | ✅ pass |
|
|
|
| TC-0043 | 新旧密码相同 | ✅ pass |
|
|
| TC-0043 | 新旧密码相同 | ✅ pass |
|
|
|
| TC-0044 | 用户不存在 | ✅ pass |
|
|
| TC-0044 | 用户不存在 | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.6 REST API — 产品管理 (TC-0045 ~ TC-0059)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0045 | 正常创建 | ✅ pass |
|
|
| TC-0045 | 正常创建 | ✅ pass |
|
|
|
| TC-0046 | 事务回滚-用户创建失败 | ✅ pass |
|
|
| TC-0046 | 事务回滚-用户创建失败 | ✅ pass |
|
|
|
| TC-0047 | 事务回滚-成员创建失败 | ✅ pass |
|
|
| TC-0047 | 事务回滚-成员创建失败 | ✅ pass |
|
|
@@ -122,6 +150,11 @@
|
|
|
| TC-0057 | page负值 | ✅ pass |
|
|
| TC-0057 | page负值 | ✅ pass |
|
|
|
| TC-0058 | 正常查询 | ✅ pass |
|
|
| TC-0058 | 正常查询 | ✅ pass |
|
|
|
| TC-0059 | 不存在 | ✅ pass |
|
|
| TC-0059 | 不存在 | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.7 REST API — 部门管理 (TC-0060 ~ TC-0079)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0060 | 创建顶级部门 | ✅ pass |
|
|
| TC-0060 | 创建顶级部门 | ✅ pass |
|
|
|
| TC-0061 | 创建子部门 | ✅ pass |
|
|
| TC-0061 | 创建子部门 | ✅ pass |
|
|
|
| TC-0062 | 父部门不存在 | ✅ pass |
|
|
| TC-0062 | 父部门不存在 | ✅ pass |
|
|
@@ -142,10 +175,20 @@
|
|
|
| TC-0077 | 正常获取 | ✅ pass |
|
|
| TC-0077 | 正常获取 | ✅ pass |
|
|
|
| TC-0078 | 空数据 | ✅ pass |
|
|
| TC-0078 | 空数据 | ✅ pass |
|
|
|
| TC-0079 | 孤儿节点 | ✅ pass |
|
|
| TC-0079 | 孤儿节点 | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.8 REST API — 权限列表 (TC-0080 ~ TC-0083)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0080 | 正常查询 | ✅ pass |
|
|
| TC-0080 | 正常查询 | ✅ pass |
|
|
|
| TC-0081 | 默认分页 | ✅ pass |
|
|
| TC-0081 | 默认分页 | ✅ pass |
|
|
|
| TC-0082 | pageSize超过上限 | ✅ pass |
|
|
| TC-0082 | pageSize超过上限 | ✅ pass |
|
|
|
| TC-0083 | 不存在的productCode | ✅ pass |
|
|
| TC-0083 | 不存在的productCode | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.9 REST API — 角色管理 (TC-0084 ~ TC-0100)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0084 | 正常创建 | ✅ pass |
|
|
| TC-0084 | 正常创建 | ✅ pass |
|
|
|
| TC-0085 | 重复角色名 | ✅ pass |
|
|
| TC-0085 | 重复角色名 | ✅ pass |
|
|
|
| TC-0086 | 并发同名创建 | ✅ pass |
|
|
| TC-0086 | 并发同名创建 | ✅ pass |
|
|
@@ -163,6 +206,11 @@
|
|
|
| TC-0098 | 清空权限 | ✅ pass |
|
|
| TC-0098 | 清空权限 | ✅ pass |
|
|
|
| TC-0099 | 重复permId | ✅ pass |
|
|
| TC-0099 | 重复permId | ✅ pass |
|
|
|
| TC-0100 | 事务回滚 | ✅ pass |
|
|
| TC-0100 | 事务回滚 | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.10 REST API — 用户管理 (TC-0101 ~ TC-0145)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0101 | 正常创建 | ✅ pass |
|
|
| TC-0101 | 正常创建 | ✅ pass |
|
|
|
| TC-0102 | 用户名已存在(预检) | ✅ pass |
|
|
| TC-0102 | 用户名已存在(预检) | ✅ pass |
|
|
|
| TC-0103 | 带完整可选字段 | ✅ pass |
|
|
| TC-0103 | 带完整可选字段 | ✅ pass |
|
|
@@ -208,6 +256,11 @@
|
|
|
| TC-0143 | 非法status(0) | ✅ pass |
|
|
| TC-0143 | 非法status(0) | ✅ pass |
|
|
|
| TC-0144 | 冻结自己 | ✅ pass |
|
|
| TC-0144 | 冻结自己 | ✅ pass |
|
|
|
| TC-0145 | 冻结超管 | ✅ pass |
|
|
| TC-0145 | 冻结超管 | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.11 REST API — 成员管理 (TC-0146 ~ TC-0160)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0146 | 正常添加 | ✅ pass |
|
|
| TC-0146 | 正常添加 | ✅ pass |
|
|
|
| TC-0147 | 产品不存在 | ✅ pass |
|
|
| TC-0147 | 产品不存在 | ✅ pass |
|
|
|
| TC-0148 | 用户不存在 | ✅ pass |
|
|
| TC-0148 | 用户不存在 | ✅ pass |
|
|
@@ -224,7 +277,7 @@
|
|
|
| TC-0159 | 成员不存在 | ✅ pass |
|
|
| TC-0159 | 成员不存在 | ✅ pass |
|
|
|
| TC-0160 | 事务回滚 | ✅ pass |
|
|
| TC-0160 | 事务回滚 | ✅ pass |
|
|
|
|
|
|
|
|
-### 2.2 gRPC 接口 (TC-0161 ~ TC-0183)
|
|
|
|
|
|
|
+### 2.12 gRPC 接口 (TC-0161 ~ TC-0183, TC-0510)
|
|
|
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
@@ -233,12 +286,13 @@
|
|
|
| TC-0163 | appSecret错误 | ✅ pass |
|
|
| TC-0163 | appSecret错误 | ✅ pass |
|
|
|
| TC-0164 | 产品已禁用 | ✅ pass |
|
|
| TC-0164 | 产品已禁用 | ✅ pass |
|
|
|
| TC-0165 | 验证disabled计数 | ✅ pass |
|
|
| TC-0165 | 验证disabled计数 | ✅ pass |
|
|
|
-| TC-0166 | 正常登录(无productCode) | ✅ pass |
|
|
|
|
|
|
|
+| TC-0166 | 正常登录(普通用户+productCode) | ✅ pass |
|
|
|
| TC-0167 | 用户不存在 | ✅ pass |
|
|
| TC-0167 | 用户不存在 | ✅ pass |
|
|
|
| TC-0168 | 密码错误 | ✅ pass |
|
|
| TC-0168 | 密码错误 | ✅ pass |
|
|
|
| TC-0169 | 账号冻结 | ✅ pass |
|
|
| TC-0169 | 账号冻结 | ✅ pass |
|
|
|
-| TC-0170 | 超管+productCode | ✅ pass |
|
|
|
|
|
|
|
+| TC-0170 | 超管被拒绝(PermissionDenied) | ✅ pass |
|
|
|
| TC-0171 | 普通用户+productCode | ✅ pass |
|
|
| TC-0171 | 普通用户+productCode | ✅ pass |
|
|
|
|
|
+| TC-0510 | productCode为空(InvalidArgument) | ✅ pass |
|
|
|
| TC-0172 | 正常刷新 | ✅ pass |
|
|
| TC-0172 | 正常刷新 | ✅ pass |
|
|
|
| TC-0173 | token无效 | ✅ pass |
|
|
| TC-0173 | token无效 | ✅ pass |
|
|
|
| TC-0174 | 账号冻结 | ✅ pass |
|
|
| TC-0174 | 账号冻结 | ✅ pass |
|
|
@@ -252,7 +306,7 @@
|
|
|
| TC-0182 | 超管 | ✅ pass |
|
|
| TC-0182 | 超管 | ✅ pass |
|
|
|
| TC-0183 | MEMBER-DENY覆盖 | ✅ pass |
|
|
| TC-0183 | MEMBER-DENY覆盖 | ✅ pass |
|
|
|
|
|
|
|
|
-### 2.3 中间件 / 统一响应 / util (TC-0184 ~ TC-0266, TC-0434, TC-0478 ~ TC-0480)
|
|
|
|
|
|
|
+### 2.13 中间件 / 统一响应 (TC-0184 ~ TC-0193, TC-0434, TC-0478 ~ TC-0480)
|
|
|
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
@@ -261,7 +315,7 @@
|
|
|
| TC-0186 | 无Bearer前缀 | ✅ pass |
|
|
| TC-0186 | 无Bearer前缀 | ✅ pass |
|
|
|
| TC-0187 | token签名错误 | ✅ pass |
|
|
| TC-0187 | token签名错误 | ✅ pass |
|
|
|
| TC-0188 | token过期 | ✅ pass |
|
|
| TC-0188 | token过期 | ✅ pass |
|
|
|
-| TC-0189 | claims类型断言失败 | ⏭️ skip(!ok 防御性分支不可达,jwt.ParseWithClaims 始终返回 *Claims) |
|
|
|
|
|
|
|
+| TC-0189 | claims类型断言失败 | ⏭️ skip(防御性分支不可达) |
|
|
|
| TC-0434 | refresh token被拒绝 | ✅ pass |
|
|
| TC-0434 | refresh token被拒绝 | ✅ pass |
|
|
|
| TC-0478 | 冻结用户被403 | ✅ pass |
|
|
| TC-0478 | 冻结用户被403 | ✅ pass |
|
|
|
| TC-0479 | 用户不存在(Status=0) | ✅ pass |
|
|
| TC-0479 | 用户不存在(Status=0) | ✅ pass |
|
|
@@ -270,6 +324,11 @@
|
|
|
| TC-0191 | 内部错误 | ✅ pass |
|
|
| TC-0191 | 内部错误 | ✅ pass |
|
|
|
| TC-0192 | 成功(有data) | ✅ pass |
|
|
| TC-0192 | 成功(有data) | ✅ pass |
|
|
|
| TC-0193 | 成功(无data) | ✅ pass |
|
|
| TC-0193 | 成功(无data) | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.14 util 层 (TC-0194 ~ TC-0216)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0194 | 正常值 | ✅ pass |
|
|
| TC-0194 | 正常值 | ✅ pass |
|
|
|
| TC-0195 | page<=0 | ✅ pass |
|
|
| TC-0195 | page<=0 | ✅ pass |
|
|
|
| TC-0196 | page=-1 | ✅ pass |
|
|
| TC-0196 | page=-1 | ✅ pass |
|
|
@@ -293,6 +352,11 @@
|
|
|
| TC-0214 | 超长16位 | ✅ pass |
|
|
| TC-0214 | 超长16位 | ✅ pass |
|
|
|
| TC-0215 | 包含字母 | ✅ pass |
|
|
| TC-0215 | 包含字母 | ✅ pass |
|
|
|
| TC-0216 | 空字符串 | ✅ pass |
|
|
| TC-0216 | 空字符串 | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.15 Logic 层单元测试 — JWT / 权限计算 / Helper (TC-0217 ~ TC-0266)
|
|
|
|
|
+
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
| TC-0217 | 正常生成 | ✅ pass |
|
|
| TC-0217 | 正常生成 | ✅ pass |
|
|
|
| TC-0218 | 解析token验证claims | ✅ pass |
|
|
| TC-0218 | 解析token验证claims | ✅ pass |
|
|
|
| TC-0219 | 空secret | ✅ pass |
|
|
| TC-0219 | 空secret | ✅ pass |
|
|
@@ -344,12 +408,10 @@
|
|
|
| TC-0265 | IsSuperAdmin-否 | ✅ pass |
|
|
| TC-0265 | IsSuperAdmin-否 | ✅ pass |
|
|
|
| TC-0266 | IsSuperAdmin-空 | ✅ pass |
|
|
| TC-0266 | IsSuperAdmin-空 | ✅ pass |
|
|
|
|
|
|
|
|
-### 2.4 Model 层 _gen.go 通用方法 (TC-0267 ~ TC-0356)
|
|
|
|
|
|
|
+### 2.16 Model 层 _gen.go 通用 CRUD / 批量方法 (TC-0267 ~ TC-0310)
|
|
|
|
|
|
|
|
> 以下每个 TC 为通用模式,适用于全部 9 个 Model,实际测试函数数 = TC × 模型数。
|
|
> 以下每个 TC 为通用模式,适用于全部 9 个 Model,实际测试函数数 = TC × 模型数。
|
|
|
|
|
|
|
|
-**CRUD / 事务 / 批量方法 (TC-0267 ~ TC-0310):**
|
|
|
|
|
-
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
|
| TC-0267 | 正常插入 | ✅ pass |
|
|
| TC-0267 | 正常插入 | ✅ pass |
|
|
@@ -397,7 +459,7 @@
|
|
|
| TC-0309 | 空ids | ✅ pass |
|
|
| TC-0309 | 空ids | ✅ pass |
|
|
|
| TC-0310 | 正常多条 | ✅ pass |
|
|
| TC-0310 | 正常多条 | ✅ pass |
|
|
|
|
|
|
|
|
-**唯一索引方法明细 (TC-0311 ~ TC-0346):**
|
|
|
|
|
|
|
+### 2.17 Model 层 _gen.go 唯一索引方法 (TC-0311 ~ TC-0346)
|
|
|
|
|
|
|
|
| TC编号 | Model | 方法 | 测试场景 | 测试结果 |
|
|
| TC编号 | Model | 方法 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- | :--- | :--- |
|
|
| :--- | :--- | :--- | :--- | :--- |
|
|
@@ -438,22 +500,22 @@
|
|
|
| TC-0345 | SysProductMember | FindOneByProductCodeUserIdWithTx | 事务内正常查询 | ✅ pass |
|
|
| TC-0345 | SysProductMember | FindOneByProductCodeUserIdWithTx | 事务内正常查询 | ✅ pass |
|
|
|
| TC-0346 | SysProductMember | FindOneByProductCodeUserIdWithTx | 事务内不存在 | ✅ pass |
|
|
| TC-0346 | SysProductMember | FindOneByProductCodeUserIdWithTx | 事务内不存在 | ✅ pass |
|
|
|
|
|
|
|
|
-**内部辅助方法 (TC-0347 ~ TC-0356):**
|
|
|
|
|
-
|
|
|
|
|
-| TC编号 | 测试场景 | 测试结果 | 未实现原因 |
|
|
|
|
|
-| :--- | :--- | :--- | :--- |
|
|
|
|
|
-| TC-0347 | 空ids | ✅ pass | role 同包测试可访问私有函数 |
|
|
|
|
|
-| TC-0348 | 正常ids | ✅ pass | role 同包测试 |
|
|
|
|
|
-| TC-0349 | 部分不存在 | ✅ pass | role 同包测试 |
|
|
|
|
|
-| TC-0350 | DB异常 | ✅ pass | 坏连接模拟 |
|
|
|
|
|
-| TC-0351 | 正常 | ✅ pass | role 同包测试 |
|
|
|
|
|
-| TC-0352 | 正常 | ✅ pass | role 同包测试 |
|
|
|
|
|
-| TC-0353 | 正常 | ✅ pass | role 同包测试 |
|
|
|
|
|
-| TC-0354 | cachePrefix为空 | ✅ pass | role 同包测试 |
|
|
|
|
|
-| TC-0355 | cachePrefix非空 | ✅ pass | role 同包测试 |
|
|
|
|
|
-| TC-0356 | 多唯一索引前缀(SysProduct) | ✅ pass | product 同包测试 |
|
|
|
|
|
|
|
+### 2.18 Model 层 _gen.go 内部辅助方法 (TC-0347 ~ TC-0356)
|
|
|
|
|
|
|
|
-### 2.5 Model 层自定义方法 (TC-0357 ~ TC-0433)
|
|
|
|
|
|
|
+| TC编号 | 测试场景 | 测试结果 |
|
|
|
|
|
+| :--- | :--- | :--- |
|
|
|
|
|
+| TC-0347 | 空ids | ✅ pass |
|
|
|
|
|
+| TC-0348 | 正常ids | ✅ pass |
|
|
|
|
|
+| TC-0349 | 部分不存在 | ✅ pass |
|
|
|
|
|
+| TC-0350 | DB异常 | ✅ pass |
|
|
|
|
|
+| TC-0351 | 正常 | ✅ pass |
|
|
|
|
|
+| TC-0352 | 正常 | ✅ pass |
|
|
|
|
|
+| TC-0353 | 正常 | ✅ pass |
|
|
|
|
|
+| TC-0354 | cachePrefix为空 | ✅ pass |
|
|
|
|
|
+| TC-0355 | cachePrefix非空 | ✅ pass |
|
|
|
|
|
+| TC-0356 | 多唯一索引前缀(SysProduct) | ✅ pass |
|
|
|
|
|
+
|
|
|
|
|
+### 2.19 Model 层自定义方法 (TC-0357 ~ TC-0433)
|
|
|
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
@@ -535,7 +597,7 @@
|
|
|
| TC-0432 | 部分不是成员 | ✅ pass |
|
|
| TC-0432 | 部分不是成员 | ✅ pass |
|
|
|
| TC-0433 | map key正确 | ✅ pass |
|
|
| TC-0433 | map key正确 | ✅ pass |
|
|
|
|
|
|
|
|
-### 2.6 访问控制 access.go (TC-0435 ~ TC-0457) 🆕
|
|
|
|
|
|
|
+### 2.20 访问控制 access.go (TC-0435 ~ TC-0457)
|
|
|
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
@@ -563,7 +625,7 @@
|
|
|
| TC-0456 | CheckManageAccess-未登录 | ✅ pass |
|
|
| TC-0456 | CheckManageAccess-未登录 | ✅ pass |
|
|
|
| TC-0457 | memberTypePriority-全类型验证 | ✅ pass |
|
|
| TC-0457 | memberTypePriority-全类型验证 | ✅ pass |
|
|
|
|
|
|
|
|
-### 2.7 UserDetailsLoader (TC-0458 ~ TC-0477) 🆕
|
|
|
|
|
|
|
+### 2.21 UserDetailsLoader (TC-0458 ~ TC-0477)
|
|
|
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
@@ -572,8 +634,8 @@
|
|
|
| TC-0460 | Load-用户不存在 | ✅ pass |
|
|
| TC-0460 | Load-用户不存在 | ✅ pass |
|
|
|
| TC-0461 | Load-productCode为空 | ✅ pass |
|
|
| TC-0461 | Load-productCode为空 | ✅ pass |
|
|
|
| TC-0462 | Del删除指定缓存 | ✅ pass |
|
|
| TC-0462 | Del删除指定缓存 | ✅ pass |
|
|
|
-| TC-0463 | Clean清除用户所有产品缓存 | ✅ pass(BUG-004 已修复) |
|
|
|
|
|
-| TC-0464 | CleanByProduct清除产品所有用户 | ✅ pass(BUG-004 已修复) |
|
|
|
|
|
|
|
+| TC-0463 | Clean清除用户所有产品缓存 | ✅ pass |
|
|
|
|
|
+| TC-0464 | CleanByProduct清除产品所有用户 | ✅ pass |
|
|
|
| TC-0465 | BatchDel批量删除 | ✅ pass |
|
|
| TC-0465 | BatchDel批量删除 | ✅ pass |
|
|
|
| TC-0466 | BatchDel空数组 | ✅ pass |
|
|
| TC-0466 | BatchDel空数组 | ✅ pass |
|
|
|
| TC-0467 | loadPerms-超管全量权限 | ✅ pass |
|
|
| TC-0467 | loadPerms-超管全量权限 | ✅ pass |
|
|
@@ -588,7 +650,7 @@
|
|
|
| TC-0476 | loadMembership-超管自动SUPER_ADMIN | ✅ pass |
|
|
| TC-0476 | loadMembership-超管自动SUPER_ADMIN | ✅ pass |
|
|
|
| TC-0477 | loadMembership-非成员MemberType为空 | ✅ pass |
|
|
| TC-0477 | loadMembership-非成员MemberType为空 | ✅ pass |
|
|
|
|
|
|
|
|
-### 2.8 Logic 层访问控制负面测试 (TC-0481 ~ TC-0491) 🆕
|
|
|
|
|
|
|
+### 2.22 Logic 层访问控制负面测试 (TC-0481 ~ TC-0491)
|
|
|
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
@@ -604,12 +666,12 @@
|
|
|
| TC-0490 | bindRolePerms-非产品管理员拒绝 | ✅ pass |
|
|
| TC-0490 | bindRolePerms-非产品管理员拒绝 | ✅ pass |
|
|
|
| TC-0491 | updateUser-非本人非超管拒绝 | ✅ pass |
|
|
| TC-0491 | updateUser-非本人非超管拒绝 | ✅ pass |
|
|
|
|
|
|
|
|
-### 2.9 Model 层新增方法 (TC-0492 ~ TC-0499) 🆕
|
|
|
|
|
|
|
+### 2.23 Model 层新增方法 (TC-0492 ~ TC-0499)
|
|
|
|
|
|
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
| TC编号 | 测试场景 | 测试结果 |
|
|
|
| :--- | :--- | :--- |
|
|
| :--- | :--- | :--- |
|
|
|
-| TC-0492 | FindMinPermsLevelByUserIdAndProductCode-正常 | ✅ pass(BUG-003 已修复) |
|
|
|
|
|
-| TC-0493 | FindMinPermsLevelByUserIdAndProductCode-无角色 | ✅ pass(BUG-003 已修复) |
|
|
|
|
|
|
|
+| TC-0492 | FindMinPermsLevelByUserIdAndProductCode-正常 | ✅ pass |
|
|
|
|
|
+| TC-0493 | FindMinPermsLevelByUserIdAndProductCode-无角色 | ✅ pass |
|
|
|
| TC-0494 | FindAllCodesByProductCode-正常 | ✅ pass |
|
|
| TC-0494 | FindAllCodesByProductCode-正常 | ✅ pass |
|
|
|
| TC-0495 | FindAllCodesByProductCode-无权限 | ✅ pass |
|
|
| TC-0495 | FindAllCodesByProductCode-无权限 | ✅ pass |
|
|
|
| TC-0496 | FindIdsByDeptId-正常 | ✅ pass |
|
|
| TC-0496 | FindIdsByDeptId-正常 | ✅ pass |
|
|
@@ -619,160 +681,16 @@
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 三、源码审计
|
|
|
|
|
-
|
|
|
|
|
-### 3.1 历史修复确认 (v1→v7)
|
|
|
|
|
-
|
|
|
|
|
-| # | 原始隐患 | 修复轮次 | 最终状态 |
|
|
|
|
|
-| :--- | :--- | :--- | :--- |
|
|
|
|
|
-| 1 | BindRoles/BindPerms/SetPerms 非事务 | v2 | ✅ TransactCtx + \*WithTx |
|
|
|
|
|
-| 2 | DeleteRole 无级联删除 | v2 | ✅ 事务内三步级联 |
|
|
|
|
|
-| 3 | RemoveMember 无级联清理 | v2→v3 | ✅ v2增加ForProduct; v3升级事务 |
|
|
|
|
|
-| 4 | UpdateUserStatus 无校验 | v2 | ✅ status∈{1,2}+自我保护+超管保护 |
|
|
|
|
|
-| 5 | SyncPerms N+1 查询 | v2 | ✅ FindMapByProductCode+批量 |
|
|
|
|
|
-| 6 | CreateProduct 非事务 | v2 | ✅ TransactCtx |
|
|
|
|
|
-| 7 | GetUserPerms 冗余查询 | v2 | ✅ isSuperAdmin参数 |
|
|
|
|
|
-| 8 | 错误信息泄露 | v2 | ✅ 统一"服务器内部错误"+logx |
|
|
|
|
|
-| 9 | VerifyToken 断言无保护 | v2 | ✅ ok检查 |
|
|
|
|
|
-| 10 | addMember 不校验产品/用户存在性 | v3 | ✅ FindOneByCode+FindOne预检 |
|
|
|
|
|
-| 11 | bindRoles/bindPerms/setPerms 不校验目标存在性 | v3 | ✅ FindOne预检 |
|
|
|
|
|
-| 12 | changePassword 新旧相同/截断 | v3 | ✅ len>72+相同密码校验 |
|
|
|
|
|
-| 13 | CreateDept 非事务 | v3 | ✅ TransactCtx |
|
|
|
|
|
-| 14 | gRPC errors.New 非规范 | v3 | ✅ status.Error(codes.Xxx) |
|
|
|
|
|
-| 15 | SyncPerms 不返回 disabled | v3 | ✅ DisableNotInCodes返回int64 |
|
|
|
|
|
-| 16 | RemoveMember 三步非事务 | v3 | ✅ TransactCtx+\*ForProductTx |
|
|
|
|
|
-| 17 | 全部路由改POST | v3 | ✅ perm.api统一POST |
|
|
|
|
|
-| 18 | updateUser 无法清空字段 | v4 | ✅ \*string 指针类型 |
|
|
|
|
|
-| 19 | pageSize 无上限 | v4 | ✅ NormalizePage cap 100 |
|
|
|
|
|
-| 20 | createUser TOCTOU 错误不友好 | v4 | ✅ 捕获 Duplicate entry→ErrConflict |
|
|
|
|
|
-| 21 | email/phone 无格式校验 | v4 | ✅ util.IsValidEmail/IsValidPhone |
|
|
|
|
|
-| 22 | changePassword 新密码允许空字符串 | v4 | ✅ len<6 最小长度校验 |
|
|
|
|
|
-| 23 | createRole 重复角色名返回500 | v5 | ✅ 捕获 Duplicate entry→ErrConflict |
|
|
|
|
|
-| 24 | memberList N+1 查用户 | v5 | ✅ FindByIds批量查询+map |
|
|
|
|
|
-| 25 | userList N+1 查成员类型 | v5 | ✅ FindMapByProductCodeUserIds批量 |
|
|
|
|
|
-| 26 | updateUser DeptId无法清零 | v5 | ✅ \*int64 指针类型 |
|
|
|
|
|
-| 27 | createDeptLogic 事务内 FindOne 隔离 bug | v6 | ✅ FindOne→FindOneWithTx(session) |
|
|
|
|
|
-| 28 | Model \_gen.go 新增 FindOneWithTx / FindOneBy...WithTx | v6 | ✅ 16 个新事务查询方法 |
|
|
|
|
|
-| 29 | DeptType 字段新增 | v6 | ✅ 创建/更新/树逻辑+consts |
|
|
|
|
|
-| 30 | GetUserPerms DEV 部门全权限分支 | v6 | ✅ deptId参数+DeptTypeDev检查 |
|
|
|
|
|
-| 31 | BUG-001: Handler 参数校验返回 500 | v7 | ✅ ErrBadRequest |
|
|
|
|
|
-| 32 | BUG-002: JWT token 类型无区分 | v7 | ✅ TokenType 字段 |
|
|
|
|
|
-| 33 | FindByPathPrefix LIKE 注入 | v7 | ✅ NewReplacer 转义 |
|
|
|
|
|
-| 34 | BUG-003: FindMinPermsLevel sql.NullInt64 不兼容 | v8 | ✅ IFNULL+int64 |
|
|
|
|
|
-| 35 | BUG-004: cleanByPattern Lua SCAN cursor 类型不匹配 | v9 | ✅ tonumber(nextCursor) |
|
|
|
|
|
-| 36 | refreshToken 无限续期安全隐患 | v10 | ✅ 不再重新生成 refreshToken,原样返回 |
|
|
|
|
|
-| 37 | refreshToken 从 body 改为 header 获取 | v10 | ✅ `header:"Authorization"` |
|
|
|
|
|
-| 38 | ExpiresIn → Expires 字段重命名+含义变更 | v11 | ✅ 秒数→unix时间戳 |
|
|
|
|
|
-
|
|
|
|
|
-### 3.2 v8 新增模块审计(access 控制 + UserDetailsLoader)
|
|
|
|
|
-
|
|
|
|
|
-#### 新增文件
|
|
|
|
|
-
|
|
|
|
|
-| 文件 | 说明 | 审计结论 |
|
|
|
|
|
-| :--- | :--- | :--- |
|
|
|
|
|
-| `internal/loaders/userDetailsLoader.go` | 用户详情加载器 + Redis 缓存 | 见下方详细分析 |
|
|
|
|
|
-| `internal/logic/auth/access.go` | 集中访问控制函数 | 逻辑正确 |
|
|
|
|
|
-
|
|
|
|
|
-#### access.go 审计结论
|
|
|
|
|
-
|
|
|
|
|
-| 函数 | 审计结论 |
|
|
|
|
|
-| :--- | :--- |
|
|
|
|
|
-| `RequireSuperAdmin` | ✅ 正确:nil 检查 → IsSuperAdmin 检查 |
|
|
|
|
|
-| `RequireProductAdmin` | ✅ 正确:nil → SuperAdmin → Admin → 拒绝 |
|
|
|
|
|
-| `CheckMemberTypeAssignment` | ✅ 正确:SuperAdmin 豁免,优先级比较用 `>=` 阻止同级分配 |
|
|
|
|
|
-| `CheckManageAccess` | ✅ 正确:SuperAdmin/Self 豁免 → 部门层级 → 权限级别 |
|
|
|
|
|
-| `checkDeptHierarchy` | ✅ 正确:ADMIN 豁免,DeptId=0 检查,HasPrefix 子部门判断 |
|
|
|
|
|
-| `checkPermLevel` | ✅ 正确:memberType 优先级 → permsLevel 比较 |
|
|
|
|
|
-| `memberTypePriority` | ✅ 正确:SA=0, A=1, D=2, M=3, unknown=MaxInt32 |
|
|
|
|
|
-
|
|
|
|
|
-#### UserDetailsLoader 审计发现
|
|
|
|
|
-
|
|
|
|
|
-| # | 发现 | 风险等级 | 说明 |
|
|
|
|
|
-| :--- | :--- | :--- | :--- |
|
|
|
|
|
-| ~~BUG-003~~ | ~~`FindMinPermsLevelByUserIdAndProductCode` 使用 `sql.NullInt64` 与 go-zero 不兼容~~ | ~~🔴 高~~ | ✅ **已修复 (v9)**:改为 `IFNULL(MIN(...), -1)` + `int64`,level < 0 时返回 `ErrNotFound`。TC-0492、TC-0493 恢复通过。 |
|
|
|
|
|
-| ~~WARN-001~~ | ~~`cleanByPattern` 使用 Redis `KEYS` 命令~~ | ~~⚠️ 中~~ | ✅ **已修改 (v9)**:改用 Lua 脚本 + `SCAN` 替代 `KEYS`。但引入 BUG-004(见下)。 |
|
|
|
|
|
-| ~~BUG-004~~ | ~~`cleanByPattern` Lua SCAN cursor 类型断言失败~~ | ~~🟡 中~~ | ✅ **已修复 (v10)**:Lua 脚本中 `return nextCursor` 改为 `return tonumber(nextCursor)`,Go 侧 `val.(int64)` 断言恢复正常。TC-0463、TC-0464 通过。 |
|
|
|
|
|
-| WARN-002 | `Load` 对不存在用户返回 Status=0 | ℹ️ 低 | 当 `loadUser` 失败(用户不存在/DB 错误),UserDetails.Status 为零值 0,中间件检查 `Status != StatusEnabled(1)` 会返回 403 "账号已被冻结"。错误消息不够精确(应为 "用户不存在"),但安全性正确(不存在用户被拒绝)。 |
|
|
|
|
|
-| WARN-003 | `loadPerms` 错误被静默吞掉 | ℹ️ 低 | `FindAllCodesByProductCode` 失败时仅 logx.Errorf,Perms 为 nil。虽有日志但调用方无法感知失败。当前设计为 "尽力加载",不影响安全性(权限为空 = 无权限)。 |
|
|
|
|
|
-
|
|
|
|
|
-#### 中间件变更审计
|
|
|
|
|
-
|
|
|
|
|
-| 变更 | 审计结论 |
|
|
|
|
|
-| :--- | :--- |
|
|
|
|
|
-| 新增 `loader.Load()` 调用 | ✅ 正确:每次请求加载最新用户详情 |
|
|
|
|
|
-| 冻结账号 403 拦截 | ✅ 正确:`ud.Status != consts.StatusEnabled` |
|
|
|
|
|
-| UserDetails 注入 context | ✅ 正确:替代旧的多个 context key |
|
|
|
|
|
-| 公共 helper 函数 | ✅ 正确:`GetUserDetails`/`GetUserId`/`GetUsername`/`GetProductCode`/`GetMemberType`/`IsSuperAdmin` |
|
|
|
|
|
-
|
|
|
|
|
-#### Logic 层 access 控制接入审计
|
|
|
|
|
-
|
|
|
|
|
-| Logic | access 检查 | 缓存失效 | 审计结论 |
|
|
|
|
|
-| :--- | :--- | :--- | :--- |
|
|
|
|
|
-| createDept | RequireSuperAdmin | — | ✅ |
|
|
|
|
|
-| updateDept | RequireSuperAdmin | Clean(dept 下所有用户) | ✅ |
|
|
|
|
|
-| deleteDept | RequireSuperAdmin | — | ✅ |
|
|
|
|
|
-| createProduct | RequireSuperAdmin | — | ✅ |
|
|
|
|
|
-| updateProduct | RequireSuperAdmin | CleanByProduct | ✅ |
|
|
|
|
|
-| createUser | RequireProductAdmin | — | ✅ |
|
|
|
|
|
-| updateUser | Self 或 SuperAdmin | Clean(userId) | ✅ |
|
|
|
|
|
-| updateUserStatus | CheckManageAccess | Clean(userId) | ✅ |
|
|
|
|
|
-| bindRoles | CheckManageAccess | Del(userId, productCode) | ✅ |
|
|
|
|
|
-| setUserPerms | CheckManageAccess | Del(userId, productCode) | ✅ |
|
|
|
|
|
-| createRole | RequireProductAdmin | — | ✅ |
|
|
|
|
|
-| updateRole | RequireProductAdmin | BatchDel(affectedUsers) | ✅ |
|
|
|
|
|
-| deleteRole | RequireProductAdmin | BatchDel(affectedUsers) | ✅ |
|
|
|
|
|
-| bindRolePerms | RequireProductAdmin | BatchDel(affectedUsers) | ✅ |
|
|
|
|
|
-| addMember | CheckManageAccess + CheckMemberTypeAssignment | Del(userId, productCode) | ✅ |
|
|
|
|
|
-| updateMember | CheckManageAccess + CheckMemberTypeAssignment | Del(userId, productCode) | ✅ |
|
|
|
|
|
-| removeMember | CheckManageAccess | Del(userId, productCode) | ✅ |
|
|
|
|
|
-| login | — (公开) | Load (查询) | ✅ |
|
|
|
|
|
-| refreshToken | — (公开) | Load (查询) | ✅ |
|
|
|
|
|
-| syncPerms | appKey/appSecret 校验 | CleanByProduct | ✅ |
|
|
|
|
|
-| userInfo | — (中间件已鉴权) | — | ✅ |
|
|
|
|
|
-
|
|
|
|
|
-### 3.3 ~~BUG-003~~ ✅ 已修复
|
|
|
|
|
-
|
|
|
|
|
-- **关联 TC**: TC-0492、TC-0493
|
|
|
|
|
-- **位置**: `internal/model/role/sysRoleModel.go` → `FindMinPermsLevelByUserIdAndProductCode`
|
|
|
|
|
-- **修复方案**: DEV 改为 `IFNULL(MIN(r.permsLevel), -1)` + 普通 `int64` 扫描,`level < 0` 时返回 `ErrNotFound`
|
|
|
|
|
-- **验证结果**: TC-0492、TC-0493 全部通过 ✅
|
|
|
|
|
-
|
|
|
|
|
-### 3.4 ~~BUG-004~~ ✅ 已修复
|
|
|
|
|
-
|
|
|
|
|
-- **关联 TC**: TC-0463、TC-0464
|
|
|
|
|
-- **位置**: `internal/loaders/userDetailsLoader.go` → `cleanByPattern`
|
|
|
|
|
-- **修复方案**: DEV 在 Lua 脚本中将 `return nextCursor` 改为 `return tonumber(nextCursor)`,使返回值为数字类型,Go 侧 `val.(int64)` 断言恢复正常
|
|
|
|
|
-- **验证结果**: TC-0463、TC-0464 全部通过 ✅
|
|
|
|
|
-
|
|
|
|
|
----
|
|
|
|
|
-
|
|
|
|
|
-## 四、代码质量总评
|
|
|
|
|
-
|
|
|
|
|
-经过三轮审计,本次新增的 access 控制和 UserDetailsLoader 实现质量良好:
|
|
|
|
|
-
|
|
|
|
|
-- **访问控制架构**: 集中式 access.go 管控,4 个关键函数覆盖超管/产品管理员/成员类型/部门层级/权限级别等维度
|
|
|
|
|
-- **缓存策略**: UserDetailsLoader 采用 Redis 缓存 + TTL(300s) + 主动失效,所有写操作均有对应的 Del/Clean/BatchDel
|
|
|
|
|
-- **安全纵深**: JWT 中间件 → UserDetailsLoader 实时加载 → 冻结账号拦截 → Logic 层 access 检查,四层防护
|
|
|
|
|
-- **部门层级管控**: HasPrefix 子部门判断 + ADMIN 豁免 + DeptId=0 边界处理
|
|
|
|
|
-- **权限级别比较**: memberType 优先级 + permsLevel 数值双重比较,确保低级别用户无法管理高级别用户
|
|
|
|
|
-- ~~**BUG-003**~~: ✅ 已修复,`FindMinPermsLevelByUserIdAndProductCode` 改为 `IFNULL` + `int64`
|
|
|
|
|
-- ~~**WARN-001**~~: ✅ 已改用 Lua + SCAN 替代 KEYS
|
|
|
|
|
-- ~~**BUG-004**~~: ✅ 已修复,Lua 脚本 `return tonumber(nextCursor)`
|
|
|
|
|
-- **WARN-002 / WARN-003**: DEV 确认为设计取舍,安全性不受影响,不修改
|
|
|
|
|
-
|
|
|
|
|
-### 测试覆盖统计
|
|
|
|
|
|
|
+## 三、测试覆盖统计
|
|
|
|
|
|
|
|
| 指标 | 数值 |
|
|
| 指标 | 数值 |
|
|
|
| :--- | :--- |
|
|
| :--- | :--- |
|
|
|
-| TC 总数 | 499 |
|
|
|
|
|
-| 已实现 | 498 (99.8%) |
|
|
|
|
|
-| 跳过 | 1 (TC-0189,`!ok` 防御性不可达分支) |
|
|
|
|
|
-| 测试函数 | 662 |
|
|
|
|
|
-| 测试子用例 | 744 |
|
|
|
|
|
-| ✅ 通过 | **743** |
|
|
|
|
|
|
|
+| TC 总数 | 510 |
|
|
|
|
|
+| 已实现 | 509 (99.8%) |
|
|
|
|
|
+| 跳过 | 1 (TC-0189,防御性不可达分支) |
|
|
|
|
|
+| 测试函数 | 673 |
|
|
|
|
|
+| 测试子用例 | 755 |
|
|
|
|
|
+| ✅ 通过 | **754** |
|
|
|
| ❌ 失败 | **0** |
|
|
| ❌ 失败 | **0** |
|
|
|
-| ⏭️ 跳过 | **1** (TC-0189 — t.Skip) |
|
|
|
|
|
-| 通过率 | **100%** (743/743) |
|
|
|
|
|
-| BUG-001 ~ BUG-004 | ✅ 全部已修复 |
|
|
|
|
|
-| WARN-001 | ✅ 已修复(KEYS → Lua SCAN) |
|
|
|
|
|
-| WARN-002 / WARN-003 | 设计取舍,不修改 |
|
|
|
|
|
|
|
+| ⏭️ 跳过 | **1** (TC-0189) |
|
|
|
|
|
+| 通过率 | **100%** (754/754,排除不可达分支) |
|