|
|
# VBase 集成文档
|
|
|
|
|
|
本文档介绍如何将 VBase 集成到您的 Golang (Vigo) 项目中,快速实现用户管理、权限控制和组织架构功能。
|
|
|
|
|
|
## 1. 快速集成 (Quick Start)
|
|
|
|
|
|
集成 VBase 仅需简单几步:
|
|
|
|
|
|
### 1.1 引入依赖
|
|
|
|
|
|
在您的项目中引入 VBase:
|
|
|
|
|
|
```go
|
|
|
import "github.com/veypi/vbase"
|
|
|
```
|
|
|
|
|
|
### 1.2 挂载路由
|
|
|
|
|
|
在您的项目根路由初始化处,挂载 VBase 路由:
|
|
|
|
|
|
```go
|
|
|
// 您的项目初始化代码
|
|
|
func init() {
|
|
|
// 挂载 vbase 路由到 /vbase 路径下
|
|
|
// 这样 vbase 的 API 将可以通过 /vb/api/auth/login 等访问
|
|
|
MyRouter.Extend("/vb", vbase.Router)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 1.3 配置数据库
|
|
|
|
|
|
确保您的项目已经配置了 GORM 数据库连接,VBase 将复用该连接。
|
|
|
|
|
|
```go
|
|
|
// VBase 会自动读取您的配置,前提是您使用了兼容的配置结构或手动设置
|
|
|
vbase.Config.SetDB(yourDB)
|
|
|
// 或者直接集成到您的项目配置中,由vigo.Flags 自动加载
|
|
|
type AppConfig struct {
|
|
|
Vbase any
|
|
|
}
|
|
|
var Config = *AppConfig{
|
|
|
Vbase: vbase.Config,
|
|
|
}
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 2. 详细集成方案
|
|
|
|
|
|
### 2.1 路由集成
|
|
|
|
|
|
VBase 提供了一个标准的 `vigo.Router` 实例,包含所有用户、组织、权限相关的 API。
|
|
|
|
|
|
```go
|
|
|
package main
|
|
|
|
|
|
import (
|
|
|
"github.com/veypi/vbase"
|
|
|
"github.com/veypi/vigo"
|
|
|
)
|
|
|
|
|
|
var Router = vigo.NewRouter()
|
|
|
|
|
|
func init() {
|
|
|
// 1. 挂载 VBase 路由
|
|
|
// 建议挂载在独立的前缀下,避免路由冲突
|
|
|
Router.Extend("/vb", vbase.Router)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.2 权限系统集成
|
|
|
|
|
|
VBase 提供了强大的 RBAC (基于角色的访问控制) 权限系统。
|
|
|
|
|
|
#### 2.2.1 初始化应用权限
|
|
|
|
|
|
在您的应用中,使用 `vbase.Auth.New` 创建应用专属的权限实例。
|
|
|
|
|
|
```go
|
|
|
import (
|
|
|
"github.com/veypi/vbase"
|
|
|
"github.com/veypi/vbase/models"
|
|
|
)
|
|
|
|
|
|
// 定义您的应用权限实例
|
|
|
var AppAuth = vbase.Auth.New("my_app", models.AppConfig{
|
|
|
Name: "My Application",
|
|
|
Description: "我的应用描述",
|
|
|
// 定义应用的默认角色
|
|
|
DefaultRoles: []models.RoleDefinition{
|
|
|
{
|
|
|
Code: "admin",
|
|
|
Name: "管理员",
|
|
|
Policies: []string{"*:*"}, // 拥有所有权限
|
|
|
},
|
|
|
{
|
|
|
Code: "editor",
|
|
|
Name: "编辑",
|
|
|
Policies: []string{"article:create", "article:update"},
|
|
|
},
|
|
|
},
|
|
|
})
|
|
|
```
|
|
|
|
|
|
#### 2.2.2 使用权限中间件
|
|
|
|
|
|
使用 `vbase.AuthMiddleware` 进行认证,并结合 `AppAuth.Perm` 进行权限检查。
|
|
|
|
|
|
```go
|
|
|
func init() {
|
|
|
// 1. 全局认证中间件 (解析 Token, 注入 user_id, org_id)
|
|
|
Router.Use(vbase.AuthMiddleware())
|
|
|
Router.Get("/info", "获取app信息", vigo.SkipBefore, getInfo)
|
|
|
// 2. 路由权限控制
|
|
|
// 检查 "article:create" 权限
|
|
|
Router.Post("/articles", "发布文章", AppAuth.Perm("article:create"), createArticle)
|
|
|
|
|
|
// 检查资源所有权 (确保用户只能修改自己的文章)
|
|
|
// 检查 "article:update" 权限,且文章的 owner_id 必须等于当前用户 ID
|
|
|
Router.Patch("/articles/{id}", "更新文章", AppAuth.PermWithOwner("article:update", "id"), updateArticle)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.3 配置管理
|
|
|
|
|
|
VBase 允许自定义部分配置。
|
|
|
|
|
|
```go
|
|
|
import "github.com/veypi/vbase"
|
|
|
|
|
|
func main() {
|
|
|
// 获取配置单例
|
|
|
cfg := vbase.Config
|
|
|
|
|
|
// 启用调试模式
|
|
|
cfg.Debug = true
|
|
|
|
|
|
// 设置 JWT 密钥 (建议从环境变量读取)
|
|
|
cfg.JwtSecret = "your-secret-key"
|
|
|
|
|
|
// 自定义短信服务提供商 (可选)
|
|
|
// vbase.Config.SetSmsProvider(...)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.4 上下文使用
|
|
|
|
|
|
通过 `vbase.AuthMiddleware` 认证后,您可以在 Handler 中通过 `*vigo.X` 获取用户信息。
|
|
|
|
|
|
```go
|
|
|
func MyHandler(x *vigo.X) error {
|
|
|
// 获取当前用户 ID
|
|
|
userID := x.Get("user_id").(string)
|
|
|
|
|
|
// 获取当前组织 ID (如果有)
|
|
|
orgID := x.Get("org_id").(string)
|
|
|
|
|
|
// ... 业务逻辑
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.5 权限管理高级用法
|
|
|
|
|
|
`AppAuth` 实例提供了丰富的接口来管理和检查权限。
|
|
|
|
|
|
#### 2.5.1 复杂权限检查中间件
|
|
|
|
|
|
除了基础的 `Perm` 和 `PermWithOwner`,还支持复合权限检查:
|
|
|
|
|
|
```go
|
|
|
// 要求同时拥有 user:read 和 order:read 权限
|
|
|
Router.Get("/stats", "统计数据", AppAuth.PermAll([]string{"user:read", "order:read"}), getStats)
|
|
|
|
|
|
// 只要拥有 user:read 或 user:admin 其中之一即可
|
|
|
Router.Get("/users", "用户列表", AppAuth.PermAny([]string{"user:read", "user:admin"}), listUsers)
|
|
|
```
|
|
|
|
|
|
#### 2.5.2 代码中动态检查权限
|
|
|
|
|
|
有时需要在 Handler 内部根据业务逻辑进行动态鉴权:
|
|
|
|
|
|
```go
|
|
|
func someHandler(x *vigo.X) error {
|
|
|
userID := x.Get("user_id").(string)
|
|
|
orgID := x.Get("org_id").(string)
|
|
|
|
|
|
// 检查是否有 "report:export" 权限
|
|
|
// 注意:resourceID 为空时检查通用权限,指定 resourceID 时检查特定资源权限
|
|
|
allowed, err := AppAuth.CheckPermission(x.Context(), userID, orgID, "report:export", "")
|
|
|
|
|
|
if err != nil || !allowed {
|
|
|
return vigo.ErrForbidden
|
|
|
}
|
|
|
|
|
|
// ...
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 2.5.3 授予和撤销角色
|
|
|
|
|
|
您可以在业务逻辑中动态授予或撤销用户角色。
|
|
|
**注意**:`orgID` 可以为空字符串,表示授予系统级(全局)角色。
|
|
|
|
|
|
```go
|
|
|
// 授予用户 "editor" 角色 (在指定组织下)
|
|
|
err := AppAuth.GrantRole(ctx, targetUserID, orgID, "editor")
|
|
|
|
|
|
// 撤销角色
|
|
|
err := AppAuth.RevokeRole(ctx, targetUserID, orgID, "editor")
|
|
|
```
|
|
|
|
|
|
#### 2.5.4 细粒度资源授权
|
|
|
|
|
|
如果角色机制不够灵活,可以直接授予用户对特定资源的权限:
|
|
|
|
|
|
```go
|
|
|
// 授予用户对 ID 为 "123" 的文章的 "read" 权限
|
|
|
err := AppAuth.GrantResourcePerm(ctx, targetUserID, orgID, "article:read", "123")
|
|
|
|
|
|
// 撤销资源权限
|
|
|
err := AppAuth.RevokeResourcePerm(ctx, targetUserID, orgID, "article:read", "123")
|
|
|
```
|
|
|
|
|
|
#### 2.5.5 检查资源权限
|
|
|
|
|
|
授予了细粒度资源权限后,可以通过以下两种方式进行检查:
|
|
|
|
|
|
1. **使用中间件 (推荐)**
|
|
|
|
|
|
`PermOnResource` 中间件会自动从路径参数或查询参数中获取资源ID,并检查用户是否有权访问该特定资源。
|
|
|
|
|
|
```go
|
|
|
// 自动从路径参数 "id" 获取资源ID (如 /articles/123)
|
|
|
// 如果用户拥有 "article:read" 角色权限,或者被单独授予了对 "123" 的 "article:read" 权限,均可通过检查
|
|
|
Router.Get("/articles/{id}", "获取文章", AppAuth.PermOnResource("article:read", "id"), getArticle)
|
|
|
```
|
|
|
|
|
|
2. **手动检查**
|
|
|
|
|
|
在 Handler 中手动调用 `CheckPermission`。
|
|
|
|
|
|
```go
|
|
|
func getArticle(x *vigo.X) error {
|
|
|
articleID := x.PathParams.Get("id")
|
|
|
userID := x.Get("user_id").(string)
|
|
|
orgID := x.Get("org_id").(string)
|
|
|
|
|
|
// 检查权限
|
|
|
allowed, err := AppAuth.CheckPermission(x.Context(), userID, orgID, "article:read", articleID)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
if !allowed {
|
|
|
return vigo.ErrForbidden
|
|
|
}
|
|
|
|
|
|
// ...
|
|
|
}
|
|
|
```
|
|
|
|