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

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 权限检查流程
根据是否有项目上下文 (`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 │
└───────┘ └───────┘
```
### 3.2 决策规则
1. **Deny 优先**: 如果匹配到 Deny 策略,直接拒绝
2. **显式 Allow**: 必须匹配到 Allow 策略才允许
3. **默认拒绝**: 未匹配到任何策略时拒绝
4. **优先级**: 高优先级策略优先匹配
---
## 4. 使用指南
### 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 项目级权限检查
**场景**:在项目内操作资源
```go
// 检查用户在项目内是否有管理员权限
result, err := checker.Check(userID, "project-123", "member", "invite", nil)
// 结果取决于用户在 project-123 中的角色
// 项目所有者检查(快速路径)
// 如果 userID == org.OwnerID直接返回允许
// 普通成员检查
// 1. 查询 OrgMember 获取角色
// 2. 查询 Role 获取策略
// 3. 评估策略
```
### 4.3 完整示例:更新用户信息
```go
func UpdateUser(x *vigo.X, req *UpdateRequest) error {
userID := middleware.CurrentUser(x)
targetUserID := req.UserID
checker := service.NewPermissionChecker()
// 场景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,
})
if err != nil || !result.Allowed {
return vigo.ErrForbidden.WithString(result.Reason)
}
// 执行删除...
return nil
}
```
### 4.5 创建自定义策略
```go
// 项目级策略(需要关联到具体项目)
policy := &model.Policy{
Code: "custom:db:admin",
Name: "数据库管理员",
Description: "管理项目数据库",
Resource: "database",
Action: "*", // 所有操作
Effect: model.EffectAllow,
Condition: "", // 无条件限制
Scope: "project", // 项目级策略
OrgID: "project-123", // 所属项目
}
model.DB.Create(policy)
// 将策略添加到角色
role := &model.Role{
OrgID: "project-123",
Name: "DBAdmin",
PolicyIDs: "custom:db:admin",
}
model.DB.Create(role)
// 分配角色给用户
member := &model.OrgMember{
OrgID: "project-123",
UserID: "user-456",
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: "admin"
// 读取策略
SysPolicyPolicyRead = "sys:policy:read"
Resource: "policy"
Action: "read"
Condition: "org_member"
// 管理策略
SysPolicyPolicyManage = "sys:policy:manage"
Resource: "policy"
Action: "*"
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
```
---
## 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 BaaS 平台角色设计
VBase 作为 Supabase-like BaaS 平台,角色设计覆盖 **2C个人开发者****2B团队/企业** 场景:
#### 2C 个人开发者场景
```
个人项目角色体系:
├── owner (项目所有者)
│ └── 全部权限(可以删除项目)
└── developer (开发者)
└── 读写资源、调用 API
```
个人开发者通常自己就是项目所有者,不需要复杂的角色体系。
#### 2B 团队协作场景
```
团队项目角色体系:
├── owner (所有者)
│ └── 全部权限、可删除项目、管理账单
├── admin (管理员)
│ └── 管理成员、角色、资源设置
├── 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,
}
```
### 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 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 权限测试
```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 权限检查失败
**检查步骤:**
**平台级权限检查失败org_id 为空):**
1. 确认用户已登录
2. 确认操作的是自己的资源(检查 owner_id 条件)
3. 检查用户是否有平台级管理员权限
4. 检查默认个人策略是否生效
**项目级权限检查失败(有 org_id:**
1. 确认用户是项目成员OrgMember 状态为 active
2. 检查用户角色是否正确分配
3. 检查角色绑定的策略
4. 检查策略的 Effect 和 Condition
5. 确认资源所属的项目是否正确
**调试日志:**
```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 添加 BaaS 资源类型
**步骤1: 定义资源常量**
```go
// 在 policy.go 中添加资源常量
const (
ResourceUser = "user"
ResourceOrg = "org"
ResourceMember = "member"
ResourceDatabase = "database"
ResourceStorage = "storage"
ResourceFunction = "function"
ResourceAPIKey = "apikey"
ResourceCustom = "custom_resource" // 新增资源类型
)
```
**步骤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
err = model.DB.Where("org_id = ?", orgID).Find(&resources).Error
return resources, err
}
```
---
## 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)