You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OneAuth/doc/permission.md

606 lines
17 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# VBase 权限系统文档
## 1. 权限模型概述
VBase 是一个类似 **Supabase** 的 BaaS 平台,为 2C个人开发者和 2B团队/企业)用户提供后端资源托管服务。权限系统采用 **RBAC + ABAC** 混合模型,支持三级权限体系:
- **平台级 (Platform)**: 用户管理自己的账号和数据
- **项目级 (Project)**: 项目内的成员管理和资源控制
- **资源级 (Resource)**: 具体资源的读写操作
---
## 2. 核心概念
### 2.1 权限层级
```
┌─────────────────────────────────────────────────────────────┐
│ 平台级权限 (Platform) │
│ - 管理自己的用户信息 │
│ - 创建新项目 │
│ - 管理第三方账号绑定 │
│ - 访问被邀请的项目 │
└─────────────────────────────────────────────────────────────┘
▼ (进入项目上下文)
┌─────────────────────────────────────────────────────────────┐
│ 项目级权限 (Project) │
│ - 项目设置管理 (所有者/管理员) │
│ - 成员邀请和管理 │
│ - 资源创建和管理 │
│ - 查看项目统计信息 │
└─────────────────────────────────────────────────────────────┘
▼ (访问具体资源)
┌─────────────────────────────────────────────────────────────┐
│ 资源级权限 (Resource) │
│ - 数据库读写操作 │
│ - 存储文件上传下载 │
│ - 函数调用和管理 │
│ - API 密钥管理 │
└─────────────────────────────────────────────────────────────┘
```
### 2.2 实体关系
```
User (平台用户)
├── Platform Permission (平台级权限)
│ └── 默认: 管理自己的数据
└── OrgMember (项目成员关系)
├── Org/Project (项目)
│ ├── Resource (项目资源)
│ └── Resource (项目资源)
└── Role (项目角色)
└── Policy (策略)
```
### 2.3 使用场景示例
**场景1: 个人开发者 (2C)**
```
小明 (User)
├── 个人信息管理 (平台级)
├── 我的项目A (Org)
│ ├── 数据库资源
│ └── 存储资源
└── 我的项目B (Org)
└── ...
```
**场景2: 团队协作 (2B)**
```
CEO (User)
├── 拥有的项目: WebApp, MobileApp
└── 角色: 所有者 (Owner)
CTO (User)
├── 参与的项目: WebApp (Admin), MobileApp (Developer)
└── 角色: 管理员/开发者
员工A (User)
├── 参与的项目: WebApp (Developer)
└── 角色: 开发者
```
### 2.2 策略 (Policy)
策略是权限控制的最小单元,定义了对特定资源的操作权限。
**策略结构:**
```go
type Policy struct {
Code string // 策略编码,唯一标识
Name string // 策略名称
Description string // 策略描述
Resource string // 资源类型: user/org/member/policy/role/*
Action string // 操作: create/read/update/delete/*
Effect string // 效果: allow/deny
Condition string // 条件表达式
Priority int // 优先级: 数字越大优先级越高
IsSystem bool // 是否系统策略
}
```
**策略分类:**
**平台级策略** (无 org_id 上下文)
| 策略 | 资源 | 操作 | 效果 | 条件 | 说明 |
|------|------|------|------|------|------|
| user:read:own | user | read | allow | owner | 读取自己的用户信息 |
| user:update:own | user | update | allow | owner | 更新自己的用户信息 |
| binding:manage | binding | * | allow | - | 管理第三方账号绑定 |
| org:create | org | create | allow | - | 创建新项目 |
**项目级策略** (需要 org_id 上下文)
| 策略 | 资源 | 操作 | 效果 | 条件 | 说明 |
|------|------|------|------|------|------|
| org:admin | * | * | allow | org_owner | 项目所有者拥有所有权限 |
| org:update | org | update | allow | admin | 更新项目设置 |
| member:read | member | read | allow | member | 读取项目成员列表 |
| member:manage | member | * | allow | admin | 管理项目成员 |
| resource:create | resource | create | allow | developer | 创建项目资源 |
| resource:delete | resource | delete | allow | admin | 删除项目资源 |
### 2.4 角色 (Role)
角色是一组策略的集合,在项目级别定义。
**角色结构:**
```go
type Role struct {
ID string // 角色ID
OrgID string // 所属项目
Name string // 角色名称
Description string // 角色描述
PolicyIDs []string // 关联的策略ID列表
Scope string // 作用域: project/resource
IsSystem bool // 是否系统角色
}
```
**系统内置角色:**
| 角色 | 适用对象 | 权限范围 | 说明 |
|------|----------|----------|------|
| **owner** | 项目所有者 | 全部权限 | 项目的创建者,拥有所有权限,可删除项目 |
| **admin** | 管理员 | 项目级管理 | 管理项目设置、成员、资源,但不能删除项目 |
| **developer** | 开发者 | 资源级操作 | 创建和管理资源(数据库、存储、函数) |
| **viewer** | 访客 | 只读访问 | 只能查看项目和资源信息,不能修改 |
### 2.4 条件 (Condition)
条件用于实现 ABAC支持以下类型
| 条件 | 说明 | 使用场景 |
|------|------|----------|
| "" | 无条件,始终匹配 | 通用权限 |
| "owner" | 资源所有者 | 只能操作自己的数据 |
| "org_member" | 组织成员 | 组织内数据访问 |
| "org_owner" | 组织所有者 | 所有者权限判断 |
---
## 3. 权限检查流程
### 3.1 流程图
```
┌─────────────────┐
│ 请求进入 │
│ user, org, │
│ resource, action│
└────────┬────────┘
┌─────────────────┐ 命中 ┌─────────────────┐
│ 检查缓存 │────────────→│ 返回缓存结果 │
│ Redis │ │ allow/deny │
└────────┬────────┘ └─────────────────┘
│ 未命中
┌─────────────────┐
│ 1. 检查组织所有者 │────────┐
└────────┬────────┘ │
│ 是 │
▼ │
┌──────────┐ │
│ 返回 Allow│────────────┘
└──────────┘
│ 否
┌─────────────────┐
│ 2. 获取用户角色 │
│ 从 OrgMember │
│ 获取 role_ids │
└────────┬────────┘
┌─────────────────┐
│ 3. 获取角色策略 │
│ 解析所有策略 │
│ 去重合并 │
└────────┬────────┘
┌─────────────────┐
│ 4. 检查 Deny 策略│────────┐
│ 高优先级优先 │ │
└────────┬────────┘ │
│ 匹配 Deny │
▼ │
┌──────────┐ │
│返回 Deny │────────────┘
│ 缓存结果 │
└──────────┘
│ 无 Deny
┌─────────────────┐
│ 5. 检查 Allow 策略│────────┐
└────────┬────────┘ │
│ 匹配 Allow │
▼ │
┌──────────┐ │
│返回 Allow│────────────┘
│ 缓存结果 │
└──────────┘
│ 无 Allow
┌─────────────────┐
│ 6. 默认拒绝 │────────→ 返回 Deny
└─────────────────┘ 缓存结果
```
### 3.2 决策规则
1. **Deny 优先**: 如果匹配到 Deny 策略,直接拒绝
2. **显式 Allow**: 必须匹配到 Allow 策略才允许
3. **默认拒绝**: 未匹配到任何策略时拒绝
4. **优先级**: 高优先级策略优先匹配
---
## 4. 使用指南
### 4.1 检查权限
**代码示例:**
```go
import "github.com/veypi/vbase/internal/service"
func SomeHandler(x *vigo.X) error {
userID := middleware.CurrentUser(x)
orgID := middleware.CurrentOrg(x)
checker := service.NewPermissionChecker()
result, err := checker.Check(userID, orgID, "user", "update", map[string]any{
"owner_id": targetUserID,
})
if err != nil || !result.Allowed {
return vigo.ErrForbidden.WithString(result.Reason)
}
// 继续处理...
}
```
### 4.2 创建自定义策略
```go
policy := &model.Policy{
Code: "custom:resource:action",
Name: "自定义策略",
Description: "允许特定用户操作",
Resource: "resource_name",
Action: "action_name", // create/read/update/delete
Effect: model.EffectAllow,
Condition: "owner", // owner/org_member/空
Priority: 50,
}
model.DB.Create(policy)
```
### 4.3 创建角色并授权
```go
// 创建角色
role := &model.Role{
OrgID: orgID,
Name: "部门管理员",
Description: "管理部门成员",
PolicyIDs: "policy1,policy2,policy3",
}
model.DB.Create(role)
// 分配给用户
member := &model.OrgMember{
OrgID: orgID,
UserID: userID,
RoleIDs: role.ID,
}
model.DB.Create(member)
```
---
## 5. 系统内置策略
### 5.1 用户相关
```go
// 读取自己
SysPolicyUserReadOwn = "sys:user:read:own"
Resource: "user"
Action: "read"
Condition: "owner"
// 更新自己
SysPolicyUserUpdateOwn = "sys:user:update:own"
Resource: "user"
Action: "update"
Condition: "owner"
// 删除自己
SysPolicyUserDeleteOwn = "sys:user:delete:own"
Resource: "user"
Action: "delete"
Condition: "owner"
```
### 5.2 组织相关
```go
// 组织管理员
SysPolicyOrgAdmin = "sys:org:admin"
Resource: "*"
Action: "*"
Condition: "org_owner"
Priority: 100
// 读取组织
SysPolicyOrgRead = "sys:org:read"
Resource: "org"
Action: "read"
Condition: "org_member"
```
### 5.3 成员相关
```go
// 读取成员
SysPolicyMemberRead = "sys:member:read"
Resource: "member"
Action: "read"
Condition: "org_member"
// 管理成员
SysPolicyMemberManage = "sys:member:manage"
Resource: "member"
Action: "*"
Condition: ""
```
### 5.4 角色策略相关
```go
// 读取角色
SysPolicyRoleRead = "sys:role:read"
Resource: "role"
Action: "read"
Condition: "org_member"
// 管理角色
SysPolicyRoleManage = "sys:role:manage"
Resource: "role"
Action: "*"
Condition: ""
// 读取策略
SysPolicyPolicyRead = "sys:policy:read"
Resource: "policy"
Action: "read"
Condition: ""
// 管理策略
SysPolicyPolicyManage = "sys:policy:manage"
Resource: "policy"
Action: "*"
Condition: ""
```
---
## 6. 权限缓存
### 6.1 缓存机制
```
缓存键: perm:{user_id}:{org_id}:{resource}:{action}
TTL: 1分钟
值: "allow" 或 "deny"
```
### 6.2 缓存失效
以下操作会触发缓存清除:
- 用户角色变更
- 角色策略变更
- 策略内容变更
- 组织成员变更
```go
// 清除用户权限缓存
service.ClearUserPermissionCache(userID)
// 清除组织权限缓存
service.ClearOrgPermissionCache(orgID)
```
### 6.3 缓存命中率优化
- 权限变更频率低1分钟 TTL 平衡了性能和实时性
- 批量操作时建议先清除缓存,操作完成后统一刷新
---
## 7. 最佳实践
### 7.1 策略设计
1. **最小权限原则**: 只授予完成任务所需的最小权限
2. **职责分离**: 敏感操作需要多个角色共同完成
3. **策略命名规范**: `{resource}:{action}:{condition}`
### 7.2 角色设计
```
组织层级角色体系:
├── owner (所有者)
│ └── 全部权限
├── admin (管理员)
│ └── 管理成员、角色、策略
├── manager (部门经理)
│ └── 管理部门成员
└── member (普通成员)
└── 基础访问权限
```
### 7.3 权限检查位置
**Controller 层检查:**
```go
func Handler(x *vigo.X) error {
// 先检查权限
if !hasPermission(x, "resource", "action") {
return vigo.ErrForbidden
}
// 执行业务逻辑
}
```
**Service 层检查(数据级):**
```go
func UpdateUser(userID string, data map[string]any) error {
// 检查是否是本人或管理员
if !isOwner(userID) && !hasAdminRole() {
return ErrForbidden
}
// 执行更新
}
```
### 7.4 权限测试
```go
func TestPermissionCheck(t *testing.T) {
tests := []struct {
name string
userID string
orgID string
resource string
action string
data map[string]any
want bool
}{
{
name: "owner can update own profile",
userID: "user1",
orgID: "",
resource: "user",
action: "update",
data: map[string]any{"owner_id": "user1"},
want: true,
},
{
name: "user cannot update others profile",
userID: "user1",
orgID: "",
resource: "user",
action: "update",
data: map[string]any{"owner_id": "user2"},
want: false,
},
}
checker := service.NewPermissionChecker()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, _ := checker.Check(tt.userID, tt.orgID, tt.resource, tt.action, tt.data)
if result.Allowed != tt.want {
t.Errorf("Check() = %v, want %v", result.Allowed, tt.want)
}
})
}
}
```
---
## 8. 故障排查
### 8.1 权限检查失败
**检查步骤:**
1. 确认用户已登录
2. 确认用户是组织成员
3. 检查用户角色
4. 检查角色绑定的策略
5. 检查策略的 Effect 和 Condition
**调试日志:**
```go
// 开启调试日志
checker := service.NewPermissionChecker()
result, err := checker.Check(userID, orgID, resource, action, data)
log.Printf("Permission check: user=%s, resource=%s, action=%s, allowed=%v, reason=%s",
userID, resource, action, result.Allowed, result.Reason)
```
### 8.2 缓存问题
```bash
# 清除 Redis 权限缓存
redis-cli KEYS "perm:*" | xargs redis-cli DEL
# 或重启应用(开发环境)
```
### 8.3 权限不生效
1. 检查策略是否保存成功
2. 检查角色是否正确绑定策略
3. 检查用户是否正确分配角色
4. 检查缓存是否已清除
---
## 9. 扩展开发
### 9.1 添加自定义条件
```go
// 在 permission.go 中扩展 evaluateCondition
func (pc *PermissionChecker) evaluateCondition(p *model.Policy, userID, orgID string, resourceData map[string]any) bool {
switch p.Condition {
case "owner":
// 现有逻辑...
case "custom_condition":
// 自定义条件逻辑
return checkCustomCondition(userID, orgID, resourceData)
default:
return true
}
}
```
### 9.2 添加资源类型
```go
// 在 policy.go 中添加资源常量
const (
ResourceUser = "user"
ResourceOrg = "org"
ResourceMember = "member"
ResourceCustom = "custom_resource" // 新增
)
```
---
## 10. 参考
- [RBAC 模型](https://en.wikipedia.org/wiki/Role-based_access_control)
- [ABAC 模型](https://en.wikipedia.org/wiki/Attribute-based_access_control)
- [NIST RBAC 标准](https://csrc.nist.gov/projects/role-based-access-control)