From 2d0a440f985823b7cf6d4264159f20e23ef6e93f Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 7 Mar 2022 16:26:13 +0800 Subject: [PATCH 1/8] fix(upload): validate path --- .../blobbercore/handler/file_command_add.go | 41 +++++++++++++++- .../go/0chain.net/blobbercore/util/strings.go | 17 +++++++ .../blobbercore/util/strings_test.go | 47 +++++++++++++++++++ 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 code/go/0chain.net/blobbercore/util/strings.go create mode 100644 code/go/0chain.net/blobbercore/util/strings_test.go diff --git a/code/go/0chain.net/blobbercore/handler/file_command_add.go b/code/go/0chain.net/blobbercore/handler/file_command_add.go index 94c69a251..486082653 100644 --- a/code/go/0chain.net/blobbercore/handler/file_command_add.go +++ b/code/go/0chain.net/blobbercore/handler/file_command_add.go @@ -3,17 +3,23 @@ package handler import ( "context" "encoding/json" + "errors" + "fmt" "net/http" + "strings" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/allocation" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/blobberhttp" + "github.com/0chain/blobber/code/go/0chain.net/blobbercore/datastore" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/filestore" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/reference" + "github.com/0chain/blobber/code/go/0chain.net/blobbercore/util" "github.com/0chain/blobber/code/go/0chain.net/core/common" "github.com/0chain/blobber/code/go/0chain.net/core/logging" "github.com/0chain/gosdk/constants" "github.com/0chain/gosdk/zboxcore/fileref" "go.uber.org/zap" + "gorm.io/gorm" ) // AddFileCommand command for resuming file @@ -42,8 +48,10 @@ func (cmd *AddFileCommand) IsAuthorized(ctx context.Context, req *http.Request, return common.NewError("duplicate_file", "File at path already exists") } - //create a FixedMerkleTree instance first, it will be reloaded from db in cmd.reloadChange if it is not first chunk - //cmd.fileChanger.FixedMerkleTree = &util.FixedMerkleTree{} + err = cmd.validatePath(ctx, allocationObj, fileChanger.Path) + if err != nil { + return err + } if fileChanger.ChunkSize <= 0 { fileChanger.ChunkSize = fileref.CHUNK_SIZE @@ -54,6 +62,35 @@ func (cmd *AddFileCommand) IsAuthorized(ctx context.Context, req *http.Request, return nil } +func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allocation.Allocation, path string) error { + files := util.SplitFiles(path) + + // only 1 directory level deep + if len(files) == 1 { + return nil + } + + parentPath := "/" + strings.Join(files, "/") + + lookupHash := reference.GetReferenceLookup(allocationObj.ID, parentPath) + + db := datastore.GetStore().GetTransaction(ctx) + var fileType string + err := db.Raw("select type from reference_objects where lookup_hash = ?", lookupHash).Pluck("type", &fileType).Error + if err != nil { + if errors.Is(gorm.ErrRecordNotFound, err) { + return nil + } + return err + } + + if fileType == fileref.FILE { + return common.NewError("invalid_path", fmt.Sprintf("parent path %v is of file type", parentPath)) + } + + return nil +} + // ProcessContent flush file to FileStorage func (cmd *AddFileCommand) ProcessContent(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, connectionObj *allocation.AllocationChangeCollector) (blobberhttp.UploadResult, error) { result := blobberhttp.UploadResult{} diff --git a/code/go/0chain.net/blobbercore/util/strings.go b/code/go/0chain.net/blobbercore/util/strings.go new file mode 100644 index 000000000..ee1331d01 --- /dev/null +++ b/code/go/0chain.net/blobbercore/util/strings.go @@ -0,0 +1,17 @@ +package util + +import ( + "strings" +) + +// SplitFiles split files from a path +func SplitFiles(path string) []string { + files := make([]string, 0) + for _, it := range strings.Split(path, "/") { + if len(it) > 0 { + files = append(files, it) + } + } + + return files +} diff --git a/code/go/0chain.net/blobbercore/util/strings_test.go b/code/go/0chain.net/blobbercore/util/strings_test.go new file mode 100644 index 000000000..775db98d2 --- /dev/null +++ b/code/go/0chain.net/blobbercore/util/strings_test.go @@ -0,0 +1,47 @@ +package util + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSplitFiles(t *testing.T) { + + tests := []struct { + name string + path string + files []string + }{ + { + name: "empty root", + path: "/", + files: []string{}, + }, + { + name: "only 1 directory level deep", + path: "/file1", + files: []string{"file1"}, + }, + { + name: "nested directories", + path: "/dir1/dir2/dir3/file1", + files: []string{"dir1", "dir2", "dir3", "file1"}, + }, + } + + for _, it := range tests { + t.Run(it.name, func(t *testing.T) { + + files := SplitFiles(it.path) + + require.Len(t, files, len(it.files)) + + for i, v := range it.files { + require.Equal(t, v, files[i]) + } + + }) + } + +} From 4f7a0b5d40ea70d974f1c85078d074fcfa95e301 Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 7 Mar 2022 16:41:09 +0800 Subject: [PATCH 2/8] fix(upload): validate path --- code/go/0chain.net/blobbercore/handler/file_command_add.go | 2 +- code/go/0chain.net/blobbercore/handler/handler_test.go | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/code/go/0chain.net/blobbercore/handler/file_command_add.go b/code/go/0chain.net/blobbercore/handler/file_command_add.go index 486082653..eeaf47d8a 100644 --- a/code/go/0chain.net/blobbercore/handler/file_command_add.go +++ b/code/go/0chain.net/blobbercore/handler/file_command_add.go @@ -76,7 +76,7 @@ func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allo db := datastore.GetStore().GetTransaction(ctx) var fileType string - err := db.Raw("select type from reference_objects where lookup_hash = ?", lookupHash).Pluck("type", &fileType).Error + err := db.Raw(`SELECT 'type' FROM "reference_objects" WHERE lookup_hash = ?`, lookupHash).Pluck("type", &fileType).Error if err != nil { if errors.Is(gorm.ErrRecordNotFound, err) { return nil diff --git a/code/go/0chain.net/blobbercore/handler/handler_test.go b/code/go/0chain.net/blobbercore/handler/handler_test.go index f09bd17d8..7b973d7a1 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_test.go @@ -1113,6 +1113,9 @@ func TestHandlers_Requiring_Signature(t *testing.T) { WithArgs(aa). WillReturnError(gorm.ErrRecordNotFound) + mock.ExpectQuery(regexp.QuoteMeta(`SELECT 'type' FROM "reference_objects" WHERE`)). + WillReturnError(gorm.ErrRecordNotFound) + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocation_connections" WHERE`)). WithArgs(connectionID, alloc.ID, alloc.OwnerID, allocation.DeletedConnection). WillReturnRows( From 375a92b5d97b596ff077c7909da65606d8dad2fd Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 7 Mar 2022 16:48:32 +0800 Subject: [PATCH 3/8] fix(upload): improved naming --- code/go/0chain.net/blobbercore/util/strings.go | 10 +++++----- .../go/0chain.net/blobbercore/util/strings_test.go | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/code/go/0chain.net/blobbercore/util/strings.go b/code/go/0chain.net/blobbercore/util/strings.go index ee1331d01..c8d8419ce 100644 --- a/code/go/0chain.net/blobbercore/util/strings.go +++ b/code/go/0chain.net/blobbercore/util/strings.go @@ -4,14 +4,14 @@ import ( "strings" ) -// SplitFiles split files from a path -func SplitFiles(path string) []string { - files := make([]string, 0) +// SplitPath split files from a path +func SplitPath(path string) []string { + items := make([]string, 0) for _, it := range strings.Split(path, "/") { if len(it) > 0 { - files = append(files, it) + items = append(items, it) } } - return files + return items } diff --git a/code/go/0chain.net/blobbercore/util/strings_test.go b/code/go/0chain.net/blobbercore/util/strings_test.go index 775db98d2..0a981fdd5 100644 --- a/code/go/0chain.net/blobbercore/util/strings_test.go +++ b/code/go/0chain.net/blobbercore/util/strings_test.go @@ -11,33 +11,33 @@ func TestSplitFiles(t *testing.T) { tests := []struct { name string path string - files []string + items []string }{ { name: "empty root", path: "/", - files: []string{}, + items: []string{}, }, { name: "only 1 directory level deep", path: "/file1", - files: []string{"file1"}, + items: []string{"file1"}, }, { name: "nested directories", path: "/dir1/dir2/dir3/file1", - files: []string{"dir1", "dir2", "dir3", "file1"}, + items: []string{"dir1", "dir2", "dir3", "file1"}, }, } for _, it := range tests { t.Run(it.name, func(t *testing.T) { - files := SplitFiles(it.path) + files := SplitPath(it.path) - require.Len(t, files, len(it.files)) + require.Len(t, files, len(it.items)) - for i, v := range it.files { + for i, v := range it.items { require.Equal(t, v, files[i]) } From 1bc97e2d6528d240d3db8e72992a3d8de56a5020 Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 7 Mar 2022 16:50:53 +0800 Subject: [PATCH 4/8] fix(upload): improved naming --- code/go/0chain.net/blobbercore/handler/file_command_add.go | 2 +- code/go/0chain.net/blobbercore/util/strings_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/go/0chain.net/blobbercore/handler/file_command_add.go b/code/go/0chain.net/blobbercore/handler/file_command_add.go index eeaf47d8a..50a06d1f5 100644 --- a/code/go/0chain.net/blobbercore/handler/file_command_add.go +++ b/code/go/0chain.net/blobbercore/handler/file_command_add.go @@ -63,7 +63,7 @@ func (cmd *AddFileCommand) IsAuthorized(ctx context.Context, req *http.Request, } func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allocation.Allocation, path string) error { - files := util.SplitFiles(path) + files := util.SplitPath(path) // only 1 directory level deep if len(files) == 1 { diff --git a/code/go/0chain.net/blobbercore/util/strings_test.go b/code/go/0chain.net/blobbercore/util/strings_test.go index 0a981fdd5..4bd866056 100644 --- a/code/go/0chain.net/blobbercore/util/strings_test.go +++ b/code/go/0chain.net/blobbercore/util/strings_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestSplitFiles(t *testing.T) { +func TestSplitPath(t *testing.T) { tests := []struct { name string From c8d369edd6b15d8d2e77f8ab794e6af59c34ba4f Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 7 Mar 2022 19:47:38 +0800 Subject: [PATCH 5/8] fix(upload): fixed parent path bug --- code/go/0chain.net/blobbercore/handler/file_command_add.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/go/0chain.net/blobbercore/handler/file_command_add.go b/code/go/0chain.net/blobbercore/handler/file_command_add.go index 50a06d1f5..0c527f4fb 100644 --- a/code/go/0chain.net/blobbercore/handler/file_command_add.go +++ b/code/go/0chain.net/blobbercore/handler/file_command_add.go @@ -70,7 +70,7 @@ func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allo return nil } - parentPath := "/" + strings.Join(files, "/") + parentPath := "/" + strings.Join(files[:len(files)-1], "/") lookupHash := reference.GetReferenceLookup(allocationObj.ID, parentPath) From 789a7ed81ca5a0e6b359ad9fa3b70ad54b725c85 Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 7 Mar 2022 20:08:23 +0800 Subject: [PATCH 6/8] fix(upload): fixed and improved path validation logic --- .../blobbercore/handler/file_command_add.go | 40 +++-- .../blobbercore/reference/ref_walker.go | 146 ++++++++++++++++++ .../blobbercore/reference/ref_walker_test.go | 81 ++++++++++ 3 files changed, 250 insertions(+), 17 deletions(-) create mode 100644 code/go/0chain.net/blobbercore/reference/ref_walker.go create mode 100644 code/go/0chain.net/blobbercore/reference/ref_walker_test.go diff --git a/code/go/0chain.net/blobbercore/handler/file_command_add.go b/code/go/0chain.net/blobbercore/handler/file_command_add.go index 0c527f4fb..484006dfd 100644 --- a/code/go/0chain.net/blobbercore/handler/file_command_add.go +++ b/code/go/0chain.net/blobbercore/handler/file_command_add.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "net/http" + "path" "strings" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/allocation" @@ -13,7 +14,6 @@ import ( "github.com/0chain/blobber/code/go/0chain.net/blobbercore/datastore" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/filestore" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/reference" - "github.com/0chain/blobber/code/go/0chain.net/blobbercore/util" "github.com/0chain/blobber/code/go/0chain.net/core/common" "github.com/0chain/blobber/code/go/0chain.net/core/logging" "github.com/0chain/gosdk/constants" @@ -62,30 +62,36 @@ func (cmd *AddFileCommand) IsAuthorized(ctx context.Context, req *http.Request, return nil } -func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allocation.Allocation, path string) error { - files := util.SplitPath(path) +func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allocation.Allocation, filePath string) error { - // only 1 directory level deep - if len(files) == 1 { + items := strings.Split(path.Clean(filePath), "/") + + // only 1 directory level deep: ["", "file"] + if len(items) == 2 { return nil } - parentPath := "/" + strings.Join(files[:len(files)-1], "/") - - lookupHash := reference.GetReferenceLookup(allocationObj.ID, parentPath) + walker := reference.NewRefWalker(items) + walker.Last() db := datastore.GetStore().GetTransaction(ctx) - var fileType string - err := db.Raw(`SELECT 'type' FROM "reference_objects" WHERE lookup_hash = ?`, lookupHash).Pluck("type", &fileType).Error - if err != nil { - if errors.Is(gorm.ErrRecordNotFound, err) { - return nil + + for walker.Back() { + currentPath := walker.Path() + lookupHash := reference.GetReferenceLookup(allocationObj.ID, currentPath) + + var fileType string + err := db.Raw(`SELECT type FROM "reference_objects" WHERE lookup_hash = ?`, lookupHash).Pluck("type", &fileType).Error + if err != nil { + if errors.Is(gorm.ErrRecordNotFound, err) { + return nil + } + return err } - return err - } - if fileType == fileref.FILE { - return common.NewError("invalid_path", fmt.Sprintf("parent path %v is of file type", parentPath)) + if fileType == fileref.FILE { + return common.NewError("invalid_path", fmt.Sprintf("parent path %v is of file type", currentPath)) + } } return nil diff --git a/code/go/0chain.net/blobbercore/reference/ref_walker.go b/code/go/0chain.net/blobbercore/reference/ref_walker.go new file mode 100644 index 000000000..3b3ba1e42 --- /dev/null +++ b/code/go/0chain.net/blobbercore/reference/ref_walker.go @@ -0,0 +1,146 @@ +package reference + +import ( + "path" + "strings" +) + +func NewRefWalkerFromPath(p string) *RefWalker { + return NewRefWalker(strings.Split(path.Clean(p), "/")) +} + +// NewRefWalker wrap dirs as RefWaller +func NewRefWalker(dirs []string) *RefWalker { + + return &RefWalker{ + items: dirs, + length: len(dirs), + index: 0, + } +} + +type RefWalker struct { + items []string + length int + index int +} + +// Name get current dir name +func (d *RefWalker) Name() string { + if d == nil { + return "/" + } + + // current is root + if d.index == 0 { + return "/" + } + + if d.index < d.length { + return d.items[d.index] + } + + return "/" +} + +// Path get current dir path +func (d *RefWalker) Path() string { + if d == nil { + return "" + } + + // current is root + if d.index == 0 { + return "/" + } + + if d.index < d.length { + return "/" + path.Join(d.items[:d.index+1]...) + } + + return "" +} + +// Parent get curerent parent path +func (d *RefWalker) Parent() string { + if d == nil { + return "" + } + + // current is root + if d.index == 0 { + return "" + } + + return "/" + path.Join(d.items[:d.index]...) +} + +// Level get current dir level +func (d *RefWalker) Level() int { + if d == nil { + return 0 + } + + return d.index + 1 +} + +// Top move to root dir +func (d *RefWalker) Top() bool { + if d == nil { + return false + } + + d.index = 0 + + return true +} + +// Last move to last sub dir +func (d *RefWalker) Last() bool { + if d == nil { + return false + } + + if d.length > 0 { + d.index = d.length - 1 + return true + } + + return false +} + +// Back back to parent dir +func (d *RefWalker) Back() bool { + if d == nil { + return false + } + + i := d.index - 1 + + // it is root + if i < 0 { + return false + } + + d.index = i + + return true +} + +// Forward go to sub dir +func (d *RefWalker) Forward() bool { + if d == nil { + return false + } + + i := d.index + 1 + + // it is root + if i >= len(d.items) { + return false + } + + d.index = i + + return true +} diff --git a/code/go/0chain.net/blobbercore/reference/ref_walker_test.go b/code/go/0chain.net/blobbercore/reference/ref_walker_test.go new file mode 100644 index 000000000..75ba6f56e --- /dev/null +++ b/code/go/0chain.net/blobbercore/reference/ref_walker_test.go @@ -0,0 +1,81 @@ +package reference + +import ( + "path" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestRefWalker(t *testing.T) { + list := []struct { + TestName string + TestPath string + WalkFunc func(w *RefWalker) bool + WalkResult bool + Name string + Level int + Path string + Parent string + }{ + {TestName: "invalid_path", TestPath: "", WalkFunc: func(w *RefWalker) bool { + return w.Top() + }, WalkResult: true, Name: "/", Level: 1, Path: "/", Parent: ""}, + + {TestName: "top", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { + return w.Top() + }, WalkResult: true, Name: "/", Level: 1, Path: "/", Parent: ""}, + + {TestName: "forward_2", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { + w.Top() + return w.Forward() + }, WalkResult: true, Name: "d1", Level: 2, Path: "/d1", Parent: "/"}, + + {TestName: "forward_3", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { + w.Top() + w.Forward() + return w.Forward() + }, WalkResult: true, Name: "d2", Level: 3, Path: "/d1/d2", Parent: "/d1"}, + + {TestName: "forward_last", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { + w.Last() + return w.Forward() + }, WalkResult: false, Name: "d3", Level: 4, Path: "/d1/d2/d3", Parent: "/d1/d2"}, + + {TestName: "last", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { + return w.Last() + }, WalkResult: true, Name: "d3", Level: 4, Path: "/d1/d2/d3", Parent: "/d1/d2"}, + + {TestName: "back_2", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { + w.Last() + return w.Back() + }, WalkResult: true, Name: "d2", Level: 3, Path: "/d1/d2", Parent: "/d1"}, + + {TestName: "back_3", TestPath: "/d1/d2/d3", WalkFunc: func(w *RefWalker) bool { + w.Last() + w.Back() + return w.Back() + }, WalkResult: true, Name: "d1", Level: 2, Path: "/d1", Parent: "/"}, + } + + for _, it := range list { + t.Run(it.TestName, func(test *testing.T) { + + dirs := strings.Split(path.Clean(it.TestPath), "/") + + rw := NewRefWalker(dirs) + result := it.WalkFunc(rw) + + r := require.New(test) + + r.Equal(it.WalkResult, result) + r.Equal(it.Name, rw.Name()) + r.Equal(it.Level, rw.Level()) + r.Equal(it.Path, rw.Path()) + r.Equal(it.Parent, rw.Parent()) + + }) + } + +} From 9ff1466114b489b1ab8e62340bbd6f4569316c51 Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 7 Mar 2022 20:16:30 +0800 Subject: [PATCH 7/8] fix(upload): fixed handler test --- code/go/0chain.net/blobbercore/handler/file_command_add.go | 7 ++++++- code/go/0chain.net/blobbercore/handler/handler_test.go | 3 --- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/code/go/0chain.net/blobbercore/handler/file_command_add.go b/code/go/0chain.net/blobbercore/handler/file_command_add.go index 484006dfd..7c706a8a6 100644 --- a/code/go/0chain.net/blobbercore/handler/file_command_add.go +++ b/code/go/0chain.net/blobbercore/handler/file_command_add.go @@ -67,7 +67,7 @@ func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allo items := strings.Split(path.Clean(filePath), "/") // only 1 directory level deep: ["", "file"] - if len(items) == 2 { + if len(items) <= 2 { return nil } @@ -78,6 +78,11 @@ func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allo for walker.Back() { currentPath := walker.Path() + + if currentPath == "/" { + return nil + } + lookupHash := reference.GetReferenceLookup(allocationObj.ID, currentPath) var fileType string diff --git a/code/go/0chain.net/blobbercore/handler/handler_test.go b/code/go/0chain.net/blobbercore/handler/handler_test.go index 7b973d7a1..f09bd17d8 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_test.go @@ -1113,9 +1113,6 @@ func TestHandlers_Requiring_Signature(t *testing.T) { WithArgs(aa). WillReturnError(gorm.ErrRecordNotFound) - mock.ExpectQuery(regexp.QuoteMeta(`SELECT 'type' FROM "reference_objects" WHERE`)). - WillReturnError(gorm.ErrRecordNotFound) - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocation_connections" WHERE`)). WithArgs(connectionID, alloc.ID, alloc.OwnerID, allocation.DeletedConnection). WillReturnRows( From cb0b17523e135ac24483f9fbac23d757f87d5eab Mon Sep 17 00:00:00 2001 From: Lz Date: Tue, 8 Mar 2022 17:30:33 +0800 Subject: [PATCH 8/8] fix(refwalker): improved code --- .../blobbercore/handler/file_command_add.go | 12 ++---- .../blobbercore/reference/ref_walker.go | 37 ++++++++++++------- .../blobbercore/reference/ref_walker_test.go | 21 +++++++++-- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/code/go/0chain.net/blobbercore/handler/file_command_add.go b/code/go/0chain.net/blobbercore/handler/file_command_add.go index 7c706a8a6..083b32c4a 100644 --- a/code/go/0chain.net/blobbercore/handler/file_command_add.go +++ b/code/go/0chain.net/blobbercore/handler/file_command_add.go @@ -6,8 +6,6 @@ import ( "errors" "fmt" "net/http" - "path" - "strings" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/allocation" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/blobberhttp" @@ -64,20 +62,18 @@ func (cmd *AddFileCommand) IsAuthorized(ctx context.Context, req *http.Request, func (cmd *AddFileCommand) validatePath(ctx context.Context, allocationObj *allocation.Allocation, filePath string) error { - items := strings.Split(path.Clean(filePath), "/") + walker := reference.NewRefWalkerFromPath(filePath) // only 1 directory level deep: ["", "file"] - if len(items) <= 2 { - return nil - } + if walker.Length() <= 2 { - walker := reference.NewRefWalker(items) + } walker.Last() db := datastore.GetStore().GetTransaction(ctx) for walker.Back() { - currentPath := walker.Path() + currentPath, _ := walker.Path() if currentPath == "/" { return nil diff --git a/code/go/0chain.net/blobbercore/reference/ref_walker.go b/code/go/0chain.net/blobbercore/reference/ref_walker.go index 3b3ba1e42..e734d1bf7 100644 --- a/code/go/0chain.net/blobbercore/reference/ref_walker.go +++ b/code/go/0chain.net/blobbercore/reference/ref_walker.go @@ -26,53 +26,53 @@ type RefWalker struct { } // Name get current dir name -func (d *RefWalker) Name() string { +func (d *RefWalker) Name() (string, bool) { if d == nil { - return "/" + return "", false } // current is root if d.index == 0 { - return "/" + return "/", true } if d.index < d.length { - return d.items[d.index] + return d.items[d.index], true } - return "/" + return "", false } // Path get current dir path -func (d *RefWalker) Path() string { +func (d *RefWalker) Path() (string, bool) { if d == nil { - return "" + return "", false } // current is root if d.index == 0 { - return "/" + return "/", true } if d.index < d.length { - return "/" + path.Join(d.items[:d.index+1]...) + return "/" + path.Join(d.items[:d.index+1]...), true } - return "" + return "", false } // Parent get curerent parent path -func (d *RefWalker) Parent() string { +func (d *RefWalker) Parent() (string, bool) { if d == nil { - return "" + return "", false } // current is root if d.index == 0 { - return "" + return "", true } - return "/" + path.Join(d.items[:d.index]...) + return "/" + path.Join(d.items[:d.index]...), true } // Level get current dir level @@ -84,6 +84,15 @@ func (d *RefWalker) Level() int { return d.index + 1 } +// Level get the numbers of dir +func (d *RefWalker) Length() int { + if d == nil { + return 0 + } + + return len(d.items) +} + // Top move to root dir func (d *RefWalker) Top() bool { if d == nil { diff --git a/code/go/0chain.net/blobbercore/reference/ref_walker_test.go b/code/go/0chain.net/blobbercore/reference/ref_walker_test.go index 75ba6f56e..bb06546d6 100644 --- a/code/go/0chain.net/blobbercore/reference/ref_walker_test.go +++ b/code/go/0chain.net/blobbercore/reference/ref_walker_test.go @@ -57,6 +57,12 @@ func TestRefWalker(t *testing.T) { w.Back() return w.Back() }, WalkResult: true, Name: "d1", Level: 2, Path: "/d1", Parent: "/"}, + + {TestName: "back_3_with_invalid_dir", TestPath: `/d1///d2/d3`, WalkFunc: func(w *RefWalker) bool { + w.Last() + w.Back() + return w.Back() + }, WalkResult: true, Name: "d1", Level: 2, Path: "/d1", Parent: "/"}, } for _, it := range list { @@ -70,10 +76,19 @@ func TestRefWalker(t *testing.T) { r := require.New(test) r.Equal(it.WalkResult, result) - r.Equal(it.Name, rw.Name()) + name, ok := rw.Name() + r.True(ok) + r.Equal(it.Name, name) + r.Equal(it.Level, rw.Level()) - r.Equal(it.Path, rw.Path()) - r.Equal(it.Parent, rw.Parent()) + + path, ok := rw.Path() + r.True(ok) + r.Equal(it.Path, path) + + parentPath, ok := rw.Parent() + r.True(ok) + r.Equal(it.Parent, parentPath) }) }