diff --git a/code/go/0chain.net/blobbercore/handler/handler_test.go b/code/go/0chain.net/blobbercore/handler/handler_test.go index 49614a930..bb1ee5317 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_test.go @@ -985,6 +985,10 @@ func TestHandlers_Requiring_Signature(t *testing.T) { AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), ) + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects"`)). + WithArgs(aa). + WillReturnError(gorm.ErrRecordNotFound) + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocation_connections" WHERE`)). WithArgs(connectionID, alloc.ID, alloc.OwnerID, allocation.DeletedConnection). WillReturnRows( @@ -992,10 +996,6 @@ func TestHandlers_Requiring_Signature(t *testing.T) { AddRow(), ) - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects"`)). - WithArgs(aa). - WillReturnError(gorm.ErrRecordNotFound) - mock.ExpectExec(`INSERT INTO "allocation_connections"`). WithArgs(aa, aa, aa, aa, aa, aa, aa). WillReturnResult(sqlmock.NewResult(0, 0)) diff --git a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go index 3f3357d0b..02cc0f9c4 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go @@ -925,7 +925,18 @@ func (fsh *StorageHandler) WriteFile(ctx context.Context, r *http.Request) (*blo return nil, common.NewError("invalid_parameters", "Invalid allocation id passed."+err.Error()) } - valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), allocationObj.OwnerPublicKey) + allocationID := allocationObj.ID + fileOperation := getFileOperation(r) + existingFileRef := getExistingFileRef(fsh, ctx, r, allocationObj, fileOperation) + isCollaborator := existingFileRef != nil && reference.IsACollaborator(ctx, existingFileRef.ID, clientID) + publicKey := allocationObj.OwnerPublicKey + + if isCollaborator { + publicKey = ctx.Value(constants.CLIENT_KEY_CONTEXT_KEY).(string) + } + + valid, err := verifySignatureFromRequest(allocationTx, r.Header.Get(common.ClientSignatureHeader), publicKey) + if !valid || err != nil { return nil, common.NewError("invalid_signature", "Invalid signature") } @@ -934,8 +945,6 @@ func (fsh *StorageHandler) WriteFile(ctx context.Context, r *http.Request) (*blo return nil, common.NewError("immutable_allocation", "Cannot write to an immutable allocation") } - allocationID := allocationObj.ID - if len(clientID) == 0 { return nil, common.NewError("invalid_operation", "Operation needs to be performed by the owner or the payer of the allocation") } @@ -960,14 +969,8 @@ func (fsh *StorageHandler) WriteFile(ctx context.Context, r *http.Request) (*blo defer mutex.Unlock() result := &blobberhttp.UploadResult{} - mode := allocation.INSERT_OPERATION - if r.Method == "PUT" { - mode = allocation.UPDATE_OPERATION - } else if r.Method == "DELETE" { - mode = allocation.DELETE_OPERATION - } - if mode == allocation.DELETE_OPERATION { + if fileOperation == allocation.DELETE_OPERATION { if allocationObj.OwnerID != clientID && allocationObj.RepairerID != clientID { return nil, common.NewError("invalid_operation", "Operation needs to be performed by the owner or the payer of the allocation") } @@ -975,44 +978,38 @@ func (fsh *StorageHandler) WriteFile(ctx context.Context, r *http.Request) (*blo if err != nil { return nil, err } - } else if mode == allocation.INSERT_OPERATION || mode == allocation.UPDATE_OPERATION { + } else if fileOperation == allocation.INSERT_OPERATION || fileOperation == allocation.UPDATE_OPERATION { + formField := getFormFieldName(fileOperation) var formData allocation.UpdateFileChange - formField := "uploadMeta" - if mode == allocation.UPDATE_OPERATION { - formField = "updateMeta" - } uploadMetaString := r.FormValue(formField) err = json.Unmarshal([]byte(uploadMetaString), &formData) if err != nil { return nil, common.NewError("invalid_parameters", "Invalid parameters. Error parsing the meta data for upload."+err.Error()) } - exisitingFileRef := fsh.checkIfFileAlreadyExists(ctx, allocationID, formData.Path) existingFileRefSize := int64(0) - exisitingFileOnCloud := false - if mode == allocation.INSERT_OPERATION { + existingFileOnCloud := false + if fileOperation == allocation.INSERT_OPERATION { if allocationObj.OwnerID != clientID && allocationObj.RepairerID != clientID { return nil, common.NewError("invalid_operation", "Operation needs to be performed by the owner or the payer of the allocation") } - if exisitingFileRef != nil { + if existingFileRef != nil { return nil, common.NewError("duplicate_file", "File at path already exists") } - } else if mode == allocation.UPDATE_OPERATION { - if exisitingFileRef == nil { + } else if fileOperation == allocation.UPDATE_OPERATION { + if existingFileRef == nil { return nil, common.NewError("invalid_file_update", "File at path does not exist for update") } - if allocationObj.OwnerID != clientID && - allocationObj.RepairerID != clientID && - !reference.IsACollaborator(ctx, exisitingFileRef.ID, clientID) { + if allocationObj.OwnerID != clientID && allocationObj.RepairerID != clientID && !isCollaborator { return nil, common.NewError("invalid_operation", "Operation needs to be performed by the owner, collaborator or the payer of the allocation") } } - if exisitingFileRef != nil { - existingFileRefSize = exisitingFileRef.Size - exisitingFileOnCloud = exisitingFileRef.OnCloud + if existingFileRef != nil { + existingFileRefSize = existingFileRef.Size + existingFileOnCloud = existingFileRef.OnCloud } origfile, _, err := r.FormFile("uploadFile") @@ -1022,13 +1019,12 @@ func (fsh *StorageHandler) WriteFile(ctx context.Context, r *http.Request) (*blo defer origfile.Close() thumbfile, thumbHeader, _ := r.FormFile("uploadThumbnailFile") - thumbnailPresent := false - if thumbHeader != nil { - thumbnailPresent = true + thumbnailPresent := thumbHeader != nil + if thumbnailPresent { defer thumbfile.Close() } - fileInputData := &filestore.FileInputData{Name: formData.Filename, Path: formData.Path, OnCloud: exisitingFileOnCloud} + fileInputData := &filestore.FileInputData{Name: formData.Filename, Path: formData.Path, OnCloud: existingFileOnCloud} fileOutputData, err := filestore.GetFileStore().WriteFile(allocationID, fileInputData, origfile, connectionObj.ConnectionID) if err != nil { return nil, common.NewError("upload_error", "Failed to upload the file. "+err.Error()) @@ -1076,12 +1072,12 @@ func (fsh *StorageHandler) WriteFile(ctx context.Context, r *http.Request) (*blo allocationChange := &allocation.AllocationChange{} allocationChange.ConnectionID = connectionObj.ConnectionID allocationChange.Size = allocationSize - existingFileRefSize - allocationChange.Operation = mode + allocationChange.Operation = fileOperation connectionObj.Size += allocationChange.Size - if mode == allocation.INSERT_OPERATION { + if fileOperation == allocation.INSERT_OPERATION { connectionObj.AddChange(allocationChange, &formData.NewFileChange) - } else if mode == allocation.UPDATE_OPERATION { + } else if fileOperation == allocation.UPDATE_OPERATION { connectionObj.AddChange(allocationChange, &formData) } } @@ -1093,3 +1089,36 @@ func (fsh *StorageHandler) WriteFile(ctx context.Context, r *http.Request) (*blo return result, nil } + +func getFormFieldName(mode string) string { + formField := "uploadMeta" + if mode == allocation.UPDATE_OPERATION { + formField = "updateMeta" + } + + return formField +} + +func getFileOperation(r *http.Request) string { + mode := allocation.INSERT_OPERATION + if r.Method == "PUT" { + mode = allocation.UPDATE_OPERATION + } else if r.Method == "DELETE" { + mode = allocation.DELETE_OPERATION + } + + return mode +} + +func getExistingFileRef(fsh *StorageHandler, ctx context.Context, r *http.Request, allocationObj *allocation.Allocation, fileOperation string) *reference.Ref { + if fileOperation == allocation.INSERT_OPERATION || fileOperation == allocation.UPDATE_OPERATION { + var formData allocation.UpdateFileChange + uploadMetaString := r.FormValue(getFormFieldName(fileOperation)) + err := json.Unmarshal([]byte(uploadMetaString), &formData) + + if err == nil { + return fsh.checkIfFileAlreadyExists(ctx, allocationObj.ID, formData.Path) + } + } + return nil +}