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

999 lines
30 KiB
Markdown

2 weeks ago
# 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" | 资源所有者 | 只能操作自己的数据 |
2 weeks ago
| "org_member" | 项目成员 | 项目内数据访问 |
| "org_owner" | 项目所有者 | 项目所有者权限判断 |
2 weeks ago
---
## 3. 权限检查流程
2 weeks ago
### 3.1 权限检查流程
根据是否有项目上下文 (`org_id`),权限检查分为两种方式:
#### 流程 A: 平台级权限检查 (无项目上下文)
```
┌─────────────────────────────┐
│ 请求进入 (无 org_id) │
│ user, resource, action │
└────────────┬────────────────┘
┌─────────────────────────────┐ 命中 ┌─────────────────┐
│ 检查缓存 │────────────→│ 返回缓存结果 │
└────────────┬────────────────┘ └─────────────────┘
│ 未命中
┌─────────────────────────────┐
│ 1. 检查是否是资源所有者 │
│ owner_id == user_id │
└────────────┬────────────────┘
│ 是
┌──────────┐
│ 返回 Allow│
└──────────┘
│ 否
┌─────────────────────────────┐
│ 2. 加载平台级默认策略 │
│ personal:* 策略 │
└────────────┬────────────────┘
┌─────────────────────────────┐
│ 3. 评估策略 (Deny优先) │
└────────────┬────────────────┘
┌─────┴─────┐
▼ ▼
┌───────┐ ┌───────┐
│ Deny │ │ Allow │
└───────┘ └───────┘
```
#### 流程 B: 项目级权限检查 (有项目上下文)
```
┌─────────────────────────────┐
│ 请求进入 (有 org_id) │
│ user, org_id, resource... │
└────────────┬────────────────┘
┌─────────────────────────────┐ 命中 ┌─────────────────┐
│ 检查缓存 │────────────→│ 返回缓存结果 │
└────────────┬────────────────┘ └─────────────────┘
│ 未命中
┌─────────────────────────────┐
│ 1. 检查是否是项目所有者 │
│ org.owner_id == user_id │────────┐
└────────────┬────────────────┘ │
│ 是 │
▼ │
┌──────────┐ │
│ 返回 Allow│───────────────────┘
└──────────┘
│ 否
┌─────────────────────────────┐
│ 2. 获取用户在项目的角色 │
│ 从 OrgMember 表查询 │
└────────────┬────────────────┘
┌─────────────────────────────┐
│ 3. 获取角色关联的策略 │
└────────────┬────────────────┘
┌─────────────────────────────┐
│ 4. 评估策略 (Deny优先) │
│ Deny策略 → Allow策略 │
└────────────┬────────────────┘
┌─────┴─────┐
▼ ▼
┌───────┐ ┌───────┐
│ Deny │ │ Allow │
└───────┘ └───────┘
2 weeks ago
```
### 3.2 决策规则
1. **Deny 优先**: 如果匹配到 Deny 策略,直接拒绝
2. **显式 Allow**: 必须匹配到 Allow 策略才允许
3. **默认拒绝**: 未匹配到任何策略时拒绝
4. **优先级**: 高优先级策略优先匹配
---
## 4. 使用指南
2 weeks ago
### 4.1 平台级权限检查
**场景**:用户管理自己的账号、创建新项目
```go
// 检查用户是否可以更新自己的信息
// orgID 传空字符串,表示平台级检查
result, err := checker.Check(userID, "", "user", "update", map[string]any{
"owner_id": userID, // 传入自己的ID
})
// 结果:允许(满足 owner 条件)
// 检查用户是否可以创建新项目
result, err := checker.Check(userID, "", "org", "create", nil)
// 结果:允许(平台级默认策略允许创建项目)
// 检查用户是否可以更新其他用户信息
result, err := checker.Check(userID, "", "user", "update", map[string]any{
"owner_id": otherUserID, // 传入他人ID
})
// 结果:拒绝(不满足 owner 条件)
```
### 4.2 项目级权限检查
2 weeks ago
2 weeks ago
**场景**:在项目内操作资源
2 weeks ago
```go
2 weeks ago
// 检查用户在项目内是否有管理员权限
result, err := checker.Check(userID, "project-123", "member", "invite", nil)
// 结果取决于用户在 project-123 中的角色
// 项目所有者检查(快速路径)
// 如果 userID == org.OwnerID直接返回允许
// 普通成员检查
// 1. 查询 OrgMember 获取角色
// 2. 查询 Role 获取策略
// 3. 评估策略
```
### 4.3 完整示例:更新用户信息
2 weeks ago
2 weeks ago
```go
func UpdateUser(x *vigo.X, req *UpdateRequest) error {
2 weeks ago
userID := middleware.CurrentUser(x)
2 weeks ago
targetUserID := req.UserID
2 weeks ago
checker := service.NewPermissionChecker()
2 weeks ago
// 场景1: 更新自己的信息(平台级)
if targetUserID == userID {
result, err := checker.Check(userID, "", "user", "update", map[string]any{
"owner_id": userID,
})
if err != nil || !result.Allowed {
return vigo.ErrForbidden.WithString(result.Reason)
}
// 执行更新...
return nil
}
// 场景2: 管理员更新其他用户信息(需要平台级管理员权限)
result, err := checker.Check(userID, "", "user", "update", nil)
if err != nil || !result.Allowed {
return vigo.ErrForbidden.WithString("only admin can update other users")
}
// 执行更新...
return nil
}
```
### 4.4 完整示例:项目内操作
```go
func DeleteProjectResource(x *vigo.X, req *DeleteResourceRequest) error {
userID := middleware.CurrentUser(x)
orgID := middleware.CurrentOrg(x) // 从请求头 X-Org-ID 获取
if orgID == "" {
return vigo.ErrArgInvalid.WithString("org_id required")
}
checker := service.NewPermissionChecker()
// 检查用户在项目内是否有删除资源的权限
result, err := checker.Check(userID, orgID, "resource", "delete", map[string]any{
"resource_id": req.ResourceID,
2 weeks ago
})
if err != nil || !result.Allowed {
return vigo.ErrForbidden.WithString(result.Reason)
}
2 weeks ago
// 执行删除...
return nil
2 weeks ago
}
```
2 weeks ago
### 4.5 创建自定义策略
2 weeks ago
```go
2 weeks ago
// 项目级策略(需要关联到具体项目)
2 weeks ago
policy := &model.Policy{
2 weeks ago
Code: "custom:db:admin",
Name: "数据库管理员",
Description: "管理项目数据库",
Resource: "database",
Action: "*", // 所有操作
2 weeks ago
Effect: model.EffectAllow,
2 weeks ago
Condition: "", // 无条件限制
Scope: "project", // 项目级策略
OrgID: "project-123", // 所属项目
2 weeks ago
}
1 week ago
cfg.DB().Create(policy)
2 weeks ago
2 weeks ago
// 将策略添加到角色
1 week ago
role := &models.Role{
2 weeks ago
OrgID: "project-123",
Name: "DBAdmin",
PolicyIDs: "custom:db:admin",
2 weeks ago
}
1 week ago
cfg.DB().Create(role)
2 weeks ago
2 weeks ago
// 分配角色给用户
1 week ago
member := &models.OrgMember{
2 weeks ago
OrgID: "project-123",
UserID: "user-456",
2 weeks ago
RoleIDs: role.ID,
}
1 week ago
cfg.DB().Create(member)
2 weeks ago
```
---
## 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: "*"
2 weeks ago
Condition: "admin"
2 weeks ago
// 读取策略
SysPolicyPolicyRead = "sys:policy:read"
Resource: "policy"
Action: "read"
2 weeks ago
Condition: "org_member"
2 weeks ago
// 管理策略
SysPolicyPolicyManage = "sys:policy:manage"
Resource: "policy"
Action: "*"
2 weeks ago
Condition: "admin"
```
### 5.5 资源级策略BaaS 核心资源)
**数据库资源 (database)**
```go
// 查询数据库
SysPolicyDBRead = "sys:db:read"
Resource: "database"
Action: "read"
Condition: "org_member"
// 管理数据库(创建表、修改结构)
SysPolicyDBManage = "sys:db:manage"
Resource: "database"
Action: "*"
Condition: "developer"
```
**存储资源 (storage)**
```go
// 读取存储文件
SysPolicyStorageRead = "sys:storage:read"
Resource: "storage"
Action: "read"
Condition: "org_member"
// 上传/删除文件
SysPolicyStorageWrite = "sys:storage:write"
Resource: "storage"
Action: "create,update,delete"
Condition: "developer"
// 管理存储桶
SysPolicyStorageAdmin = "sys:storage:admin"
Resource: "storage"
Action: "*"
Condition: "admin"
```
**函数资源 (function)**
```go
// 调用函数
SysPolicyFunctionCall = "sys:function:call"
Resource: "function"
Action: "call"
Condition: "org_member"
// 管理函数(部署、删除)
SysPolicyFunctionManage = "sys:function:manage"
Resource: "function"
Action: "create,update,delete"
Condition: "developer"
```
**API 密钥管理 (apikey)**
```go
// 读取 API 密钥(只能读取自己创建的密钥)
SysPolicyAPIKeyRead = "sys:apikey:read"
Resource: "apikey"
Action: "read"
Condition: "owner"
// 管理 API 密钥
SysPolicyAPIKeyManage = "sys:apikey:manage"
Resource: "apikey"
Action: "*"
Condition: "developer"
```
### 5.6 平台超级管理员策略
```go
// 超级管理员 - 拥有所有权限
SysPolicySuperAdmin = "sys:super:admin"
Resource: "*"
Action: "*"
Condition: "is_super_admin"
Priority: 999
2 weeks ago
```
---
## 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}`
2 weeks ago
### 7.2 BaaS 平台角色设计
2 weeks ago
2 weeks ago
VBase 作为 Supabase-like BaaS 平台,角色设计覆盖 **2C个人开发者****2B团队/企业** 场景:
#### 2C 个人开发者场景
```
个人项目角色体系:
├── owner (项目所有者)
│ └── 全部权限(可以删除项目)
└── developer (开发者)
└── 读写资源、调用 API
2 weeks ago
```
2 weeks ago
个人开发者通常自己就是项目所有者,不需要复杂的角色体系。
#### 2B 团队协作场景
```
团队项目角色体系:
2 weeks ago
├── owner (所有者)
2 weeks ago
│ └── 全部权限、可删除项目、管理账单
2 weeks ago
├── admin (管理员)
2 weeks ago
│ └── 管理成员、角色、资源设置
├── developer (开发者)
│ ├── 数据库: 创建表、查询、修改结构
│ ├── 存储: 上传/下载文件、管理存储桶
│ ├── 函数: 部署、调用、删除函数
│ └── API密钥: 创建、管理
├── viewer (访客/只读)
│ └── 查看数据、只读访问
└── auditor (审计员 - 可选)
└── 查看日志、审计记录
```
#### 角色权限对照表
| 角色 | 成员管理 | 资源管理 | 数据读写 | API密钥 | 项目设置 |
|------|----------|----------|----------|---------|----------|
| **owner** | ✓ | ✓ | ✓ | ✓ | ✓ |
| **admin** | ✓ | ✓ | ✓ | ✓ | ✗ |
| **developer** | ✗ | ✓ | ✓ | ✓ | ✗ |
| **viewer** | ✗ | ✗ | 只读 | ✗ | ✗ |
#### 系统角色配置示例
```go
// Owner 角色 - 绑定所有权限
var RoleOwner = model.Role{
Name: "owner",
Description: "项目所有者",
PolicyIDs: "sys:org:admin,sys:member:manage,sys:role:manage,sys:policy:manage",
IsSystem: true,
}
// Admin 角色 - 管理权限
var RoleAdmin = model.Role{
Name: "admin",
Description: "项目管理员",
PolicyIDs: "sys:member:manage,sys:role:read,sys:db:manage,sys:storage:admin,sys:function:manage",
IsSystem: true,
}
// Developer 角色 - 开发权限
var RoleDeveloper = model.Role{
Name: "developer",
Description: "开发者",
PolicyIDs: "sys:db:manage,sys:storage:write,sys:function:manage,sys:apikey:manage",
IsSystem: true,
}
// Viewer 角色 - 只读权限
var RoleViewer = model.Role{
Name: "viewer",
Description: "访客",
PolicyIDs: "sys:org:read,sys:db:read,sys:storage:read,sys:function:call",
IsSystem: true,
}
2 weeks ago
```
### 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
}
// 执行更新
}
```
2 weeks ago
### 7.4 BaaS 平台权限场景示例
**场景1: 个人开发者创建项目**
```go
// 小明是个人开发者,注册后创建项目
// 1. 创建项目(平台级权限检查)
result, _ := checker.Check("xiaoming_user_id", "", "org", "create", nil)
// 结果: 允许personal:org:create 策略)
// 2. 小明成为项目所有者
// org.owner_id = "xiaoming_user_id"
// 3. 小明在项目内操作数据库(项目级权限)
result, _ = checker.Check("xiaoming_user_id", "my-project", "database", "create", nil)
// 结果: 允许(小明是项目所有者)
```
**场景2: 团队协作开发**
```go
// CEO 创建 WebApp 项目,邀请 CTO 为管理员,员工为开发者
// - CEO: owner
// - CTO: admin
// - 员工A: developer
// - 外包人员: viewer
// CTO 邀请成员(有 member:manage 权限)
result, _ := checker.Check("cto_user_id", "webapp-project", "member", "create", nil)
// 结果: 允许admin 角色有 member:manage 策略)
// 员工A 创建数据库表(有 db:manage 权限)
result, _ = checker.Check("employee_a_id", "webapp-project", "database", "create", nil)
// 结果: 允许developer 角色有 db:manage 策略)
// 外包人员 尝试删除表viewer 没有 delete 权限)
result, _ = checker.Check("contractor_id", "webapp-project", "database", "delete", nil)
// 结果: 拒绝viewer 只有 db:read 权限)
```
**场景3: API 密钥访问控制**
```go
// 开发者创建 API 密钥用于后端服务
// 只能查看自己创建的密钥
result, _ := checker.Check("developer_id", "project-123", "apikey", "read", map[string]any{
"owner_id": "developer_id",
})
// 结果: 允许(满足 owner 条件)
// 尝试查看他人创建的密钥
result, _ = checker.Check("developer_id", "project-123", "apikey", "read", map[string]any{
"owner_id": "other_developer_id",
})
// 结果: 拒绝(不满足 owner 条件)
```
**场景4: 跨项目资源访问**
```go
// 用户小明在 project-A 是开发者,在 project-B 是访客
// 在 project-A 上传文件
result, _ := checker.Check("xiaoming_id", "project-A", "storage", "create", nil)
// 结果: 允许developer 角色有 storage:write 权限)
// 在 project-B 上传文件
result, _ = checker.Check("xiaoming_id", "project-B", "storage", "create", nil)
// 结果: 拒绝viewer 角色只有 storage:read 权限)
```
### 7.5 权限测试
2 weeks ago
```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 权限检查失败
**检查步骤:**
2 weeks ago
**平台级权限检查失败org_id 为空):**
2 weeks ago
1. 确认用户已登录
2 weeks ago
2. 确认操作的是自己的资源(检查 owner_id 条件)
3. 检查用户是否有平台级管理员权限
4. 检查默认个人策略是否生效
**项目级权限检查失败(有 org_id:**
1. 确认用户是项目成员OrgMember 状态为 active
2. 检查用户角色是否正确分配
3. 检查角色绑定的策略
4. 检查策略的 Effect 和 Condition
5. 确认资源所属的项目是否正确
2 weeks ago
**调试日志:**
```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
}
}
```
2 weeks ago
### 9.2 添加 BaaS 资源类型
**步骤1: 定义资源常量**
2 weeks ago
```go
// 在 policy.go 中添加资源常量
const (
2 weeks ago
ResourceUser = "user"
ResourceOrg = "org"
ResourceMember = "member"
ResourceDatabase = "database"
ResourceStorage = "storage"
ResourceFunction = "function"
ResourceAPIKey = "apikey"
ResourceCustom = "custom_resource" // 新增资源类型
2 weeks ago
)
```
2 weeks ago
**步骤2: 创建资源级策略**
```go
// 为新增资源创建策略
func (pc *PermissionChecker) getCustomResourcePolicies() []model.Policy {
return []model.Policy{
{
Code: "custom:read",
Name: "读取自定义资源",
Resource: ResourceCustom,
Action: "read",
Effect: model.EffectAllow,
Condition: "org_member",
},
{
Code: "custom:manage",
Name: "管理自定义资源",
Resource: ResourceCustom,
Action: "create,update,delete",
Effect: model.EffectAllow,
Condition: "developer",
},
}
}
```
**步骤3: 在角色中使用**
```go
// 创建新角色使用自定义策略
customRole := &model.Role{
OrgID: orgID,
Name: "custom_manager",
Description: "自定义资源管理员",
PolicyIDs: "custom:read,custom:manage",
Scope: "resource",
}
```
### 9.3 多租户资源隔离
在 BaaS 平台中,资源需要严格的项目隔离:
```go
// 查询时自动添加 org_id 过滤
func ListResources(userID, orgID string) ([]Resource, error) {
// 检查用户在项目中的权限
checker := service.NewPermissionChecker()
result, err := checker.Check(userID, orgID, "custom_resource", "read", nil)
if err != nil || !result.Allowed {
return nil, vigo.ErrForbidden
}
// 查询该项目的资源(自动隔离)
var resources []Resource
1 week ago
err = cfg.DB().Where("org_id = ?", orgID).Find(&resources).Error
2 weeks ago
return resources, err
}
```
2 weeks ago
---
## 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)