Skip to main content

Sprint 2 接口文档 — 用户群组管理

Phase 2.5 API-First:先定接口,再写代码。

版本:v1.0 Draft | 日期:2026-03-13 | 作者:小虎


0. 约定

通用响应格式

// 成功
{ "code": 0, "data": { ... } }

// 失败
{ "code": 10001, "message": "错误描述" }

错误码定义

含义说明
0成功
10001参数错误请求体校验失败
10002未登录缺少或无效 Bearer Token
10003权限不足当前用户无权执行此操作
10004资源不存在目标用户/群组/权限不存在
10005账号或密码错误登录专用
10006账号不可用被禁用或已删除
10007密码强度不足至少8位,含大小写+数字
10008用户名已存在创建/修改用户时重复
10009群组 key 已存在创建/修改群组时重复
10010不允许提权不能创建/修改更高角色
10011不允许操作自己不能删除/禁用自己
10012默认群组不可删is_default=1 的群组

认证

所有接口(除 /auth/login)需在 Header 中携带:

Authorization: Bearer <access_token>

分页

通用分页参数(Query String):

参数类型默认说明
pageint1页码,从 1 开始
page_sizeint20每页条数,最大 100

通用分页响应:

{
"items": [...],
"total": 120,
"page": 1,
"page_size": 20
}

角色层级

superadmin > admin > user
  • superadmin:超级管理员,免群组鉴权,拥有所有权限
  • admin:管理员,可管理 user 级别用户和群组
  • user:普通用户,只能查看/修改自己的信息

防提权原则:不能创建/修改与自己同级或更高的 role_type。


1. 用户管理(T-BE-07)

1.1 获取用户列表

GET /api/v1/users

权限:admin+ | 权限 key:user:list

Query 参数

参数类型必填说明
pageint页码
page_sizeint每页条数
keywordstring搜索(模糊匹配 username / nickname / email)
statusint0=禁用 1=启用
role_typestring筛选角色类型
group_idint筛选群组

响应

{
"code": 0,
"data": {
"items": [
{
"user_id": 1,
"username": "tom",
"nickname": "Tom",
"email": "tom@example.com",
"phone": "13800138000",
"avatar": "",
"role_type": "admin",
"status": 1,
"last_login_at": 1773400000,
"last_login_ip": "192.168.1.1",
"groups": [
{ "group_id": 1, "group_name": "运营组" }
],
"created_at": "2026-03-01T00:00:00Z"
}
],
"total": 50,
"page": 1,
"page_size": 20
}
}

注意

  • 不返回 password 字段
  • user 角色只能看到自己(返回单条)
  • admin 不能看到 superadmin 的列表
  • create_time DESC 排序

1.2 获取用户详情

GET /api/v1/users/:id

权限:admin+ | 自己可查自己 | 权限 key:user:read

响应:同 1.1 单条,额外包含:

{
"code": 0,
"data": {
"user_id": 2,
"username": "alice",
"nickname": "Alice",
"email": "alice@example.com",
"phone": "13800138001",
"avatar": "",
"role_type": "user",
"status": 1,
"last_login_at": 1773400000,
"last_login_ip": "192.168.1.2",
"groups": [
{ "group_id": 1, "group_name": "运营组" },
{ "group_id": 2, "group_name": "财务组" }
],
"permissions": ["user:list", "order:read"],
"created_at": "2026-03-01T00:00:00Z",
"updated_at": "2026-03-10T00:00:00Z"
}
}

1.3 创建用户

POST /api/v1/users

权限:admin+ | 权限 key:user:create

请求体

{
"username": "bob",
"password": "StrongPwd123",
"nickname": "Bob",
"email": "bob@example.com",
"phone": "13800138002",
"role_type": "user",
"status": 1,
"group_ids": [1, 2]
}

校验规则

字段规则
username必填,3-64 字符,唯一
password必填,≥8 位,含大小写+数字
nickname必填,1-64 字符
email必填,合法邮箱格式,唯一
phone可选
role_type必填,只能是低于当前用户的角色
group_ids可选,整数数组

响应

{
"code": 0,
"data": {
"user_id": 3
}
}

防提权

  • admin 只能创建 user
  • superadmin 可以创建 adminuser
  • 不能创建 superadmin(系统唯一)

1.4 更新用户

PUT /api/v1/users/:id

权限:admin+ | 权限 key:user:update

请求体(全量更新,不传的字段保持不变):

{
"nickname": "Bob Updated",
"email": "bob_new@example.com",
"phone": "13900139000",
"role_type": "user",
"group_ids": [1, 3]
}

注意

  • 不能通过此接口修改密码(走专用改密接口)
  • 不能通过此接口修改 username(创建后不可变)
  • 修改 role_type 触发防提权校验
  • 修改 group_ids 全量替换(先删后增)
  • 修改成功后 auth_version + 1,使已有 session 失效

1.5 删除用户(软删除)

DELETE /api/v1/users/:id

权限:admin+ | 权限 key:user:delete

响应

{ "code": 0, "data": { "deleted": true } }

规则

  • 软删除:is_deleted = 1
  • 不能删自己(10011)
  • admin 不能删 admin 和 superadmin(10010)
  • 删除后 auth_version + 1,踢出所有 session
  • 同时清理 sys_user_group 关联

1.6 启用/禁用用户

PATCH /api/v1/users/:id/status

权限:admin+ | 权限 key:user:update

请求体

{ "status": 0 }
  • 1 = 启用,0 = 禁用
  • 禁用后 auth_version + 1,踢出所有 session
  • 不能禁用自己(10011)

1.7 管理员重置密码

PATCH /api/v1/users/:id/password

权限:admin+ | 权限 key:user:reset-password

请求体

{ "new_password": "NewStrongPwd456" }

规则

  • 密码强度校验(同创建用户)
  • 成功后 auth_version + 1,踢出目标用户所有 session
  • admin 不能重置 admin/superadmin 的密码(10010)

2. 群组管理(T-BE-09)

2.1 获取群组列表

GET /api/v1/groups

权限:admin+ | 权限 key:group:list

Query 参数

参数类型必填说明
pageint页码
page_sizeint每页条数
keywordstring搜索 group_name
statusint0=禁用 1=启用

响应

{
"code": 0,
"data": {
"items": [
{
"group_id": 1,
"group_name": "运营组",
"group_key": "ops",
"description": "运营团队",
"is_default": 0,
"status": 1,
"member_count": 12,
"permission_count": 8,
"created_at": "2026-03-01T00:00:00Z"
}
],
"total": 5,
"page": 1,
"page_size": 20
}
}

2.2 获取群组详情

GET /api/v1/groups/:id

权限:admin+ | 权限 key:group:read

响应:同 2.1 单条,额外包含 permissionsmembers 摘要。


2.3 创建群组

POST /api/v1/groups

权限:admin+ | 权限 key:group:create

请求体

{
"group_name": "财务组",
"group_key": "finance",
"description": "财务团队",
"status": 1,
"sort_order": 0,
"permission_ids": [1, 2, 3]
}

校验

字段规则
group_name必填,1-64 字符
group_key必填,1-64 字符,唯一,推荐英文 snake_case
description可选,最多 256 字符
permission_ids可选,只能分配自己拥有的权限(防提权)

2.4 更新群组

PUT /api/v1/groups/:id

权限:admin+ | 权限 key:group:update

请求体

{
"group_name": "财务组(新)",
"description": "更新描述",
"status": 1,
"sort_order": 10
}

注意

  • group_key 创建后不可修改
  • 修改群组后,群组内所有用户 auth_version + 1

2.5 删除群组

DELETE /api/v1/groups/:id

权限:admin+ | 权限 key:group:delete

规则

  • 默认群组(is_default=1)不可删(10012)
  • 软删除:is_deleted = 1
  • 同时清理 sys_user_groupsys_group_permission 关联
  • 群组内所有用户 auth_version + 1

3. 群组权限分配(T-BE-10)

3.1 获取群组权限

GET /api/v1/groups/:id/permissions

权限:admin+ | 权限 key:group:read

响应

{
"code": 0,
"data": {
"group_id": 1,
"permissions": [
{
"perm_id": 1,
"permission_key": "user:list",
"permission_name": "用户列表",
"module": "user"
},
{
"perm_id": 2,
"permission_key": "user:read",
"permission_name": "用户详情",
"module": "user"
}
]
}
}

3.2 设置群组权限(全量替换)

PUT /api/v1/groups/:id/permissions

权限:admin+ | 权限 key:group:assign-permission

请求体

{
"permission_ids": [1, 2, 3, 5]
}

规则

  • 全量替换:先删除旧关联,再插入新关联
  • 防提权:admin 只能分配自己拥有的权限(superadmin 不受限)
  • 成功后群组内所有用户 auth_version + 1

4. 群组成员管理(T-BE-11)

4.1 获取群组成员

GET /api/v1/groups/:id/members

权限:admin+ | 权限 key:group:read

Query 参数:分页 + keyword(搜索用户名/昵称)

响应

{
"code": 0,
"data": {
"items": [
{
"user_id": 2,
"username": "alice",
"nickname": "Alice",
"email": "alice@example.com",
"role_type": "user",
"status": 1,
"joined_at": "2026-03-05T00:00:00Z"
}
],
"total": 12,
"page": 1,
"page_size": 20
}
}

4.2 批量添加成员

POST /api/v1/groups/:id/members

权限:admin+ | 权限 key:group:manage-member

请求体

{
"user_ids": [2, 3, 5]
}

规则

  • 已在群组内的用户自动跳过(幂等)
  • 添加成功后目标用户 auth_version + 1

4.3 移除成员

DELETE /api/v1/groups/:id/members/:userId

权限:admin+ | 权限 key:group:manage-member

规则

  • 移除后目标用户 auth_version + 1

5. 权限列表(辅助接口)

5.1 获取所有权限(按 module 分组)

GET /api/v1/permissions

权限:admin+ | 权限 key:permission:list

响应

{
"code": 0,
"data": {
"modules": [
{
"module": "user",
"permissions": [
{ "perm_id": 1, "permission_key": "user:list", "permission_name": "用户列表" },
{ "perm_id": 2, "permission_key": "user:read", "permission_name": "用户详情" },
{ "perm_id": 3, "permission_key": "user:create", "permission_name": "创建用户" },
{ "perm_id": 4, "permission_key": "user:update", "permission_name": "更新用户" },
{ "perm_id": 5, "permission_key": "user:delete", "permission_name": "删除用户" },
{ "perm_id": 6, "permission_key": "user:reset-password", "permission_name": "重置密码" }
]
},
{
"module": "group",
"permissions": [
{ "perm_id": 7, "permission_key": "group:list", "permission_name": "群组列表" },
{ "perm_id": 8, "permission_key": "group:read", "permission_name": "群组详情" },
{ "perm_id": 9, "permission_key": "group:create", "permission_name": "创建群组" },
{ "perm_id": 10, "permission_key": "group:update", "permission_name": "更新群组" },
{ "perm_id": 11, "permission_key": "group:delete", "permission_name": "删除群组" },
{ "perm_id": 12, "permission_key": "group:assign-permission", "permission_name": "分配权限" },
{ "perm_id": 13, "permission_key": "group:manage-member", "permission_name": "管理成员" }
]
}
]
}
}

6. 资源可见性过滤(T-BE-12)

不是独立接口,而是横切逻辑。

规则

角色可见范围
superadmin所有资源,无限制
admin所有 user 级别用户 + 自己创建的群组 + 被分配的群组
user只能看到自己的信息

实现方式

  • 在所有 LIST / GET 接口的 SQL 查询中注入角色过滤条件
  • 建议封装为公共方法:ApplyVisibilityFilter(query, identity) query
  • superadmin 跳过过滤
  • admin 过滤掉 role_type = 'superadmin' 的用户
  • user 固定 WHERE user_id = ?

7. auth_version 递增 + 缓存失效(T-BE-13)

不是独立接口,而是写操作的副作用。

触发 auth_version + 1 的操作

操作影响范围
修改用户信息该用户
重置密码该用户
禁用/删除用户该用户
修改群组权限群组内所有用户
删除群组群组内所有用户
用户加入/移出群组该用户

流程

  1. 业务操作 → DB 更新
  2. auth_version + 1(SQL UPDATE sys_user SET auth_version = auth_version + 1 WHERE user_id IN (...))
  3. 清除 Redis 中受影响用户的 session(DEL session:<userId>:*
  4. 被踢用户下次请求会因 session 不存在而 401

8. Redis Session 删除补偿(T-BE-14)

不是独立接口,而是后台逻辑。

场景

Redis 清除 session 时可能因网络抖动失败,导致被踢用户仍能访问。

方案

在 AuthRequired 中间件中增加版本校验:

1. 从 JWT 解析 uid
2. 从 Redis 获取 session
3. 从 DB 读取当前 auth_version(可 Redis 缓存,TTL 30s)
4. 对比 JWT 签发时的 auth_version vs 当前值
5. 不匹配 → 返回 401 + 清除该 session

这样即使 Redis 删除失败,中间件也能兜底拦截。


9. 接口总览

#方法路径权限 key任务
1GET/api/v1/usersuser:listT-BE-07
2GET/api/v1/users/:iduser:readT-BE-07
3POST/api/v1/usersuser:createT-BE-07
4PUT/api/v1/users/:iduser:updateT-BE-07
5DELETE/api/v1/users/:iduser:deleteT-BE-07
6PATCH/api/v1/users/:id/statususer:updateT-BE-07
7PATCH/api/v1/users/:id/passworduser:reset-passwordT-BE-07
8GET/api/v1/groupsgroup:listT-BE-09
9GET/api/v1/groups/:idgroup:readT-BE-09
10POST/api/v1/groupsgroup:createT-BE-09
11PUT/api/v1/groups/:idgroup:updateT-BE-09
12DELETE/api/v1/groups/:idgroup:deleteT-BE-09
13GET/api/v1/groups/:id/permissionsgroup:readT-BE-10
14PUT/api/v1/groups/:id/permissionsgroup:assign-permissionT-BE-10
15GET/api/v1/groups/:id/membersgroup:readT-BE-11
16POST/api/v1/groups/:id/membersgroup:manage-memberT-BE-11
17DELETE/api/v1/groups/:id/members/:userIdgroup:manage-memberT-BE-11
18GET/api/v1/permissionspermission:list辅助

总计:18 个接口


10. 权限 Seed 数据

Sprint 2 上线时需要初始化 sys_permission 表:

INSERT INTO sys_permission (permission_key, permission_name, module, description, status, create_time) VALUES
-- user 模块
('user:list', '用户列表', 'user', '查看用户列表', 1, UNIX_TIMESTAMP()),
('user:read', '用户详情', 'user', '查看用户详情', 1, UNIX_TIMESTAMP()),
('user:create', '创建用户', 'user', '创建新用户', 1, UNIX_TIMESTAMP()),
('user:update', '更新用户', 'user', '修改用户信息', 1, UNIX_TIMESTAMP()),
('user:delete', '删除用户', 'user', '删除用户', 1, UNIX_TIMESTAMP()),
('user:reset-password', '重置密码', 'user', '管理员重置用户密码', 1, UNIX_TIMESTAMP()),
-- group 模块
('group:list', '群组列表', 'group', '查看群组列表', 1, UNIX_TIMESTAMP()),
('group:read', '群组详情', 'group', '查看群组详情及成员', 1, UNIX_TIMESTAMP()),
('group:create', '创建群组', 'group', '创建新群组', 1, UNIX_TIMESTAMP()),
('group:update', '更新群组', 'group', '修改群组信息', 1, UNIX_TIMESTAMP()),
('group:delete', '删除群组', 'group', '删除群组', 1, UNIX_TIMESTAMP()),
('group:assign-permission', '分配权限', 'group', '为群组分配权限', 1, UNIX_TIMESTAMP()),
('group:manage-member', '管理成员', 'group', '添加/移除群组成员', 1, UNIX_TIMESTAMP()),
-- permission 模块
('permission:list', '权限列表', 'permission', '查看所有权限', 1, UNIX_TIMESTAMP());

11. 技术评审决策(2026-03-13 大猫确认)

#决策项结论理由
1username 可否修改不可修改登录凭据 + 审计关联字段,改了日志追溯断裂;显示名用 nickname
2superadmin API 创建不允许只能 DB 直插,系统唯一,降低提权风险
3群组删除级联 sys_api不清理sys_api 是全局定义,生命周期跟权限绑定,不跟群组走
4auth_version 校验位置中间件横切关注点,与 T-BE-14 Redis 补偿融合,一处搞定
5批量操作接口Sprint 2 不做用户量小,YAGNI,等前端提需求再加
6操作日志 AOPSprint 3 做禅道 Sprint 3 专项,DB 表已就位,Sprint 2 先跑通业务