From 35e79e54f12907cd4943391988b799ac4baeaae8 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Mon, 29 Sep 2025 00:42:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor(vfs):=20=E9=87=8D=E6=9E=84VFS=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=EF=BC=8C=E6=8B=86=E5=88=86=E6=95=B0=E6=8D=AE=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E9=80=BB=E8=BE=91=E4=B8=8E=E8=B7=AF=E5=BE=84=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将原先的 `vfs.go` 文件中的功能进行拆分,创建了独立的 DAO 层文件 `vfs_dao.go` 和路径处理文件 `vfs_path.go`,以提升代码结构清晰度和可维护性。 - 将数据库操作相关方法迁移至 `VfsDAO` 结构体中 - 新增 `vfs_dao.go` 文件用于管理底层数据访问对象 - 新增 `vfs_path.go` 文件专门处理路径解析逻辑 - 移除了原 `vfs.go` 中的数据库初始化、用户及节点操作等冗余代码 --- internal/vfs/models/vfs.go | 563 ------------------ internal/vfs/models/vfs_dao.go | 336 +++++++++++ internal/vfs/models/vfs_path.go | 44 ++ internal/vfs/services/vfs_core.go | 396 ++++++++++++ internal/vfs/services/vfs_error.go | 50 ++ .../{vfs_service.go => services/vfs_proxy.go} | 38 +- internal/vfs/services/vfs_user.go | 82 +++ .../{ => services}/vfsdriver/vfs_bookmark.go | 8 +- internal/vfs/vfs.go | 26 +- internal/vfs/vfs_auth.go | 14 +- internal/vfs/vfs_impl.go | 549 +++++------------ internal/vfs/vfs_user.go | 1 - main.go | 4 +- 13 files changed, 1106 insertions(+), 1005 deletions(-) create mode 100644 internal/vfs/models/vfs_dao.go create mode 100644 internal/vfs/models/vfs_path.go create mode 100644 internal/vfs/services/vfs_core.go create mode 100644 internal/vfs/services/vfs_error.go rename internal/vfs/{vfs_service.go => services/vfs_proxy.go} (72%) create mode 100644 internal/vfs/services/vfs_user.go rename internal/vfs/{ => services}/vfsdriver/vfs_bookmark.go (94%) delete mode 100644 internal/vfs/vfs_user.go diff --git a/internal/vfs/models/vfs.go b/internal/vfs/models/vfs.go index c63fc9d..0fea100 100644 --- a/internal/vfs/models/vfs.go +++ b/internal/vfs/models/vfs.go @@ -2,21 +2,11 @@ package models import ( - "crypto/rand" - "database/sql" - "errors" - "fmt" - "path" - "strings" "time" _ "github.com/mattn/go-sqlite3" ) -type Vfs struct { - DB *sql.DB -} - type VfsNodeType int const ( @@ -39,556 +29,3 @@ type VfsUser struct { Name string Token string } - -type VfsDirEntry struct { - ID uint64 - Name string - Type VfsNodeType -} - -// NewVfs 创建新的 VFS 实例 -func NewVfs(dbPath string) (*Vfs, error) { - db, err := sql.Open("sqlite3", dbPath) - if err != nil { - return nil, err - } - - _, err = db.Exec(` - CREATE TABLE IF NOT EXISTS vfs_nodes ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - parent_id INTEGER, - type INTEGER NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - UNIQUE(parent_id, name) - )`) - if err != nil { - return nil, err - } - - _, err = db.Exec(` - CREATE TABLE IF NOT EXISTS vfs_users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE, - token TEXT NOT NULL UNIQUE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - )`) - if err != nil { - return nil, err - } - - err = createInitialDirectories(db) - if err != nil { - return nil, err - } - - return &Vfs{DB: db}, nil -} - -// 创建初始目录结构 -func createInitialDirectories(db *sql.DB) error { - var err error - // 创建 /home 目录 - _, err = db.Exec(` - INSERT OR IGNORE INTO vfs_nodes (name, parent_id, type, created_at, updated_at) - VALUES ('home', 0, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, - VfsNodeTypeDirectory) - if err != nil { - return err - } - - // 创建 /public 目录 - _, err = db.Exec(` - INSERT OR IGNORE INTO vfs_nodes (name, parent_id, type, created_at, updated_at) - VALUES ('public', 0, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, - VfsNodeTypeDirectory) - if err != nil { - return err - } - - return nil -} - -func generateToken() string { - bytes := make([]byte, 16) - if _, err := rand.Read(bytes); err != nil { - // fallback to time-based token - return fmt.Sprintf("%x", time.Now().UnixNano()) - } - return fmt.Sprintf("%x", bytes) -} - -// 添加用户相关操作 -func (v *Vfs) CreateUser(username string) (string, error) { - // 生成随机token - token := generateToken() - - // 检查用户是否已存在 - _, err := v.GetUserByName(username) - if err == nil { - return "", errors.New("user already exists") - } - - // 插入用户(不使用事务) - _, err = v.DB.Exec("INSERT INTO vfs_users (name, token) VALUES (?, ?)", username, token) - if err != nil { - return "", err - } - - // 使用 defer 确保出错时能清理已创建的用户 - defer func() { - if err != nil { - v.DB.Exec("DELETE FROM vfs_users WHERE name = ? AND token = ?", username, token) - } - }() - - // 确保 /home 目录存在 - homeDir, getHomeErr := v.GetNodeByPath("/home/") - if getHomeErr != nil { - // 如果 /home 不存在,创建它 - homeDir = &VfsNode{ - Name: "home", - ParentID: 0, - Type: VfsNodeTypeDirectory, - } - if createHomeErr := v.CreateVFSNode(*homeDir); createHomeErr != nil { - err = createHomeErr - return "", err - } - } - - // 创建用户目录 /home/username - userDir := VfsNode{ - Name: username, - ParentID: homeDir.ID, - Type: VfsNodeTypeDirectory, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - } - if createDirErr := v.CreateVFSNode(userDir); createDirErr != nil { - err = createDirErr - return "", err - } - - if userDir, getUserErr := v.GetNodeByParentIDAndName(homeDir.ID, username); getUserErr != nil { - panic(getUserErr) - } else { - dotDir := VfsNode{ - Name: ".Recycle_Bin", - ParentID: userDir.ID, - Type: VfsNodeTypeDirectory, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - } - if createDirErr := v.CreateVFSNode(dotDir); createDirErr != nil { - err = createDirErr - return "", err - } - } - - return token, nil -} - -func (v *Vfs) DeleteUser(username string) error { - // TODO: 递归删除用户相关文件 - // 这里暂时只删除用户记录 - _, err := v.DB.Exec("DELETE FROM vfs_users WHERE name = ?", username) - return err -} - -func (v *Vfs) GetUserByToken(token string) (*VfsUser, error) { - user := &VfsUser{} - err := v.DB.QueryRow("SELECT name, token FROM vfs_users WHERE token = ?", token). - Scan(&user.Name, &user.Token) - if err != nil { - if err == sql.ErrNoRows { - return nil, errors.New("user not found") - } - return nil, err - } - return user, nil -} - -func (v *Vfs) GetUserByName(username string) (*VfsUser, error) { - user := &VfsUser{} - err := v.DB.QueryRow("SELECT name, token FROM vfs_users WHERE name = ?", username). - Scan(&user.Name, &user.Token) - if err != nil { - if err == sql.ErrNoRows { - return nil, errors.New("user not found") - } - return nil, err - } - return user, nil -} - -// GetChildrenID 获取目录下所有子项的 ID -func (v *Vfs) GetChildren(parentID uint64) ([]VfsDirEntry, error) { - rows, err := v.DB.Query("SELECT id, name, type FROM vfs_nodes WHERE parent_id = ?", parentID) - if err != nil { - return nil, err - } - defer rows.Close() - - var dirEntrys []VfsDirEntry - for rows.Next() { - var entry VfsDirEntry - if err := rows.Scan(&entry.ID, &entry.Name, &entry.Type); err != nil { - return nil, err - } - dirEntrys = append(dirEntrys, entry) - } - - return dirEntrys, nil -} - -func (v *Vfs) GetChildrenID(parentID uint64, recursive bool) (ids []uint64, services []uint64, err error) { - if recursive { - // 递归获取所有子项ID - err := v.getChildrenIDRecursive(parentID, &ids, &services) - if err != nil { - return nil, nil, err - } - } else { - // 只获取直接子项ID - rows, err := v.DB.Query("SELECT id FROM vfs_nodes WHERE parent_id = ?", parentID) - if err != nil { - return nil, nil, err - } - defer rows.Close() - - for rows.Next() { - var id uint64 - if err := rows.Scan(&id); err != nil { - return nil, nil, err - } - ids = append(ids, id) - } - } - - return ids, services, nil -} - -// DeleteNodeRecursively 递归删除节点及其所有子项 -func (v *Vfs) DeleteNodeRecursively(nodeID uint64) ([]uint64, error) { - // 获取所有需要删除的ID(包括自己和所有子项) - idsToDelete := []uint64{nodeID} - - // 获取所有子项ID - childIDs, sericeIDs, err := v.GetChildrenID(nodeID, true) - if err != nil { - return nil, err - } - - idsToDelete = append(idsToDelete, childIDs...) - - // 构建删除语句 - if len(idsToDelete) == 0 { - return nil, nil - } - - // 创建占位符 - placeholders := make([]string, len(idsToDelete)) - args := make([]any, len(idsToDelete)) - for i, id := range idsToDelete { - placeholders[i] = "?" - args[i] = id - } - - query := fmt.Sprintf("DELETE FROM vfs_nodes WHERE id IN (%s)", strings.Join(placeholders, ",")) - - _, err = v.DB.Exec(query, args...) - return sericeIDs, err -} - -// getChildrenIDRecursive 递归获取所有子项ID的辅助函数 -func (v *Vfs) getChildrenIDRecursive(parentID uint64, ids *[]uint64, services *[]uint64) error { - // 获取当前层级的子项 - rows, err := v.DB.Query("SELECT id, type FROM vfs_nodes WHERE parent_id = ?", parentID) - if err != nil { - return err - } - defer rows.Close() - - for rows.Next() { - var id uint64 - var nodeType VfsNodeType - if err := rows.Scan(&id, &nodeType); err != nil { - return err - } - - // 将当前节点ID添加到列表中 - *ids = append(*ids, id) - - // 如果是目录,递归获取其子项 - switch nodeType { - case VfsNodeTypeDirectory: - err := v.getChildrenIDRecursive(id, ids, services) - if err != nil { - return err - } - case VfsNodeTypeService: - *services = append(*services, id) - } - } - - return nil -} - -// GetParentID 根据父路径查找父节点 ID -// parentPath 应该是 ParsePathComponents 的第一个返回值 -func (v *Vfs) GetParentID(parentPath string) (uint64, error) { - // 根目录特殊处理 - if parentPath == "/" || parentPath == "" { - return 0, nil - } - - // 递归查找父路径ID - // 先解析父路径的父路径和节点名 - grandParentPath, parentName, _, err := ParsePathComponents(parentPath) - if err != nil { - return 0, err - } - - // 递归获取祖父节点ID - grandParentID, err := v.GetParentID(grandParentPath) - if err != nil { - return 0, err - } - - // 在祖父节点下查找父节点 - var parentID uint64 - err = v.DB.QueryRow("SELECT id FROM vfs_nodes WHERE parent_id = ? AND name = ?", - grandParentID, parentName).Scan(&parentID) - - if err != nil { - if err == sql.ErrNoRows { - return 0, errors.New("parent path not found") - } - return 0, err - } - - return parentID, nil -} - -// GetNodeByPath 根据完整路径查找节点 -func (v *Vfs) GetNodeByPath(fullPath string) (*VfsNode, error) { - // 根目录特殊处理 - if path.Clean(fullPath) == "/" { - return &VfsNode{ - ID: 0, - Name: "/", - ParentID: 0, - Type: VfsNodeTypeDirectory, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, nil - } - - // 使用 ParsePathComponents 解析路径 - parentPath, nodeName, nodeType, err := ParsePathComponents(fullPath) - if err != nil { - return nil, err - } - - // 获取父节点ID - parentID, err := v.GetParentID(parentPath) - if err != nil { - return nil, err - } - - // 根据 parentID, nodeName, nodeType 查找或创建节点 - node, err := v.GetNodeByParentIDAndName(parentID, nodeName) - if err != nil { - // 如果节点不存在,可以选择创建它或者返回错误 - // 这里根据你的需求决定是返回错误还是创建节点 - return nil, err - } - - if node.Type != nodeType { - return nil, errors.New("node type mismatch") - } - - return node, nil -} - -// GetNodeByParentIDAndName 根据父ID和名称查找节点 -func (v *Vfs) GetNodeByParentIDAndName(parentID uint64, name string) (*VfsNode, error) { - node := &VfsNode{} - err := v.DB.QueryRow(` - SELECT id, name, parent_id, type, created_at, updated_at - FROM vfs_nodes - WHERE parent_id = ? AND name = ?`, parentID, name).Scan( - &node.ID, &node.Name, &node.ParentID, &node.Type, &node.CreatedAt, &node.UpdatedAt) - - if err != nil { - if err == sql.ErrNoRows { - return nil, errors.New("node not found") - } - return nil, err - } - - return node, nil -} - -// CreateNodeByComponents 根据路径组件创建节点 -func (v *Vfs) CreateNodeByComponents(parentPath, nodeName string, nodeType VfsNodeType) (*VfsNode, error) { - // 获取父节点ID - parentID, err := v.GetParentID(parentPath) - if err != nil { - return nil, err - } - - // 创建新节点 - node := &VfsNode{ - Name: nodeName, - ParentID: parentID, - Type: nodeType, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - } - - // 保存到数据库 - result, err := v.DB.Exec(` - INSERT INTO vfs_nodes (name, parent_id, type, created_at, updated_at) - VALUES (?, ?, ?, ?, ?)`, - node.Name, node.ParentID, node.Type, node.CreatedAt, node.UpdatedAt) - - if err != nil { - return nil, err - } - - // 获取插入的ID - id, err := result.LastInsertId() - if err != nil { - return nil, err - } - - node.ID = uint64(id) - return node, nil -} - -func ParsePathComponents(pathStr string) (parentPath, nodeName string, nodeType VfsNodeType, err error) { - // FIXME: 路径判断以及update的类型判断 - abspath := path.Clean(pathStr) - if !path.IsAbs(abspath) { - return "", "", 0, errors.New("path must be absolute") - } - - // 特殊处理根路径 - if abspath == "/" { - return "", "", VfsNodeTypeDirectory, nil - } - - // 判断是文件还是目录 - nodeType = VfsNodeTypeFile - // 如果原始路径以 / 结尾,则为目录 - if len(pathStr) > 1 && pathStr[len(pathStr)-1] == '/' { - nodeType = VfsNodeTypeDirectory - } - if nodeType == VfsNodeTypeFile && path.Ext(pathStr) == ".api" { - nodeType = VfsNodeTypeService - } - - // 分割路径 - parentPath, nodeName = path.Split(abspath) - - // 清理父路径 - if parentPath != "/" && parentPath != "" { - parentPath = path.Clean(parentPath) - } - - // 处理特殊情况 - if parentPath == "." { - parentPath = "/" - } - - return parentPath, nodeName, nodeType, nil -} - -// MoveToPath 将节点移动到指定路径 -func (v *Vfs) MoveToPath(node *VfsNode, destPath string) error { - // FIXME: 路径和权限的检查 - // 1. 解析目标路径 - parentPath, nodeName, _, err := ParsePathComponents(destPath) - if err != nil { - return fmt.Errorf("invalid destination path: %w", err) - } - - // 2. 查找目标父节点 - parentID, err := v.GetParentID(parentPath) - if err != nil { - return fmt.Errorf("failed to find parent directory '%s': %w", parentPath, err) - } - - // 3. 检查目标位置是否已存在同名节点 - _, err = v.GetNodeByParentIDAndName(parentID, nodeName) - if err == nil { - return fmt.Errorf("destination path '%s' already exists", destPath) - } - if err.Error() != "node not found" { - return fmt.Errorf("error checking destination path: %w", err) - } - - // 4. 更新节点的父节点ID和名称 - node.ParentID = parentID - node.Name = nodeName - node.UpdatedAt = time.Now() - - // 5. 更新数据库中的节点信息 - _, err = v.DB.Exec(` - UPDATE vfs_nodes - SET name = ?, parent_id = ?, updated_at = ? - WHERE id = ?`, - node.Name, node.ParentID, node.UpdatedAt, node.ID) - if err != nil { - return fmt.Errorf("failed to update node: %w", err) - } - - return nil -} - -func (v *Vfs) CheckNameValid(name string) error { - if name == "" || strings.Contains(name, "/") { - return fmt.Errorf("invalid node name") - } - return nil -} - -func (v *Vfs) CreateVFSNode(p VfsNode) error { - _, err := v.DB.Exec(` - INSERT INTO vfs_nodes (name, parent_id, type, created_at, updated_at) - VALUES (?, ?, ?, ?, ?)`, - p.Name, p.ParentID, p.Type, time.Now(), time.Now()) - return err -} - -func (v *Vfs) DeleteVFSNode(p *VfsNode) error { - _, err := v.DB.Exec("DELETE FROM vfs_nodes WHERE id = ?", p.ID) - return err -} - -func (v *Vfs) GetVFSNode(ID uint64) *VfsNode { - node := &VfsNode{} - err := v.DB.QueryRow(` - SELECT id, name, parent_id, type, created_at, updated_at - FROM vfs_nodes - WHERE id = ?`, ID).Scan( - &node.ID, &node.Name, &node.ParentID, &node.Type, &node.CreatedAt, &node.UpdatedAt) - - if err != nil { - return nil - } - - return node -} - -func (v *Vfs) UpdateVFSNode(p *VfsNode) error { - _, err := v.DB.Exec(` - UPDATE vfs_nodes - SET name = ?, parent_id = ?, type = ?, updated_at = ? - WHERE id = ?`, - p.Name, p.ParentID, p.Type, time.Now(), p.ID) - return err -} diff --git a/internal/vfs/models/vfs_dao.go b/internal/vfs/models/vfs_dao.go new file mode 100644 index 0000000..3381124 --- /dev/null +++ b/internal/vfs/models/vfs_dao.go @@ -0,0 +1,336 @@ +// models/vfs_dao.go - 数据访问对象 +package models + +import ( + "database/sql" + "errors" + "fmt" + "strings" + "time" +) + +// VfsDAO 处理底层数据库操作 +type VfsDAO struct { + DB *sql.DB +} + +type VfsDirEntry struct { + ID uint64 + Name string + Type VfsNodeType +} + +func NewVfsDAO(dbPath string) (*VfsDAO, error) { + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return nil, err + } + + _, err = db.Exec(` + CREATE TABLE IF NOT EXISTS vfs_nodes ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + parent_id INTEGER, + type INTEGER NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(parent_id, name) + )`) + if err != nil { + return nil, err + } + + _, err = db.Exec(` + CREATE TABLE IF NOT EXISTS vfs_users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE, + token TEXT NOT NULL UNIQUE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )`) + if err != nil { + return nil, err + } + + vfsdao := VfsDAO{DB: db} + err = vfsdao.createInitialDirectories() + if err != nil { + return nil, err + } + + return &vfsdao, nil +} + +// 创建初始目录结构 +func (dao *VfsDAO) createInitialDirectories() error { + var err error + // 创建 /home 目录 + _, err = dao.DB.Exec(` + INSERT OR IGNORE INTO vfs_nodes (name, parent_id, type, created_at, updated_at) + VALUES ('home', 0, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, + VfsNodeTypeDirectory) + if err != nil { + return err + } + + // 创建 /public 目录 + _, err = dao.DB.Exec(` + INSERT OR IGNORE INTO vfs_nodes (name, parent_id, type, created_at, updated_at) + VALUES ('public', 0, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, + VfsNodeTypeDirectory) + if err != nil { + return err + } + + return nil +} + +// Node 相关操作 +func (dao *VfsDAO) CreateNode(node VfsNode) error { + _, err := dao.DB.Exec(` + INSERT INTO vfs_nodes (name, parent_id, type, created_at, updated_at) + VALUES (?, ?, ?, ?, ?)`, + node.Name, node.ParentID, node.Type, time.Now(), time.Now()) + return err +} + +func (dao *VfsDAO) UpdateNode(node *VfsNode) error { + _, err := dao.DB.Exec(` + UPDATE vfs_nodes + SET name = ?, parent_id = ?, type = ?, updated_at = ? + WHERE id = ?`, + node.Name, node.ParentID, node.Type, time.Now(), node.ID) + return err +} + +func (dao *VfsDAO) DeleteNode(id uint64) error { + _, err := dao.DB.Exec("DELETE FROM vfs_nodes WHERE id = ?", id) + return err +} + +func (dao *VfsDAO) GetNodeByID(id uint64) (*VfsNode, error) { + node := &VfsNode{} + err := dao.DB.QueryRow(` + SELECT id, name, parent_id, type, created_at, updated_at + FROM vfs_nodes + WHERE id = ?`, id).Scan( + &node.ID, &node.Name, &node.ParentID, &node.Type, &node.CreatedAt, &node.UpdatedAt) + + if err != nil { + if err == sql.ErrNoRows { + return nil, errors.New("node not found") + } + return nil, err + } + + return node, nil +} + +func (dao *VfsDAO) GetNodeByParentIDAndName(parentID uint64, name string) (*VfsNode, error) { + node := &VfsNode{} + err := dao.DB.QueryRow(` + SELECT id, name, parent_id, type, created_at, updated_at + FROM vfs_nodes + WHERE parent_id = ? AND name = ?`, parentID, name).Scan( + &node.ID, &node.Name, &node.ParentID, &node.Type, &node.CreatedAt, &node.UpdatedAt) + + if err != nil { + if err == sql.ErrNoRows { + return nil, nil + } + return nil, err + } + + return node, nil +} + +// GetParentID 根据父路径查找父节点 ID +// parentPath 应该是 ParsePathComponents 的第一个返回值 +func (dao *VfsDAO) GetNodeByPath(parentPath string) (*VfsNode, error) { + // log.Printf("GetNodeByPath: %s", parentPath) + // 根目录特殊处理 + if parentPath == "/" || parentPath == "" { + return &VfsNode{ + ID: 0, + Name: "Root", + ParentID: 0, + }, nil + } + + // 递归查找父路径ID + // 先解析父路径的父路径和节点名 + grandParentPath, parentName, _, err := ParsePathComponents(parentPath) + if err != nil { + return nil, err + } + + // 递归获取祖父节点ID + grandParentNode, err := dao.GetNodeByPath(grandParentPath) + if err != nil { + return nil, err + } + + // 在祖父节点下查找父节点 + var parentID uint64 + err = dao.DB.QueryRow("SELECT id FROM vfs_nodes WHERE parent_id = ? AND name = ?", + grandParentNode.ID, parentName).Scan(&parentID) + // log.Printf("parentID: %+v, %+v, %+v", grandParentNode, parentName, parentID) + + if err != nil { + if err == sql.ErrNoRows { + return nil, errors.New("parent path not found") + } + return nil, err + } + + return dao.GetNodeByID(parentID) +} + +func (dao *VfsDAO) GetChildren(parentID uint64) ([]VfsDirEntry, error) { + rows, err := dao.DB.Query("SELECT id, name, type FROM vfs_nodes WHERE parent_id = ?", parentID) + if err != nil { + return nil, err + } + defer rows.Close() + + var dirEntries []VfsDirEntry + for rows.Next() { + var entry VfsDirEntry + if err := rows.Scan(&entry.ID, &entry.Name, &entry.Type); err != nil { + return nil, err + } + dirEntries = append(dirEntries, entry) + } + + return dirEntries, nil +} + +// 递归获取所有子项ID的辅助函数 +func (dao *VfsDAO) getChildrenIDRecursive(parentID uint64, ids *[]uint64, services *[]uint64) error { + // 获取当前层级的子项 + rows, err := dao.DB.Query("SELECT id, type FROM vfs_nodes WHERE parent_id = ?", parentID) + if err != nil { + return err + } + defer rows.Close() + + for rows.Next() { + var id uint64 + var nodeType VfsNodeType + if err := rows.Scan(&id, &nodeType); err != nil { + return err + } + + // 将当前节点ID添加到列表中 + *ids = append(*ids, id) + + // 如果是目录,递归获取其子项 + switch nodeType { + case VfsNodeTypeDirectory: + err := dao.getChildrenIDRecursive(id, ids, services) + if err != nil { + return err + } + case VfsNodeTypeService: + *services = append(*services, id) + } + } + + return nil +} + +// GetChildrenID 获取目录下所有子项的 ID +func (dao *VfsDAO) GetChildrenID(parentID uint64, recursive bool) (ids []uint64, services []uint64, err error) { + if recursive { + // 递归获取所有子项ID + err := dao.getChildrenIDRecursive(parentID, &ids, &services) + if err != nil { + return nil, nil, err + } + } else { + // 只获取直接子项ID + rows, err := dao.DB.Query("SELECT id FROM vfs_nodes WHERE parent_id = ?", parentID) + if err != nil { + return nil, nil, err + } + defer rows.Close() + + for rows.Next() { + var id uint64 + if err := rows.Scan(&id); err != nil { + return nil, nil, err + } + ids = append(ids, id) + } + } + + return ids, services, nil +} + +// DeleteNodeRecursively 递归删除节点及其所有子项 +func (dao *VfsDAO) DeleteNodeRecursively(nodeID uint64) ([]uint64, error) { + // 获取所有需要删除的ID(包括自己和所有子项) + idsToDelete := []uint64{nodeID} + + // 获取所有子项ID + childIDs, serviceIDs, err := dao.GetChildrenID(nodeID, true) + if err != nil { + return nil, err + } + + idsToDelete = append(idsToDelete, childIDs...) + + // 构建删除语句 + if len(idsToDelete) == 0 { + return nil, nil + } + + // 创建占位符 + placeholders := make([]string, len(idsToDelete)) + args := make([]any, len(idsToDelete)) + for i, id := range idsToDelete { + placeholders[i] = "?" + args[i] = id + } + + query := fmt.Sprintf("DELETE FROM vfs_nodes WHERE id IN (%s)", strings.Join(placeholders, ",")) + + _, err = dao.DB.Exec(query, args...) + return serviceIDs, err +} + +// User 相关操作 +func (dao *VfsDAO) GetUserByToken(token string) (*VfsUser, error) { + user := &VfsUser{} + err := dao.DB.QueryRow("SELECT name, token FROM vfs_users WHERE token = ?", token). + Scan(&user.Name, &user.Token) + if err != nil { + if err == sql.ErrNoRows { + return nil, errors.New("user not found") + } + return nil, err + } + return user, nil +} + +func (dao *VfsDAO) GetUserByName(username string) (*VfsUser, error) { + user := &VfsUser{} + err := dao.DB.QueryRow("SELECT name, token FROM vfs_users WHERE name = ?", username). + Scan(&user.Name, &user.Token) + if err != nil { + if err == sql.ErrNoRows { + return nil, errors.New("user not found") + } + return nil, err + } + return user, nil +} + +func (dao *VfsDAO) CreateUser(username, token string) error { + _, err := dao.DB.Exec("INSERT INTO vfs_users (name, token) VALUES (?, ?)", username, token) + return err +} + +func (dao *VfsDAO) DeleteUser(username string) error { + _, err := dao.DB.Exec("DELETE FROM vfs_users WHERE name = ?", username) + return err +} diff --git a/internal/vfs/models/vfs_path.go b/internal/vfs/models/vfs_path.go new file mode 100644 index 0000000..046de6c --- /dev/null +++ b/internal/vfs/models/vfs_path.go @@ -0,0 +1,44 @@ +package models + +import ( + "errors" + "path" +) + +func ParsePathComponents(pathStr string) (parentPath, nodeName string, nodeType VfsNodeType, err error) { + // FIXME: 路径判断以及update的类型判断 + abspath := path.Clean(pathStr) + if !path.IsAbs(abspath) { + return "", "", 0, errors.New("path must be absolute") + } + + // 特殊处理根路径 + if abspath == "/" { + return "", "", VfsNodeTypeDirectory, nil + } + + // 判断是文件还是目录 + nodeType = VfsNodeTypeFile + // 如果原始路径以 / 结尾,则为目录 + if len(pathStr) > 1 && pathStr[len(pathStr)-1] == '/' { + nodeType = VfsNodeTypeDirectory + } + if nodeType == VfsNodeTypeFile && path.Ext(pathStr) == ".api" { + nodeType = VfsNodeTypeService + } + + // 分割路径 + parentPath, nodeName = path.Split(abspath) + + // 清理父路径 + if parentPath != "/" && parentPath != "" { + parentPath = path.Clean(parentPath) + } + + // 处理特殊情况 + if parentPath == "." { + parentPath = "/" + } + + return parentPath, nodeName, nodeType, nil +} diff --git a/internal/vfs/services/vfs_core.go b/internal/vfs/services/vfs_core.go new file mode 100644 index 0000000..fb70325 --- /dev/null +++ b/internal/vfs/services/vfs_core.go @@ -0,0 +1,396 @@ +package vfs_service + +import ( + "fmt" + + "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/models" +) + +type VfsCoreService struct { + vfs *models.VfsDAO +} + +type VfsCallback func(this any, node *models.VfsNode, input []byte) ([]byte, error) + +func NewVfsCoreService(vfs *models.VfsDAO) *VfsCoreService { + return &VfsCoreService{vfs: vfs} +} + +type CreateVFSNodeResult struct { + Node *models.VfsNode + Content []byte // 回调处理后的结果 +} + +func (s *VfsCoreService) CreateVFSNode(path string, content []byte, callback VfsCallback, thisArg any) (*CreateVFSNodeResult, *VFSError) { + // 解析路径组件 + parentPath, nodeName, nodeType, err := models.ParsePathComponents(path) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeInvalidPath, + Error: err, + } + } + + parentNode, err := s.vfs.GetNodeByPath(parentPath) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypePathNotFound, + Error: err, + } + } + + node := models.VfsNode{ + Name: nodeName, + ParentID: parentNode.ID, + Type: nodeType, + } + + if err := s.vfs.CreateNode(node); err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeCreationFailed, + Error: err, + } + } + + // 获取创建后的完整节点信息 + createdNode, err := s.vfs.GetNodeByParentIDAndName(parentNode.ID, nodeName) + if err != nil { + // 回滚 + s.vfs.DeleteNode(node.ID) + return nil, &VFSError{ + Type: ErrorTypeNodeCreationFailed, + Error: err, + } + } + + // 执行回调处理 + var resultContent []byte + if callback != nil && createdNode.Type == models.VfsNodeTypeService { + ret, err := callback(thisArg, createdNode, content) + if err != nil { + // 回滚操作 + s.vfs.DeleteNode(createdNode.ID) + return nil, &VFSError{ + Type: ErrorTypeServiceProxyFailed, + Error: err, + } + } + resultContent = ret + } + + return &CreateVFSNodeResult{ + Node: createdNode, + Content: resultContent, + }, nil +} + +func (s *VfsCoreService) DeleteVFSNodeRecursively(path string, callback VfsCallback, thisArg any) (*models.VfsNode, *VFSError) { + // 获取节点 + node, err := s.vfs.GetNodeByPath(path) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeNotFound, + Error: err, + } + } + + // 递归删除节点 + if err := s.deleteNodeRecursively(node, callback, thisArg); err != nil { + return nil, err + } + + return node, nil +} + +// deleteNodeRecursively 递归删除节点及其所有子节点 +func (s *VfsCoreService) deleteNodeRecursively(node *models.VfsNode, callback VfsCallback, thisArg any) *VFSError { + // 如果是目录,先递归删除所有子节点 + if node.Type == models.VfsNodeTypeDirectory { + // 获取所有子节点 + children, err := s.vfs.GetChildren(node.ID) + if err != nil { + return &VFSError{ + Type: ErrorTypeInternal, + Error: fmt.Errorf("failed to get directory children: %v", err), + } + } + + // 递归删除每个子节点 + for _, childEntry := range children { + // 根据子条目获取完整节点信息 + childNode, err := s.vfs.GetNodeByParentIDAndName(node.ID, childEntry.Name) + if err != nil { + return &VFSError{ + Type: ErrorTypeNodeNotFound, + Error: fmt.Errorf("failed to get child node %s: %v", childEntry.Name, err), + } + } + + // 递归删除子节点 + if err := s.deleteNodeRecursively(childNode, callback, thisArg); err != nil { + return err + } + } + } else if node.Type == models.VfsNodeTypeService { + // 对于服务节点,执行回调 + if callback != nil { + _, err := callback(thisArg, node, nil) + if err != nil { + return &VFSError{ + Type: ErrorTypeServiceProxyFailed, + Error: fmt.Errorf("failed to execute callback for service %s: %v", node.Name, err), + } + } + } + } + + // 删除当前节点 + if err := s.vfs.DeleteNode(node.ID); err != nil { + return &VFSError{ + Type: ErrorTypeNodeDeletionFailed, + Error: fmt.Errorf("failed to delete node %s: %v", node.Name, err), + } + } + + return nil +} + +func (s *VfsCoreService) DeleteVFSNode(path string, callback VfsCallback, thisArg any) (*models.VfsNode, *VFSError) { + // 获取节点 + node, err := s.vfs.GetNodeByPath(path) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeNotFound, + Error: err, + } + } + + // 根据节点类型进行不同处理 + switch node.Type { + case models.VfsNodeTypeService: + if callback != nil { + _, err := callback(thisArg, node, nil) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeServiceProxyFailed, + Error: err, + } + } + } + + case models.VfsNodeTypeDirectory: + // 检查目录是否为空 + children, err := s.vfs.GetChildren(node.ID) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeInternal, + Error: fmt.Errorf("failed to get directory children: %v", err), + } + } + + if len(children) != 0 { + return nil, &VFSError{ + Type: ErrorTypeConflict, + Error: fmt.Errorf("directory is not empty"), + } + } + default: + return nil, &VFSError{ + Type: ErrorTypeInvalidArgument, + Error: fmt.Errorf("node type not supported for deletion"), + } + } + + // 执行实际的删除操作 + if err := s.vfs.DeleteNode(node.ID); err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeDeletionFailed, + Error: fmt.Errorf("failed to delete node: %v", err), + } + } + + // 成功删除返回204状态 + return node, nil +} + +// GetVFSNodeResult 获取节点的返回结果 +type GetVFSNodeResult struct { + Node *models.VfsNode + Entries []models.VfsDirEntry + Content []byte +} + +// GetVFSNode 获取VFS节点 +func (s *VfsCoreService) GetVFSNode(path string, callback VfsCallback, thisArg any) (*GetVFSNodeResult, *VFSError) { + // 获取节点 + node, err := s.vfs.GetNodeByPath(path) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeNotFound, + Error: err, + } + } + + // 根据节点类型进行不同处理 + switch node.Type { + case models.VfsNodeTypeDirectory: + // 处理目录类型 + entries, err := s.vfs.GetChildren(node.ID) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeInternal, + Error: err, + } + } + + return &GetVFSNodeResult{ + Node: node, + Entries: entries, + }, nil + + case models.VfsNodeTypeService: + // 处理服务类型 + var resultContent []byte + if callback != nil { + ret, err := callback(thisArg, node, nil) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeServiceProxyFailed, + Error: err, + } + } + resultContent = ret + } + + return &GetVFSNodeResult{ + Node: node, + Content: resultContent, + }, nil + + default: + return &GetVFSNodeResult{ + Node: node, + }, nil + } +} + +// UpdateOperation 更新操作类型 +type UpdateOperation int + +const ( + UpdateOperationRename UpdateOperation = iota + UpdateOperationChange + UpdateOperationMove + UpdateOperationCopy +) + +// UpdateVFSNode 更新VFS节点 +func (s *VfsCoreService) UpdateVFSNode(path string, operation UpdateOperation, data []byte, callback VfsCallback, thisArg any) (*models.VfsNode, *VFSError) { + // 获取节点 + node, err := s.vfs.GetNodeByPath(path) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeNotFound, + Error: err, + } + } + + // 根据操作类型进行不同处理 + switch operation { + case UpdateOperationRename: + // TODO: + // if err := s.vfs.CheckNameValid(string(data)); err != nil { + // return nil, &VFSError{ + // Type: ErrorTypeBadRequest, + // Error: err, + // } + // } + // FIXME: 检查新名称是否合法 + // 对于服务类型节点,可能需要保留特定后缀 + // 更新节点名称 + node.Name = string(data) + if err := s.vfs.UpdateNode(node); err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeUpdateFailed, + Error: fmt.Errorf("failed to rename node: %v", err), + } + } + + case UpdateOperationChange: + // Change操作仅适用于文件和服务类型节点 + if node.Type != models.VfsNodeTypeFile && node.Type != models.VfsNodeTypeService { + return nil, &VFSError{ + Type: ErrorTypeBadRequest, + Error: fmt.Errorf("change operation is only supported for file and service nodes"), + } + } + + if callback != nil && node.Type == models.VfsNodeTypeService { + _, err := callback(thisArg, node, data) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeServiceProxyFailed, + Error: fmt.Errorf("failed to proxy change to service: %v", err), + } + } + } + + case UpdateOperationMove: + // FIXME: 需要添加权限控制 + if len(data) == 0 { + return nil, &VFSError{ + Type: ErrorTypeBadRequest, + Error: fmt.Errorf("target path cannot be empty"), + } + } + + // 移动节点到新路径 + parentPath, nodeName, nodeType, err := models.ParsePathComponents(string(data)) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeInvalidPath, + Error: err, + } + } + + if nodeType != node.Type { + return nil, &VFSError{ + Type: ErrorTypeInvalidArgument, + Error: fmt.Errorf("invalid path type"), + } + } + + parentNode, err := s.vfs.GetNodeByPath(parentPath) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypePathNotFound, + Error: err, + } + } + + sameNode, err := s.vfs.GetNodeByParentIDAndName(parentNode.ID, nodeName) + if sameNode != nil || err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeMoveFailed, + Error: err, + } + } + + node.ParentID = parentNode.ID + if err := s.vfs.UpdateNode(node); err != nil { + return nil, &VFSError{ + Type: ErrorTypeNodeMoveFailed, + Error: fmt.Errorf("failed to move node: %v", err), + } + } + + default: + return nil, &VFSError{ + Type: ErrorTypeBadRequest, + Error: fmt.Errorf("unsupported operation type"), + } + } + + // 返回更新后的节点信息 + return node, nil +} diff --git a/internal/vfs/services/vfs_error.go b/internal/vfs/services/vfs_error.go new file mode 100644 index 0000000..e0e8354 --- /dev/null +++ b/internal/vfs/services/vfs_error.go @@ -0,0 +1,50 @@ +package vfs_service + +type VFSErrorType int + +const ( + ErrorTypeNoError = iota + + // 通用错误类型 + ErrorTypeNotFound + ErrorTypeAlreadyExists + ErrorTypeForbidden + ErrorTypeInternal + ErrorTypeBadRequest + ErrorTypeUnauthorized + ErrorTypeConflict + ErrorTypeNotImplemented + ErrorTypeInvalidArgument + + // 用户相关错误 + ErrorTypeUserNotFound + ErrorTypeUserAlreadyExists + ErrorTypeUserCreationFailed + ErrorTypeUserDeletionFailed + + // 节点相关错误 + ErrorTypeNodeNotFound + ErrorTypeNodeAlreadyExists + ErrorTypeNodeCreationFailed + ErrorTypeNodeDeletionFailed + ErrorTypeNodeUpdateFailed + ErrorTypeNodeMoveFailed + ErrorTypeNodeAccessDenied + + // 权限相关错误 + ErrorTypePermissionDenied + ErrorTypeInvalidToken + + // 服务代理相关错误 + ErrorTypeServiceProxyNotFound + ErrorTypeServiceProxyFailed + + // 路径相关错误 + ErrorTypeInvalidPath + ErrorTypePathNotFound +) + +type VFSError struct { + Type VFSErrorType + Error error +} diff --git a/internal/vfs/vfs_service.go b/internal/vfs/services/vfs_proxy.go similarity index 72% rename from internal/vfs/vfs_service.go rename to internal/vfs/services/vfs_proxy.go index 81e175f..b5147ae 100644 --- a/internal/vfs/vfs_service.go +++ b/internal/vfs/services/vfs_proxy.go @@ -1,9 +1,10 @@ -package vfs +package vfs_service import ( "fmt" "net/http" "strings" + "sync" "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/models" ) @@ -33,17 +34,29 @@ type ProxyEntry struct { Proxy ServiceProxy // 对应的代理实现 } +type ProxyService struct { + Proxies []*ProxyEntry + proxyMutex sync.RWMutex +} + +func NewProxyService() *ProxyService { + return &ProxyService{ + Proxies: make([]*ProxyEntry, 0), + proxyMutex: sync.RWMutex{}, + } +} + // FindProxyByServiceName 根据服务节点名称查找对应的代理 -func (v *VfsImpl) FindProxyByServiceName(serviceName string) ServiceProxy { - v.proxyMutex.RLock() - defer v.proxyMutex.RUnlock() +func (s *ProxyService) findProxyByServiceName(serviceName string) ServiceProxy { + s.proxyMutex.RLock() + defer s.proxyMutex.RUnlock() if serviceName == "" { return nil } // 根据服务名称匹配前缀 - for _, entry := range v.proxyTable { + for _, entry := range s.Proxies { if entry.MatchExt == serviceName { return entry.Proxy } @@ -52,19 +65,22 @@ func (v *VfsImpl) FindProxyByServiceName(serviceName string) ServiceProxy { return nil } -func (v *VfsImpl) RegisterProxy(entry *ProxyEntry) { - v.proxyMutex.Lock() - defer v.proxyMutex.Unlock() +func (s *ProxyService) RegisterProxy(entry *ProxyEntry) { + s.proxyMutex.Lock() + defer s.proxyMutex.Unlock() - v.proxyTable = append(v.proxyTable, entry) + s.Proxies = append(s.Proxies, entry) } -func (v *VfsImpl) StrictProxy2Service(method string, data []byte, node *models.VfsNode) ([]byte, error) { +func (s *ProxyService) StrictProxy2Service(method string, data []byte, node *models.VfsNode) ([]byte, error) { + if node.Type != models.VfsNodeTypeService { + return nil, fmt.Errorf("node is not a service") + } exts := strings.Split(node.Name, ".") var serviceName = exts[1] // log.Println("Proxy2Service: ", serviceName) // 查找对应的代理 - proxy := v.FindProxyByServiceName(serviceName) + proxy := s.findProxyByServiceName(serviceName) if proxy == nil { return nil, fmt.Errorf("service proxy not found for: %s", serviceName) } diff --git a/internal/vfs/services/vfs_user.go b/internal/vfs/services/vfs_user.go new file mode 100644 index 0000000..b4b4d68 --- /dev/null +++ b/internal/vfs/services/vfs_user.go @@ -0,0 +1,82 @@ +package vfs_service + +import ( + "crypto/rand" + "fmt" + "log" + "time" + + "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/models" + "github.com/casbin/casbin/v2" +) + +type UserService struct { + // vfs *models.VfsService + vfs *models.VfsDAO + enforcer *casbin.Enforcer + // errorHandler *ErrorHandler +} + +func NewUserService(vfs *models.VfsDAO, enforcer *casbin.Enforcer) *UserService { + return &UserService{ + vfs: vfs, + enforcer: enforcer, + } +} + +func generateToken() string { + bytes := make([]byte, 16) + if _, err := rand.Read(bytes); err != nil { + // fallback to time-based token + return fmt.Sprintf("%x", time.Now().UnixNano()) + } + return fmt.Sprintf("%x", bytes) +} + +func (s *UserService) CreateUser(username string) (*string, *VFSError) { + token := generateToken() + // 创建用户 + err := s.vfs.CreateUser(username, token) + if err != nil { + return nil, &VFSError{ + Type: ErrorTypeUserCreationFailed, + Error: err, + } + } + + // 为新用户添加角色 + _, err = s.enforcer.AddRoleForUser(username, "user") + if err != nil { + log.Printf("Failed to add role for user %s: %v", username, err) + } + + // 保存策略 + s.enforcer.SavePolicy() + + // 返回带有token的响应 + return &token, nil +} + +func (s *UserService) DeleteUser(username string) *VFSError { + // 删除用户 + err := s.vfs.DeleteUser(username) + if err != nil { + return &VFSError{ + Type: ErrorTypeUserDeletionFailed, + Error: err, + } + } + + // 从权限系统中移除用户 + // 移除用户的所有角色 + _, err = s.enforcer.DeleteRolesForUser(username) + if err != nil { + log.Printf("Failed to delete roles for user %s: %v", username, err) + } + + // 保存策略 + s.enforcer.SavePolicy() + + // 成功删除返回204状态 + return nil +} diff --git a/internal/vfs/vfsdriver/vfs_bookmark.go b/internal/vfs/services/vfsdriver/vfs_bookmark.go similarity index 94% rename from internal/vfs/vfsdriver/vfs_bookmark.go rename to internal/vfs/services/vfsdriver/vfs_bookmark.go index 659c45c..5a8da97 100644 --- a/internal/vfs/vfsdriver/vfs_bookmark.go +++ b/internal/vfs/services/vfsdriver/vfs_bookmark.go @@ -9,8 +9,8 @@ import ( "net/http" api "git.zzyxyz.com/zzy/zzyxyz_go_api/gen/bookmarks_client" - "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs" "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/models" + vfs_service "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/services" ) type VfsBookMarkService struct { @@ -18,13 +18,13 @@ type VfsBookMarkService struct { token string } -func NewVfsBookMarkService(serverURL string) (*vfs.ProxyEntry, error) { +func NewVfsBookMarkService(serverURL string) (*vfs_service.ProxyEntry, error) { client, err := api.NewClientWithResponses(serverURL) if err != nil { return nil, err } - ret := vfs.ProxyEntry{ + ret := vfs_service.ProxyEntry{ Name: "bookmark", MatchExt: "bk", Proxy: &VfsBookMarkService{ @@ -180,4 +180,4 @@ func (v *VfsBookMarkService) GetName() string { return "bookmark" } -var _ vfs.ServiceProxy = (*VfsBookMarkService)(nil) +var _ vfs_service.ServiceProxy = (*VfsBookMarkService)(nil) diff --git a/internal/vfs/vfs.go b/internal/vfs/vfs.go index feefb8f..52ceb89 100644 --- a/internal/vfs/vfs.go +++ b/internal/vfs/vfs.go @@ -4,27 +4,28 @@ import ( "log" "os" "path/filepath" - "sync" "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/models" + vfs_service "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/services" "github.com/casbin/casbin/v2" "github.com/casbin/casbin/v2/model" fileadapter "github.com/casbin/casbin/v2/persist/file-adapter" ) type VfsImpl struct { - vfs *models.Vfs - enfocer *casbin.Enforcer - config VFSConfig - proxyTable []*ProxyEntry // 动态代理表 - proxyMutex sync.RWMutex // 保护代理表的读写锁 + Core *vfs_service.VfsCoreService + Proxy *vfs_service.ProxyService + User *vfs_service.UserService + DAO *models.VfsDAO + Enfocer *casbin.Enforcer + Config VFSConfig } // 在NewVfsHandler中注册中间件 func NewVfsHandler(config *Config) (*VfsImpl, error) { var err error - vfs, err := models.NewVfs(config.VFS.DbPath) + dao, err := models.NewVfsDAO(config.VFS.DbPath) if err != nil { return nil, err } @@ -67,11 +68,12 @@ func NewVfsHandler(config *Config) (*VfsImpl, error) { log.Printf("Register Token: %s", config.VFS.RegisterToken) impl := &VfsImpl{ - vfs: vfs, - enfocer: e, - config: config.VFS, - proxyTable: make([]*ProxyEntry, 0), - proxyMutex: sync.RWMutex{}, + Core: vfs_service.NewVfsCoreService(dao), + Proxy: vfs_service.NewProxyService(), + User: vfs_service.NewUserService(dao, e), + DAO: dao, + Enfocer: e, + Config: config.VFS, } // 注册中间件 diff --git a/internal/vfs/vfs_auth.go b/internal/vfs/vfs_auth.go index 83845e2..74e5452 100644 --- a/internal/vfs/vfs_auth.go +++ b/internal/vfs/vfs_auth.go @@ -30,7 +30,7 @@ func (v *VfsImpl) PermissionMiddleware(handler api.StrictHandlerFunc, operation token := ctx.GetHeader("X-VFS-Token") // Admin token 拥有所有权限 - if token == v.config.AdminToken && len(token) != 0 { + if token == v.Config.AdminToken && len(token) != 0 { return handler(ctx, request) } @@ -38,7 +38,7 @@ func (v *VfsImpl) PermissionMiddleware(handler api.StrictHandlerFunc, operation switch operation { case "CreateUser": // 只有admin或register token可以创建用户 - if token != v.config.RegisterToken { + if token != v.Config.RegisterToken { return api.CreateUser403JSONResponse{ ForbiddenErrorJSONResponse: api.ForbiddenErrorJSONResponse{ Errtype: api.ErrorErrtypeForbidden, @@ -57,8 +57,8 @@ func (v *VfsImpl) PermissionMiddleware(handler api.StrictHandlerFunc, operation } // 验证token对应的用户是否存在 - user, err := v.vfs.GetUserByToken(token) - if err != nil || (user.Name != username && token != v.config.AdminToken) { + 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, @@ -155,12 +155,12 @@ func (v *VfsImpl) PermissionMiddleware(handler api.StrictHandlerFunc, operation // 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 { + if token == v.Config.AdminToken && len(token) != 0 { return true, nil } // 根据 token 获取用户信息 - user, err := v.vfs.GetUserByToken(token) + user, err := v.DAO.GetUserByToken(token) if err != nil { // 匿名用户 user = &models.VfsUser{Name: "", Token: ""} @@ -180,7 +180,7 @@ func (v *VfsImpl) CheckPermission(token, path, method string) (bool, error) { // sub: 用户名 (匿名用户为空字符串) // obj: 路径 // act: HTTP方法 - allowed, err := v.enfocer.Enforce(user.Name, path, method) + allowed, err := v.Enfocer.Enforce(user.Name, path, method) if err != nil { return false, err } diff --git a/internal/vfs/vfs_impl.go b/internal/vfs/vfs_impl.go index 39fd617..7e1911d 100644 --- a/internal/vfs/vfs_impl.go +++ b/internal/vfs/vfs_impl.go @@ -8,61 +8,40 @@ import ( api "git.zzyxyz.com/zzy/zzyxyz_go_api/gen/vfs_server" "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/models" + vfs_service "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/services" ) // TODO 重命名名称冲突,以及合法名称检测,以及JSONBody and TextBody的检测 +// TODO: 特殊字符过滤 // CreateVFSNode implements server.StrictServerInterface. func (v *VfsImpl) CreateVFSNode(ctx context.Context, request api.CreateVFSNodeRequestObject) (api.CreateVFSNodeResponseObject, error) { - // 解析路径组件 - parentPath, nodeName, nodeType, err := models.ParsePathComponents(request.Params.Path) - if err != nil { - return api.CreateVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: err.Error(), - }, - }, nil + var content []byte + if request.Body != nil { + content = []byte(*request.Body) } + res, err := v.Core.CreateVFSNode(request.Params.Path, content, func(this any, node *models.VfsNode, input []byte) ([]byte, error) { + if svc, ok := this.(*vfs_service.ProxyService); ok { + result, err := svc.StrictProxy2Service(http.MethodPost, input, node) + return result, err + } else { + // 可选日志记录或错误处理 + log.Println("this is not of type ProxyService") + return nil, nil + } + }, v.Proxy) - // 读取请求体数据 - // FIXME: 使用stream可能更好 - var content []byte = []byte(*request.Body) - - // 创建节点 (可能需要传递content数据到vfs层) - node, err := v.vfs.CreateNodeByComponents(parentPath, nodeName, nodeType) if err != nil { + log.Printf("Error creating VFS node: %+v", err) return api.CreateVFSNode500JSONResponse{ ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ Errtype: api.ErrorErrtypeInternalServerError, - Message: err.Error(), + Message: fmt.Errorf("failed to delete node: %+v", err).Error(), }, }, nil } - // 处理服务类型节点 - if nodeType == models.VfsNodeTypeService { - // 这里可能需要将content传递给服务处理 - if result, err := v.StrictProxy2Service(http.MethodPost, content, node); err != nil { - // 回滚操作 - delete_err := v.vfs.DeleteVFSNode(node) - log.Printf("service node: %s, err %s", node.Name, err.Error()) - if delete_err != nil { - // FIXME: 需要解决这种原子性 - return nil, fmt.Errorf("consistency error: %w", err) - } - return api.CreateVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeServiceProxyError, - Message: err.Error(), - }, - }, nil - } else { - // 返回二进制数据响应 - return api.CreateVFSNode201TextResponse(result), nil - } - } - + node := res.Node // 返回JSON响应 return api.CreateVFSNode201JSONResponse{ Name: node.Name, @@ -72,172 +51,97 @@ func (v *VfsImpl) CreateVFSNode(ctx context.Context, request api.CreateVFSNodeRe }, nil } -// DeleteVFSNode implements server.StrictServerInterface. -func (v *VfsImpl) DeleteVFSNode(ctx context.Context, request api.DeleteVFSNodeRequestObject) (api.DeleteVFSNodeResponseObject, error) { - // 获取节点 - node, err := v.vfs.GetNodeByPath(request.Params.Path) +// GetVFSNode implements server.StrictServerInterface. +func (v *VfsImpl) GetVFSNode(ctx context.Context, request api.GetVFSNodeRequestObject) (api.GetVFSNodeResponseObject, error) { + res, err := v.Core.GetVFSNode(request.Params.Path, func(this any, node *models.VfsNode, input []byte) ([]byte, error) { + if svc, ok := this.(*vfs_service.ProxyService); ok { + result, err := svc.StrictProxy2Service(http.MethodGet, nil, node) + return result, err + } else { + // 可选日志记录或错误处理 + log.Println("this is not of type ProxyService") + return nil, nil + } + }, v.Proxy) + if err != nil { - return api.DeleteVFSNode404JSONResponse{ - PathNotFoundErrorJSONResponse: api.PathNotFoundErrorJSONResponse{ - Errtype: api.ErrorErrtypePathNotFound, - Message: err.Error(), + return api.GetVFSNode500JSONResponse{ + ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ + Errtype: api.ErrorErrtypeInternalServerError, + Message: fmt.Errorf("failed to delete node: %+v", err).Error(), }, }, nil } - // 根据节点类型进行不同处理 - switch node.Type { - case models.VfsNodeTypeService: - // 对于服务类型节点,通过代理删除 - _, err := v.StrictProxy2Service(http.MethodDelete, nil, node) + if res.Node.Type == models.VfsNodeTypeDirectory { + // 手动构造响应对象 + entries := make([]api.VFSDirectoryEntry, len(res.Entries)) + for i, entry := range res.Entries { + entries[i] = api.VFSDirectoryEntry{ + Name: entry.Name, + Type: ModelType2ResponseType(entry.Type), + } + } + return api.GetVFSNode200JSONResponse(entries), nil + } else { + return api.GetVFSNode200TextResponse(res.Content), nil + } +} + +// DeleteVFSNode implements server.StrictServerInterface. +func (v *VfsImpl) DeleteVFSNode(ctx context.Context, request api.DeleteVFSNodeRequestObject) (api.DeleteVFSNodeResponseObject, error) { + op := request.Params.Op + if op == nil { + _, err := v.Core.DeleteVFSNode(request.Params.Path, func(this any, node *models.VfsNode, input []byte) ([]byte, error) { + if svc, ok := this.(*vfs_service.ProxyService); ok { + result, err := svc.StrictProxy2Service(http.MethodDelete, nil, node) + return result, err + } else { + // 可选日志记录或错误处理 + log.Println("this is not of type ProxyService") + return nil, nil + } + }, v.Proxy) + if err != nil { return api.DeleteVFSNode500JSONResponse{ ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeServiceProxyError, - Message: err.Error(), + Errtype: api.ErrorErrtypeInternalServerError, + Message: fmt.Errorf("failed to delete node: %+v", err).Error(), }, }, nil } - case models.VfsNodeTypeDirectory: - if request.Params.Op != nil && *request.Params.Op == api.Recursive { - if sericeIDs, err := v.vfs.DeleteNodeRecursively(node.ID); err != nil { - return api.DeleteVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeInternalServerError, - Message: "Failed to delete node: " + err.Error(), - }, - }, nil + // 成功删除返回204状态 + return api.DeleteVFSNode204Response{}, nil + } else if *op == api.Recursive { + _, err := v.Core.DeleteVFSNodeRecursively(request.Params.Path, func(this any, node *models.VfsNode, input []byte) ([]byte, error) { + if svc, ok := this.(*vfs_service.ProxyService); ok { + result, err := svc.StrictProxy2Service(http.MethodDelete, nil, node) + return result, err } else { - for _, serviceID := range sericeIDs { - // 对于服务类型节点,通过代理删除 - _, err := v.StrictProxy2Service(http.MethodDelete, nil, v.vfs.GetVFSNode(serviceID)) - if err != nil { - return api.DeleteVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeServiceProxyError, - Message: err.Error(), - }, - }, nil - } - } - return api.DeleteVFSNode204Response{}, nil - } - } else { - // 检查目录是否为空 - children, err := v.vfs.GetChildren(node.ID) - if err != nil { - return api.DeleteVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeInternalServerError, - Message: "Failed to get directory children: " + err.Error(), - }, - }, nil + // 可选日志记录或错误处理 + log.Println("this is not of type ProxyService") + return nil, nil } + }, v.Proxy) - if len(children) != 0 { - return api.DeleteVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeConflictError, - Message: "Directory is not empty", - }, - }, nil - } + if err != nil { + return api.DeleteVFSNode500JSONResponse{ + ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ + Errtype: api.ErrorErrtypeInternalServerError, + Message: fmt.Errorf("failed to delete node: %+v", err).Error(), + }, + }, nil } - default: - return api.DeleteVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: "Node type not supported for deletion", - }, - }, nil - } - // 执行实际的删除操作 - if err := v.vfs.DeleteVFSNode(node); err != nil { + // 成功删除返回204状态 + return api.DeleteVFSNode204Response{}, nil + } else { return api.DeleteVFSNode500JSONResponse{ ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ Errtype: api.ErrorErrtypeInternalServerError, - Message: "Failed to delete node: " + err.Error(), - }, - }, nil - } - - // 成功删除返回204状态 - return api.DeleteVFSNode204Response{}, nil -} - -// GetVFSNode implements server.StrictServerInterface. -func (v *VfsImpl) GetVFSNode(ctx context.Context, request api.GetVFSNodeRequestObject) (api.GetVFSNodeResponseObject, error) { - // 获取节点 - node, err := v.vfs.GetNodeByPath(request.Params.Path) - if err != nil { - return api.GetVFSNode404JSONResponse{ - PathNotFoundErrorJSONResponse: api.PathNotFoundErrorJSONResponse{ - Errtype: api.ErrorErrtypePathNotFound, - Message: err.Error(), - }, - }, nil - } - - switch node.Type { - case models.VfsNodeTypeDirectory: - // 处理目录类型 - entries, err := v.vfs.GetChildren(node.ID) - if err != nil { - return api.GetVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeInternalServerError, - Message: err.Error(), - }, - }, nil - } - - var responseEntries []api.VFSDirectoryEntry - for _, entry := range entries { - responseEntries = append(responseEntries, api.VFSDirectoryEntry{ - Name: entry.Name, - Type: ModelType2ResponseType(entry.Type), - }) - } - return api.GetVFSNode200JSONResponse(responseEntries), nil - - // case models.VfsNodeTypeFile: - // // 处理文件类型,返回二进制数据 - // // 这里需要从vfs中获取文件内容 - // fileContent, err := v.vfs.GetFileContent(node.ID) // 假设有此方法 - // if err != nil { - // return api.GetVFSNode500JSONResponse{ - // ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - // Errtype: api.ErrorErrtypeInternalServerError, - // Message: err.Error(), - // }, - // }, nil - // } - // return api.GetVFSNode200ApplicationoctetStreamResponse{ - // Body: bytes.NewReader(fileContent), - // ContentLength: int64(len(fileContent)), - // }, nil - - case models.VfsNodeTypeService: - // 处理服务类型 - result, err := v.StrictProxy2Service(http.MethodGet, nil, node) - if err != nil { - return api.GetVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeServiceProxyError, - Message: err.Error(), - }, - }, nil - } - - return api.GetVFSNode200TextResponse(result), nil - - default: - return api.GetVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: "Not a valid node type", + Message: fmt.Errorf("not suported op").Error(), }, }, nil } @@ -245,172 +149,48 @@ func (v *VfsImpl) GetVFSNode(ctx context.Context, request api.GetVFSNodeRequestO // UpdateVFSNode implements server.StrictServerInterface. func (v *VfsImpl) UpdateVFSNode(ctx context.Context, request api.UpdateVFSNodeRequestObject) (api.UpdateVFSNodeResponseObject, error) { - // 获取节点 - node, err := v.vfs.GetNodeByPath(request.Params.Path) - if err != nil { - return api.UpdateVFSNode404JSONResponse{ - PathNotFoundErrorJSONResponse: api.PathNotFoundErrorJSONResponse{ - Errtype: api.ErrorErrtypePathNotFound, - Message: err.Error(), - }, - }, nil + var content []byte + if request.JSONBody != nil { + content = []byte(*request.JSONBody) + } else if request.TextBody != nil { + content = []byte(*request.TextBody) } - - // 根据操作类型进行不同处理 + var op vfs_service.UpdateOperation switch request.Params.Op { - case api.Rename: - // 检查请求体 - if request.JSONBody == nil { - return api.UpdateVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: "Request body is required for rename operation", - }, - }, nil - } - - newName := string(*request.JSONBody) - if err := v.vfs.CheckNameValid(newName); err != nil { - return api.UpdateVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: err.Error(), - }, - }, nil - } - - // FIXME: 检查新名称是否合法 - // 对于服务类型节点,可能需要保留特定后缀 - if node.Type == models.VfsNodeTypeService { - // 可以添加对服务节点重命名的特殊处理 - // 例如确保保留.service后缀 - } - - // 更新节点名称 - node.Name = newName - if err := v.vfs.UpdateVFSNode(node); err != nil { - return api.UpdateVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeInternalServerError, - Message: "Failed to rename node: " + err.Error(), - }, - }, nil - } - case api.Change: - // Change操作仅适用于文件和服务类型节点 - if node.Type != models.VfsNodeTypeFile && node.Type != models.VfsNodeTypeService { - return api.UpdateVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: "Change operation is only supported for file and service nodes", - }, - }, nil - } - - // 读取请求体数据 - // FIXME: 使用stream可能更好 - var content []byte = []byte(*request.TextBody) - - // 对于服务节点,通过代理发送变更 - if node.Type == models.VfsNodeTypeService { - _, err := v.StrictProxy2Service(http.MethodPatch, content, node) - if err != nil { - return api.UpdateVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeServiceProxyError, - Message: "Failed to proxy change to service: " + err.Error(), - }, - }, nil - } - } else { - // 对于文件节点,可能需要更新文件内容 - // 这里可以根据需要实现文件内容更新逻辑 - return api.UpdateVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeInternalServerError, - Message: "File Opreation Not Supported", - }, - }, nil - } - - case api.Move: - // FIXME: 需要添加权限控制 - if request.JSONBody == nil { - return api.UpdateVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: "Request body is required for move operation", - }, - }, nil - } - - targetPath := string(*request.JSONBody) - if targetPath == "" { - return api.UpdateVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: "Target path cannot be empty", - }, - }, nil - } - - // 移动节点到新路径 - if err := v.vfs.MoveToPath(node, targetPath); err != nil { - return api.UpdateVFSNode500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeInternalServerError, - Message: "Failed to move node: " + err.Error(), - }, - }, nil - } - + op = vfs_service.UpdateOperationChange case api.Copy: - fallthrough - // if request.Body == nil { - // return api.UpdateVFSNode400JSONResponse{ - // ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - // Errtype: api.ErrorErrtypeParameterError, - // Message: "Request body is required for copy operation", - // }, - // }, nil - // } + op = vfs_service.UpdateOperationCopy + case api.Move: + op = vfs_service.UpdateOperationMove + case api.Rename: + op = vfs_service.UpdateOperationRename + } + res, err := v.Core.UpdateVFSNode(request.Params.Path, op, content, func(this any, node *models.VfsNode, input []byte) ([]byte, error) { + if svc, ok := this.(*vfs_service.ProxyService); ok { + result, err := svc.StrictProxy2Service(http.MethodPut, input, node) + return result, err + } else { + // 可选日志记录或错误处理 + log.Println("this is not of type ProxyService") + return nil, nil + } + }, v.Proxy) - // targetPath := string(*request.Body) - // if targetPath == "" { - // return api.UpdateVFSNode400JSONResponse{ - // ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - // Errtype: api.ErrorErrtypeParameterError, - // Message: "Target path cannot be empty", - // }, - // }, nil - // } - - // // 复制节点到新路径 - // if err := v.vfs.CopyToPath(node, targetPath); err != nil { - // return api.UpdateVFSNode500JSONResponse{ - // ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - // Errtype: api.ErrorErrtypeInternalServerError, - // Message: "Failed to copy node: " + err.Error(), - // }, - // }, nil - // } - - default: - return api.UpdateVFSNode400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeParameterError, - Message: "Unsupported operation type", + if err != nil { + return api.UpdateVFSNode500JSONResponse{ + ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ + Errtype: api.ErrorErrtypeInternalServerError, + Message: fmt.Errorf("failed to delete node: %+v", err).Error(), }, }, nil } - // 返回更新后的节点信息 return api.UpdateVFSNode200JSONResponse{ - Name: node.Name, - Type: ModelType2ResponseType(node.Type), - CreatedAt: node.CreatedAt, - UpdatedAt: node.UpdatedAt, + Name: res.Name, + Type: ModelType2ResponseType(res.Type), + CreatedAt: res.CreatedAt, + UpdatedAt: res.UpdatedAt, }, nil } @@ -430,42 +210,23 @@ func ModelType2ResponseType(nodeType models.VfsNodeType) api.VFSNodeType { // CreateUser implements server.StrictServerInterface. func (v *VfsImpl) CreateUser(ctx context.Context, request api.CreateUserRequestObject) (api.CreateUserResponseObject, error) { // 创建用户 - token, err := v.vfs.CreateUser(request.Username) - if err != nil { - // 检查是否是用户已存在的错误 - if err.Error() == "user already exists" { - return api.CreateUser400JSONResponse{ - ParameterErrorJSONResponse: api.ParameterErrorJSONResponse{ - Errtype: api.ErrorErrtypeConflictError, - Message: "User already exists", - }, - }, nil - } - + token, err := v.User.CreateUser(request.Username) + if err != nil || token == nil { return api.CreateUser500JSONResponse{ ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ Errtype: api.ErrorErrtypeInternalServerError, - Message: "Failed to create user: " + err.Error(), + Message: fmt.Errorf("failed to delete node: %+v", err).Error(), }, }, nil } - // 为新用户添加角色 - _, err = v.enfocer.AddRoleForUser(request.Username, "user") - if err != nil { - log.Printf("Failed to add role for user %s: %v", request.Username, err) - // 注意:这里即使添加角色失败,我们也不会回滚用户创建 - // 因为用户创建已经成功,且这是两个独立的系统 - // FIXME: unknown - } - - // 保存策略 - v.enfocer.SavePolicy() + v.Core.CreateVFSNode("/home/"+request.Username+"/", nil, nil, nil) + v.Core.CreateVFSNode("/home/"+request.Username+"/.Recycle_Bin/", nil, nil, nil) // 返回带有token的响应 return api.CreateUser201Response{ Headers: api.CreateUser201ResponseHeaders{ - XVFSToken: token, + XVFSToken: *token, }, }, nil } @@ -473,58 +234,36 @@ func (v *VfsImpl) CreateUser(ctx context.Context, request api.CreateUserRequestO // DeleteUser implements server.StrictServerInterface. func (v *VfsImpl) DeleteUser(ctx context.Context, request api.DeleteUserRequestObject) (api.DeleteUserResponseObject, error) { // 删除用户 - err := v.vfs.DeleteUser(request.Username) - if err != nil { - // 检查是否是用户未找到的错误 - if err.Error() == "user not found" { - return api.DeleteUser404JSONResponse{ - Errtype: api.ErrorErrtypeNotFoundError, - Message: "User not found", - }, nil - } - + if err := v.User.DeleteUser(request.Username); err != nil { return api.DeleteUser500JSONResponse{ ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ Errtype: api.ErrorErrtypeInternalServerError, - Message: "Failed to delete user: " + err.Error(), + Message: err.Error.Error(), }, }, nil } - if userDir, err := v.vfs.GetNodeByPath("/home/" + request.Username + "/"); err != nil { - panic(err) - } else { - if serviceIDs, err := v.vfs.DeleteNodeRecursively(userDir.ID); err != nil { - panic(err) + // TODO: Remove User DIR + _, err := v.Core.DeleteVFSNodeRecursively("/home/"+request.Username+"/", func(this any, node *models.VfsNode, input []byte) ([]byte, error) { + if svc, ok := this.(*vfs_service.ProxyService); ok { + result, err := svc.StrictProxy2Service(http.MethodDelete, nil, node) + return result, err } else { - for _, serviceID := range serviceIDs { - // 对于服务类型节点,通过代理删除 - _, err := v.StrictProxy2Service(http.MethodDelete, nil, v.vfs.GetVFSNode(serviceID)) - if err != nil { - return api.DeleteUser500JSONResponse{ - ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ - Errtype: api.ErrorErrtypeServiceProxyError, - Message: err.Error(), - }, - }, nil - } - } + // 可选日志记录或错误处理 + log.Println("this is not of type ProxyService") + return nil, nil } - } + }, v.Proxy) - // 从权限系统中移除用户 - // 移除用户的所有角色 - _, err = v.enfocer.DeleteRolesForUser(request.Username) if err != nil { - log.Printf("Failed to delete roles for user %s: %v", request.Username, err) - // 注意:这里即使删除角色失败,我们也不会回滚用户删除 - // 因为数据库中的用户已经删除,且这是两个独立的系统 - // FIXME: unknown + return api.DeleteUser500JSONResponse{ + ServerInternalErrorJSONResponse: api.ServerInternalErrorJSONResponse{ + Errtype: api.ErrorErrtypeInternalServerError, + Message: fmt.Errorf("failed to delete node: %+v", err).Error(), + }, + }, nil } - // 保存策略 - v.enfocer.SavePolicy() - // 成功删除返回204状态 return api.DeleteUser204Response{}, nil } diff --git a/internal/vfs/vfs_user.go b/internal/vfs/vfs_user.go deleted file mode 100644 index 54c6094..0000000 --- a/internal/vfs/vfs_user.go +++ /dev/null @@ -1 +0,0 @@ -package vfs diff --git a/main.go b/main.go index e8d3ad8..1ef3421 100644 --- a/main.go +++ b/main.go @@ -8,7 +8,7 @@ import ( "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/handlers" "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs" - "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/vfsdriver" + "git.zzyxyz.com/zzy/zzyxyz_go_api/internal/vfs/services/vfsdriver" "github.com/gin-gonic/gin" "github.com/spf13/viper" @@ -49,7 +49,7 @@ func main() { if err != nil { log.Fatal("Failed to create bookmark service client:", err) } - server.RegisterProxy(bookmarkService) + server.Proxy.RegisterProxy(bookmarkService) } handlers.TodoHandler(api_router) }