Files
2026-10-25 22:52:47 +08:00

451 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 后台管理 · RBAC 模块(管理员 / 角色 / 权限)
> 本文件描述 `/api/admin/rbac` 下的**后台 RBAC 管理**(管理员、角色、权限)相关接口。公共约定(请求头、统一响应、鉴权中间件、错误码、配置)见 [admin-api.md](./admin-api.md)。
## 1. 接口列表
所有接口均需登录后携带 `Authorization: Bearer <JWT>`(由 `AdminAuth` 校验),并经由 `PermissionLoader` 加载权限集合后,由路由守卫(`RequirePerm`)按权限 code 拦截:
| 资源 | 路由前缀 | 所需权限 code |
| --- | --- | --- |
| 管理员 | `/api/admin/rbac/admins` | `admin:manage` |
| 角色 | `/api/admin/rbac/roles` | `role:manage` |
| 权限 | `/api/admin/rbac/permissions` | `perm:manage` |
> 超级管理员角色(`super_admin`)对所有接口短路放行,无需逐条匹配权限。
状态枚举(`admin_users` / `admin_roles` 的 `status`):`0` 禁用,`1` 启用(默认 `1`)。
---
### 1.1 管理员接口(需 `admin:manage`)
#### 1.1.1 `POST /api/admin/rbac/admins`
新建管理员。用户名全局唯一,密码以 bcrypt 哈希存储。
**请求体**
```json
{
"username": "alice",
"nickname": "Alice",
"password": "Admin@123456",
"status": 1
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `username` | string | 是 | 管理员账号,全局唯一。已存在返回 `40900`。 |
| `nickname` | string | 否 | 昵称。 |
| `password` | string | 是 | 明文密码,后端以 bcrypt 哈希存储。 |
| `status` | int8 | 否 | `0` 禁用,`1` 启用;缺省或 `0` 时置为 `1`;非法值返回 `40000`。 |
**响应**:返回创建后的 `User` 对象(见 §2.1),`password_hash` 不返回。
**curl 示例**
```bash
curl -X POST http://localhost:8080/api/admin/rbac/admins \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"Admin@123456","status":1}'
```
#### 1.1.2 `GET /api/admin/rbac/admins`
分页查询管理员列表,支持按关键字与状态过滤。
**查询参数**
| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `keyword` | string | 空 | 模糊匹配 `username` 或 `nickname`。 |
| `status` | int8 | `-1`(全部) | `0` 禁用,`1` 启用,`-1` 全部。 |
| `page` | int | `1` | 页码,从 1 开始。 |
| `size` | int | `20` | 每页条数。 |
**响应**
```json
{
"code": 0,
"msg": "ok",
"data": {
"list": [
{
"id": 1,
"username": "alice",
"nickname": "Alice",
"status": 1,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z"
}
],
"total": 1,
"page": 1,
"size": 20
}
}
```
#### 1.1.3 `GET /api/admin/rbac/admins/:id`
查询单个管理员。
**路径参数**:`id`(uint64)。
**响应**:返回 `User` 对象;不存在返回 `40400`。
#### 1.1.4 `PUT /api/admin/rbac/admins/:id`
编辑管理员昵称 / 状态。字段以指针区分「未提供」与「置空」,全部为空时直接返回原记录。
**路径参数**:`id`(uint64)。
**请求体**
```json
{
"nickname": "新昵称",
"status": 0
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `nickname` | string | 否 | 昵称,提供即更新。 |
| `status` | int8 | 否 | `0` 禁用,`1` 启用;非法值返回 `40000`。 |
**响应**:返回更新后的 `User` 对象。
#### 1.1.5 `DELETE /api/admin/rbac/admins/:id`
删除管理员(同时清理其角色关联并失效权限缓存)。
**路径参数**:`id`(uint64)。
**响应**:`{ "code": 0, "msg": "ok" }`。
#### 1.1.6 `POST /api/admin/rbac/admins/:id/roles`
为管理员分配角色(**全量替换**)。
**路径参数**:`id`(uint64)。
**请求体**
```json
{ "role_ids": [1, 2] }
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `role_ids` | []uint64 | 是(binding:`required`) | 角色 ID 列表,覆盖该管理员原有关联。 |
**响应**:`{ "code": 0, "msg": "ok" }`。
#### 1.1.7 `POST /api/admin/rbac/admins/:id/reset-pwd`
重置管理员密码。
**路径参数**:`id`(uint64)。
**请求体**
```json
{ "password": "New@123456" }
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `password` | string | 是(binding:`required`) | 新明文密码,后端以 bcrypt 哈希存储。 |
**响应**:`{ "code": 0, "msg": "ok" }`。
---
### 1.2 角色接口(需 `role:manage`)
#### 1.2.1 `POST /api/admin/rbac/roles`
新建角色。`code` 全局唯一。
**请求体**
```json
{
"code": "editor",
"name": "编辑",
"description": "内容编辑角色",
"status": 1
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `code` | string | 是 | 角色标识,全局唯一;已存在返回 `40900`。 |
| `name` | string | 是 | 角色名称。 |
| `description` | string | 否 | 描述。 |
| `status` | int8 | 否 | `0` 禁用,`1` 启用;缺省或 `0` 时置为 `1`;非法值返回 `40000`。 |
**响应**:返回创建后的 `Role` 对象(见 §2.2)。
**curl 示例**
```bash
curl -X POST http://localhost:8080/api/admin/rbac/roles \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"code":"editor","name":"编辑","status":1}'
```
#### 1.2.2 `GET /api/admin/rbac/roles`
分页查询角色列表,支持按关键字与状态过滤。
**查询参数**
| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `keyword` | string | 空 | 模糊匹配 `code` 或 `name`。 |
| `status` | int8 | `-1`(全部) | `0` 禁用,`1` 启用,`-1` 全部。 |
| `page` | int | `1` | 页码。 |
| `size` | int | `20` | 每页条数。 |
**响应**:`data` 为 `{ "list": [...Role], "total": N, "page": 1, "size": 20 }`。
#### 1.2.3 `GET /api/admin/rbac/roles/:id`
查询单个角色。
**路径参数**:`id`(uint64)。
**响应**:返回 `Role` 对象;不存在返回 `40400`。
#### 1.2.4 `PUT /api/admin/rbac/roles/:id`
编辑角色。字段以指针区分「未提供」与「置空」,全部为空时直接返回原记录。
**路径参数**:`id`(uint64)。
**请求体**
```json
{
"name": "新名称",
"description": "新描述",
"status": 0
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `name` | string | 否 | 角色名称,提供即更新。 |
| `description` | string | 否 | 描述,提供即更新。 |
| `status` | int8 | 否 | `0` 禁用,`1` 启用;非法值返回 `40000`。 |
**响应**:返回更新后的 `Role` 对象。
#### 1.2.5 `DELETE /api/admin/rbac/roles/:id`
删除角色(清理关联并失效权限缓存)。
**路径参数**:`id`(uint64)。
**响应**:`{ "code": 0, "msg": "ok" }`。
#### 1.2.6 `POST /api/admin/rbac/roles/:id/permissions`
为角色分配权限(**全量替换**)。
**路径参数**:`id`(uint64)。
**请求体**
```json
{ "permission_ids": [1, 2, 3] }
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `permission_ids` | []uint64 | 是(binding:`required`) | 权限 ID 列表,覆盖该角色原有关联。 |
**响应**:`{ "code": 0, "msg": "ok" }`。
---
### 1.3 权限接口(需 `perm:manage`)
权限分两类:`api`(接口权限,对应后端守卫 code)与 `menu`(菜单权限,用于前端动态渲染菜单树)。
#### 1.3.1 `POST /api/admin/rbac/permissions`
新建权限。`code` 全局唯一。
**请求体**
```json
{
"code": "user:view",
"name": "用户查看",
"type": "api",
"method": "GET",
"path": "/api/admin/users",
"parent_id": 0,
"sort": 0
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `code` | string | 是 | 权限标识,全局唯一;已存在返回 `40900`。 |
| `name` | string | 是 | 权限名称。 |
| `type` | string | 是 | 权限类型:`api` 或 `menu`;非法值返回 `40000`。 |
| `method` | string | 否 | 接口方法(如 `GET`/`POST`),`type=api` 时建议填写。 |
| `path` | string | 否 | 接口路径或菜单路由;`type=api` 时建议填写。 |
| `parent_id` | uint64 | 否 | 父级权限 ID,菜单树用;`0` 表示顶级。 |
| `sort` | int | 否 | 排序号,菜单树用。 |
**响应**:返回创建后的 `Permission` 对象(见 §2.3)。
**curl 示例**
```bash
curl -X POST http://localhost:8080/api/admin/rbac/permissions \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"code":"user:view","name":"用户查看","type":"api","method":"GET","path":"/api/admin/users"}'
```
#### 1.3.2 `GET /api/admin/rbac/permissions`
分页查询权限列表,支持按类型与关键字过滤。
**查询参数**
| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `type` | string | 空(全部) | `api` 或 `menu`;为空表示全部类型。 |
| `keyword` | string | 空 | 模糊匹配 `code` 或 `name`。 |
| `page` | int | `1` | 页码。 |
| `size` | int | `20` | 每页条数。 |
**响应**:`data` 为 `{ "list": [...Permission], "total": N, "page": 1, "size": 20 }`。
#### 1.3.3 `GET /api/admin/rbac/permissions/:id`
查询单个权限。
**路径参数**:`id`(uint64)。
**响应**:返回 `Permission` 对象;不存在返回 `40400`。
#### 1.3.4 `PUT /api/admin/rbac/permissions/:id`
编辑权限。字段以指针区分「未提供」与「置空」,全部为空时直接返回原记录。
**路径参数**:`id`(uint64)。
**请求体**
```json
{
"name": "新名称",
"type": "menu",
"method": "GET",
"path": "/dashboard",
"parent_id": 0,
"sort": 1
}
```
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `name` | string | 否 | 名称,提供即更新。 |
| `type` | string | 否 | `api` 或 `menu`;非法值返回 `40000`。 |
| `method` | string | 否 | 接口方法,提供即更新。 |
| `path` | string | 否 | 路径/路由,提供即更新。 |
| `parent_id` | uint64 | 否 | 父级权限 ID,提供即更新。 |
| `sort` | int | 否 | 排序号,提供即更新。 |
**响应**:返回更新后的 `Permission` 对象。
#### 1.3.5 `DELETE /api/admin/rbac/permissions/:id`
删除权限(清理关联并失效权限缓存)。
**路径参数**:`id`(uint64)。
**响应**:`{ "code": 0, "msg": "ok" }`。
---
## 2. 数据模型
### 2.1 User(后台管理员)
| 字段 | 类型 | JSON | 说明 |
| --- | --- | --- | --- |
| `ID` | uint64 | `id` | 主键,自增。 |
| `Username` | string | `username` | 账号,全局唯一。 |
| `PasswordHash` | string | `password_hash` | **不返回**(json `-`)。 |
| `Nickname` | string | `nickname` | 昵称。 |
| `Status` | int8 | `status` | `0` 禁用,`1` 启用(默认 `1`)。 |
| `CreatedAt` | time | `created_at` | 创建时间。 |
| `UpdatedAt` | time | `updated_at` | 更新时间。 |
### 2.2 Role(角色)
| 字段 | 类型 | JSON | 说明 |
| --- | --- | --- | --- |
| `ID` | uint64 | `id` | 主键,自增。 |
| `Code` | string | `code` | 角色标识,全局唯一。 |
| `Name` | string | `name` | 角色名称。 |
| `Description` | string | `description` | 描述。 |
| `Status` | int8 | `status` | `0` 禁用,`1` 启用(默认 `1`)。 |
| `CreatedAt` | time | `created_at` | 创建时间。 |
| `UpdatedAt` | time | `updated_at` | 更新时间。 |
### 2.3 Permission(权限)
| 字段 | 类型 | JSON | 说明 |
| --- | --- | --- | --- |
| `ID` | uint64 | `id` | 主键,自增。 |
| `Code` | string | `code` | 权限标识,全局唯一。 |
| `Name` | string | `name` | 权限名称。 |
| `Type` | string | `type` | `api`(接口)或 `menu`(菜单)。 |
| `Method` | string | `method` | 接口方法(如 `GET`)。 |
| `Path` | string | `path` | 接口路径或菜单路由。 |
| `ParentID` | uint64 | `parent_id` | 父级权限 ID(`0` 为顶级)。 |
| `Sort` | int | `sort` | 排序号(菜单树用)。 |
| `CreatedAt` | time | `created_at` | 创建时间。 |
### 2.4 关联中间表
| 表名 | 字段 | 说明 |
| --- | --- | --- |
| `admin_user_roles` | `admin_id`, `role_id` | 管理员-角色多对多。 |
| `admin_role_permissions` | `role_id`, `permission_id` | 角色-权限多对多。 |
---
## 3. 补充错误码
除 [admin-api.md](./admin-api.md) §2.4 所列错误码外,RBAC 模块额外使用:
| 业务码 | 含义 |
| --- | --- |
| `40900` | 资源冲突(用户名已存在 / 角色 `code` 已存在 / 权限 `code` 已存在)。 |
> 资源不存在统一返回 `40400`;状态/类型等非法枚举统一返回 `40000`。
## 4. 备注
- **权限守卫**:RBAC 管理接口自身受 `RequirePerm` 守卫(见 §1 表),需调用方具备对应权限 `code`;`super_admin` 角色短路放行。权限 `code` 常量定义见 `internal/middleware/permission.go`(`PermAdminManage` / `PermRoleManage` / `PermPermManage`)。
- **缓存失效**:新建/编辑/删除管理员、角色、权限,或调整角色-权限、管理员-角色关联后,会失效对应权限缓存(`PermissionProvider` 的 `Load`/`MenuTree` 优先走缓存),下次请求重新加载。
- **种子初始化**:服务启动时由 `provider.Seed` 用环境变量 `ADMIN_SEED_USERNAME` / `ADMIN_SEED_PASSWORD`(缺省 `admin` / `Admin@123456`)初始化首个管理员,详见 `internal/router/router.go`。
- **建表脚本**:RBAC 相关表结构见 `scripts/001_rbac.sql`(项目未开启 AutoMigrate,需手动执行)。
- 新增/修改上述接口时须同步更新本文档。