|
|
|
|
# VBase 集成指南
|
|
|
|
|
|
|
|
|
|
## 1. 引入路由
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
import "github.com/veypi/vbase/api"
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
// 挂载 vbase 路由到 /api/vb
|
|
|
|
|
rootRouter.Extend("/api/vb", api.Router)
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 2. 配置权限中间件
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
import "github.com/veypi/vbase/api/middleware"
|
|
|
|
|
|
|
|
|
|
// 全局启用路由权限检查(推荐)
|
|
|
|
|
router.Use(middleware.Perm("your-domain"))
|
|
|
|
|
|
|
|
|
|
// 未配置的接口默认拒绝
|
|
|
|
|
// 无权限时返回 X-Required-URL 响应头
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 3. 注册路由权限
|
|
|
|
|
|
|
|
|
|
### 3.1 自动注册(推荐)
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
// 启动时自动扫描并注册所有路由
|
|
|
|
|
middleware.InitVBaseRoutePolicies()
|
|
|
|
|
|
|
|
|
|
// 首次启动后,在数据库中修改权限配置即可
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 3.2 手动注册
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
// 公开接口
|
|
|
|
|
middleware.RegisterRoutePolicy("myapp", "/api", "/public", "GET", "public", "read", true)
|
|
|
|
|
|
|
|
|
|
// 需要权限的接口
|
|
|
|
|
middleware.RegisterRoutePolicy("myapp", "/api", "/users", "GET", "user", "list", false)
|
|
|
|
|
middleware.RegisterRoutePolicy("myapp", "/api", "/users/{id}", "PATCH", "user", "update", false)
|
|
|
|
|
|
|
|
|
|
// 重新加载缓存
|
|
|
|
|
middleware.ReloadRoutePolicies()
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 4. 数据库配置权限
|
|
|
|
|
|
|
|
|
|
### 4.1 路由权限表 (route_policies)
|
|
|
|
|
|
|
|
|
|
| 字段 | 说明 | 示例 |
|
|
|
|
|
|------|------|------|
|
|
|
|
|
| domain | 领域标识 | "myapp" |
|
|
|
|
|
| prefix | 路由前缀 | "/api" |
|
|
|
|
|
| pattern | 路由模式 | "/users/{id}" |
|
|
|
|
|
| method | HTTP方法 | "GET" |
|
|
|
|
|
| resource | 资源类型 | "user" |
|
|
|
|
|
| action | 操作类型 | "read" |
|
|
|
|
|
| effect | 效果 | "allow"/"deny" |
|
|
|
|
|
| condition | 条件 | "owner"/"admin" |
|
|
|
|
|
| required_url | 申请地址 | "/apply-perm?r=user&a=read" |
|
|
|
|
|
| is_public | 是否公开 | true/false |
|
|
|
|
|
|
|
|
|
|
### 4.2 用户权限表 (policies)
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
-- 用户拥有 user:read 权限
|
|
|
|
|
INSERT INTO policies (code, resource, action, effect)
|
|
|
|
|
VALUES ('user-read', 'user', 'read', 'allow');
|
|
|
|
|
|
|
|
|
|
-- 关联到角色
|
|
|
|
|
INSERT INTO roles (code, name, policy_ids)
|
|
|
|
|
VALUES ('viewer', '查看者', 'policy-id-1,policy-id-2');
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 5. 在 Handler 中设置资源所有者
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
func getUser(x *vigo.X, req *GetUserReq) (*User, error) {
|
|
|
|
|
user := queryUser(req.ID)
|
|
|
|
|
|
|
|
|
|
// 设置所有者到上下文,用于 condition=owner 检查
|
|
|
|
|
x.Set("owner_id", user.ID)
|
|
|
|
|
|
|
|
|
|
return user, nil
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 6. 完整示例
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"github.com/veypi/vbase/api"
|
|
|
|
|
"github.com/veypi/vbase/api/middleware"
|
|
|
|
|
"github.com/veypi/vigo"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
r := vigo.NewRouter()
|
|
|
|
|
|
|
|
|
|
// 1. 挂载 vbase
|
|
|
|
|
r.Extend("/api/vb", api.Router)
|
|
|
|
|
|
|
|
|
|
// 2. 业务路由
|
|
|
|
|
api := r.SubRouter("/api/v1")
|
|
|
|
|
|
|
|
|
|
// 3. 启用权限检查
|
|
|
|
|
api.Use(middleware.AuthRequired())
|
|
|
|
|
api.Use(middleware.OrgContext())
|
|
|
|
|
api.Use(middleware.Perm("myapp"))
|
|
|
|
|
|
|
|
|
|
// 4. 注册权限(只需一次,后续在数据库中配置)
|
|
|
|
|
middleware.RegisterRoutePolicy("myapp", "/api/v1", "/projects", "GET", "project", "list", false)
|
|
|
|
|
middleware.RegisterRoutePolicy("myapp", "/api/v1", "/projects", "POST", "project", "create", false)
|
|
|
|
|
middleware.RegisterRoutePolicy("myapp", "/api/v1", "/projects/{id}", "GET", "project", "read", false)
|
|
|
|
|
middleware.RegisterRoutePolicy("myapp", "/api/v1", "/projects/{id}", "PATCH", "project", "update", false)
|
|
|
|
|
middleware.RegisterRoutePolicy("myapp", "/api/v1", "/projects/{id}", "DELETE", "project", "delete", false)
|
|
|
|
|
|
|
|
|
|
// 5. 无需在 handler 中加权限代码
|
|
|
|
|
api.Get("/projects", "项目列表", listProjects)
|
|
|
|
|
api.Post("/projects", "创建项目", createProject)
|
|
|
|
|
api.Get("/projects/{id}", "项目详情", getProject)
|
|
|
|
|
api.Patch("/projects/{id}", "更新项目", updateProject)
|
|
|
|
|
api.Delete("/projects/{id}", "删除项目", deleteProject)
|
|
|
|
|
|
|
|
|
|
vigo.Run(r)
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 7. 权限检查流程
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
请求 → AuthRequired(认证) → OrgContext(组织) → Perm(权限检查) → Handler
|
|
|
|
|
↓
|
|
|
|
|
查找 route_policies
|
|
|
|
|
↓
|
|
|
|
|
匹配 domain + method + path
|
|
|
|
|
↓
|
|
|
|
|
检查 resource:action 权限
|
|
|
|
|
↓
|
|
|
|
|
无权限 → 返回 X-Required-URL
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 8. 配置热更新
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
// 修改数据库后,调用 API 刷新缓存
|
|
|
|
|
middleware.ReloadRoutePolicies()
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
无需重启服务,权限配置实时生效。
|