diff --git a/docs/auth.md b/docs/auth.md index ed9bd37..84414d7 100644 --- a/docs/auth.md +++ b/docs/auth.md @@ -27,19 +27,19 @@ app:vbase:role:admin → 第4层 (偶数) - 实例 ### 2.1 奇数层(资源类型) -| level | 二进制 | 含义 | +| level | 二进制 | 含义 | | ----- | ------ | -------------------- | -| 0 | 000 | 无权限 | +| 0 | 000 | 无权限 | | 1 | 001 | 可创建该类型的子资源 | ### 2.2 偶数层(实例) -| level | 二进制 | 含义 | -| ----- | ------ | ---------------------- | -| 0 | 000 | 无权限 | -| 2 | 010 | 读取 | -| 4 | 100 | 写入(修改,不能删除) | -| 6 | 110 | 读写(读取+修改) | +| level | 二进制 | 含义 | +| ----- | ------ | ---------------------------------- | +| 0 | 000 | 无权限 | +| 2 | 010 | 读取 | +| 4 | 100 | 写入(修改,不能删除) | +| 6 | 110 | 读写(读取+修改) | | 7 | 111 | 管理员(完全控制:读写+删除+授权) | --- @@ -48,13 +48,13 @@ app:vbase:role:admin → 第4层 (偶数) - 实例 ### 3.1 层级与权限对应 -| 权限 | level | 检查层级 | 说明 | -|------|-------|----------|------| -| 创建 | 1 | 奇数层 | 检查资源类型层 | -| 读取 | 2 | 偶数层 | 检查实例层 | -| 写入 | 4 | 偶数层 | 检查实例层 | -| 读写 | 6 | 偶数层 | 检查实例层 | -| 管理 | 7 | 偶数层 | 检查实例层 | +| 权限 | level | 检查层级 | 说明 | +| ---- | ----- | -------- | -------------- | +| 创建 | 1 | 奇数层 | 检查资源类型层 | +| 读取 | 2 | 偶数层 | 检查实例层 | +| 写入 | 4 | 偶数层 | 检查实例层 | +| 读写 | 6 | 偶数层 | 检查实例层 | +| 管理 | 7 | 偶数层 | 检查实例层 | ### 3.2 具体规则 @@ -114,19 +114,19 @@ app:vbase:role:admin → 第4层 (偶数) - 实例 package auth import ( - "context" - "github.com/veypi/vigo" + "context" + "github.com/veypi/vigo" ) // ========== 权限等级 ========== const ( - LevelNone = 0 - LevelCreate = 1 // 001 创建 (检查奇数层) - LevelRead = 2 // 010 读取 (检查偶数层) - LevelWrite = 4 // 100 写入 (检查偶数层) - LevelReadWrite = 6 // 110 读写 (检查偶数层) - LevelAdmin = 7 // 111 管理员 (完全控制) + LevelNone = 0 + LevelCreate = 1 // 001 创建 (检查奇数层) + LevelRead = 2 // 010 读取 (检查偶数层) + LevelWrite = 4 // 100 写入 (检查偶数层) + LevelReadWrite = 6 // 110 读写 (检查偶数层) + LevelAdmin = 7 // 111 管理员 (完全控制) ) // PermFunc 权限检查函数类型 @@ -134,86 +134,86 @@ type PermFunc func(x *vigo.X) error // Auth 权限管理接口 type Auth interface { - // ========== 上下文 ========== + // ========== 上下文 ========== - // UserID 获取当前用户ID - UserID(x *vigo.X) string + // UserID 获取当前用户ID + UserID(x *vigo.X) string - // ========== 登录检查 ========== + // ========== 登录检查 ========== - // Login 检查用户是否登录 - Login() PermFunc + // Login 检查用户是否登录 + Login() PermFunc - // ========== 权限检查 ========== + // ========== 权限检查 ========== - // Perm 检查权限 - // code: 权限码,支持动态解析 - // - 固定写法: "app:vbase" - // - 动态解析: "app:{appID}" 从 path 获取 - // "app:{appID@query}" 从 query 获取 - // "app:{appID@header}" 从 header 获取 - // "app:{appID@ctx}" 从 ctx 获取 - // level: 需要的权限等级 - Perm(code string, level int) PermFunc + // Perm 检查权限 + // code: 权限码,支持动态解析 + // - 固定写法: "app:vbase" + // - 动态解析: "app:{appID}" 从 path 获取 + // "app:{appID@query}" 从 query 获取 + // "app:{appID@header}" 从 header 获取 + // "app:{appID@ctx}" 从 ctx 获取 + // level: 需要的权限等级 + Perm(code string, level int) PermFunc - // ========== 快捷方法 ========== + // ========== 快捷方法 ========== - // PermCreate 检查创建权限 (level 1,检查奇数层) - PermCreate(code string) PermFunc + // PermCreate 检查创建权限 (level 1,检查奇数层) + PermCreate(code string) PermFunc - // PermRead 检查读取权限 (level 2,检查偶数层) - PermRead(code string) PermFunc + // PermRead 检查读取权限 (level 2,检查偶数层) + PermRead(code string) PermFunc - // PermWrite 检查更新权限 (level 4,检查偶数层) - PermWrite(code string) PermFunc + // PermWrite 检查更新权限 (level 4,检查偶数层) + PermWrite(code string) PermFunc - // PermAdmin 检查管理员权限 (level 7,检查偶数层) - PermAdmin(code string) PermFunc + // PermAdmin 检查管理员权限 (level 7,检查偶数层) + PermAdmin(code string) PermFunc - // ========== 权限授予(业务调用) ========== + // ========== 权限授予(业务调用) ========== - // Grant 授予权限 - // 在创建资源、被授权等业务逻辑中调用 - // permissionID: 权限码,如 "app:vbase" - // level: 权限等级 - Grant(ctx context.Context, userID, permissionID string, level int) error + // Grant 授予权限 + // 在创建资源、被授权等业务逻辑中调用 + // permissionID: 权限码,如 "app:vbase" + // level: 权限等级 + Grant(ctx context.Context, userID, permissionID string, level int) error - // Revoke 撤销权限 - Revoke(ctx context.Context, userID, permissionID string) error + // Revoke 撤销权限 + Revoke(ctx context.Context, userID, permissionID string) error - // ========== 权限查询 ========== + // ========== 权限查询 ========== - // Check 检查权限 不支持动态解析 - // permissionID: 完整的权限码,如 "app:vbase" - Check(ctx context.Context, userID, permissionID string, level int) bool + // Check 检查权限 不支持动态解析 + // permissionID: 完整的权限码,如 "app:vbase" + Check(ctx context.Context, userID, permissionID string, level int) bool - // ========== 资源列表查询 ========== + // ========== 资源列表查询 ========== - // ListResources 查询用户在特定资源类型下的详细权限信息 - // 用于解决 "查询我有权限的 app 列表" 等场景 - // userID: 用户ID - // resourceType: 资源类型 (奇数层),如 "app" 或 "app:{appID}:role" - // 返回: map[实例ID]权限等级 (如 {"vbase": 2, "other": 7}) - ListResources(ctx context.Context, userID, resourceType string) (map[string]int, error) + // ListResources 查询用户在特定资源类型下的详细权限信息 + // 用于解决 "查询我有权限的 app 列表" 等场景 + // userID: 用户ID + // resourceType: 资源类型 (奇数层),如 "app" 或 "app:{appID}:role" + // 返回: map[实例ID]权限等级 (如 {"vbase": 2, "other": 7}) + ListResources(ctx context.Context, userID, resourceType string) (map[string]int, error) - // ListUsers 查询特定资源的所有协作者及其权限 - // 用于解决 "查看这个应用有哪些成员" 等场景 - // permissionID: 资源实例权限码,如 "app:vbase" - // 返回: map[用户ID]权限等级 (如 {"user1": 2, "user2": 7}) - ListUsers(ctx context.Context, permissionID string) (map[string]int, error) + // ListUsers 查询特定资源的所有协作者及其权限 + // 用于解决 "查看这个应用有哪些成员" 等场景 + // permissionID: 资源实例权限码,如 "app:vbase" + // 返回: map[用户ID]权限等级 (如 {"user1": 2, "user2": 7}) + ListUsers(ctx context.Context, permissionID string) (map[string]int, error) } // ========== 数据结构 ========== // Permission 用户权限 type Permission struct { - ID string `json:"id"` - UserID string `json:"user_id"` - RoleID string `json:"role_id"` - PermissionID string `json:"permission_id"` - Level int `json:"level"` - CreatedAt int64 `json:"created_at"` - UpdatedAt int64 `json:"updated_at"` + ID string `json:"id"` + UserID string `json:"user_id"` + RoleID string `json:"role_id"` + PermissionID string `json:"permission_id"` + Level int `json:"level"` + CreatedAt int64 `json:"created_at"` + UpdatedAt int64 `json:"updated_at"` } ``` @@ -227,11 +227,11 @@ type Permission struct { var Router = vigo.NewRouter() func init() { - // 创建应用 - 需要系统级 app 权限 - Router.Post("/apps", cfg.Auth.PermCreate("app"), CreateApp) + // 创建应用 - 需要系统级 app 权限 + Router.Post("/apps", cfg.Auth.PermCreate("app"), CreateApp) - // 超级管理员接口 - Router.Get("/admin/users", cfg.Auth.PermAdmin("*"), AdminListUsers) + // 超级管理员接口 + Router.Get("/admin/users", cfg.Auth.PermAdmin("*"), AdminListUsers) } ``` @@ -239,20 +239,20 @@ func init() { ```go func init() { - // 从路径参数获取 appID (默认) - // GET /apps/{appID} - Router.Get("/apps/{appID}", cfg.Auth.PermRead("app:{appID}"), GetApp) - - // 从 query 参数获取 - // GET /apps?appID=xxx - Router.Get("/apps", cfg.Auth.PermRead("app:{appID@query}"), GetApp) - - // 多层嵌套 - // GET /apps/{appID}/roles/{roleID} - Router.Get("/apps/{appID}/roles/{roleID}", - cfg.Auth.PermRead("app:{appID}:role:{roleID}"), - GetRole, - ) + // 从路径参数获取 appID (默认) + // GET /apps/{appID} + Router.Get("/apps/{appID}", cfg.Auth.PermRead("app:{appID}"), GetApp) + + // 从 query 参数获取 + // GET /apps?appID=xxx + Router.Get("/apps", cfg.Auth.PermRead("app:{appID@query}"), GetApp) + + // 多层嵌套 + // GET /apps/{appID}/roles/{roleID} + Router.Get("/apps/{appID}/roles/{roleID}", + cfg.Auth.PermRead("app:{appID}:role:{roleID}"), + GetRole, + ) } ``` @@ -262,33 +262,33 @@ func init() { var Router = vigo.NewRouter().Use(cfg.Auth.Login()) func init() { - // 创建应用 - 系统级权限 - Router.Post("/apps", cfg.Auth.PermCreate("app"), CreateApp) - - // 列出我的应用 - 只需登录 - Router.Get("/apps", ListMyApps) - - // 应用操作 - 从路径获取 - Router.Get("/apps/{appID}", cfg.Auth.PermRead("app:{appID}"), GetApp) - Router.Put("/apps/{appID}", cfg.Auth.PermWrite("app:{appID}"), UpdateApp) - Router.Delete("/apps/{appID}", cfg.Auth.PermAdmin("app:{appID}"), DeleteApp) - - // 角色操作 - 嵌套资源 - Router.Post("/apps/{appID}/roles", cfg.Auth.PermCreate("app:{appID}:role"), CreateRole) - Router.Get("/apps/{appID}/roles/{roleID}", cfg.Auth.PermRead("app:{appID}:role:{roleID}"), GetRole) - Router.Put("/apps/{appID}/roles/{roleID}", cfg.Auth.PermWrite("app:{appID}:role:{roleID}"), UpdateRole) - Router.Delete("/apps/{appID}/roles/{roleID}", cfg.Auth.PermAdmin("app:{appID}:role:{roleID}"), DeleteRole) + // 创建应用 - 系统级权限 + Router.Post("/apps", cfg.Auth.PermCreate("app"), CreateApp) + + // 列出我的应用 - 只需登录 + Router.Get("/apps", ListMyApps) + + // 应用操作 - 从路径获取 + Router.Get("/apps/{appID}", cfg.Auth.PermRead("app:{appID}"), GetApp) + Router.Put("/apps/{appID}", cfg.Auth.PermWrite("app:{appID}"), UpdateApp) + Router.Delete("/apps/{appID}", cfg.Auth.PermAdmin("app:{appID}"), DeleteApp) + + // 角色操作 - 嵌套资源 + Router.Post("/apps/{appID}/roles", cfg.Auth.PermCreate("app:{appID}:role"), CreateRole) + Router.Get("/apps/{appID}/roles/{roleID}", cfg.Auth.PermRead("app:{appID}:role:{roleID}"), GetRole) + Router.Put("/apps/{appID}/roles/{roleID}", cfg.Auth.PermWrite("app:{appID}:role:{roleID}"), UpdateRole) + Router.Delete("/apps/{appID}/roles/{roleID}", cfg.Auth.PermAdmin("app:{appID}:role:{roleID}"), DeleteRole) } ``` ### 6.4 动态解析规则 -| 语法 | 来源 | 示例 | -|------|------|------| -| `{key}` | path 参数 | `{appID}` | -| `{key@query}` | query 参数 | `{appID@query}` | -| `{key@header}` | header | `{appID@header}` | -| `{key@ctx}` | context | `{appID@ctx}` | +| 语法 | 来源 | 示例 | +| -------------- | ---------- | ---------------- | +| `{key}` | path 参数 | `{appID}` | +| `{key@query}` | query 参数 | `{appID@query}` | +| `{key@header}` | header | `{appID@header}` | +| `{key@ctx}` | context | `{appID@ctx}` | --- @@ -297,6 +297,7 @@ func init() { ### 7.1 业务调用 vs 管理端 此接口是**业务层**调用,用于: + - 创建资源时自动授予权限 - 业务逻辑中检查权限 @@ -307,13 +308,13 @@ func init() { ```go // 创建应用时 func CreateApp(x *vigo.X, req *CreateAppReq) (*AppResp, error) { - app := models.App{Name: req.Name} - db.Create(&app) + app := models.App{Name: req.Name} + db.Create(&app) - // 授予创建者完全控制权限 - cfg.Auth.Grant(x.Context(), userID, "app:"+app.ID, auth.LevelAdmin) + // 授予创建者完全控制权限 + cfg.Auth.Grant(x.Context(), userID, "app:"+app.ID, auth.LevelAdmin) - return &AppResp{App: app}, nil + return &AppResp{App: app}, nil } ``` @@ -322,6 +323,7 @@ func CreateApp(x *vigo.X, req *CreateAppReq) (*AppResp, error) { 对于资源列表(List)或搜索接口,推荐以下设计模式: 1. **全量管理接口**(如后台管理系统): + - 使用 `PermAdmin("*")` 或 `PermAdmin("app:*")`。 - 这类接口返回所有数据,必须严格控制权限。