refactor(bookmark): 重构书签服务入口文件并整合用户权限功能
将 bookmark.go 重命名为 main.go,并调整包引用路径。将 bookmarks 和 user_np 两个模块的处理逻辑合并到同一个服务中,统一注册路由。同时更新了相关 API 的引用路径,确保生成代码与内部实现正确绑定。 此外,移除了独立的 user_np 服务入口文件,其功能已整合至 bookmark 服务中。 配置文件中调整了 user_np 和 vfs 服务的端口及部分接口定义,完善了用户 相关操作的路径参数和请求体结构。
This commit is contained in:
@ -1,240 +0,0 @@
|
||||
// internal/handlers/note_link.go
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
api "git.zzyxyz.com/zzy/zzyxyz_go_api/gen/bookmarks"
|
||||
"git.zzyxyz.com/zzy/zzyxyz_go_api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type BookMarksImpl struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
var adminToken *string
|
||||
|
||||
func validateApiKey(apiKey string) bool {
|
||||
if adminToken != nil && apiKey == *adminToken {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func AuthMiddleware() api.MiddlewareFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 检查当前请求是否需要认证
|
||||
if _, exists := c.Get(api.ApiKeyAuthScopes); exists {
|
||||
// 提取 API Key
|
||||
apiKey := c.GetHeader("X-BookMark-Token")
|
||||
|
||||
return
|
||||
// 验证 API Key(您需要实现这个逻辑)
|
||||
if apiKey == "" || !validateApiKey(apiKey) {
|
||||
c.JSON(http.StatusUnauthorized, api.Error{
|
||||
Errtype: "Unauthorized",
|
||||
Message: "Invalid or missing API key",
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func NewBookMarkPermission() (*api.GinServerOptions, error) {
|
||||
return &api.GinServerOptions{
|
||||
Middlewares: []api.MiddlewareFunc{AuthMiddleware()},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func bookmarkReq2Model(req api.BookmarkRequest) models.Bookmark {
|
||||
return models.Bookmark{
|
||||
Name: req.Name,
|
||||
Link: req.Link,
|
||||
Detail: req.Detail,
|
||||
Description: req.Description,
|
||||
}
|
||||
}
|
||||
|
||||
func bookmarkModel2Res(bookmark models.Bookmark) api.BookmarkResponse {
|
||||
return api.BookmarkResponse{
|
||||
Id: bookmark.ID,
|
||||
Name: bookmark.Name,
|
||||
Link: bookmark.Link,
|
||||
Detail: bookmark.Detail,
|
||||
Description: bookmark.Description,
|
||||
CreatedAt: bookmark.CreatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func NewBookMarks(dbPath string) (*BookMarksImpl, error) {
|
||||
var err error
|
||||
var db *gorm.DB
|
||||
db, err = gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 自动迁移表结构
|
||||
err = db.AutoMigrate(&models.Bookmark{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &BookMarksImpl{db: db}, nil
|
||||
}
|
||||
|
||||
func (b *BookMarksImpl) FindBMFromExternalID(externalID int64) (models.Bookmark, error) {
|
||||
var db = b.db
|
||||
var bookmark models.Bookmark
|
||||
|
||||
// 使用ExternalID查询书签
|
||||
if err := db.Where("external_id = ?", externalID).First(&bookmark).Error; err != nil {
|
||||
return bookmark, err
|
||||
}
|
||||
|
||||
return bookmark, nil
|
||||
}
|
||||
|
||||
// CreateBookmark implements api.ServerInterface.
|
||||
func (b *BookMarksImpl) CreateBookmark(c *gin.Context, id int64) {
|
||||
var db = b.db
|
||||
var req api.BookmarkRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, api.Error{
|
||||
Errtype: "ParameterError",
|
||||
Message: "Invalid request parameters",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查外部ID是否已经存在
|
||||
var existingBookmark models.Bookmark
|
||||
result := db.Where("external_id = ?", id).First(&existingBookmark)
|
||||
if result.Error == nil {
|
||||
// ExternalID已存在,返回冲突错误
|
||||
c.JSON(http.StatusConflict, api.Error{
|
||||
Errtype: "ConflictError",
|
||||
Message: "Bookmark with this External ID already exists",
|
||||
})
|
||||
return
|
||||
} else if result.Error != gorm.ErrRecordNotFound {
|
||||
// 数据库查询出错
|
||||
c.JSON(http.StatusInternalServerError, api.Error{
|
||||
Errtype: "DatabaseError",
|
||||
Message: "Database query error",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
bookmark := bookmarkReq2Model(req)
|
||||
bookmark.ExternalID = id // 设置外部ID
|
||||
if err := db.Create(&bookmark).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, api.Error{
|
||||
Errtype: "DatabaseError",
|
||||
Message: "Failed to create bookmark",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
response := bookmarkModel2Res(bookmark)
|
||||
c.JSON(http.StatusCreated, response)
|
||||
}
|
||||
|
||||
// DeleteBookmark implements api.ServerInterface.
|
||||
func (b *BookMarksImpl) DeleteBookmark(c *gin.Context, id int64) {
|
||||
var db = b.db
|
||||
var bookmark models.Bookmark
|
||||
|
||||
// 使用ExternalID删除书签
|
||||
if err := db.Where("external_id = ?", id).Delete(&bookmark).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, api.Error{
|
||||
Errtype: "DatabaseError",
|
||||
Message: "Failed to delete bookmark",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// GetBookmark implements api.ServerInterface.
|
||||
func (b *BookMarksImpl) GetBookmark(c *gin.Context, id int64) {
|
||||
var db = b.db
|
||||
var bookmark models.Bookmark
|
||||
|
||||
// 使用ExternalID查询书签
|
||||
if err := db.Where("external_id = ?", id).First(&bookmark).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, api.Error{
|
||||
Errtype: "NotFoundError",
|
||||
Message: "Bookmark not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 构造响应
|
||||
response := bookmarkModel2Res(bookmark)
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// UpdateBookmark implements api.ServerInterface.
|
||||
func (b *BookMarksImpl) UpdateBookmark(c *gin.Context, id int64) {
|
||||
var db = b.db
|
||||
var req api.BookmarkRequest
|
||||
|
||||
// 绑定请求参数
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, api.Error{
|
||||
Errtype: "ParameterError",
|
||||
Message: "Invalid request parameters",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 查找要更新的书签(使用ExternalID)
|
||||
var bookmark models.Bookmark
|
||||
if err := db.Where("external_id = ?", id).First(&bookmark).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, api.Error{
|
||||
Errtype: "NotFoundError",
|
||||
Message: "Bookmark not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新书签字段
|
||||
if req.Name != "" {
|
||||
bookmark.Name = req.Name
|
||||
}
|
||||
if req.Link != nil {
|
||||
bookmark.Link = req.Link
|
||||
}
|
||||
if req.Detail != nil {
|
||||
bookmark.Detail = req.Detail
|
||||
}
|
||||
if req.Description != nil {
|
||||
bookmark.Description = req.Description
|
||||
}
|
||||
|
||||
// 保存更新
|
||||
if err := db.Save(&bookmark).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, api.Error{
|
||||
Errtype: "DatabaseError",
|
||||
Message: "Failed to update bookmark",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 构造响应
|
||||
response := bookmarkModel2Res(bookmark)
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Make sure we conform to ServerInterface
|
||||
var _ api.ServerInterface = (*BookMarksImpl)(nil)
|
@ -1,172 +0,0 @@
|
||||
// internal/handlers/user_np.go
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
api "git.zzyxyz.com/zzy/zzyxyz_go_api/gen/user_np"
|
||||
"git.zzyxyz.com/zzy/zzyxyz_go_api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type UserNPImpl struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserNP(dbPath string) (*UserNPImpl, error) {
|
||||
var err error
|
||||
var db *gorm.DB
|
||||
db, err = gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 自动迁移表结构
|
||||
err = db.AutoMigrate(&models.UserNP{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &UserNPImpl{db: db}, nil
|
||||
}
|
||||
|
||||
// PostAuthLogin 用户登录
|
||||
func (u *UserNPImpl) PostAuthLogin(c *gin.Context) {
|
||||
var req api.PostAuthLoginJSONRequestBody
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 查找用户
|
||||
var user models.UserNP
|
||||
if err := u.db.Where("username = ?", req.Username).First(&user).Error; err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
if !user.CheckPassword(req.Password) {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
// 生成JWT token
|
||||
token, err := user.GenerateSimpleJWT()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法生成访问令牌"})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新用户token字段(可选)
|
||||
user.Token = &token
|
||||
u.db.Save(&user)
|
||||
|
||||
c.JSON(http.StatusOK, api.LoginResponse{
|
||||
Token: &token,
|
||||
UserId: &user.ID,
|
||||
})
|
||||
}
|
||||
|
||||
// PostAuthRegister 用户注册
|
||||
func (u *UserNPImpl) PostAuthRegister(c *gin.Context) {
|
||||
var req api.PostAuthRegisterJSONRequestBody
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户名是否已存在
|
||||
var existingUser models.UserNP
|
||||
if err := u.db.Where("username = ?", req.Username).First(&existingUser).Error; err == nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "用户名已存在"})
|
||||
return
|
||||
}
|
||||
|
||||
// 创建新用户
|
||||
user := models.UserNP{
|
||||
Username: req.Username,
|
||||
Email: req.Email,
|
||||
}
|
||||
|
||||
// 加密密码
|
||||
if err := user.HashPassword(req.Password); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "密码处理失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 保存到数据库
|
||||
if err := u.db.Create(&user).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "用户创建失败"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, nil)
|
||||
}
|
||||
|
||||
// PutAuthPassword 修改密码
|
||||
func (u *UserNPImpl) PutAuthPassword(c *gin.Context) {
|
||||
// 获取Authorization头中的token
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if authHeader == "" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "缺少访问令牌"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证token并获取用户名
|
||||
username, err := models.CheckSimpleJWT(authHeader)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var req api.PutAuthPasswordJSONRequestBody
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 查找用户
|
||||
var user models.UserNP
|
||||
if err := u.db.Where("username = ?", username).First(&user).Error; err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证旧密码
|
||||
if !user.CheckPassword(req.OldPassword) {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "旧密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
// 加密新密码
|
||||
if err := user.HashPassword(req.NewPassword); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "密码处理失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 保存到数据库
|
||||
if err := u.db.Save(&user).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "密码更新失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 生成新的JWT token
|
||||
token, err := user.GenerateSimpleJWT()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法生成新的访问令牌"})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新用户token字段
|
||||
user.Token = &token
|
||||
u.db.Save(&user)
|
||||
|
||||
c.JSON(http.StatusOK, nil)
|
||||
}
|
||||
|
||||
// Make sure we conform to ServerInterface
|
||||
var _ api.ServerInterface = (*UserNPImpl)(nil)
|
@ -1,354 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
// internal/handlers/vfs_driver/vfs_bookmark.go
|
||||
|
||||
package vfsdriver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
api "git.zzyxyz.com/zzy/zzyxyz_go_api/gen/bookmarks"
|
||||
"git.zzyxyz.com/zzy/zzyxyz_go_api/internal/handlers"
|
||||
"git.zzyxyz.com/zzy/zzyxyz_go_api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type VfsBookMarkService struct {
|
||||
client *api.ClientWithResponses
|
||||
}
|
||||
|
||||
func NewVfsBookMarkService(serverURL string) (*VfsBookMarkService, error) {
|
||||
client, err := api.NewClientWithResponses(serverURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &VfsBookMarkService{
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Create implements ServiceProxy.
|
||||
func (v *VfsBookMarkService) Create(c *gin.Context, servicePath string, node *models.VfsNode, data []byte) (string, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
// 解析传入的数据为 BookmarkRequest
|
||||
var req api.BookmarkRequest
|
||||
if err := json.Unmarshal(data, &req); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 调用 bookmark 服务创建书签
|
||||
resp, err := v.client.CreateBookmarkWithResponse(ctx, int64(node.ID), req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 处理响应
|
||||
if resp.JSON201 != nil {
|
||||
result, err := json.Marshal(resp.JSON201)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(result), nil
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if resp.JSON400 != nil {
|
||||
return "", fmt.Errorf("bad request: %s", resp.JSON400.Message)
|
||||
}
|
||||
|
||||
if resp.JSON500 != nil {
|
||||
return "", fmt.Errorf("server error: %s", resp.JSON500.Message)
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("unknown error")
|
||||
}
|
||||
|
||||
// Delete implements ServiceProxy.
|
||||
func (v *VfsBookMarkService) Delete(c *gin.Context, servicePath string, node *models.VfsNode) error {
|
||||
ctx := context.Background()
|
||||
|
||||
// 调用 bookmark 服务删除书签
|
||||
resp, err := v.client.DeleteBookmarkWithResponse(ctx, int64(node.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 处理响应
|
||||
if resp.StatusCode() == 204 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if resp.JSON404 != nil {
|
||||
return fmt.Errorf("not found: %s", resp.JSON404.Message)
|
||||
}
|
||||
|
||||
if resp.JSON500 != nil {
|
||||
return fmt.Errorf("server error: %s", resp.JSON500.Message)
|
||||
}
|
||||
|
||||
return fmt.Errorf("unknown error")
|
||||
}
|
||||
|
||||
// Get implements ServiceProxy.
|
||||
func (v *VfsBookMarkService) Get(c *gin.Context, servicePath string, node *models.VfsNode) (any, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
// 调用 bookmark 服务获取书签
|
||||
resp, err := v.client.GetBookmarkWithResponse(ctx, int64(node.ID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 处理响应
|
||||
if resp.JSON200 != nil {
|
||||
return resp.JSON200, nil
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if resp.JSON404 != nil {
|
||||
return nil, fmt.Errorf("not found: %s", resp.JSON404.Message)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown error")
|
||||
}
|
||||
|
||||
// GetName implements ServiceProxy.
|
||||
func (v *VfsBookMarkService) GetName() string {
|
||||
return "bookmark"
|
||||
}
|
||||
|
||||
// Update implements ServiceProxy.
|
||||
func (v *VfsBookMarkService) Update(c *gin.Context, servicePath string, node *models.VfsNode, data []byte) error {
|
||||
ctx := context.Background()
|
||||
|
||||
// 解析传入的数据为 BookmarkRequest
|
||||
var req api.BookmarkRequest
|
||||
if err := json.Unmarshal(data, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 调用 bookmark 服务更新书签
|
||||
resp, err := v.client.UpdateBookmarkWithResponse(ctx, int64(node.ID), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 处理响应
|
||||
if resp.JSON200 != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if resp.JSON400 != nil {
|
||||
return fmt.Errorf("bad request: %s", resp.JSON400.Message)
|
||||
}
|
||||
|
||||
if resp.JSON404 != nil {
|
||||
return fmt.Errorf("not found: %s", resp.JSON404.Message)
|
||||
}
|
||||
|
||||
if resp.JSON500 != nil {
|
||||
return fmt.Errorf("server error: %s", resp.JSON500.Message)
|
||||
}
|
||||
|
||||
return fmt.Errorf("unknown error")
|
||||
}
|
||||
|
||||
var _ handlers.ServiceProxy = (*VfsBookMarkService)(nil)
|
Reference in New Issue
Block a user