package handlers import ( "log" "net/http" "strings" "sync" api "git.zzyxyz.com/zzy/zzyxyz_go_api/gen/vfs" "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/models" "github.com/gin-gonic/gin" ) // // 一行代码生成安全的随机token // token := make([]byte, 16) // rand.Read(token) // 忽略错误处理以简化代码(生产环境建议处理) // tokenStr := hex.EncodeToString(token) // adminToken = &tokenStr // log.Printf("Admin API Token (for Swagger testing): %s", *adminToken) // if e, err := casbin.NewEnforcer("./config/model.conf", ".data/policy.csv"); err == nil { // log.Fatalf("Failed to create casbin enforcer: %v", err) // } else { // enforcer = e // } // ServiceProxy 服务代理接口 type ServiceProxy interface { // Get 从后端服务获取数据 Get(c *gin.Context, servicePath string, node *models.VfsNode) (any, error) // Create 在后端服务创建资源 Create(c *gin.Context, servicePath string, node *models.VfsNode, data []byte) (string, error) // 返回创建的资源ID // Update 更新后端服务资源 Update(c *gin.Context, servicePath string, node *models.VfsNode, data []byte) error // Delete 删除后端服务资源 Delete(c *gin.Context, servicePath string, node *models.VfsNode) error // GetName 获取代理名称 GetName() string } // ProxyEntry 代理表条目 type ProxyEntry struct { Name string Proxy ServiceProxy // 对应的代理实现 } type VfsImpl struct { vfs *models.Vfs proxyTable []*ProxyEntry // 动态代理表 proxyMutex sync.RWMutex // 保护代理表的读写锁 } func NewVfsHandler(vfs models.Vfs) (*VfsImpl, error) { return &VfsImpl{ vfs: &vfs, proxyTable: make([]*ProxyEntry, 0), proxyMutex: sync.RWMutex{}, }, nil } // CreateUser implements api.ServerInterface. func (v *VfsImpl) CreateUser(c *gin.Context) { panic("unimplemented") } // DeleteUser implements api.ServerInterface. func (v *VfsImpl) DeleteUser(c *gin.Context) { panic("unimplemented") } // CreateVFSNode implements api.ServerInterface. func (v *VfsImpl) CreateVFSNode(c *gin.Context, params api.CreateVFSNodeParams) { // 解析路径组件 parentPath, nodeName, nodeType, err := models.ParsePathComponents(params.Path) if err != nil { c.JSON(http.StatusBadRequest, api.Error{ Errtype: "error", Message: err.Error(), }) return } // 创建节点 node, err := v.vfs.CreateNodeByComponents(parentPath, nodeName, nodeType) if err != nil { c.JSON(http.StatusInternalServerError, api.Error{ Errtype: "CreateNodeByComponents", Message: err.Error(), }) return } if nodeType == models.VfsNodeTypeService { if !v.Proxy2Service(c, node) { v.vfs.DeleteVFSNode(node) return } } // 返回创建成功的节点 c.JSON(http.StatusCreated, api.VFSNodeResponse{ Name: node.Name, Type: ModelType2ResponseType(node.Type), CreatedAt: node.CreatedAt, UpdatedAt: node.UpdatedAt, }) } // DeleteVFSNode implements api.ServerInterface. func (v *VfsImpl) DeleteVFSNode(c *gin.Context, params api.DeleteVFSNodeParams) { node, err := v.vfs.GetNodeByPath(params.Path) if err != nil { c.JSON(http.StatusNotFound, api.Error{ Errtype: "error", Message: err.Error(), }) return } if node.Type == models.VfsNodeTypeService { if !v.Proxy2Service(c, node) { return } } if err := v.vfs.DeleteVFSNode(node); err != nil { c.JSON(http.StatusInternalServerError, api.Error{ Errtype: "error", Message: err.Error(), }) return } c.JSON(http.StatusNoContent, nil) } // GetVFSNode implements api.ServerInterface. func (v *VfsImpl) GetVFSNode(c *gin.Context, params api.GetVFSNodeParams) { node, err := v.vfs.GetNodeByPath(params.Path) if err != nil { c.JSON(http.StatusNotFound, api.Error{ Errtype: "error", Message: err.Error(), }) return } switch node.Type { case models.VfsNodeTypeDirectory: if entries, err := v.vfs.GetChildren(node.ID); err != nil { c.JSON(http.StatusInternalServerError, api.Error{ Errtype: "error", Message: err.Error(), }) return } else { var responseEntries []api.VFSDirectoryEntry for _, entry := range entries { responseEntries = append(responseEntries, api.VFSDirectoryEntry{ Name: entry.Name, Type: ModelType2ResponseType(entry.Type), }) } c.JSON(http.StatusOK, responseEntries) return } case models.VfsNodeTypeService: v.Proxy2Service(c, node) default: c.JSON(http.StatusBadRequest, api.Error{ Errtype: "error", Message: "Not a directory", }) } } // UpdateVFSNode implements api.ServerInterface. func (v *VfsImpl) UpdateVFSNode(c *gin.Context, params api.UpdateVFSNodeParams) { var req api.UpdateVFSNodeJSONRequestBody if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, api.Error{ Errtype: "ParameterError", Message: "Invalid request parameters", }) return } node, err := v.vfs.GetNodeByPath(params.Path) if err != nil { c.JSON(http.StatusNotFound, api.Error{ Errtype: "error", Message: err.Error(), }) return } if req.NewName != nil { node.Name = *req.NewName } // FIXME if node.Type == models.VfsNodeTypeService { if !v.Proxy2Service(c, node) { return } } // TODO if err := v.vfs.UpdateVFSNode(node); err != nil { c.JSON(http.StatusInternalServerError, api.Error{ Errtype: "error", Message: err.Error(), }) return } } // Make sure we conform to ServerInterface var _ api.ServerInterface = (*VfsImpl)(nil) func ModelType2ResponseType(nodeType models.VfsNodeType) api.VFSNodeType { var reponseType api.VFSNodeType switch nodeType { case models.VfsNodeTypeFile: reponseType = api.File case models.VfsNodeTypeDirectory: reponseType = api.Directory case models.VfsNodeTypeService: reponseType = api.Service } return reponseType } // FindProxyByServiceName 根据服务节点名称查找对应的代理 func (v *VfsImpl) FindProxyByServiceName(serviceName string) ServiceProxy { v.proxyMutex.RLock() defer v.proxyMutex.RUnlock() if serviceName == "" { return nil } // 根据服务名称匹配前缀 for _, entry := range v.proxyTable { if entry.Name == serviceName { return entry.Proxy } } return nil } func (v *VfsImpl) RegisterProxy(entry *ProxyEntry) { v.proxyMutex.Lock() defer v.proxyMutex.Unlock() v.proxyTable = append(v.proxyTable, entry) } // Proxy2Service 通用服务代理处理函数 func (v *VfsImpl) Proxy2Service(c *gin.Context, node *models.VfsNode) bool { exts := strings.Split(node.Name, ".") var serviceName = exts[1] log.Println("Proxy2Service: ", serviceName) // 查找对应的代理 proxy := v.FindProxyByServiceName(serviceName) if proxy == nil { c.JSON(http.StatusNotImplemented, api.Error{ Errtype: "error", Message: "Service proxy not found for: " + serviceName, }) return false } // 根据HTTP方法调用相应的代理方法 switch c.Request.Method { case http.MethodGet: result, err := proxy.Get(c, serviceName, node) if err != nil { c.JSON(http.StatusInternalServerError, api.Error{ Errtype: "error", Message: "Failed to get service data: " + err.Error(), }) return false } c.JSON(http.StatusOK, result) return true case http.MethodPost: // 读取请求体数据 data, err := c.GetRawData() if err != nil { c.JSON(http.StatusBadRequest, api.Error{ Errtype: "error", Message: "Failed to read request data: " + err.Error(), }) return false } resourceID, err := proxy.Create(c, serviceName, node, data) if err != nil { c.JSON(http.StatusInternalServerError, api.Error{ Errtype: "error", Message: "Failed to create service resource: " + err.Error(), }) return false } c.JSON(http.StatusCreated, gin.H{"resource_id": resourceID}) return true case http.MethodPut, http.MethodPatch: // 读取请求体数据 data, err := c.GetRawData() if err != nil { c.JSON(http.StatusBadRequest, api.Error{ Errtype: "error", Message: "Failed to read request data: " + err.Error(), }) return false } err = proxy.Update(c, serviceName, node, data) if err != nil { c.JSON(http.StatusInternalServerError, api.Error{ Errtype: "error", Message: "Failed to update service resource: " + err.Error(), }) return false } c.JSON(http.StatusOK, gin.H{"message": "Updated successfully"}) return true case http.MethodDelete: err := proxy.Delete(c, serviceName, node) if err != nil { c.JSON(http.StatusInternalServerError, api.Error{ Errtype: "error", Message: "Failed to delete service resource: " + err.Error(), }) return false } c.JSON(http.StatusNoContent, nil) return true default: c.JSON(http.StatusMethodNotAllowed, api.Error{ Errtype: "error", Message: "Method not allowed", }) return false } }