package vfs import ( _ "embed" "strings" api "git.zzyxyz.com/zzy/zzyxyz_go_api/gen/vfs_server" "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/models" "github.com/gin-gonic/gin" ) //go:embed vfs_model.conf var CasbinModel string // 使用示例:在main.go或路由注册处 func RegisterVFSRoutes(router gin.IRouter, vfsHandler *VfsImpl) { // 创建严格模式handler并添加权限中间件 strictHandler := api.NewStrictHandler(vfsHandler, []api.StrictMiddlewareFunc{ vfsHandler.PermissionMiddleware, }) // 注册handler api.RegisterHandlers(router, strictHandler) } // PermissionMiddleware 是一个权限验证中间件 func (v *VfsImpl) PermissionMiddleware(handler api.StrictHandlerFunc, operation string) api.StrictHandlerFunc { return func(ctx *gin.Context, request interface{}) (interface{}, error) { // 从请求头获取token token := ctx.GetHeader("X-VFS-Token") // Admin token 拥有所有权限 if token == v.config.AdminToken && len(token) != 0 { return handler(ctx, request) } // 根据操作类型进行不同的权限检查 switch operation { case "CreateUser": // 只有admin或register token可以创建用户 if token != v.config.RegisterToken { return api.CreateUser403JSONResponse{ ForbiddenErrorJSONResponse: api.ForbiddenErrorJSONResponse{ Errtype: api.ErrorErrtypeForbidden, Message: "Access denied", }, }, nil } return handler(ctx, request) // 如果是删除用户操作,检查是否具有管理员权限 case "DeleteUser": // 获取要删除的用户名 var username string if req, ok := request.(api.DeleteUserRequestObject); ok { username = req.Username } // 验证token对应的用户是否存在 user, err := v.vfs.GetUserByToken(token) if err != nil || (user.Name != username && token != v.config.AdminToken) { return api.DeleteUser403JSONResponse{ ForbiddenErrorJSONResponse: api.ForbiddenErrorJSONResponse{ Errtype: api.ErrorErrtypeForbidden, Message: "Access denied", }, }, nil } // 如果验证通过,继续执行原处理函数 return handler(ctx, request) case "GetVFSNode", "CreateVFSNode", "UpdateVFSNode", "DeleteVFSNode": // VFS节点操作的权限检查 var path string var method string // 根据操作类型获取路径和HTTP方法 switch operation { case "GetVFSNode": if req, ok := request.(api.GetVFSNodeRequestObject); ok { path = req.Params.Path } method = "GET" case "CreateVFSNode": if req, ok := request.(api.CreateVFSNodeRequestObject); ok { path = req.Params.Path } method = "POST" case "UpdateVFSNode": if req, ok := request.(api.UpdateVFSNodeRequestObject); ok { path = req.Params.Path } method = "PATCH" case "DeleteVFSNode": if req, ok := request.(api.DeleteVFSNodeRequestObject); ok { path = req.Params.Path } method = "DELETE" } // 检查权限 allowed, err := v.CheckPermission(token, path, method) if err != nil { return api.GetVFSNode500JSONResponse{ ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ Errtype: api.ErrorErrtypeInternalServerError, Message: "Failed to check permission: " + err.Error(), }, }, nil } if !allowed { // 根据操作类型返回相应的错误响应 switch operation { case "GetVFSNode": return api.GetVFSNode403JSONResponse{ ForbiddenErrorJSONResponse: api.ForbiddenErrorJSONResponse{ Errtype: api.ErrorErrtypeForbidden, Message: "Access denied", }, }, nil case "CreateVFSNode": return api.CreateVFSNode403JSONResponse{ ForbiddenErrorJSONResponse: api.ForbiddenErrorJSONResponse{ Errtype: api.ErrorErrtypeForbidden, Message: "Access denied", }, }, nil case "UpdateVFSNode": return api.UpdateVFSNode403JSONResponse{ ForbiddenErrorJSONResponse: api.ForbiddenErrorJSONResponse{ Errtype: api.ErrorErrtypeForbidden, Message: "Access denied", }, }, nil case "DeleteVFSNode": return api.DeleteVFSNode403JSONResponse{ ForbiddenErrorJSONResponse: api.ForbiddenErrorJSONResponse{ Errtype: api.ErrorErrtypeForbidden, Message: "Access denied", }, }, nil } } return handler(ctx, request) default: return api.Error{ Errtype: api.ErrorErrtypeForbidden, Message: "not supported function it's a bug in backend", }, nil } } } // CheckPermission 检查用户对指定路径的权限 // FIXME: using casbin to check it func (v *VfsImpl) CheckPermission(token, path, method string) (bool, error) { // Admin token 拥有所有权限 if token == v.config.AdminToken && len(token) != 0 { return true, nil } // 根据 token 获取用户信息 user, err := v.vfs.GetUserByToken(token) if err != nil { // 匿名用户 user = &models.VfsUser{Name: "", Token: ""} } // 允许任何人读取 public 目录 if method == "GET" && strings.HasPrefix(path, "/public") { return true, nil } // 如果是普通用户访问自己的主目录,则允许 if user.Name != "" && strings.HasPrefix(path, "/home/"+user.Name) { return true, nil } // 使用 Casbin 检查权限 // sub: 用户名 (匿名用户为空字符串) // obj: 路径 // act: HTTP方法 allowed, err := v.enfocer.Enforce(user.Name, path, method) if err != nil { return false, err } return allowed, nil }