|
@@ -296,8 +296,8 @@ POST /api/role/bindPerms {"roleId": 3, "permIds": [1,5]} # 客服:
|
|
|
|
|
|
|
|
```bash
|
|
```bash
|
|
|
# 创建用户,归属研发部
|
|
# 创建用户,归属研发部
|
|
|
-POST /api/user/create {"username": "zhangsan", "password": "123456", "nickname": "张三", "deptId": 1}
|
|
|
|
|
-# 返回 userId=10
|
|
|
|
|
|
|
+POST /api/user/create {"username": "zhangsan", "nickname": "张三", "deptId": 1}
|
|
|
|
|
+# 返回 userId=10, credentialsTicket(用于领取初始密码)
|
|
|
|
|
|
|
|
# 将张三添加为 CRM 和 OA 的成员(MEMBER 类型即可)
|
|
# 将张三添加为 CRM 和 OA 的成员(MEMBER 类型即可)
|
|
|
POST /api/member/add {"productCode": "crm", "userId": 10, "memberType": "MEMBER"}
|
|
POST /api/member/add {"productCode": "crm", "userId": 10, "memberType": "MEMBER"}
|
|
@@ -317,8 +317,8 @@ POST /api/member/remove {"id": <张三在OA中的成员记录ID>}
|
|
|
**场景 C:市场部李四** — 需要使用 CRM,分配销售角色
|
|
**场景 C:市场部李四** — 需要使用 CRM,分配销售角色
|
|
|
|
|
|
|
|
```bash
|
|
```bash
|
|
|
-POST /api/user/create {"username": "lisi", "password": "123456", "nickname": "李四", "deptId": 2}
|
|
|
|
|
-# 返回 userId=11
|
|
|
|
|
|
|
+POST /api/user/create {"username": "lisi", "nickname": "李四", "deptId": 2}
|
|
|
|
|
+# 返回 userId=11, credentialsTicket
|
|
|
|
|
|
|
|
POST /api/member/add {"productCode": "crm", "userId": 11, "memberType": "MEMBER"}
|
|
POST /api/member/add {"productCode": "crm", "userId": 11, "memberType": "MEMBER"}
|
|
|
POST /api/user/bindRoles {"userId": 11, "roleIds": [2], "productCode": "crm"} # 分配"普通销售"角色
|
|
POST /api/user/bindRoles {"userId": 11, "roleIds": [2], "productCode": "crm"} # 分配"普通销售"角色
|
|
@@ -344,7 +344,7 @@ POST /api/user/setPerms {
|
|
|
**场景 E:外部临时协作人员** — 不属于任何部门
|
|
**场景 E:外部临时协作人员** — 不属于任何部门
|
|
|
|
|
|
|
|
```bash
|
|
```bash
|
|
|
-POST /api/user/create {"username": "temp_wang", "password": "123456", "nickname": "外包王五"}
|
|
|
|
|
|
|
+POST /api/user/create {"username": "temp_wang", "nickname": "外包王五"}
|
|
|
# deptId 不传,不归属任何部门
|
|
# deptId 不传,不归属任何部门
|
|
|
|
|
|
|
|
POST /api/member/add {"productCode": "crm", "userId": 12, "memberType": "MEMBER"}
|
|
POST /api/member/add {"productCode": "crm", "userId": 12, "memberType": "MEMBER"}
|
|
@@ -407,7 +407,9 @@ flowchart LR
|
|
|
| 删除角色 | 超管 或 产品管理员 | 级联删除关联数据 |
|
|
| 删除角色 | 超管 或 产品管理员 | 级联删除关联数据 |
|
|
|
| 绑定角色权限 | 超管 或 产品管理员 | — |
|
|
| 绑定角色权限 | 超管 或 产品管理员 | — |
|
|
|
| **用户管理** | | |
|
|
| **用户管理** | | |
|
|
|
-| 创建用户 | 超管 或 产品管理员 | — |
|
|
|
|
|
|
|
+| 创建用户 | 超管 或 产品管理员 | 服务端生成密码,ticket 下发 |
|
|
|
|
|
+| 重置密码 | 通过 `CheckManageAccess` | 不可重置超管密码 |
|
|
|
|
|
+| 获取用户凭证 | 超管 或 产品管理员 | ticket 一次性消费 |
|
|
|
| 更新用户信息 | 仅本人 或 超管 | — |
|
|
| 更新用户信息 | 仅本人 或 超管 | — |
|
|
|
| 冻结/解冻用户 | 通过 `CheckManageAccess` | 不可冻结自己和超管 |
|
|
| 冻结/解冻用户 | 通过 `CheckManageAccess` | 不可冻结自己和超管 |
|
|
|
| 绑定角色 | 通过 `CheckManageAccess` | 目标用户的成员状态必须启用 |
|
|
| 绑定角色 | 通过 `CheckManageAccess` | 目标用户的成员状态必须启用 |
|
|
@@ -1295,27 +1297,69 @@ Content-Type: application/json
|
|
|
|
|
|
|
|
#### POST /api/user/create — 创建用户(超级管理员 或 产品管理员)
|
|
#### POST /api/user/create — 创建用户(超级管理员 或 产品管理员)
|
|
|
|
|
|
|
|
-创建一个全局用户账号。用户是全局概念,创建后可通过「添加成员」接口加入多个产品。
|
|
|
|
|
|
|
+创建一个全局用户账号。服务端自动生成符合强度要求的随机密码,通过一次性凭证票据(ticket)安全下发,避免密码明文出现在请求/响应体中。
|
|
|
|
|
|
|
|
**调用场景:**
|
|
**调用场景:**
|
|
|
|
|
|
|
|
-- **新员工入职**:HR 或管理员为新员工创建账号,设置初始密码,并归属到对应部门
|
|
|
|
|
|
|
+- **新员工入职**:HR 或管理员为新员工创建账号并归属到对应部门,创建成功后通过 ticket 领取初始密码交给员工
|
|
|
- **批量建立账号**:运维脚本遍历员工花名册,批量调用此接口创建用户账号
|
|
- **批量建立账号**:运维脚本遍历员工花名册,批量调用此接口创建用户账号
|
|
|
- **外部协作人员**:为外包或合作伙伴创建账号(可不设 `deptId`),后续通过成员管理授予特定产品访问权
|
|
- **外部协作人员**:为外包或合作伙伴创建账号(可不设 `deptId`),后续通过成员管理授予特定产品访问权
|
|
|
|
|
|
|
|
-**注意事项:** 创建用户后还需通过 `/member/add` 将其加入产品才能登录使用该产品。
|
|
|
|
|
|
|
+**注意事项:** 创建用户后还需通过 `/member/add` 将其加入产品才能登录使用该产品。响应中携带 `credentialsTicket`(5 分钟有效),需立即调用 `/api/user/fetchCredentials` 领取用户名和初始密码。ticket 一次消费即失效。用户首次登录后会被强制要求修改密码(`mustChangePassword=1`)。
|
|
|
|
|
|
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|
|
| ------ | ------ | ------ | ------ |
|
|
| ------ | ------ | ------ | ------ |
|
|
|
| username | string | 是 | 登录名(全局唯一) |
|
|
| username | string | 是 | 登录名(全局唯一) |
|
|
|
-| password | string | 是 | 密码(6-72 字符) |
|
|
|
|
|
| nickname | string | 否 | 昵称 |
|
|
| nickname | string | 否 | 昵称 |
|
|
|
| email | string | 否 | 邮箱(需合法格式) |
|
|
| email | string | 否 | 邮箱(需合法格式) |
|
|
|
| phone | string | 否 | 手机号(7-15 位数字,可含 `+` 前缀) |
|
|
| phone | string | 否 | 手机号(7-15 位数字,可含 `+` 前缀) |
|
|
|
| remark | string | 否 | 备注 |
|
|
| remark | string | 否 | 备注 |
|
|
|
| deptId | int64 | 否 | 部门 ID(归属研发部门的用户加入产品后自动获得全部权限) |
|
|
| deptId | int64 | 否 | 部门 ID(归属研发部门的用户加入产品后自动获得全部权限) |
|
|
|
|
|
|
|
|
-**响应 data:** `{"id": 1}`
|
|
|
|
|
|
|
+**响应 data:** `{"id": 1, "credentialsTicket": "...", "credentialsExpiresAt": 1716000000}`
|
|
|
|
|
+
|
|
|
|
|
+#### POST /api/user/resetPassword — 重置用户密码(超级管理员 或 产品管理员)
|
|
|
|
|
+
|
|
|
|
|
+管理员为指定用户重置密码。服务端生成新的随机强密码,通过一次性凭证票据安全下发。重置后旧令牌即时失效(tokenVersion 递增),用户下次登录需使用新密码且会被强制要求修改密码。
|
|
|
|
|
+
|
|
|
|
|
+**调用场景:**
|
|
|
|
|
+
|
|
|
|
|
+- **用户忘记密码**:用户无法自行修改密码时,管理员为其重置
|
|
|
|
|
+- **安全事件处置**:发现账号异常时,管理员重置密码使旧凭据失效
|
|
|
|
|
+- **新员工初始密码遗失**:创建用户时的 ticket 过期或已消费,管理员通过重置密码重新生成
|
|
|
|
|
+
|
|
|
|
|
+**安全约束:**
|
|
|
|
|
+
|
|
|
|
|
+- 不允许重置超级管理员的密码(超管只能通过 `/auth/changePassword` 自行修改)
|
|
|
|
|
+- 需通过 `CheckManageAccess` 权限检查(防止越权重置高级别用户)
|
|
|
|
|
+- 重置后递增 `tokenVersion`,所有已签发令牌即时失效
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 类型 | 必填 | 说明 |
|
|
|
|
|
+| ------ | ------ | ------ | ------ |
|
|
|
|
|
+| userId | int64 | 是 | 目标用户 ID |
|
|
|
|
|
+
|
|
|
|
|
+**响应 data:** `{"credentialsTicket": "...", "credentialsExpiresAt": 1716000000}`
|
|
|
|
|
+
|
|
|
|
|
+#### POST /api/user/fetchCredentials — 获取用户凭证(超级管理员 或 产品管理员)
|
|
|
|
|
+
|
|
|
|
|
+安全地获取用户创建或密码重置时生成的凭证(用户名 + 密码)。采用一次性 ticket 机制,凭证仅可获取一次。
|
|
|
|
|
+
|
|
|
|
|
+**调用场景:**
|
|
|
|
|
+
|
|
|
|
|
+- **创建用户后获取凭证**:管理后台创建用户成功后,前端使用返回的 ticket 调用此接口获取初始密码并展示给管理员
|
|
|
|
|
+- **重置密码后获取凭证**:管理员重置用户密码后,前端使用返回的 ticket 获取新密码
|
|
|
|
|
+
|
|
|
|
|
+**安全约束:**
|
|
|
|
|
+
|
|
|
|
|
+- 仅超级管理员或产品管理员可调用
|
|
|
|
|
+- ticket 存储在 Redis 中,TTL 为 5 分钟,过期后无法获取
|
|
|
|
|
+- ticket 采用原子性 GetDel 操作,确保一次性消费,防止重放攻击
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 类型 | 必填 | 说明 |
|
|
|
|
|
+| ------ | ------ | ------ | ------ |
|
|
|
|
|
+| ticket | string | 是 | 创建用户或重置密码时返回的一次性凭证票据 |
|
|
|
|
|
+
|
|
|
|
|
+**响应 data:** `{"username": "zhangsan", "password": "Ax7#kL9m..."}`
|
|
|
|
|
|
|
|
#### POST /api/user/update — 更新用户(仅本人 或 超级管理员)
|
|
#### POST /api/user/update — 更新用户(仅本人 或 超级管理员)
|
|
|
|
|
|
|
@@ -1694,7 +1738,7 @@ server/
|
|
|
├── gen-api.sh # API 代码生成脚本
|
|
├── gen-api.sh # API 代码生成脚本
|
|
|
├── gen-model.sh # Model 代码生成脚本
|
|
├── gen-model.sh # Model 代码生成脚本
|
|
|
├── run-test.sh # 测试运行脚本
|
|
├── run-test.sh # 测试运行脚本
|
|
|
-├── test-design.md # 测试用例设计文档(433 TC)
|
|
|
|
|
|
|
+├── test-design.md # 测试用例设计文档(1065 TC)
|
|
|
├── test-report.md # 测试报告
|
|
├── test-report.md # 测试报告
|
|
|
├── etc/
|
|
├── etc/
|
|
|
│ └── perm-api.yaml # 服务配置
|
|
│ └── perm-api.yaml # 服务配置
|
|
@@ -1818,12 +1862,12 @@ server {
|
|
|
|
|
|
|
|
| 指标 | 数值 |
|
|
| 指标 | 数值 |
|
|
|
| ------ | ------ |
|
|
| ------ | ------ |
|
|
|
-| 测试用例总数 | 499 |
|
|
|
|
|
-| 已覆盖 TC | 498(99.8%) |
|
|
|
|
|
-| 测试函数 | 662 |
|
|
|
|
|
-| 测试子用例 | 744 |
|
|
|
|
|
-| 测试包 | 23 |
|
|
|
|
|
-| 通过率 | 99.7% |
|
|
|
|
|
|
|
+| 测试用例总数 | 1065 |
|
|
|
|
|
+| 已覆盖 TC | 1065(100%) |
|
|
|
|
|
+| 测试函数 | 1170 |
|
|
|
|
|
+| 测试子用例 | 1309 |
|
|
|
|
|
+| 测试包 | 28 |
|
|
|
|
|
+| 通过率 | 100% |
|
|
|
|
|
|
|
|
测试覆盖范围:
|
|
测试覆盖范围:
|
|
|
|
|
|
|
@@ -1841,7 +1885,7 @@ server {
|
|
|
|
|
|
|
|
| 文件 | 说明 |
|
|
| 文件 | 说明 |
|
|
|
| ------ | ------ |
|
|
| ------ | ------ |
|
|
|
-| `test-design.md` | 测试用例设计文档(499 个 TC,含测试场景、输入数据、预期结果) |
|
|
|
|
|
|
|
+| `test-design.md` | 测试用例设计文档(1065 个 TC,含测试场景、输入数据、预期结果) |
|
|
|
| `test-report.md` | 测试执行报告(含各包耗时、TC 明细、源码审计结果) |
|
|
| `test-report.md` | 测试执行报告(含各包耗时、TC 明细、源码审计结果) |
|
|
|
|
|
|
|
|
### 运行测试
|
|
### 运行测试
|