Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/delete requests #672

Merged
merged 10 commits into from
May 14, 2022
6 changes: 5 additions & 1 deletion code/go/0chain.net/blobbercore/handler/file_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import (

// FileCommand execute command for a file operation
type FileCommand interface {

// GetExistingFileRef get file ref if it exists
GetExistingFileRef() *reference.Ref

// IsValidated validate request, and try build ChangeProcesser instance
IsValidated(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, clientID string) error

Expand All @@ -35,7 +39,7 @@ func createFileCommand(req *http.Request) FileCommand {
case http.MethodPut:
return &UpdateFileCommand{}
case http.MethodDelete:
return &FileCommandDelete{}
return &DeleteFileCommand{}

default:
return &UploadFileCommand{}
Expand Down
20 changes: 12 additions & 8 deletions code/go/0chain.net/blobbercore/handler/file_command_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,25 @@ import (
"github.com/0chain/blobber/code/go/0chain.net/core/common"
)

// FileCommandDelete command for deleting file
type FileCommandDelete struct {
// DeleteFileCommand command for deleting file
type DeleteFileCommand struct {
existingFileRef *reference.Ref
changeProcessor *allocation.DeleteFileChange
allocationChange *allocation.AllocationChange
}

func (cmd *DeleteFileCommand) GetExistingFileRef() *reference.Ref {
return cmd.existingFileRef
}

// IsValidated validate request.
func (cmd *FileCommandDelete) IsValidated(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, clientID string) error {
func (cmd *DeleteFileCommand) IsValidated(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, clientID string) error {
if allocationObj.OwnerID != clientID && allocationObj.RepairerID != clientID {
return common.NewError("invalid_operation", "Operation needs to be performed by the owner or the payer of the allocation")
}

path := req.FormValue("path")
if path == "" {
path, ok := GetField(req, "path")
if !ok {
return common.NewError("invalid_parameters", "Invalid path")
}
var err error
Expand All @@ -43,14 +47,14 @@ func (cmd *FileCommandDelete) IsValidated(ctx context.Context, req *http.Request
}

// UpdateChange add DeleteFileChange in db
func (cmd *FileCommandDelete) UpdateChange(ctx context.Context, connectionObj *allocation.AllocationChangeCollector) error {
func (cmd *DeleteFileCommand) UpdateChange(ctx context.Context, connectionObj *allocation.AllocationChangeCollector) error {
connectionObj.AddChange(cmd.allocationChange, cmd.changeProcessor)

return connectionObj.Save(ctx)
}

// ProcessContent flush file to FileStorage
func (cmd *FileCommandDelete) ProcessContent(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, connectionObj *allocation.AllocationChangeCollector) (blobberhttp.UploadResult, error) {
func (cmd *DeleteFileCommand) ProcessContent(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, connectionObj *allocation.AllocationChangeCollector) (blobberhttp.UploadResult, error) {
deleteSize := cmd.existingFileRef.Size

cmd.changeProcessor = &allocation.DeleteFileChange{ConnectionID: connectionObj.ID,
Expand All @@ -74,7 +78,7 @@ func (cmd *FileCommandDelete) ProcessContent(ctx context.Context, req *http.Requ
}

// ProcessThumbnail no thumbnail should be processed for delete. A deffered delete command has been added on ProcessContent
func (cmd *FileCommandDelete) ProcessThumbnail(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, connectionObj *allocation.AllocationChangeCollector) error {
func (cmd *DeleteFileCommand) ProcessThumbnail(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, connectionObj *allocation.AllocationChangeCollector) error {
//DO NOTHING
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ type UpdateFileCommand struct {
allocationChange *allocation.AllocationChange
}

func (cmd *UpdateFileCommand) GetExistingFileRef() *reference.Ref {
return cmd.existingFileRef
}

// IsValidated validate request.
func (cmd *UpdateFileCommand) IsValidated(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, clientID string) error {
uploadMetaString := req.FormValue("uploadMeta")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ type UploadFileCommand struct {
fileChanger *allocation.UploadFileChanger
}

func (cmd *UploadFileCommand) GetExistingFileRef() *reference.Ref {
return nil
}

// IsValidated validate request.
func (cmd *UploadFileCommand) IsValidated(ctx context.Context, req *http.Request, allocationObj *allocation.Allocation, clientID string) error {
if allocationObj.OwnerID != clientID && allocationObj.RepairerID != clientID {
Expand Down
12 changes: 11 additions & 1 deletion code/go/0chain.net/blobbercore/handler/grpc_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,17 @@ func (b *blobberGRPCService) Collaborator(ctx context.Context, req *blobbergrpc.
"collab_id": {req.CollabId},
}

resp, err := CollaboratorHandler(ctx, r)
var resp interface{}

switch req.Method {
case http.MethodPost:
resp, err = AddCollaboratorHandler(ctx, r)
case http.MethodGet:
resp, err = GetCollaboratorHandler(ctx, r)
case http.MethodDelete:
resp, err = RemoveCollaboratorHandler(ctx, r)
}

if err != nil {
return nil, err
}
Expand Down
13 changes: 9 additions & 4 deletions code/go/0chain.net/blobbercore/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,14 @@ func SetupHandlers(r *mux.Router) {

r.HandleFunc("/v1/connection/commit/{allocation}", common.ToStatusCode(WithStatusConnection(CommitHandler)))
r.HandleFunc("/v1/file/commitmetatxn/{allocation}", common.ToJSONResponse(WithConnection(CommitMetaTxnHandler)))
r.HandleFunc("/v1/file/collaborator/{allocation}", common.ToJSONResponse(WithConnection(CollaboratorHandler)))

r.HandleFunc("/v1/file/calculatehash/{allocation}", common.ToJSONResponse(WithConnection(CalculateHashHandler)))

// collaborator
r.HandleFunc("/v1/file/collaborator/{allocation}", common.ToJSONResponse(WithConnection(AddCollaboratorHandler))).Methods(http.MethodOptions, http.MethodPost)
r.HandleFunc("/v1/file/collaborator/{allocation}", common.ToJSONResponse(WithConnection(GetCollaboratorHandler))).Methods(http.MethodOptions, http.MethodGet)
r.HandleFunc("/v1/file/collaborator/{allocation}", common.ToJSONResponse(WithConnection(RemoveCollaboratorHandler))).Methods(http.MethodOptions, http.MethodDelete)

//object info related apis
r.HandleFunc("/allocation", common.ToJSONResponse(WithConnection(AllocationHandler)))
r.HandleFunc("/v1/file/meta/{allocation}", common.ToJSONResponse(WithReadOnlyConnection(FileMetaHandler)))
Expand Down Expand Up @@ -293,7 +298,7 @@ func UpdateAttributesHandler(ctx context.Context, r *http.Request) (interface{},
return response, nil
}

func writeResponse (w http.ResponseWriter, resp []byte) {
func writeResponse(w http.ResponseWriter, resp []byte) {
_, err := w.Write(resp)

if err != nil {
Expand Down Expand Up @@ -395,8 +400,8 @@ func RevokeShare(ctx context.Context, r *http.Request) (interface{}, error) {
return nil, common.NewError("invalid_signature", "Invalid signature")
}

path := r.FormValue("path")
refereeClientID := r.FormValue("refereeClientID")
path, _ := GetField(r, "path")
refereeClientID, _ := GetField(r, "refereeClientID")
filePathHash := fileref.GetReferenceLookup(allocationID, path)
//_, err = reference.GetReferenceByLookupHashForAddCollaborator(ctx, allocationID, filePathHash)
_, err = reference.GetLimitedRefFieldsByLookupHash(ctx, allocationID, filePathHash, []string{"id", "type"})
Expand Down
40 changes: 31 additions & 9 deletions code/go/0chain.net/blobbercore/handler/handler_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func CalculateHashHandler(ctx context.Context, r *http.Request) (interface{}, er
return response, nil
}

func CollaboratorHandler(ctx context.Context, r *http.Request) (interface{}, error) {
func AddCollaboratorHandler(ctx context.Context, r *http.Request) (interface{}, error) {

ctx = setupHandlerContext(ctx, r)

Expand All @@ -69,6 +69,28 @@ func CollaboratorHandler(ctx context.Context, r *http.Request) (interface{}, err
return response, nil
}

func GetCollaboratorHandler(ctx context.Context, r *http.Request) (interface{}, error) {

ctx = setupHandlerContext(ctx, r)

response, err := storageHandler.GetCollaborator(ctx, r)
cnlangzi marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}
return response, nil
}

func RemoveCollaboratorHandler(ctx context.Context, r *http.Request) (interface{}, error) {

ctx = setupHandlerContext(ctx, r)

response, err := storageHandler.RemoveCollaborator(ctx, r)
cnlangzi marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}
return response, nil
}

func HomepageHandler(w http.ResponseWriter, r *http.Request) {
mc := chain.GetServerChain()

Expand All @@ -95,21 +117,21 @@ func HomepageHandler(w http.ResponseWriter, r *http.Request) {
}

type BlobberInfo struct {
ChainId string `json:"chain_id"`
BlobberId string `json:"blobber_id"`
BlobberPublicKey string `json:"public_key"`
BuildTag string `json:"build_tag"`
Stats interface{} `json:"stats"`
ChainId string `json:"chain_id"`
BlobberId string `json:"blobber_id"`
BlobberPublicKey string `json:"public_key"`
BuildTag string `json:"build_tag"`
Stats interface{} `json:"stats"`
}

func GetBlobberInfoJson() BlobberInfo {
mc := chain.GetServerChain()

blobberInfo := BlobberInfo{
ChainId: mc.ID,
BlobberId: node.Self.ID,
ChainId: mc.ID,
BlobberId: node.Self.ID,
BlobberPublicKey: node.Self.PublicKey,
BuildTag: build.BuildTag,
BuildTag: build.BuildTag,
}

return blobberInfo
Expand Down
39 changes: 16 additions & 23 deletions code/go/0chain.net/blobbercore/handler/handler_share_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"mime/multipart"
"net/http"
"net/http/httptest"
"net/url"
"os"
"regexp"
"testing"
Expand Down Expand Up @@ -372,23 +373,21 @@ func TestHandlers_Share(t *testing.T) {
args: args{
w: httptest.NewRecorder(),
r: func() *http.Request {
url, err := router.Get(revokeShare).URL("allocation", alloc.Tx)
u, err := router.Get(revokeShare).URL("allocation", alloc.Tx)
if err != nil {
t.Fatal()
}

body := bytes.NewBuffer(nil)
formWriter := multipart.NewWriter(body)
query := &url.Values{}
shareClientID := "da4b54d934890aa415bb043ce1126f2e30a96faf63a4c65c25bbddcb32824d77"
remotePath := "/file.txt"

require.NoError(t, formWriter.WriteField("refereeClientID", shareClientID))
require.NoError(t, formWriter.WriteField("path", remotePath))
if err := formWriter.Close(); err != nil {
t.Fatal(err)
}
r, err := http.NewRequest(http.MethodDelete, url.String(), body)
r.Header.Add("Content-Type", formWriter.FormDataContentType())
query.Add("refereeClientID", shareClientID)
query.Add("path", remotePath)

u.RawQuery = query.Encode()
r, err := http.NewRequest(http.MethodDelete, u.String(), nil)

if err != nil {
t.Fatal(err)
}
Expand All @@ -399,7 +398,6 @@ func TestHandlers_Share(t *testing.T) {
t.Fatal(err)
}

r.Header.Set("Content-Type", formWriter.FormDataContentType())
r.Header.Set(common.ClientSignatureHeader, sign)
r.Header.Set(common.ClientHeader, alloc.OwnerID)

Expand Down Expand Up @@ -451,34 +449,29 @@ func TestHandlers_Share(t *testing.T) {
args: args{
w: httptest.NewRecorder(),
r: func() *http.Request {
url, err := router.Get(revokeShare).URL("allocation", alloc.Tx)
u, err := router.Get(revokeShare).URL("allocation", alloc.Tx)
if err != nil {
t.Fatal()
}

body := bytes.NewBuffer(nil)
formWriter := multipart.NewWriter(body)
query := &url.Values{}
shareClientID := "da4b54d934890aa415bb043ce1126f2e30a96faf63a4c65c25bbddcb32824d77"
remotePath := "/file.txt"

require.NoError(t, formWriter.WriteField("refereeClientID", shareClientID))
require.NoError(t, formWriter.WriteField("path", remotePath))
if err := formWriter.Close(); err != nil {
t.Fatal(err)
}
r, err := http.NewRequest(http.MethodDelete, url.String(), body)
r.Header.Add("Content-Type", formWriter.FormDataContentType())
query.Add("refereeClientID", shareClientID)
query.Add("path", remotePath)

u.RawQuery = query.Encode()
r, err := http.NewRequest(http.MethodDelete, u.String(), nil)
if err != nil {
t.Fatal(err)
}

hash := encryption.Hash(alloc.Tx)
sign, err := sch.Sign(hash)
if err != nil {
t.Fatal(err)
}

r.Header.Set("Content-Type", formWriter.FormDataContentType())
r.Header.Set(common.ClientSignatureHeader, sign)
r.Header.Set(common.ClientHeader, alloc.OwnerID)

Expand Down
3 changes: 2 additions & 1 deletion code/go/0chain.net/blobbercore/handler/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func setupHandlers() (*mux.Router, map[string]string) {
collName := "Collaborator"
router.HandleFunc(collPath, common.UserRateLimit(
common.ToJSONResponse(
WithReadOnlyConnection(CollaboratorHandler),
WithReadOnlyConnection(GetCollaboratorHandler),
),
),
).Name(collName)
Expand Down Expand Up @@ -1141,6 +1141,7 @@ func TestHandlers_Requiring_Signature(t *testing.T) {
}
tests := append(positiveTests, negativeTests...)
tests = append(tests, uploadNegativeTests...)

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
mock := datastore.MockTheStore(t)
Expand Down
17 changes: 17 additions & 0 deletions code/go/0chain.net/blobbercore/handler/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,20 @@ func TryParseForm(r *http.Request) {
}
}
}

// GetField get field from form or query
func GetField(r *http.Request, key string) (string, bool) {
TryParseForm(r)

v, ok := r.Form[key]
if ok {
return v[0], true
}

v, ok = r.URL.Query()[key]
if ok {
return v[0], true
}

return "", false
}
Loading