将 bookmark.go 重命名为 main.go,并调整包引用路径。将 bookmarks 和 user_np 两个模块的处理逻辑合并到同一个服务中,统一注册路由。同时更新了相关 API 的引用路径,确保生成代码与内部实现正确绑定。 此外,移除了独立的 user_np 服务入口文件,其功能已整合至 bookmark 服务中。 配置文件中调整了 user_np 和 vfs 服务的端口及部分接口定义,完善了用户 相关操作的路径参数和请求体结构。
90 lines
2.2 KiB
Go
90 lines
2.2 KiB
Go
package vfs
|
||
|
||
import (
|
||
_ "embed"
|
||
"net/http"
|
||
"strings"
|
||
|
||
api "git.zzyxyz.com/zzy/zzyxyz_go_api/gen/vfs"
|
||
"git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/models"
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
//go:embed vfs_model.conf
|
||
var CasbinModel string
|
||
|
||
func NewVfsPermission() (*api.GinServerOptions, error) {
|
||
return &api.GinServerOptions{
|
||
Middlewares: []api.MiddlewareFunc{VfsMiddleware()},
|
||
}, nil
|
||
}
|
||
|
||
func (v *VfsImpl) CheckPermission(token, path, action string) (bool, error) {
|
||
// 根据 token 获取用户信息
|
||
user, err := v.vfs.GetUserByToken(token)
|
||
if err != nil {
|
||
// 匿名用户
|
||
user = &models.VfsUser{Name: "", Token: ""}
|
||
}
|
||
|
||
// 特殊处理:admin 用户拥有所有权限
|
||
if token == v.config.AdminToken && len(token) != 0 { // admin 用户拥有所有权限
|
||
return true, nil
|
||
}
|
||
|
||
// 允许任何人读取 public 目录
|
||
if strings.HasPrefix(path, "/public") && action == "GET" {
|
||
return true, nil
|
||
}
|
||
|
||
// 如果是普通用户访问自己的主目录,则允许
|
||
if user.Name != "" && strings.HasPrefix(path, "/home/"+user.Name) {
|
||
return true, nil
|
||
}
|
||
|
||
// 构造 Casbin 请求
|
||
// 对于普通用户,需要将策略中的 {{username}} 替换为实际用户名
|
||
obj := path
|
||
sub := user.Name
|
||
// 使用 Casbin 检查权限
|
||
allowed, err := v.enfocer.Enforce(sub, obj, action)
|
||
if err != nil {
|
||
return false, err
|
||
}
|
||
|
||
return allowed, nil
|
||
}
|
||
|
||
func (v *VfsImpl) CheckPermissionMiddleware(c *gin.Context, path string) bool {
|
||
token := c.GetHeader("X-VFS-Token")
|
||
allowed, err := v.CheckPermission(token, path, c.Request.Method)
|
||
// log.Println("CheckPermission:", allowed, err)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, api.Error{
|
||
Errtype: "PermissionCheckError",
|
||
Message: "Failed to check permission: " + err.Error(),
|
||
})
|
||
return false
|
||
}
|
||
if !allowed {
|
||
c.JSON(http.StatusForbidden, api.Error{
|
||
Errtype: "AccessDenied",
|
||
Message: "Access denied",
|
||
})
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
func VfsMiddleware() api.MiddlewareFunc {
|
||
return func(c *gin.Context) {
|
||
// 检查当前请求是否需要认证
|
||
if _, exists := c.Get(api.ApiKeyAuthScopes); exists {
|
||
// 提取 API Key
|
||
apiKey := c.GetHeader("X-VFS-Token")
|
||
c.Set(api.ApiKeyAuthScopes, apiKey)
|
||
}
|
||
c.Next()
|
||
}
|
||
}
|