[server] resource bind conflict resolution for copy and move

This commit is contained in:
Abhishek Shroff
2024-12-25 21:53:56 +05:30
parent 10bb3f225e
commit ce53844d68
6 changed files with 48 additions and 19 deletions

View File

@@ -4,12 +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 cpParams struct {
ID uuid.UUID `json:"id" binding:"required"`
Target string `json:"target"`
Overwrite bool `json:"overwrite"`
ID uuid.UUID `json:"id" binding:"required"`
Target string `json:"target"`
Conflict fs.ResourceBindConflictResolution `json:"conflict"`
}
func handleCpRequest(c *gin.Context) {
@@ -30,7 +31,7 @@ func handleCpRequest(c *gin.Context) {
panic(err)
}
if r, _, err := r.Copy(params.Target, params.ID, true, params.Overwrite); err != nil {
if r, _, err := r.Copy(params.Target, params.ID, true, params.Conflict); err != nil {
panic(err)
} else {
c.JSON(200, ResponseFromResourceInfo(r.Info))

View File

@@ -4,11 +4,12 @@ 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 mvParams struct {
Target string `json:"target"`
Overwrite bool `json:"overwrite"`
Target string `json:"target"`
Conflict fs.ResourceBindConflictResolution `json:"conflict"`
}
func handleMvRequest(c *gin.Context) {
@@ -29,7 +30,7 @@ func handleMvRequest(c *gin.Context) {
panic(err)
}
if r, _, err := r.Move(params.Target, params.Overwrite); err != nil {
if r, _, err := r.Move(params.Target, params.Conflict); err != nil {
panic(err)
} else {
c.JSON(200, ResponseFromResourceInfo(r.Info))

View File

@@ -6,6 +6,7 @@ import (
"github.com/google/uuid"
"github.com/shroff/phylum/server/internal/core/errors"
"github.com/shroff/phylum/server/internal/core/fs"
)
func (h *Handler) handleCopyMove(_ http.ResponseWriter, r *http.Request) (status int, err error) {
@@ -83,14 +84,18 @@ func (h *Handler) handleCopyMove(_ http.ResponseWriter, r *http.Request) (status
// moveFiles moves files and/or directories from src to dst.
//
// See section 9.9.4 for when various HTTP status codes apply.
func moveFiles(fs FileSystem, srcPath, dstPath string, overwrite bool) (status int, err error) {
if src, err := fs.ResourceByPath(srcPath); err != nil {
func moveFiles(f FileSystem, srcPath, dstPath string, overwrite bool) (status int, err error) {
if src, err := f.ResourceByPath(srcPath); err != nil {
if e, ok := err.(*errors.Error); ok {
return e.Status, e
}
return http.StatusInternalServerError, err
} else {
if _, deleted, err := src.Move(dstPath, overwrite); err != nil {
var conflictResolution fs.ResourceBindConflictResolution = fs.ResourceBindConflictResolutionNone
if overwrite {
conflictResolution = fs.ResourceBindConflictResolutionOverwrite
}
if _, deleted, err := src.Move(dstPath, conflictResolution); err != nil {
if e, ok := err.(*errors.Error); ok {
return e.Status, e
}
@@ -108,15 +113,19 @@ func moveFiles(fs FileSystem, srcPath, dstPath string, overwrite bool) (status i
// copyFiles copies files and/or directories from src to dst.
//
// See section 9.8.5 for when various HTTP status codes apply.
func copyFiles(fs FileSystem, srcPath, dstPath string, overwrite bool, depth int) (status int, err error) {
if src, err := fs.ResourceByPath(srcPath); err != nil {
func copyFiles(f FileSystem, srcPath, dstPath string, overwrite bool, depth int) (status int, err error) {
if src, err := f.ResourceByPath(srcPath); err != nil {
if e, ok := err.(*errors.Error); ok {
return e.Status, e
}
return http.StatusInternalServerError, err
} else {
id, _ := uuid.NewV7()
if _, deleted, err := src.Copy(dstPath, id, depth != 0, overwrite); err != nil {
var conflictResolution fs.ResourceBindConflictResolution = fs.ResourceBindConflictResolutionNone
if overwrite {
conflictResolution = fs.ResourceBindConflictResolutionOverwrite
}
if _, deleted, err := src.Copy(dstPath, id, depth != 0, conflictResolution); err != nil {
if e, ok := err.(*errors.Error); ok {
return e.Status, e
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/google/uuid"
"github.com/shroff/phylum/server/internal/command/common"
"github.com/shroff/phylum/server/internal/core/fs"
"github.com/spf13/cobra"
)
@@ -32,7 +33,11 @@ func setupCpCommand() *cobra.Command {
}
id, _ := uuid.NewV7()
if _, _, err := src.Copy(args[1], id, true, force); err != nil {
var conflictResolution fs.ResourceBindConflictResolution = fs.ResourceBindConflictResolutionNone
if force {
conflictResolution = fs.ResourceBindConflictResolutionOverwrite
}
if _, _, err := src.Copy(args[1], id, true, conflictResolution); err != nil {
fmt.Println("cannot copy'" + srcPathOrUUID + "' to '" + args[1] + "': " + err.Error())
os.Exit(1)
}

View File

@@ -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"
)
@@ -24,7 +25,11 @@ func setupMvCommand() *cobra.Command {
force, _ := cmd.Flags().GetBool("force")
if _, _, err := src.Move(args[1], force); err != nil {
var conflictResolution fs.ResourceBindConflictResolution = fs.ResourceBindConflictResolutionNone
if force {
conflictResolution = fs.ResourceBindConflictResolutionOverwrite
}
if _, _, err := src.Move(args[1], conflictResolution); err != nil {
fmt.Println("cannot move'" + srcPathOrUUID + "' to '" + args[1] + "': " + err.Error())
os.Exit(1)
}

View File

@@ -10,7 +10,15 @@ import (
"github.com/sirupsen/logrus"
)
func (r Resource) Move(target string, overwrite bool) (Resource, bool, error) {
type ResourceBindConflictResolution int32
const (
ResourceBindConflictResolutionNone = 0
ResourceBindConflictResolutionOverwrite = 1
ResourceBindConflictResolutionRename = 2
)
func (r Resource) Move(target string, conflictResolution ResourceBindConflictResolution) (Resource, bool, error) {
if r.ParentID() == nil {
return Resource{}, false, ErrInsufficientPermissions
}
@@ -51,7 +59,7 @@ func (r Resource) Move(target string, overwrite bool) (Resource, bool, error) {
var deleted = false
return r, deleted, r.f.db.WithTx(r.f.ctx, func(dbh *db.DbHandler) error {
f := r.f.withDb(dbh)
if overwrite {
if conflictResolution == ResourceBindConflictResolutionOverwrite {
if _, err := destParent.DeleteChildRecursive(destName, false); err == nil {
deleted = true
} else if !errors.Is(err, ErrResourceNotFound) {
@@ -71,7 +79,7 @@ func (r Resource) Move(target string, overwrite bool) (Resource, bool, error) {
})
}
func (r Resource) Copy(target string, id uuid.UUID, recursive, overwrite bool) (Resource, bool, error) {
func (r Resource) Copy(target string, id uuid.UUID, recursive bool, conflictResolution ResourceBindConflictResolution) (Resource, bool, error) {
// Check source directory permissions
if !r.hasPermission(PermissionRead) {
return Resource{}, false, ErrInsufficientPermissions
@@ -143,7 +151,7 @@ func (r Resource) Copy(target string, id uuid.UUID, recursive, overwrite bool) (
var deleted = false
err = r.f.db.WithTx(r.f.ctx, func(dbh *db.DbHandler) error {
f := r.f.withDb(dbh)
if overwrite {
if conflictResolution == ResourceBindConflictResolutionOverwrite {
if _, err := destParent.DeleteChildRecursive(destName, false); err == nil {
deleted = true
} else if !errors.Is(err, ErrResourceNotFound) {