# VBase 开发者使用手册 ## 架构概述 ``` ┌─────────────────────────────────────────────────────────────┐ │ vbase/Auth 包 │ │ ├─ New(appKey, config) - 创建权限管理实例 │ │ ├─ Init() - 启动时检查冲突并同步数据库 │ │ └─ Auth 接口 - 权限检查和管理方法 │ └─────────────────────────────────────────────────────────────┘ │ ├─────────────────────┼─────────────────────┐ ▼ ▼ ▼ 注册权限配置 接口权限检查 编程式授权 (代码中声明) (中间件使用) (运行时调用) ``` ## 快速开始 ```go package main import ( "github.com/veypi/vbase" "github.com/veypi/vbase/api" "github.com/veypi/vigo" ) // 全局权限管理实例 crmAuth := vbase.Auth.New("crm", vbase.AppConfig{ Name: "客户关系管理", Description: "CRM系统", }) func main() { r := vigo.NewRouter() // 1. 挂载 VBase 基础设施 r.Extend("/api/vb", api.Router) // 2. 程序启动时初始化所有权限配置 if err := vbase.Auth.Init(); err != nil { log.Fatal("权限初始化失败:", err) } // 3. 创建业务路由 crm := r.SubRouter("/api/crm") crm.Use(middleware.AuthRequired()) crm.Use(middleware.OrgContext()) // 4. 使用 crmAuth 配置接口权限 crm.Get("/customers", crmAuth.Perm("customer", "list"), "客户列表", listCustomers) crm.Post("/customers", crmAuth.Perm("customer", "create"), "创建客户", createCustomer) crm.Get("/customers/{id}", crmAuth.Perm("customer", "read"), "客户详情", getCustomer) crm.Patch("/customers/{id}", crmAuth.Perm("customer", "update"), "更新客户", updateCustomer) crm.Delete("/customers/{id}", crmAuth.Perm("customer", "delete"), "删除客户", deleteCustomer) // 5. 资源所有者权限 crm.Patch("/customers/{id}/private", crmAuth.PermWithOwner("customer", "update", "owner_id"), "仅限所有者", privateUpdate) vigo.Run(r) } ``` --- ## 1. 权限管理包 vbase/Auth ### 1.1 包结构 ```go package auth // Auth 权限管理接口 type Auth interface { // ========== 中间件生成 ========== // 基础权限检查 Perm(resource, action string) func(*vigo.X) error // 资源所有者权限 PermWithOwner(resource, action, ownerKey string) func(*vigo.X) error // 满足任一权限 PermAny(permissions [][2]string) func(*vigo.X) error // 满足所有权限 PermAll(permissions [][2]string) func(*vigo.X) error // ========== 权限管理 ========== // 授予角色 GrantRole(ctx context.Context, req GrantRoleRequest) error // 撤销角色 RevokeRole(ctx context.Context, userID, orgID, roleCode string) error // 授予特定资源权限 GrantResourcePerm(ctx context.Context, req GrantResourcePermRequest) error // 撤销特定资源权限 RevokeResourcePerm(ctx context.Context, userID, orgID, resource, resourceID string) error // 撤销用户所有权限 RevokeAll(ctx context.Context, userID, orgID string) error // ========== 权限查询 ========== // 检查权限 CheckPermission(ctx context.Context, req CheckPermRequest) (bool, error) // 列出用户权限 ListUserPermissions(ctx context.Context, userID, orgID string) ([]UserPermission, error) // 列出资源授权用户 ListResourceUsers(ctx context.Context, orgID, resource, resourceID string) ([]ResourceUser, error) } // 全局 Auth 工厂 var Auth = &authFactory{} type authFactory struct { apps map[string]*appAuth // appKey -> auth实例 } // New 创建权限管理实例(注册应用) func (f *authFactory) New(appKey string, config AppConfig) Auth // Init 初始化所有注册的权限配置 // - 检查不同 app 之间是否有冲突 // - 同步 Policy 到数据库 // - 建立路由匹配缓存 func (f *authFactory) Init() error ``` ### 1.2 使用流程 ```go // 阶段1:程序初始化(全局变量/ init 函数) package main // CRM 模块权限 crmAuth := vbase.Auth.New("crm", vbase.AppConfig{ Name: "客户关系管理", DefaultRoles: []RoleDefinition{ {Code: "admin", Name: "管理员", Policies: []string{"*:*"}}, {Code: "sales", Name: "销售", Policies: []string{"customer:*", "order:read"}}, }, }) // ERP 模块权限 erpAuth := vbase.Auth.New("erp", vbase.AppConfig{ Name: "企业资源计划", DefaultRoles: []RoleDefinition{ {Code: "admin", Name: "管理员", Policies: []string{"*:*"}}, {Code: "buyer", Name: "采购", Policies: []string{"supplier:read", "purchase:*"}}, }, }) func main() { // 阶段2:程序启动时初始化 if err := vbase.Auth.Init(); err != nil { log.Fatal(err) } // 阶段3:运行时使用 // crmAuth.Perm(...) // erpAuth.GrantRole(...) } ``` --- ## 2. AppConfig 配置 ```go type AppConfig struct { Name string // 应用名称 Description string // 应用描述 DefaultRoles []RoleDefinition // 预设角色 } type RoleDefinition struct { Code string // 角色代码: admin/manager/sales/viewer Name string // 角色名称 Policies []string // 权限列表: ["customer:read", "customer:create", "*:*"] } ``` ### 多模块隔离示例 ```go // 模块1:CRM crmAuth := vbase.Auth.New("crm", vbase.AppConfig{ Name: "客户关系管理", DefaultRoles: []vbase.RoleDefinition{ {Code: "admin", Name: "管理员", Policies: []string{"customer:*", "contract:*"}}, {Code: "sales", Name: "销售", Policies: []string{"customer:read", "customer:create", "customer:update"}}, }, }) // 模块2:ERP(资源名可以重复,通过 appKey 隔离) erpAuth := vbase.Auth.New("erp", vbase.AppConfig{ Name: "企业资源计划", DefaultRoles: []vbase.RoleDefinition{ {Code: "admin", Name: "管理员", Policies: []string{"customer:*", "supplier:*"}}, // erp:customer:read 和 crm:customer:read 是两个不同权限 }, }) // 启动时统一检查 crmAuth, erpAuth 会被 Init() 同时处理 ``` --- ## 3. 接口权限配置 ### 3.1 基础权限 ```go func main() { // ... vbase.Auth.Init() ... api := r.SubRouter("/api/crm") api.Use(middleware.AuthRequired()) api.Use(middleware.OrgContext()) // 标准 CRUD api.Get("/customers", crmAuth.Perm("customer", "list"), "客户列表", listHandler) api.Post("/customers", crmAuth.Perm("customer", "create"), "创建客户", createHandler) api.Get("/customers/{id}", crmAuth.Perm("customer", "read"), "客户详情", getHandler) api.Patch("/customers/{id}", crmAuth.Perm("customer", "update"), "更新客户", updateHandler) api.Delete("/customers/{id}", crmAuth.Perm("customer", "delete"), "删除客户", deleteHandler) // 自定义操作 api.Post("/customers/{id}/export", crmAuth.Perm("customer", "export"), "导出客户", exportHandler) api.Post("/customers/{id}/transfer", crmAuth.Perm("customer", "transfer"), "转交客户", transferHandler) // 通配权限(拥有 customer 任意操作即可) api.Get("/customers/stats", crmAuth.Perm("customer", "*"), "客户统计", statsHandler) } ``` ### 3.2 资源所有者权限 ```go func getCustomer(x *vigo.X, req *GetReq) (*Customer, error) { customer := query(req.ID) x.Set("owner_id", customer.OwnerID) // 必须设置 owner_id return customer, nil } // 只有所有者或管理员能更新 api.Patch("/customers/{id}", crmAuth.PermWithOwner("customer", "update", "owner_id"), "更新客户", updateHandler, ) // 只有所有者能删除(管理员也不行) api.Delete("/customers/{id}/danger", crmAuth.PermWithOwner("customer", "delete", "owner_id"), "危险删除", dangerDeleteHandler, ) ``` ### 3.3 组合权限 ```go // 满足任一权限即可 api.Patch("/customers/{id}", crmAuth.PermAny([][2]string{ {"customer", "update"}, {"customer", "admin"}, }), "更新客户", updateHandler, ) // 必须同时满足所有权限 api.Post("/customers/batch-import", crmAuth.PermAll([][2]string{ {"customer", "create"}, {"customer", "batch"}, }), "批量导入", batchImportHandler, ) ``` --- ## 4. 编程式权限管理 开发者在自己的业务逻辑中调用这些方法管理权限。 ### 4.1 授予角色 ```go func inviteMember(ctx context.Context, req InviteReq) error { // 检查当前用户是否有邀请权限 ok, _ := crmAuth.CheckPermission(ctx, CheckPermRequest{ UserID: req.CurrentUserID, OrgID: req.OrgID, Resource: "org_member", Action: "invite", }) if !ok { return fmt.Errorf("无权邀请") } // 创建用户 user, _ := vbase.User.FindOrCreateByEmail(req.Email) // 加入组织并授予角色 if err := crmAuth.GrantRole(ctx, GrantRoleRequest{ UserID: user.ID, OrgID: req.OrgID, Role: req.Role, // "admin" / "sales" / "viewer" }); err != nil { return err } return nil } ``` ### 4.2 授予特定资源权限 ```go // 场景:将客户转交给销售 B 跟进 func transferCustomer(ctx context.Context, customerID, fromUserID, toUserID, orgID string) error { // 1. 撤销 A 的权限 if err := crmAuth.RevokeResourcePerm(ctx, fromUserID, orgID, "customer", customerID); err != nil { return err } // 2. 授予 B 权限 if err := crmAuth.GrantResourcePerm(ctx, GrantResourcePermRequest{ UserID: toUserID, OrgID: orgID, Resource: "customer", ResourceID: customerID, Action: "*", // 所有操作 }); err != nil { return err } return nil } // 场景:临时授权(3天后过期) func tempGrant(ctx context.Context, userID, orgID string) error { return crmAuth.GrantResourcePerm(ctx, GrantResourcePermRequest{ UserID: userID, OrgID: orgID, Resource: "report", ResourceID: "*", Action: "export", ExpireAt: time.Now().Add(3 * 24 * time.Hour), }) } ``` ### 4.3 查询权限 ```go // 检查用户是否能操作某客户 func canEditCustomer(ctx context.Context, userID, orgID, customerID string) bool { ok, _ := crmAuth.CheckPermission(ctx, CheckPermRequest{ UserID: userID, OrgID: orgID, Resource: "customer", ResourceID: customerID, Action: "update", }) return ok } // 获取用户在组织的所有权限 perms, _ := crmAuth.ListUserPermissions(ctx, "user-123", "org-456") // 返回: // [ // {Resource: "customer", ResourceID: "*", Actions: ["read","list"]}, // {Resource: "customer", ResourceID: "c-789", Actions: ["*"]}, // {Resource: "order", ResourceID: "*", Actions: ["read"]} // ] // 获取某客户的所有授权用户 users, _ := crmAuth.ListResourceUsers(ctx, "org-456", "customer", "c-789") // 返回: // [ // {UserID: "u1", Actions: ["admin"]}, // {UserID: "u2", Actions: ["read","update"]} // ] ``` ### 4.4 撤销权限 ```go // 撤销角色 crmAuth.RevokeRole(ctx, "user-123", "org-456", "sales") // 撤销特定资源权限 crmAuth.RevokeResourcePerm(ctx, "user-123", "org-456", "customer", "c-789") // 撤销用户在组织的所有权限(离职) crmAuth.RevokeAll(ctx, "user-123", "org-456") ``` --- ## 5. 完整示例:多模块应用 ```go package main import ( "github.com/veypi/vbase" "github.com/veypi/vbase/api" "github.com/veypi/vbase/api/middleware" "github.com/veypi/vigo" ) // ========== 阶段1:定义权限(全局)========== // CRM 模块 crmAuth := vbase.Auth.New("crm", vbase.AppConfig{ Name: "客户关系管理", DefaultRoles: []vbase.RoleDefinition{ {Code: "admin", Name: "管理员", Policies: []string{"*:*"}}, {Code: "manager", Name: "主管", Policies: []string{"customer:*", "contract:*", "report:*"}}, {Code: "sales", Name: "销售", Policies: []string{"customer:read", "customer:create", "customer:update"}}, {Code: "viewer", Name: "查看者", Policies: []string{"customer:read"}}, }, }) // 合同模块(独立,但共用 crm 用户体系) contractAuth := vbase.Auth.New("contract", vbase.AppConfig{ Name: "合同管理", DefaultRoles: []vbase.RoleDefinition{ {Code: "admin", Name: "管理员", Policies: []string{"*:*"}}, {Code: "legal", Name: "法务", Policies: []string{"contract:read", "contract:audit", "contract:approve"}}, {Code: "manager", Name: "业务经理", Policies: []string{"contract:read", "contract:create", "contract:sign"}}, }, }) func main() { // ========== 阶段2:初始化 ========== if err := vbase.Auth.Init(); err != nil { log.Fatal("权限初始化失败:", err) } r := vigo.NewRouter() // 挂载 VBase r.Extend("/api/vb", api.Router) // ========== 阶段3:配置路由 ========== // CRM 路由 crm := r.SubRouter("/api/crm") crm.Use(middleware.AuthRequired()) crm.Use(middleware.OrgContext()) crm.Get("/customers", crmAuth.Perm("customer", "list"), "客户列表", listCustomers) crm.Post("/customers", crmAuth.Perm("customer", "create"), "创建客户", createCustomer) crm.Get("/customers/{id}", crmAuth.Perm("customer", "read"), "客户详情", getCustomer) crm.Patch("/customers/{id}", crmAuth.PermWithOwner("customer", "update", "owner_id"), "更新客户", updateCustomer) crm.Delete("/customers/{id}", crmAuth.Perm("customer", "delete"), "删除客户", deleteCustomer) // 合同路由(独立模块) contract := r.SubRouter("/api/contract") contract.Use(middleware.AuthRequired()) contract.Use(middleware.OrgContext()) contract.Get("/contracts", contractAuth.Perm("contract", "list"), "合同列表", listContracts) contract.Post("/contracts", contractAuth.Perm("contract", "create"), "创建合同", createContract) contract.Post("/contracts/{id}/audit", contractAuth.Perm("contract", "audit"), "审核合同", auditContract) contract.Post("/contracts/{id}/sign", contractAuth.Perm("contract", "sign"), "签署合同", signContract) vigo.Run(r) } ``` --- ## 6. API 参考 ### 6.1 全局函数 ```go // 创建权限管理实例 func (f *authFactory) New(appKey string, config AppConfig) Auth // 初始化所有权限配置 func (f *authFactory) Init() error ``` ### 6.2 Auth 接口 ```go // ========== 中间件 ========== Perm(resource, action string) func(*vigo.X) error PermWithOwner(resource, action, ownerKey string) func(*vigo.X) error PermAny(permissions [][2]string) func(*vigo.X) error PermAll(permissions [][2]string) func(*vigo.X) error // ========== 授权管理 ========== GrantRole(ctx context.Context, req GrantRoleRequest) error RevokeRole(ctx context.Context, userID, orgID, roleCode string) error GrantResourcePerm(ctx context.Context, req GrantResourcePermRequest) error RevokeResourcePerm(ctx context.Context, userID, orgID, resource, resourceID string) error RevokeAll(ctx context.Context, userID, orgID string) error // ========== 权限查询 ========== CheckPermission(ctx context.Context, req CheckPermRequest) (bool, error) ListUserPermissions(ctx context.Context, userID, orgID string) ([]UserPermission, error) ListResourceUsers(ctx context.Context, orgID, resource, resourceID string) ([]ResourceUser, error) ``` ### 6.3 请求/响应结构 ```go type GrantRoleRequest struct { UserID string // 用户ID OrgID string // 组织ID Role string // 角色代码 } type GrantResourcePermRequest struct { UserID string // 用户ID OrgID string // 组织ID Resource string // 资源类型 ResourceID string // 资源实例ID,"*" 表示所有 Action string // 操作类型,"*" 表示所有 ExpireAt time.Time // 过期时间(可选) } type CheckPermRequest struct { UserID string // 用户ID OrgID string // 组织ID Resource string // 资源类型 ResourceID string // 资源实例ID(可选) Action string // 操作类型 } type UserPermission struct { Resource string // 资源类型 ResourceID string // 资源ID Actions []string // 允许的操作 } type ResourceUser struct { UserID string // 用户ID Actions []string // 允许的操作 } ``` --- **确认此设计后,我将实现底层代码。**