From 5bd7ac964ff88293dcf34557b99ad0d08b8d61f0 Mon Sep 17 00:00:00 2001 From: Abhishek Shroff Date: Wed, 25 Dec 2024 22:18:45 +0530 Subject: [PATCH] [server] Hook up resource bind conflict resolution --- server/internal/api/v1/fs/mkdir.go | 8 +++++--- server/internal/api/v1/fs/upload.go | 7 ++++++- server/internal/api/webdav/impl/copy_move.go | 2 +- server/internal/api/webdav/impl/webdav.go | 8 ++++---- server/internal/command/fs/mkdir.go | 3 ++- server/internal/command/fs/mv.go | 2 +- server/internal/command/user/add.go | 2 +- server/internal/core/fs/copy_move.go | 7 ++++--- server/internal/core/fs/create.go | 8 ++++---- server/internal/core/fs/fs.go | 2 +- 10 files changed, 29 insertions(+), 20 deletions(-) diff --git a/server/internal/api/v1/fs/mkdir.go b/server/internal/api/v1/fs/mkdir.go index 6e5f24df..251749d6 100644 --- a/server/internal/api/v1/fs/mkdir.go +++ b/server/internal/api/v1/fs/mkdir.go @@ -4,11 +4,13 @@ import ( "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/shroff/phylum/server/internal/api/auth" + "github.com/shroff/phylum/server/internal/core/fs" ) type mkdirParams struct { - Name string `json:"name" binding:"required"` - ParentID uuid.UUID `json:"parent_id" binding:"required"` + Name string `json:"name" binding:"required"` + ParentID uuid.UUID `json:"parent_id" binding:"required"` + Conflict fs.ResourceBindConflictResolution `json:"conflict"` } func handleMkdirRequest(c *gin.Context) { @@ -29,7 +31,7 @@ func handleMkdirRequest(c *gin.Context) { panic(err) } - r, err := parent.CreateMemberResource(params.Name, resourceID, true) + r, err := parent.CreateMemberResource(params.Name, resourceID, true, params.Conflict) if err != nil { panic(err) } diff --git a/server/internal/api/v1/fs/upload.go b/server/internal/api/v1/fs/upload.go index 00f76822..31a22a3d 100644 --- a/server/internal/api/v1/fs/upload.go +++ b/server/internal/api/v1/fs/upload.go @@ -3,6 +3,7 @@ package fs import ( "io" "net/http" + "strconv" "github.com/gin-gonic/gin" "github.com/google/uuid" @@ -21,6 +22,10 @@ func handleUploadRequest(c *gin.Context) { if err != nil || name == "" { panic(errInvalidParams) } + conflict, err := strconv.Atoi(c.Request.FormValue("conflict")) + if err != nil || name == "" { + panic(errInvalidParams) + } // TODO: Calculate and verify sha sum // c.Request.FormValue("sha256sum") @@ -31,7 +36,7 @@ func handleUploadRequest(c *gin.Context) { return err } - res, err := parent.CreateMemberResource(name, resourceID, false) + res, err := parent.CreateMemberResource(name, resourceID, false, fs.ResourceBindConflictResolution(conflict)) if err != nil { return err } diff --git a/server/internal/api/webdav/impl/copy_move.go b/server/internal/api/webdav/impl/copy_move.go index bab82dfb..687930b3 100644 --- a/server/internal/api/webdav/impl/copy_move.go +++ b/server/internal/api/webdav/impl/copy_move.go @@ -93,7 +93,7 @@ func moveFiles(f FileSystem, srcPath, dstPath string, overwrite bool) (status in } else { var conflictResolution fs.ResourceBindConflictResolution = fs.ResourceBindConflictResolutionNone if overwrite { - conflictResolution = fs.ResourceBindConflictResolutionOverwrite + conflictResolution = fs.ResourceBindConflictResolutionDelete } if _, deleted, err := src.Move(dstPath, conflictResolution); err != nil { if e, ok := err.(*errors.Error); ok { diff --git a/server/internal/api/webdav/impl/webdav.go b/server/internal/api/webdav/impl/webdav.go index 2b0ff2fd..9d70d046 100644 --- a/server/internal/api/webdav/impl/webdav.go +++ b/server/internal/api/webdav/impl/webdav.go @@ -36,7 +36,7 @@ type Handler struct { // of host operating system convention. type FileSystem interface { ResourceByPath(name string) (fs.Resource, error) - CreateResourceByPath(name string, dir, recursive bool) (fs.Resource, error) + CreateResourceByPath(name string, dir, recursive bool, conflictResolution fs.ResourceBindConflictResolution) (fs.Resource, error) } func (h *Handler) stripPrefix(p string) (string, int, error) { @@ -259,7 +259,7 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request) (status int, res, err := h.FileSystem.ResourceByPath(reqPath) if errors.Is(err, fs.ErrResourceNotFound) { - res, err = h.FileSystem.CreateResourceByPath(reqPath, false, false) + res, err = h.FileSystem.CreateResourceByPath(reqPath, false, false, fs.ResourceBindConflictResolutionOverwrite) if err != nil { if errors.Is(err, fs.ErrParentNotFound) { return http.StatusConflict, err @@ -304,7 +304,7 @@ func (h *Handler) handleMkcol(_ http.ResponseWriter, r *http.Request) (status in if r.ContentLength > 0 { return http.StatusUnsupportedMediaType, nil } - if _, err := h.FileSystem.CreateResourceByPath(reqPath, true, false); err != nil { + if _, err := h.FileSystem.CreateResourceByPath(reqPath, true, false, fs.ResourceBindConflictResolutionNone); err != nil { if errors.Is(err, fs.ErrParentNotFound) { return http.StatusConflict, err } @@ -381,7 +381,7 @@ func (h *Handler) handleLock(w http.ResponseWriter, r *http.Request) (retStatus // Create the resource if it didn't previously exist. if _, err := h.FileSystem.ResourceByPath(reqPath); err != nil { - _, err = h.FileSystem.CreateResourceByPath(reqPath, false, false) + _, err = h.FileSystem.CreateResourceByPath(reqPath, false, false, fs.ResourceBindConflictResolutionNone) if err != nil { if errors.Is(err, fs.ErrParentNotFound) { return http.StatusConflict, err diff --git a/server/internal/command/fs/mkdir.go b/server/internal/command/fs/mkdir.go index 3237be24..a5701521 100644 --- a/server/internal/command/fs/mkdir.go +++ b/server/internal/command/fs/mkdir.go @@ -5,6 +5,7 @@ import ( "os" "github.com/shroff/phylum/server/internal/command/common" + "github.com/shroff/phylum/server/internal/core/fs" "github.com/spf13/cobra" ) @@ -23,7 +24,7 @@ func setupMkdirCommand() *cobra.Command { } else { recursive = b } - if _, err := f.CreateResourceByPath(path, true, recursive); err != nil { + if _, err := f.CreateResourceByPath(path, true, recursive, fs.ResourceBindConflictResolutionNone); err != nil { fmt.Println("could not create directory: " + err.Error()) os.Exit(1) } diff --git a/server/internal/command/fs/mv.go b/server/internal/command/fs/mv.go index cd2bf5a1..c9403dc2 100644 --- a/server/internal/command/fs/mv.go +++ b/server/internal/command/fs/mv.go @@ -27,7 +27,7 @@ func setupMvCommand() *cobra.Command { var conflictResolution fs.ResourceBindConflictResolution = fs.ResourceBindConflictResolutionNone if force { - conflictResolution = fs.ResourceBindConflictResolutionOverwrite + conflictResolution = fs.ResourceBindConflictResolutionDelete } if _, _, err := src.Move(args[1], conflictResolution); err != nil { fmt.Println("cannot move'" + srcPathOrUUID + "' to '" + args[1] + "': " + err.Error()) diff --git a/server/internal/command/user/add.go b/server/internal/command/user/add.go index abb9f8f9..e4292934 100644 --- a/server/internal/command/user/add.go +++ b/server/internal/command/user/add.go @@ -103,7 +103,7 @@ func setupUserAddCommand() *cobra.Command { if homePath != "" { rootFS = rootFS.WithDb(db) - home, err := rootFS.CreateResourceByPath(homePath, true, true) + home, err := rootFS.CreateResourceByPath(homePath, true, true, fs.ResourceBindConflictResolutionNone) if err != nil { return err } diff --git a/server/internal/core/fs/copy_move.go b/server/internal/core/fs/copy_move.go index b6f7200f..d5392e35 100644 --- a/server/internal/core/fs/copy_move.go +++ b/server/internal/core/fs/copy_move.go @@ -13,9 +13,10 @@ import ( type ResourceBindConflictResolution int32 const ( - ResourceBindConflictResolutionNone = 0 - ResourceBindConflictResolutionOverwrite = 1 - ResourceBindConflictResolutionRename = 2 + ResourceBindConflictResolutionNone = 0 // Throw Error + ResourceBindConflictResolutionRename = 1 // Auto rename with suffix + ResourceBindConflictResolutionOverwrite = 2 // Try to preserve props, delete only if type mismatch (dir vs regular) + ResourceBindConflictResolutionDelete = 3 // Delete existing resource first ) func (r Resource) Move(target string, conflictResolution ResourceBindConflictResolution) (Resource, bool, error) { diff --git a/server/internal/core/fs/create.go b/server/internal/core/fs/create.go index b9721b0e..51754236 100644 --- a/server/internal/core/fs/create.go +++ b/server/internal/core/fs/create.go @@ -9,7 +9,7 @@ import ( "github.com/shroff/phylum/server/internal/core/db" ) -func (f filesystem) CreateResourceByPath(path string, dir, recursive bool) (Resource, error) { +func (f filesystem) CreateResourceByPath(path string, dir, recursive bool, conflictResolution ResourceBindConflictResolution) (Resource, error) { path = strings.TrimRight(path, "/") index := strings.LastIndex(path, "/") name := path[index+1:] @@ -19,7 +19,7 @@ func (f filesystem) CreateResourceByPath(path string, dir, recursive bool) (Reso if errors.Is(err, ErrResourceNotFound) { if recursive { // TODO: this is very inefficient, but used only directly from the command line - parent, err = f.CreateResourceByPath(parentPath, true, true) + parent, err = f.CreateResourceByPath(parentPath, true, true, conflictResolution) } else { err = ErrParentNotFound } @@ -28,10 +28,10 @@ func (f filesystem) CreateResourceByPath(path string, dir, recursive bool) (Reso return Resource{}, err } } - return parent.CreateMemberResource(name, uuid.Nil, dir) + return parent.CreateMemberResource(name, uuid.Nil, dir, conflictResolution) } -func (r Resource) CreateMemberResource(name string, id uuid.UUID, dir bool) (Resource, error) { +func (r Resource) CreateMemberResource(name string, id uuid.UUID, dir bool, conflictResolution ResourceBindConflictResolution) (Resource, error) { if !r.Dir() { return Resource{}, ErrResourceNotCollection } diff --git a/server/internal/core/fs/fs.go b/server/internal/core/fs/fs.go index 9776e5d8..70a695d4 100644 --- a/server/internal/core/fs/fs.go +++ b/server/internal/core/fs/fs.go @@ -17,7 +17,7 @@ type FileSystem interface { RunInTx(fn func(FileSystem) error) error // create.go - CreateResourceByPath(path string, dir, recursive bool) (Resource, error) + CreateResourceByPath(path string, dir, recursive bool, conflictResolution ResourceBindConflictResolution) (Resource, error) // find.go ResourceByID(id uuid.UUID) (Resource, error)