Files
zzyxyz_go_api/internal/vfs/vfs_auth.go
zzy 35e79e54f1 refactor(vfs): 重构VFS模块,拆分数据访问逻辑与路径解析逻辑
将原先的 `vfs.go` 文件中的功能进行拆分,创建了独立的 DAO 层文件 `vfs_dao.go`
和路径处理文件 `vfs_path.go`,以提升代码结构清晰度和可维护性。

- 将数据库操作相关方法迁移至 `VfsDAO` 结构体中
- 新增 `vfs_dao.go` 文件用于管理底层数据访问对象
- 新增 `vfs_path.go` 文件专门处理路径解析逻辑
- 移除了原 `vfs.go` 中的数据库初始化、用户及节点操作等冗余代码
2025-09-29 00:42:45 +08:00

190 lines
5.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.DAO.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.DAO.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
}