library-picturebook-activity/backend/docs/RBAC_GUIDE.md
aid 418aa57ea8 Day4: 超管端设计优化 + UGC绘本创作社区P0实现
一、超管端设计优化
- 文档管理SOP体系建立,docs目录重组
- 统一用户管理:跨租户全局视角,合并用户管理+公众用户
- 活动监管全模块重构:全部活动(统计卡片+阶段筛选+SuperDetail详情页)、报名数据/作品数据/评审进度(两层合一扁平列表)、成果发布(去Tab+统计+隐藏写操作)
- 菜单精简:移除评委管理/评审规则/通知管理
- Bug修复:租户编辑丢失隐藏菜单、pageSize限制、主色统一

二、UGC绘本创作社区P0
- 数据库:10张新表(user_works/user_work_pages/work_tags等)
- 子女账号独立化:Child升级为独立User,家长切换+独立登录
- 用户作品库:CRUD+发布审核,8个API
- AI创作流程:提交→生成→保存到作品库,4个API
- 作品广场:首页改造为推荐流,标签+搜索+排序
- 内容审核(超管端):作品审核+作品管理+标签管理
- 活动联动:WorkSelector作品选择器
- 布局改造:底部5Tab(发现/创作/活动/作品库/我的)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:20:25 +08:00

398 lines
9.0 KiB
Markdown
Raw 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 权限控制详解
## 📚 什么是 RBAC
**RBACRole-Based Access Control** 即**基于角色的访问控制**,是一种权限管理模型。它的核心思想是:
> **用户 → 角色 → 权限**
通过给用户分配角色,角色拥有权限,从而间接地给用户授予权限。
## 🎯 RBAC 的核心概念
### 1. **用户User**
系统中的实际使用者,如:张三、李四
### 2. **角色Role**
一组权限的集合,如:管理员、编辑、访客
### 3. **权限Permission**
对资源的操作能力,如:创建用户、删除文章、查看报表
### 4. **资源Resource**
系统中的实体对象,如:用户、文章、订单
### 5. **操作Action**
对资源的操作类型create创建、read查看、update更新、delete删除
## 🏗️ 项目中的 RBAC 架构
### 数据模型关系
```
User (用户)
↓ (多对多)
UserRole (用户角色关联)
Role (角色)
↓ (多对多)
RolePermission (角色权限关联)
Permission (权限)
├─ resource: 资源名称 (如: user, role, menu)
└─ action: 操作类型 (如: create, read, update, delete)
```
### 数据库表结构
#### 1. **users** - 用户表
存储系统用户的基本信息
#### 2. **roles** - 角色表
存储角色信息,如:
- `admin` - 管理员
- `editor` - 编辑
- `viewer` - 查看者
#### 3. **permissions** - 权限表
存储权限信息,权限由 `resource` + `action` 组成,如:
- `user:create` - 创建用户
- `user:read` - 查看用户
- `user:update` - 更新用户
- `user:delete` - 删除用户
- `role:create` - 创建角色
- `menu:read` - 查看菜单
#### 4. **user_roles** - 用户角色关联表
用户和角色的多对多关系
#### 5. **role_permissions** - 角色权限关联表
角色和权限的多对多关系
## 🔄 RBAC 工作流程
### 1. **权限分配流程**
```
1. 创建权限
└─> 定义资源resource和操作action
└─> 例如user:create, user:read
2. 创建角色
└─> 给角色分配权限
└─> 例如:管理员角色 = [user:create, user:read, user:update, user:delete]
3. 给用户分配角色
└─> 用户继承角色的所有权限
└─> 例如:张三 = 管理员角色
```
### 2. **权限验证流程**
```
用户请求 API
JWT 认证(验证用户身份)
提取用户信息(包含 roles 和 permissions
RolesGuard 检查(检查用户是否有指定角色)
PermissionGuard 检查(检查用户是否有指定权限)
允许/拒绝访问
```
## 💻 代码实现示例
### 1. **定义权限**
权限由 `resource` + `action` 组成:
```typescript
// 权限示例
{
code: 'user:create', // 权限编码
resource: 'user', // 资源:用户
action: 'create', // 操作:创建
name: '创建用户',
description: '允许创建新用户'
}
{
code: 'user:read',
resource: 'user',
action: 'read',
name: '查看用户',
description: '允许查看用户列表和详情'
}
```
### 2. **创建角色并分配权限**
```typescript
// 创建管理员角色
const adminRole = await prisma.role.create({
data: {
name: '管理员',
code: 'admin',
permissions: {
create: [
{ permission: { connect: { code: 'user:create' } } },
{ permission: { connect: { code: 'user:read' } } },
{ permission: { connect: { code: 'user:update' } } },
{ permission: { connect: { code: 'user:delete' } } },
{ permission: { connect: { code: 'role:create' } } },
// ... 更多权限
],
},
},
});
```
### 3. **给用户分配角色**
```typescript
// 给用户分配管理员角色
await prisma.userRole.create({
data: {
user: { connect: { id: userId } },
role: { connect: { code: 'admin' } },
},
});
```
### 4. **在控制器中使用权限控制**
#### 方式一:使用角色装饰器
```typescript
import { Controller, Get, UseGuards } from '@nestjs/common';
import { Roles } from '../auth/decorators/roles.decorator';
import { RolesGuard } from '../auth/guards/roles.guard';
@Controller('users')
@UseGuards(RolesGuard)
export class UsersController {
@Get()
@Roles('admin', 'editor') // 需要 admin 或 editor 角色
findAll() {
// 只有拥有 admin 或 editor 角色的用户才能访问
}
@Delete(':id')
@Roles('admin') // 只有 admin 角色可以删除
remove() {
// 只有管理员可以删除用户
}
}
```
#### 方式二:使用权限装饰器(可扩展)
```typescript
// 可以创建 PermissionGuard 和 @Permissions() 装饰器
@Get()
@Permissions('user:read') // 需要 user:read 权限
findAll() {
// 只有拥有 user:read 权限的用户才能访问
}
```
### 5. **获取用户权限**
```typescript
// 在 AuthService 中
private async getUserPermissions(userId: number): Promise<string[]> {
const user = await this.usersService.findOne(userId);
if (!user) return [];
const permissions = new Set<string>();
// 遍历用户的所有角色
user.roles?.forEach((ur: any) => {
// 遍历角色的所有权限
ur.role.permissions?.forEach((rp: any) => {
permissions.add(rp.permission.code);
});
});
return Array.from(permissions);
// 返回: ['user:create', 'user:read', 'user:update', 'role:create', ...]
}
```
## 📊 RBAC 的优势
### 1. **灵活性**
- ✅ 一个用户可以有多个角色
- ✅ 一个角色可以有多个权限
- ✅ 权限可以动态分配和回收
### 2. **可维护性**
- ✅ 权限变更只需修改角色,不需要逐个修改用户
- ✅ 角色可以复用,减少重复配置
### 3. **可扩展性**
- ✅ 新增资源只需添加新的权限
- ✅ 新增角色只需组合现有权限
### 4. **安全性**
- ✅ 最小权限原则:用户只获得必要的权限
- ✅ 权限集中管理,便于审计
## 🎨 实际应用场景
### 场景 1内容管理系统
```
角色定义:
- 超级管理员:所有权限
- 内容管理员:文章 CRUD、评论管理
- 编辑:文章创建、编辑
- 作者:文章创建
- 访客:文章查看
权限示例:
- article:create
- article:read
- article:update
- article:delete
- comment:moderate
```
### 场景 2电商系统
```
角色定义:
- 平台管理员:所有权限
- 店铺管理员:店铺管理、订单管理
- 客服:订单查看、退款处理
- 财务:订单查看、财务报表
权限示例:
- order:create
- order:read
- order:update
- order:refund
- report:financial
```
## 🔐 项目中的权限控制实现
### 1. **JWT 认证**
用户登录后获得 JWT TokenToken 中包含用户 ID
### 2. **JwtAuthGuard**
验证 JWT Token提取用户信息
### 3. **RolesGuard**
检查用户是否拥有指定的角色
### 4. **权限获取**
登录时,系统会:
1. 查询用户的所有角色
2. 查询角色关联的所有权限
3. 合并所有权限并返回给前端
### 5. **前端权限控制**
前端可以根据返回的 `roles``permissions` 数组:
- 控制菜单显示
- 控制按钮显示
- 控制路由访问
## 📝 最佳实践
### 1. **权限命名规范**
```
格式resource:action
示例:
- user:create
- user:read
- user:update
- user:delete
- role:assign
- menu:manage
```
### 2. **角色命名规范**
```
使用有意义的英文代码:
- admin: 管理员
- editor: 编辑
- viewer: 查看者
- guest: 访客
```
### 3. **权限粒度**
- ✅ 不要过粗:避免一个权限包含太多操作
- ✅ 不要过细:避免权限过多难以管理
- ✅ 按业务模块划分user、role、menu、dict 等
### 4. **默认角色**
建议创建以下默认角色:
- **超级管理员**:拥有所有权限
- **普通用户**:基础查看权限
- **访客**:只读权限
## 🚀 扩展功能
### 1. **权限继承**
可以实现角色继承,子角色继承父角色的权限
### 2. **动态权限**
可以根据数据范围动态控制权限,如:
- 用户只能管理自己创建的订单
- 部门管理员只能管理本部门的用户
### 3. **权限缓存**
将用户权限缓存到 Redis提高性能
### 4. **权限审计**
记录权限变更日志,便于追溯
## 📖 总结
RBAC 权限控制通过 **用户 → 角色 → 权限** 的三层关系,实现了灵活、可维护的权限管理系统。在你的项目中:
1.**用户** 通过 `user_roles` 表关联 **角色**
2.**角色** 通过 `role_permissions` 表关联 **权限**
3.**权限**`resource` + `action` 组成
4. ✅ 使用 `@Roles()` 装饰器控制接口访问
5. ✅ 登录时返回用户的角色和权限列表
这样的设计既保证了安全性,又提供了良好的扩展性和可维护性!