From 4ed83c93999c9ca6cbc21a49d9431ec87ab175eb Mon Sep 17 00:00:00 2001 From: Pradip Parmar Date: Tue, 22 Feb 2022 21:52:11 +0530 Subject: [PATCH 01/12] change data reading from form to header for download. Signed-off-by: Pradip Parmar --- .../handler/object_operation_handler.go | 19 +++++++------------ .../blobbercore/handler/storage_handler.go | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 12 deletions(-) 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 30d17f85d..40ab6fe59 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go @@ -192,17 +192,12 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r return nil, common.NewErrorf("download_file", "invalid allocation id passed: %v", err) } - if err = r.ParseMultipartForm(FormFileParseMaxMemory); err != nil { - Logger.Info("download_file - request_parse_error", zap.Error(err)) - return nil, common.NewErrorf("download_file", "request_parse_error: %v", err) - } - - pathHash, err := pathHashFromReq(r, alloc.ID) + pathHash, _, err := getPathHashFromHeader(r, alloc.ID) if err != nil { return nil, common.NewError("download_file", "invalid path") } - var blockNumStr = r.FormValue("block_num") + var blockNumStr = r.Header.Get("block_num") if blockNumStr == "" { return nil, common.NewError("download_file", "no block number") } @@ -214,7 +209,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r } numBlocks := int64(1) - numBlocksStr := r.FormValue("num_blocks") + numBlocksStr := r.Header.Get("num_blocks") if numBlocksStr != "" { numBlocks, err = strconv.ParseInt(numBlocksStr, 10, 64) @@ -223,7 +218,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r } } - readMarkerString := r.FormValue("read_marker") + readMarkerString := r.Header.Get("read_marker") readMarker := new(readmarker.ReadMarker) if err := json.Unmarshal([]byte(readMarkerString), readMarker); err != nil { @@ -264,7 +259,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r var shareInfo *reference.ShareInfo if !(isOwner || isCollaborator) { - authTokenString := r.FormValue("auth_token") + authTokenString := r.Header.Get("auth_token") if authTokenString == "" { return nil, common.NewError("invalid_client", "authticket is required") } @@ -283,7 +278,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r } // set payer: check for command line payer flag (--rx_pay) - if r.FormValue("rx_pay") == "true" { + if r.Header.Get("rx_pay") == "true" { payerID = clientID } @@ -332,7 +327,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r // reading is allowed var ( - downloadMode = r.FormValue("content") + downloadMode = r.Header.Get("content") respData []byte ) if downloadMode == DownloadContentThumb { diff --git a/code/go/0chain.net/blobbercore/handler/storage_handler.go b/code/go/0chain.net/blobbercore/handler/storage_handler.go index e543f02cc..e7bf4f26e 100644 --- a/code/go/0chain.net/blobbercore/handler/storage_handler.go +++ b/code/go/0chain.net/blobbercore/handler/storage_handler.go @@ -980,6 +980,20 @@ func pathHashFromReq(r *http.Request, allocationID string) (pathHash string, err return } +func getPathHashFromHeader(r *http.Request, allocationID string) (pathHash, path string, err error) { + pathHash = r.Header.Get("path_hash") + path = r.Header.Get("path") + + if pathHash == "" { + if path == "" { + return "", "", common.NewError("invalid_parameters", "Invalid path") + } + pathHash = reference.GetReferenceLookup(allocationID, path) + } + + return pathHash, path, nil +} + func getPathHash(r *http.Request, allocationID string) (pathHash, path string, err error) { pathHash = r.FormValue("path_hash") path = r.FormValue("path") From ad8f1bd9c2fc37c41d3d9dc4b20b3ce8db602ab0 Mon Sep 17 00:00:00 2001 From: Pradip Parmar Date: Wed, 23 Feb 2022 05:42:59 +0530 Subject: [PATCH 02/12] unit test fix Signed-off-by: Pradip Parmar --- .../handler/object_operation_handler_test.go | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/code/go/0chain.net/blobbercore/handler/object_operation_handler_test.go b/code/go/0chain.net/blobbercore/handler/object_operation_handler_test.go index 71dc038c7..467cbd915 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler_test.go @@ -1,12 +1,10 @@ package handler import ( - "bytes" "context" "database/sql/driver" "encoding/json" "fmt" - "mime/multipart" "net/http" "net/http/httptest" "time" @@ -111,7 +109,7 @@ func TestDownloadFile(t *testing.T) { // reuse code from GOSDK, https://github.com/0chain/gosdk/blob/staging/zboxcore/sdk/blockdownloadworker.go#L150 var addToForm = func( t *testing.T, - formWriter *multipart.Writer, + req *http.Request, p parameters, ) *marker.ReadMarker { rm := &marker.ReadMarker{} @@ -126,14 +124,14 @@ func TestDownloadFile(t *testing.T) { require.NoError(t, err) rmData, err := json.Marshal(rm) require.NoError(t, err) - require.NoError(t, formWriter.WriteField("path_hash", p.inData.pathHash)) - require.NoError(t, formWriter.WriteField("path", p.inData.remotefilepath)) + req.Header.Set("path_hash", p.inData.pathHash) + req.Header.Set("path", p.inData.remotefilepath) if p.inData.rxPay { - require.NoError(t, formWriter.WriteField("rx_pay", "true")) + req.Header.Set("rx_pay", "true") } - require.NoError(t, formWriter.WriteField("block_num", fmt.Sprintf("%d", p.inData.blockNum))) - require.NoError(t, formWriter.WriteField("num_blocks", fmt.Sprintf("%d", p.inData.numBlocks))) - require.NoError(t, formWriter.WriteField("read_marker", string(rmData))) + req.Header.Set("block_num", fmt.Sprintf("%d", p.inData.blockNum)) + req.Header.Set("num_blocks", fmt.Sprintf("%d", p.inData.numBlocks)) + req.Header.Set("read_marker", string(rmData)) if p.useAuthTicket { authTicket := &marker.AuthTicket{ AllocationID: p.inData.allocationID, @@ -147,12 +145,11 @@ func TestDownloadFile(t *testing.T) { require.NoError(t, authTicket.Sign()) require.NoError(t, client.PopulateClient(mockClientWallet, "bls0chain")) authTicketBytes, _ := json.Marshal(authTicket) - require.NoError(t, formWriter.WriteField("auth_token", string(authTicketBytes))) + req.Header.Set("auth_token", string(authTicketBytes)) } if len(p.inData.contentMode) > 0 { - require.NoError(t, formWriter.WriteField("content", p.inData.contentMode)) + req.Header.Set("content", p.inData.contentMode) } - require.NoError(t, formWriter.Close()) return rm } @@ -432,12 +429,8 @@ func TestDownloadFile(t *testing.T) { } setupRequest := func(p parameters) (*http.Request, *marker.ReadMarker) { - body := new(bytes.Buffer) - formWriter := multipart.NewWriter(body) - rm := addToForm(t, formWriter, p) - req := httptest.NewRequest(http.MethodGet, "/v1/file/download/", body) - require.NoError(t, req.ParseForm()) - req.Header.Add("Content-Type", formWriter.FormDataContentType()) + req := httptest.NewRequest(http.MethodGet, "/v1/file/download/", nil) + rm := addToForm(t, req, p) return req, rm } From dafadd48fa6224e0a390be6ba3bfc6772c589f08 Mon Sep 17 00:00:00 2001 From: Pradip Parmar Date: Wed, 23 Feb 2022 06:02:33 +0530 Subject: [PATCH 03/12] handler test fix Signed-off-by: Pradip Parmar --- .../blobbercore/handler/handler_test.go | 123 +++++------------- 1 file changed, 34 insertions(+), 89 deletions(-) diff --git a/code/go/0chain.net/blobbercore/handler/handler_test.go b/code/go/0chain.net/blobbercore/handler/handler_test.go index 49615e78e..60305ddb1 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_test.go @@ -1506,12 +1506,8 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal() } - body := bytes.NewBuffer(nil) - formWriter := multipart.NewWriter(body) remotePath := "/file.txt" - require.NoError(t, formWriter.WriteField("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath))) - require.NoError(t, formWriter.WriteField("block_num", fmt.Sprintf("%d", 1))) rm := &marker.ReadMarker{} rm.ClientID = ownerClient.ClientID rm.ClientPublicKey = ownerClient.ClientKey @@ -1524,14 +1520,9 @@ func TestHandlers_Requiring_Signature(t *testing.T) { } rmData, err := json.Marshal(rm) require.NoError(t, err) - require.NoError(t, formWriter.WriteField("read_marker", string(rmData))) - if err := formWriter.Close(); err != nil { - t.Fatal(err) - } - r, err := http.NewRequest(http.MethodPost, url.String(), body) - r.Header.Add("Content-Type", formWriter.FormDataContentType()) + r, err := http.NewRequest(http.MethodPost, url.String(), nil) if err != nil { - t.Fatal(err) + require.NoError(t, err) } hash := encryption.Hash(alloc.Tx) @@ -1540,7 +1531,9 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("Content-Type", formWriter.FormDataContentType()) + r.Header.Set("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("read_marker", string(rmData)) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, alloc.OwnerID) r.Header.Set(common.ClientKeyHeader, alloc.OwnerPublicKey) @@ -1591,12 +1584,8 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal() } - body := bytes.NewBuffer(nil) - formWriter := multipart.NewWriter(body) remotePath := "/file.txt" - require.NoError(t, formWriter.WriteField("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath))) - require.NoError(t, formWriter.WriteField("block_num", fmt.Sprintf("%d", 1))) rm := &marker.ReadMarker{} rm.ClientID = ownerClient.ClientID rm.ClientPublicKey = ownerClient.ClientKey @@ -1610,12 +1599,7 @@ func TestHandlers_Requiring_Signature(t *testing.T) { } rmData, err := json.Marshal(rm) require.NoError(t, err) - require.NoError(t, formWriter.WriteField("read_marker", string(rmData))) - if err := formWriter.Close(); err != nil { - t.Fatal(err) - } - r, err := http.NewRequest(http.MethodPost, url.String(), body) - r.Header.Add("Content-Type", formWriter.FormDataContentType()) + r, err := http.NewRequest(http.MethodPost, url.String(), nil) if err != nil { t.Fatal(err) } @@ -1626,7 +1610,9 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("Content-Type", formWriter.FormDataContentType()) + r.Header.Set("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("read_marker", string(rmData)) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, alloc.OwnerID) r.Header.Set(common.ClientKeyHeader, alloc.OwnerPublicKey) @@ -1699,19 +1685,14 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal() } - body := bytes.NewBuffer(nil) - formWriter := multipart.NewWriter(body) remotePath := "/file.txt" pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) - require.NoError(t, formWriter.WriteField("path_hash", pathHash)) - require.NoError(t, formWriter.WriteField("block_num", fmt.Sprintf("%d", 1))) authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, ownerClient.Keys[0].PublicKey) if err != nil { t.Fatal(err) } - require.NoError(t, formWriter.WriteField("auth_token", authTicket)) rm := &marker.ReadMarker{} rm.ClientID = guestClient.ClientID rm.ClientPublicKey = guestClient.ClientKey @@ -1725,12 +1706,7 @@ func TestHandlers_Requiring_Signature(t *testing.T) { } rmData, err := json.Marshal(rm) require.NoError(t, err) - require.NoError(t, formWriter.WriteField("read_marker", string(rmData))) - if err := formWriter.Close(); err != nil { - t.Fatal(err) - } - r, err := http.NewRequest(http.MethodPost, url.String(), body) - r.Header.Add("Content-Type", formWriter.FormDataContentType()) + r, err := http.NewRequest(http.MethodPost, url.String(), nil) if err != nil { t.Fatal(err) } @@ -1741,7 +1717,10 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("Content-Type", formWriter.FormDataContentType()) + r.Header.Set("read_marker", string(rmData)) + r.Header.Set("path_hash", pathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) @@ -1819,18 +1798,13 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal() } - body := bytes.NewBuffer(nil) - formWriter := multipart.NewWriter(body) remotePath := "/file.txt" pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) - require.NoError(t, formWriter.WriteField("path_hash", pathHash)) - require.NoError(t, formWriter.WriteField("block_num", fmt.Sprintf("%d", 1))) authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") if err != nil { t.Fatal(err) } - require.NoError(t, formWriter.WriteField("auth_token", authTicket)) rm := &marker.ReadMarker{} rm.ClientID = guestClient.ClientID rm.ClientPublicKey = guestClient.ClientKey @@ -1844,12 +1818,7 @@ func TestHandlers_Requiring_Signature(t *testing.T) { } rmData, err := json.Marshal(rm) require.NoError(t, err) - require.NoError(t, formWriter.WriteField("read_marker", string(rmData))) - if err := formWriter.Close(); err != nil { - t.Fatal(err) - } - r, err := http.NewRequest(http.MethodPost, url.String(), body) - r.Header.Add("Content-Type", formWriter.FormDataContentType()) + r, err := http.NewRequest(http.MethodPost, url.String(), nil) if err != nil { t.Fatal(err) } @@ -1860,7 +1829,10 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("Content-Type", formWriter.FormDataContentType()) + r.Header.Set("read_marker", string(rmData)) + r.Header.Set("path_hash", pathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) @@ -1966,21 +1938,14 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal() } - body := bytes.NewBuffer(nil) - formWriter := multipart.NewWriter(body) - remotePath := "/" pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") - require.NoError(t, formWriter.WriteField("path_hash", filePathHash)) - - require.NoError(t, formWriter.WriteField("block_num", fmt.Sprintf("%d", 1))) authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") if err != nil { t.Fatal(err) } - require.NoError(t, formWriter.WriteField("auth_token", authTicket)) rm := &marker.ReadMarker{} rm.ClientID = guestClient.ClientID rm.ClientPublicKey = guestClient.ClientKey @@ -1995,13 +1960,8 @@ func TestHandlers_Requiring_Signature(t *testing.T) { rmData, err := json.Marshal(rm) require.NoError(t, err) - require.NoError(t, formWriter.WriteField("read_marker", string(rmData))) - if err := formWriter.Close(); err != nil { - t.Fatal(err) - } - r, err := http.NewRequest(http.MethodPost, url.String(), body) - r.Header.Add("Content-Type", formWriter.FormDataContentType()) + r, err := http.NewRequest(http.MethodPost, url.String(), nil) if err != nil { t.Fatal(err) } @@ -2012,7 +1972,10 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("Content-Type", formWriter.FormDataContentType()) + r.Header.Set("path_hash", filePathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) + r.Header.Set("read_marker", string(rmData)) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) @@ -2121,21 +2084,14 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal() } - body := bytes.NewBuffer(nil) - formWriter := multipart.NewWriter(body) - remotePath := "/folder1" pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1/subfolder1/file.txt") - require.NoError(t, formWriter.WriteField("path_hash", filePathHash)) - - require.NoError(t, formWriter.WriteField("block_num", fmt.Sprintf("%d", 1))) authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") if err != nil { t.Fatal(err) } - require.NoError(t, formWriter.WriteField("auth_token", authTicket)) rm := &marker.ReadMarker{} rm.ClientID = guestClient.ClientID rm.ClientPublicKey = guestClient.ClientKey @@ -2150,13 +2106,8 @@ func TestHandlers_Requiring_Signature(t *testing.T) { rmData, err := json.Marshal(rm) require.NoError(t, err) - require.NoError(t, formWriter.WriteField("read_marker", string(rmData))) - if err := formWriter.Close(); err != nil { - t.Fatal(err) - } - r, err := http.NewRequest(http.MethodPost, url.String(), body) - r.Header.Add("Content-Type", formWriter.FormDataContentType()) + r, err := http.NewRequest(http.MethodPost, url.String(), nil) if err != nil { t.Fatal(err) } @@ -2167,7 +2118,10 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("Content-Type", formWriter.FormDataContentType()) + r.Header.Set("path_hash", filePathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) + r.Header.Set("read_marker", string(rmData)) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) @@ -2276,21 +2230,14 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal() } - body := bytes.NewBuffer(nil) - formWriter := multipart.NewWriter(body) - remotePath := "/folder1" pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder2/subfolder1/file.txt") - require.NoError(t, formWriter.WriteField("path_hash", filePathHash)) - - require.NoError(t, formWriter.WriteField("block_num", fmt.Sprintf("%d", 1))) authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") if err != nil { t.Fatal(err) } - require.NoError(t, formWriter.WriteField("auth_token", authTicket)) rm := &marker.ReadMarker{} rm.ClientID = guestClient.ClientID rm.ClientPublicKey = guestClient.ClientKey @@ -2305,13 +2252,8 @@ func TestHandlers_Requiring_Signature(t *testing.T) { rmData, err := json.Marshal(rm) require.NoError(t, err) - require.NoError(t, formWriter.WriteField("read_marker", string(rmData))) - if err := formWriter.Close(); err != nil { - t.Fatal(err) - } - r, err := http.NewRequest(http.MethodPost, url.String(), body) - r.Header.Add("Content-Type", formWriter.FormDataContentType()) + r, err := http.NewRequest(http.MethodPost, url.String(), nil) if err != nil { t.Fatal(err) } @@ -2322,7 +2264,10 @@ func TestHandlers_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("Content-Type", formWriter.FormDataContentType()) + r.Header.Set("read_marker", string(rmData)) + r.Header.Set("path_hash", filePathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) From 1969ac6e23cece939445d20f9de52338acce20c2 Mon Sep 17 00:00:00 2001 From: Pradip Parmar Date: Wed, 23 Feb 2022 06:17:30 +0530 Subject: [PATCH 04/12] path hash method updated to read from form and header both. Signed-off-by: Pradip Parmar --- .../handler/object_operation_handler.go | 2 +- .../blobbercore/handler/storage_handler.go | 19 +++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) 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 40ab6fe59..24da506ea 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go @@ -192,7 +192,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r return nil, common.NewErrorf("download_file", "invalid allocation id passed: %v", err) } - pathHash, _, err := getPathHashFromHeader(r, alloc.ID) + pathHash, _, err := getPathHash(r, alloc.ID) if err != nil { return nil, common.NewError("download_file", "invalid path") } diff --git a/code/go/0chain.net/blobbercore/handler/storage_handler.go b/code/go/0chain.net/blobbercore/handler/storage_handler.go index e7bf4f26e..8c717cae2 100644 --- a/code/go/0chain.net/blobbercore/handler/storage_handler.go +++ b/code/go/0chain.net/blobbercore/handler/storage_handler.go @@ -980,24 +980,15 @@ func pathHashFromReq(r *http.Request, allocationID string) (pathHash string, err return } -func getPathHashFromHeader(r *http.Request, allocationID string) (pathHash, path string, err error) { - pathHash = r.Header.Get("path_hash") - path = r.Header.Get("path") - - if pathHash == "" { - if path == "" { - return "", "", common.NewError("invalid_parameters", "Invalid path") - } - pathHash = reference.GetReferenceLookup(allocationID, path) - } - - return pathHash, path, nil -} - func getPathHash(r *http.Request, allocationID string) (pathHash, path string, err error) { pathHash = r.FormValue("path_hash") path = r.FormValue("path") + if pathHash == "" && path == "" { + pathHash = r.Header.Get("path_hash") + path = r.Header.Get("path") + } + if pathHash == "" { if path == "" { return "", "", common.NewError("invalid_parameters", "Invalid path") From 2ee52fb04f5face277680e3ccc77ca6c6b0a2031 Mon Sep 17 00:00:00 2001 From: Pradip Parmar Date: Wed, 23 Feb 2022 07:13:45 +0530 Subject: [PATCH 05/12] integration test handling. Signed-off-by: Pradip Parmar --- .../0chain.net/blobbercore/convert/convert.go | 57 +++---------------- 1 file changed, 9 insertions(+), 48 deletions(-) diff --git a/code/go/0chain.net/blobbercore/convert/convert.go b/code/go/0chain.net/blobbercore/convert/convert.go index ab399015f..7766e766f 100644 --- a/code/go/0chain.net/blobbercore/convert/convert.go +++ b/code/go/0chain.net/blobbercore/convert/convert.go @@ -6,7 +6,6 @@ import ( "encoding/json" "mime/multipart" "net/http" - "strings" "time" "github.com/0chain/blobber/code/go/0chain.net/blobbercore/readmarker" @@ -483,57 +482,19 @@ func WriteFileGRPCToHTTP(req *blobbergrpc.UploadFileRequest) (*http.Request, err } func DownloadFileGRPCToHTTP(req *blobbergrpc.DownloadFileRequest) (*http.Request, error) { - body := bytes.NewBuffer([]byte{}) - writer := multipart.NewWriter(body) - err := writer.WriteField("path", req.Path) + r, err := http.NewRequest("GET", "", nil) if err != nil { return nil, err } - err = writer.WriteField("path_hash", req.PathHash) - if err != nil { - return nil, err - } - - err = writer.WriteField("rx_pay", req.RxPay) - if err != nil { - return nil, err - } - - err = writer.WriteField("block_num", req.BlockNum) - if err != nil { - return nil, err - } - - err = writer.WriteField("num_blocks", req.NumBlocks) - if err != nil { - return nil, err - } - - err = writer.WriteField("read_marker", req.ReadMarker) - if err != nil { - return nil, err - } - - err = writer.WriteField("auth_token", req.AuthToken) - if err != nil { - return nil, err - } - - err = writer.WriteField("content", req.Content) - if err != nil { - return nil, err - } - - writer.Close() - - r, err := http.NewRequest("POST", "", strings.NewReader(body.String())) - if err != nil { - return nil, err - } - - r.Header.Set("Content-Type", writer.FormDataContentType()) - + r.Header.Set("path", req.Path) + r.Header.Set("path_hash", req.PathHash) + r.Header.Set("rx_pay", req.RxPay) + r.Header.Set("block_num", req.BlockNum) + r.Header.Set("num_blocks", req.NumBlocks) + r.Header.Set("read_marker", req.ReadMarker) + r.Header.Set("auth_token", req.AuthToken) + r.Header.Set("content", req.Content) return r, nil } From 4579b339744c6a1f54f3c8b7c3c2c6e7ab532580 Mon Sep 17 00:00:00 2001 From: Lz Date: Thu, 24 Feb 2022 16:07:16 +0800 Subject: [PATCH 06/12] fix(download): extract download args to DownloadRequest --- .../0chain.net/blobbercore/handler/context.go | 10 +- .../blobbercore/handler/download_request.go | 124 ++++++++++++++++++ .../0chain.net/blobbercore/handler/helper.go | 13 ++ .../handler/object_operation_handler.go | 57 ++------ 4 files changed, 152 insertions(+), 52 deletions(-) create mode 100644 code/go/0chain.net/blobbercore/handler/download_request.go diff --git a/code/go/0chain.net/blobbercore/handler/context.go b/code/go/0chain.net/blobbercore/handler/context.go index 2475b8527..0f27146a5 100644 --- a/code/go/0chain.net/blobbercore/handler/context.go +++ b/code/go/0chain.net/blobbercore/handler/context.go @@ -71,15 +71,7 @@ func WithHandler(handler func(ctx *Context) (interface{}, error)) func(w http.Re return } - if r.Method == http.MethodPost || r.Method == http.MethodPut || r.Method == http.MethodPatch { - ct := r.Header.Get("Content-Type") - if ct == "application/x-www-form-urlencoded" { - r.ParseForm() //nolint: errcheck - } else { - r.ParseMultipartForm(FormFileParseMaxMemory) //nolint: errcheck - } - - } + TryParseForm(r) w.Header().Set("Access-Control-Allow-Origin", "*") // CORS for all. w.Header().Set("Content-Type", "application/json") diff --git a/code/go/0chain.net/blobbercore/handler/download_request.go b/code/go/0chain.net/blobbercore/handler/download_request.go new file mode 100644 index 000000000..504af29f8 --- /dev/null +++ b/code/go/0chain.net/blobbercore/handler/download_request.go @@ -0,0 +1,124 @@ +package handler + +import ( + "encoding/json" + "net/http" + "strconv" + + "github.com/0chain/blobber/code/go/0chain.net/blobbercore/readmarker" + "github.com/0chain/blobber/code/go/0chain.net/blobbercore/reference" + "github.com/0chain/blobber/code/go/0chain.net/core/common" + "github.com/0chain/errors" +) + +// DownloadRequest metedata of download request +type DownloadRequest struct { + req *http.Request + allocationID string + PathHash string + Path string + BlockNum int64 + NumBlocks int64 + ReadMarker *readmarker.ReadMarker + AuthToken string + RxPay bool + DownloadMode string +} + +func FromDownloadRequest(allocationID string, req *http.Request) (*DownloadRequest, error) { + if allocationID == "" { + return nil, errors.Throw(common.ErrInvalidParameter, "allocationID") + } + + if req == nil { + return nil, errors.Throw(common.ErrInvalidParameter, "req") + } + + dr := &DownloadRequest{ + allocationID: allocationID, + req: req, + } + + err := dr.Parse() + if err != nil { + return nil, err + } + + return dr, nil +} + +func (dr *DownloadRequest) Parse() error { + if dr.req == nil { + return errors.Throw(common.ErrInvalidParameter, "req") + } + + pathHash := dr.Get("path_hash") + path := dr.Get("path") + if pathHash == "" { + if path == "" { + return errors.Throw(common.ErrInvalidParameter, "path") + } + pathHash = reference.GetReferenceLookup(dr.allocationID, path) + } + + dr.PathHash = pathHash + dr.Path = path + + blockNum := dr.GetInt64("block_num", -1) + if blockNum <= 0 { + return errors.Throw(common.ErrInvalidParameter, "block_num") + } + dr.BlockNum = blockNum + + numBlocks := dr.GetInt64("num_blocks", -1) + if numBlocks <= 0 { + return errors.Throw(common.ErrInvalidParameter, "num_blocks") + } + dr.NumBlocks = numBlocks + + readMarker := dr.Get("read_marker") + + if readMarker == "" { + return errors.Throw(common.ErrInvalidParameter, "read_marker") + } + + err := json.Unmarshal([]byte(readMarker), dr.ReadMarker) + if err != nil { + return errors.Throw(common.ErrInvalidParameter, "read_marker") + } + + authToken := dr.Get("auth_token") + if authToken == "" { + return errors.Throw(common.ErrInvalidParameter, "auth_token") + } + dr.AuthToken = authToken + + dr.RxPay = dr.Get("rx_pay") == "true" + dr.DownloadMode = dr.Get("content") + + return nil +} + +func (dr *DownloadRequest) Get(key string) string { + if dr.req == nil { + return "" + } + v := dr.req.Header.Get(key) + + if v == "" { + v = dr.req.FormValue(key) + } + + return v + +} + +func (dr *DownloadRequest) GetInt64(key string, defaultValue int64) int64 { + v := dr.Get(key) + i, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return defaultValue + } + + return i +} diff --git a/code/go/0chain.net/blobbercore/handler/helper.go b/code/go/0chain.net/blobbercore/handler/helper.go index 408aed256..651077ccb 100644 --- a/code/go/0chain.net/blobbercore/handler/helper.go +++ b/code/go/0chain.net/blobbercore/handler/helper.go @@ -1,6 +1,7 @@ package handler import ( + "net/http" "time" "github.com/0chain/blobber/code/go/0chain.net/core/common" @@ -15,3 +16,15 @@ func checkValidDate(s, dateLayOut string) error { } return nil } + +// TryParseForm try populates r.Form and r.PostForm. +func TryParseForm(r *http.Request) { + if r.Method == http.MethodPost || r.Method == http.MethodPut || r.Method == http.MethodPatch { + ct := r.Header.Get("Content-Type") + if ct == "application/x-www-form-urlencoded" { + r.ParseForm() //nolint: errcheck + } else { + r.ParseMultipartForm(FormFileParseMaxMemory) //nolint: errcheck + } + } +} 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 24da506ea..4bca26e60 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go @@ -192,49 +192,20 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r return nil, common.NewErrorf("download_file", "invalid allocation id passed: %v", err) } - pathHash, _, err := getPathHash(r, alloc.ID) + dr, err := FromDownloadRequest(allocationTx, r) if err != nil { - return nil, common.NewError("download_file", "invalid path") - } - - var blockNumStr = r.Header.Get("block_num") - if blockNumStr == "" { - return nil, common.NewError("download_file", "no block number") - } - - var blockNum int64 - blockNum, err = strconv.ParseInt(blockNumStr, 10, 64) - if err != nil || blockNum < 1 { - return nil, common.NewError("download_file", "invalid block number") - } - - numBlocks := int64(1) - numBlocksStr := r.Header.Get("num_blocks") - - if numBlocksStr != "" { - numBlocks, err = strconv.ParseInt(numBlocksStr, 10, 64) - if err != nil || numBlocks <= 0 { - return nil, common.NewError("download_file", "invalid number of blocks") - } - } - - readMarkerString := r.Header.Get("read_marker") - readMarker := new(readmarker.ReadMarker) - - if err := json.Unmarshal([]byte(readMarkerString), readMarker); err != nil { - return nil, common.NewErrorf("download_file", "invalid parameters, "+ - "error parsing the readmarker for download: %v", err) + return nil, err } rmObj := new(readmarker.ReadMarkerEntity) - rmObj.LatestRM = readMarker + rmObj.LatestRM = dr.ReadMarker if err = rmObj.VerifyMarker(ctx, alloc); err != nil { return nil, common.NewErrorf("download_file", "invalid read marker, "+"failed to verify the read marker: %v", err) } // get file reference - fileref, err := reference.GetReferenceFromLookupHash(ctx, alloc.ID, pathHash) + fileref, err := reference.GetReferenceFromLookupHash(ctx, alloc.ID, dr.PathHash) if err != nil { return nil, common.NewErrorf("download_file", "invalid file path: %v", err) } @@ -259,7 +230,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r var shareInfo *reference.ShareInfo if !(isOwner || isCollaborator) { - authTokenString := r.Header.Get("auth_token") + authTokenString := dr.AuthToken if authTokenString == "" { return nil, common.NewError("invalid_client", "authticket is required") } @@ -278,11 +249,11 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r } // set payer: check for command line payer flag (--rx_pay) - if r.Header.Get("rx_pay") == "true" { + if dr.RxPay { payerID = clientID } - readMarker.AuthTicket = datatypes.JSON(authTokenString) + dr.ReadMarker.AuthTicket = datatypes.JSON(authTokenString) // check for file payer flag if fileAttrs, err := fileref.GetAttributes(); err != nil { @@ -310,7 +281,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r } } - if latestRM != nil && latestRM.ReadCounter+(numBlocks) != readMarker.ReadCounter { + if latestRM != nil && latestRM.ReadCounter+(dr.NumBlocks) != dr.ReadMarker.ReadCounter { return &blobberhttp.DownloadResponse{ Success: false, LatestRM: latestRM, @@ -320,14 +291,14 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r } // check out read pool tokens if read_price > 0 - err = readPreRedeem(ctx, alloc, numBlocks, pendNumBlocks, payerID) + err = readPreRedeem(ctx, alloc, dr.NumBlocks, pendNumBlocks, payerID) if err != nil { return nil, common.NewErrorf("download_file", "pre-redeeming read marker: %v", err) } // reading is allowed var ( - downloadMode = r.Header.Get("content") + downloadMode = dr.DownloadMode respData []byte ) if downloadMode == DownloadContentThumb { @@ -337,7 +308,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r fileData.Hash = fileref.ThumbnailHash fileData.OnCloud = fileref.OnCloud fileData.ChunkSize = fileref.ChunkSize - respData, err = filestore.GetFileStore().GetFileBlock(alloc.ID, fileData, blockNum, numBlocks) + respData, err = filestore.GetFileStore().GetFileBlock(alloc.ID, fileData, dr.BlockNum, dr.NumBlocks) if err != nil { return nil, common.NewErrorf("download_file", "couldn't get thumbnail block: %v", err) } @@ -349,14 +320,14 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r fileData.OnCloud = fileref.OnCloud fileData.ChunkSize = fileref.ChunkSize - respData, err = filestore.GetFileStore().GetFileBlock(alloc.ID, fileData, blockNum, numBlocks) + respData, err = filestore.GetFileStore().GetFileBlock(alloc.ID, fileData, dr.BlockNum, dr.NumBlocks) if err != nil { return nil, common.NewErrorf("download_file", "couldn't get file block: %v", err) } } - readMarker.PayerID = payerID - err = readmarker.SaveLatestReadMarker(ctx, readMarker, latestRM == nil) + dr.ReadMarker.PayerID = payerID + err = readmarker.SaveLatestReadMarker(ctx, dr.ReadMarker, latestRM == nil) if err != nil { Logger.Error(err.Error()) return nil, common.NewErrorf("download_file", "couldn't save latest read marker") From 34c5237da2c436a6f6988060127d043f15ff4a33 Mon Sep 17 00:00:00 2001 From: Lz Date: Thu, 24 Feb 2022 16:35:55 +0800 Subject: [PATCH 07/12] fix(download): fixed tests --- .../blobbercore/handler/download_request.go | 12 ++++-------- .../0chain.net/blobbercore/handler/handler_test.go | 1 - .../blobbercore/handler/object_operation_handler.go | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/code/go/0chain.net/blobbercore/handler/download_request.go b/code/go/0chain.net/blobbercore/handler/download_request.go index 504af29f8..08611796f 100644 --- a/code/go/0chain.net/blobbercore/handler/download_request.go +++ b/code/go/0chain.net/blobbercore/handler/download_request.go @@ -19,7 +19,7 @@ type DownloadRequest struct { Path string BlockNum int64 NumBlocks int64 - ReadMarker *readmarker.ReadMarker + ReadMarker readmarker.ReadMarker AuthToken string RxPay bool DownloadMode string @@ -70,7 +70,7 @@ func (dr *DownloadRequest) Parse() error { } dr.BlockNum = blockNum - numBlocks := dr.GetInt64("num_blocks", -1) + numBlocks := dr.GetInt64("num_blocks", 1) if numBlocks <= 0 { return errors.Throw(common.ErrInvalidParameter, "num_blocks") } @@ -82,16 +82,12 @@ func (dr *DownloadRequest) Parse() error { return errors.Throw(common.ErrInvalidParameter, "read_marker") } - err := json.Unmarshal([]byte(readMarker), dr.ReadMarker) + err := json.Unmarshal([]byte(readMarker), &dr.ReadMarker) if err != nil { return errors.Throw(common.ErrInvalidParameter, "read_marker") } - authToken := dr.Get("auth_token") - if authToken == "" { - return errors.Throw(common.ErrInvalidParameter, "auth_token") - } - dr.AuthToken = authToken + dr.AuthToken = dr.Get("auth_token") dr.RxPay = dr.Get("rx_pay") == "true" dr.DownloadMode = dr.Get("content") diff --git a/code/go/0chain.net/blobbercore/handler/handler_test.go b/code/go/0chain.net/blobbercore/handler/handler_test.go index 60305ddb1..e4bad086f 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_test.go @@ -2337,7 +2337,6 @@ func TestHandlers_Requiring_Signature(t *testing.T) { } tests := append(positiveTests, negativeTests...) - // tests := positiveTests for _, test := range tests { t.Run(test.name, func(t *testing.T) { 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 4bca26e60..4fd456ff1 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler.go @@ -198,7 +198,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r } rmObj := new(readmarker.ReadMarkerEntity) - rmObj.LatestRM = dr.ReadMarker + rmObj.LatestRM = &dr.ReadMarker if err = rmObj.VerifyMarker(ctx, alloc); err != nil { return nil, common.NewErrorf("download_file", "invalid read marker, "+"failed to verify the read marker: %v", err) @@ -327,7 +327,7 @@ func (fsh *StorageHandler) DownloadFile(ctx context.Context, r *http.Request) (r } dr.ReadMarker.PayerID = payerID - err = readmarker.SaveLatestReadMarker(ctx, dr.ReadMarker, latestRM == nil) + err = readmarker.SaveLatestReadMarker(ctx, &dr.ReadMarker, latestRM == nil) if err != nil { Logger.Error(err.Error()) return nil, common.NewErrorf("download_file", "couldn't save latest read marker") From e71d3e7628f9274ab0a8941792f96082d5ea58fd Mon Sep 17 00:00:00 2001 From: Pradip Parmar Date: Fri, 25 Feb 2022 06:38:36 +0530 Subject: [PATCH 08/12] test change. Signed-off-by: Pradip Parmar --- code/go/0chain.net/blobbercore/handler/handler_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/go/0chain.net/blobbercore/handler/handler_test.go b/code/go/0chain.net/blobbercore/handler/handler_test.go index e4bad086f..9af46dee8 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_test.go @@ -1520,7 +1520,7 @@ func TestHandlers_Requiring_Signature(t *testing.T) { } rmData, err := json.Marshal(rm) require.NoError(t, err) - r, err := http.NewRequest(http.MethodPost, url.String(), nil) + r, err := http.NewRequest(http.MethodGet, url.String(), nil) if err != nil { require.NoError(t, err) } From 6f9cd778a2389c96d7e10b70ea4b070f9dbcdcca Mon Sep 17 00:00:00 2001 From: Pradip Parmar Date: Sat, 26 Feb 2022 23:41:25 +0530 Subject: [PATCH 09/12] download testcases separated from other handler tests. Signed-off-by: Pradip Parmar --- .../handler/handler_download_test.go | 1082 +++++++++++++++++ .../blobbercore/handler/handler_test.go | 865 +------------ 2 files changed, 1084 insertions(+), 863 deletions(-) create mode 100644 code/go/0chain.net/blobbercore/handler/handler_download_test.go diff --git a/code/go/0chain.net/blobbercore/handler/handler_download_test.go b/code/go/0chain.net/blobbercore/handler/handler_download_test.go new file mode 100644 index 000000000..6a49282cc --- /dev/null +++ b/code/go/0chain.net/blobbercore/handler/handler_download_test.go @@ -0,0 +1,1082 @@ +package handler + +import ( + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "os" + "regexp" + "testing" + "time" + + "github.com/0chain/gosdk/core/zcncrypto" + "github.com/0chain/gosdk/zboxcore/client" + zencryption "github.com/0chain/gosdk/zboxcore/encryption" + "github.com/0chain/gosdk/zboxcore/fileref" + "github.com/0chain/gosdk/zboxcore/marker" + "github.com/DATA-DOG/go-sqlmock" + "github.com/gorilla/mux" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gorm.io/gorm" + + "github.com/0chain/blobber/code/go/0chain.net/blobbercore/allocation" + "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/core/common" + "github.com/0chain/blobber/code/go/0chain.net/core/encryption" +) + +func setupDownloadHandlers() (*mux.Router, map[string]string) { + router := mux.NewRouter() + + dPath := "/v1/file/download/{allocation}" + dName := "Download" + router.HandleFunc(dPath, common.UserRateLimit( + common.ToJSONResponse( + WithConnection(DownloadHandler), + ), + ), + ).Name(dName) + + return router, map[string]string{ + dPath: dName, + } +} + +func getEncryptionScheme(mnemonic string) (zencryption.EncryptionScheme, error) { + encscheme := zencryption.NewEncryptionScheme() + if _, err := encscheme.Initialize(mnemonic); err != nil { + return nil, err + } + encscheme.InitForEncryption("filetype:audio") + return encscheme, nil +} + +func TestHandlers_Download_Requiring_Signature(t *testing.T) { + setup(t) + + clientJson := `{"client_id":"2f34516ed8c567089b7b5572b12950db34a62a07e16770da14b15b170d0d60a9","client_key":"bc94452950dd733de3b4498afdab30ff72741beae0b82de12b80a14430018a09ba119ff0bfe69b2a872bded33d560b58c89e071cef6ec8388268d4c3e2865083","keys":[{"public_key":"bc94452950dd733de3b4498afdab30ff72741beae0b82de12b80a14430018a09ba119ff0bfe69b2a872bded33d560b58c89e071cef6ec8388268d4c3e2865083","private_key":"9fef6ff5edc39a79c1d8e5eb7ca7e5ac14d34615ee49e6d8ca12ecec136f5907"}],"mnemonics":"expose culture dignity plastic digital couple promote best pool error brush upgrade correct art become lobster nature moment obtain trial multiply arch miss toe","version":"1.0","date_created":"2021-05-30 17:45:06.492093 +0545 +0545 m=+0.139083805"}` + guestClientJson := `{"client_id":"213297e22c8282ff85d1d5c99f4967636fe68f842c1351b24bd497246cbd26d9","client_key":"7710b547897e0bddf93a28903875b244db4d320e4170172b19a5d51280c73522e9bb381b184fa3d24d6e1464882bf7f89d24ac4e8d05616d55eb857a6e235383","keys":[{"public_key":"7710b547897e0bddf93a28903875b244db4d320e4170172b19a5d51280c73522e9bb381b184fa3d24d6e1464882bf7f89d24ac4e8d05616d55eb857a6e235383","private_key":"19ca446f814dcd56e28e11d4147f73590a07c7f1a9a6012087808a8602024a08"}],"mnemonics":"crazy dutch object arrest jump fragile oak amateur taxi trigger gap aspect marriage hat slice wool island spike unlock alter include easily say ramp","version":"1.0","date_created":"2022-01-26T07:26:41+05:45"}` + + require.NoError(t, client.PopulateClients([]string{clientJson, guestClientJson}, "bls0chain")) + clients := client.GetClients() + + ownerClient, guestClient := clients[0], clients[1] + + ownerScheme, err := getEncryptionScheme(ownerClient.Mnemonic) + if err != nil { + t.Fatal(err) + } + + guestScheme, err := getEncryptionScheme(guestClient.Mnemonic) + if err != nil { + t.Fatal(err) + } + // require.NoError(t, client.PopulateClient(clientJson, "bls0chain")) + // setupEncryptionScheme() + + router, handlers := setupDownloadHandlers() + + sch := zcncrypto.NewSignatureScheme("bls0chain") + //sch.Mnemonic = "expose culture dignity plastic digital couple promote best pool error brush upgrade correct art become lobster nature moment obtain trial multiply arch miss toe" + _, err = sch.RecoverKeys("expose culture dignity plastic digital couple promote best pool error brush upgrade correct art become lobster nature moment obtain trial multiply arch miss toe") + if err != nil { + t.Fatal(err) + } + + ts := time.Now().Add(time.Hour) + alloc := makeTestAllocation(common.Timestamp(ts.Unix())) + alloc.OwnerPublicKey = ownerClient.Keys[0].PublicKey + alloc.OwnerID = ownerClient.ClientID + + const ( + path = "/path" + newName = "new name" + connectionID = "connection id" + ) + + type ( + args struct { + w *httptest.ResponseRecorder + r *http.Request + } + test struct { + name string + args args + alloc *allocation.Allocation + setupDbMock func(mock sqlmock.Sqlmock) + begin func() + end func() + wantCode int + wantBody string + } + ) + negativeTests := make([]test, 0) + for _, name := range handlers { + if !isEndpointRequireSignature(name) { + continue + } + + baseSetupDbMock := func(mock sqlmock.Sqlmock) { + mock.ExpectBegin() + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). + WithArgs(alloc.Tx). + WillReturnRows( + sqlmock.NewRows([]string{"id", "tx", "expiration_date", "owner_public_key", "owner_id"}). + AddRow(alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). + WithArgs(alloc.ID). + WillReturnRows( + sqlmock.NewRows([]string{"id", "allocation_id"}). + AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), + ) + + mock.ExpectCommit() + } + + emptySignature := test{ + name: name + "_Empty_Signature", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + url, err := router.Get(name).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + method := http.MethodGet + if !isEndpointAllowGetReq(name) { + method = http.MethodPost + } + r, err := http.NewRequest(method, url.String(), nil) + if err != nil { + t.Fatal(err) + } + + return r + }(), + }, + alloc: alloc, + setupDbMock: baseSetupDbMock, + wantCode: http.StatusBadRequest, + wantBody: "{\"code\":\"invalid_signature\",\"error\":\"invalid_signature: Invalid signature\"}\n\n", + } + negativeTests = append(negativeTests, emptySignature) + + wrongSignature := test{ + name: name + "_Wrong_Signature", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + url, err := router.Get(name).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + method := http.MethodGet + if !isEndpointAllowGetReq(name) { + method = http.MethodPost + } + r, err := http.NewRequest(method, url.String(), nil) + if err != nil { + t.Fatal(err) + } + + hash := encryption.Hash("another data") + sign, err := sch.Sign(hash) + if err != nil { + t.Fatal(err) + } + + r.Header.Set(common.ClientSignatureHeader, sign) + r.Header.Set(common.ClientHeader, alloc.OwnerID) + + return r + }(), + }, + alloc: alloc, + setupDbMock: baseSetupDbMock, + wantCode: http.StatusBadRequest, + wantBody: "{\"code\":\"invalid_signature\",\"error\":\"invalid_signature: Invalid signature\"}\n\n", + } + negativeTests = append(negativeTests, wrongSignature) + } + + positiveTests := []test{ + { + name: "DownloadFile_Record_Not_Found", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + handlerName := handlers["/v1/file/download/{allocation}"] + url, err := router.Get(handlerName).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + remotePath := "/file.txt" + + rm := &marker.ReadMarker{} + rm.ClientID = ownerClient.ClientID + rm.ClientPublicKey = ownerClient.ClientKey + rm.BlobberID = "" + rm.AllocationID = alloc.ID + rm.OwnerID = ownerClient.ClientID + rm.Signature, err = signHash(ownerClient, rm.GetHash()) + if err != nil { + t.Fatal(err) + } + rmData, err := json.Marshal(rm) + require.NoError(t, err) + r, err := http.NewRequest(http.MethodGet, url.String(), nil) + if err != nil { + require.NoError(t, err) + } + + hash := encryption.Hash(alloc.Tx) + sign, err := sch.Sign(hash) + if err != nil { + t.Fatal(err) + } + + r.Header.Set("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("read_marker", string(rmData)) + r.Header.Set(common.ClientSignatureHeader, sign) + r.Header.Set(common.ClientHeader, alloc.OwnerID) + r.Header.Set(common.ClientKeyHeader, alloc.OwnerPublicKey) + + return r + }(), + }, + alloc: alloc, + setupDbMock: func(mock sqlmock.Sqlmock) { + mock.ExpectBegin() + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). + WithArgs(alloc.Tx). + WillReturnRows( + sqlmock.NewRows( + []string{ + "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", + }, + ). + AddRow( + alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), + ), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). + WithArgs(alloc.ID). + WillReturnRows( + sqlmock.NewRows([]string{"id", "allocation_id"}). + AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), + ) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, filePathHash).WillReturnError(gorm.ErrRecordNotFound) + + }, + wantCode: http.StatusBadRequest, + wantBody: "{\"code\":\"download_file\",\"error\":\"download_file: invalid file path: record not found\"}\n\n", + }, + { + name: "DownloadFile_Unencrypted_return_file", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + handlerName := handlers["/v1/file/download/{allocation}"] + url, err := router.Get(handlerName).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + remotePath := "/file.txt" + + rm := &marker.ReadMarker{} + rm.ClientID = ownerClient.ClientID + rm.ClientPublicKey = ownerClient.ClientKey + rm.BlobberID = "" + rm.AllocationID = alloc.ID + rm.ReadCounter = 1 + rm.OwnerID = ownerClient.ClientID + rm.Signature, err = signHash(ownerClient, rm.GetHash()) + if err != nil { + t.Fatal(err) + } + rmData, err := json.Marshal(rm) + require.NoError(t, err) + r, err := http.NewRequest(http.MethodGet, url.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("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("read_marker", string(rmData)) + r.Header.Set(common.ClientSignatureHeader, sign) + r.Header.Set(common.ClientHeader, alloc.OwnerID) + r.Header.Set(common.ClientKeyHeader, alloc.OwnerPublicKey) + + return r + }(), + }, + alloc: alloc, + setupDbMock: func(mock sqlmock.Sqlmock) { + mock.ExpectBegin() + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). + WithArgs(alloc.Tx). + WillReturnRows( + sqlmock.NewRows( + []string{ + "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", + }, + ). + AddRow( + alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), + ), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). + WithArgs(alloc.ID). + WillReturnRows( + sqlmock.NewRows([]string{"id", "allocation_id"}). + AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), + ) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, filePathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "lookup_hash", "content_hash"}). + AddRow("/file.txt", "f", filePathHash, "abcd"), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). + WithArgs(ownerClient.ClientID). + WillReturnError(gorm.ErrRecordNotFound) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). + WithArgs(ownerClient.ClientID). + WillReturnRows( + sqlmock.NewRows([]string{"client_id"}). + AddRow(ownerClient.ClientID), + ) + + aa := sqlmock.AnyArg() + + mock.ExpectExec(`(UPDATE "read_markers" SET)(.+)`). + WithArgs(ownerClient.ClientKey, alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa). + WillReturnResult(sqlmock.NewResult(0, 0)) + + mock.ExpectCommit() + }, + wantCode: http.StatusOK, + wantBody: "\"bW9jaw==\"\n", //base64encoded for mock string + }, + { + name: "DownloadFile_Encrypted_Permission_Denied_Unshared_File", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + handlerName := handlers["/v1/file/download/{allocation}"] + url, err := router.Get(handlerName).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + remotePath := "/file.txt" + + pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) + authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, ownerClient.Keys[0].PublicKey) + if err != nil { + t.Fatal(err) + } + + rm := &marker.ReadMarker{} + rm.ClientID = guestClient.ClientID + rm.ClientPublicKey = guestClient.ClientKey + rm.BlobberID = "" + rm.AllocationID = alloc.ID + rm.ReadCounter = 1 + rm.OwnerID = ownerClient.ClientID + rm.Signature, err = signHash(guestClient, rm.GetHash()) + if err != nil { + t.Fatal(err) + } + rmData, err := json.Marshal(rm) + require.NoError(t, err) + r, err := http.NewRequest(http.MethodGet, url.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("read_marker", string(rmData)) + r.Header.Set("path_hash", pathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) + r.Header.Set(common.ClientSignatureHeader, sign) + r.Header.Set(common.ClientHeader, guestClient.ClientID) + r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) + + return r + }(), + }, + alloc: alloc, + setupDbMock: func(mock sqlmock.Sqlmock) { + mock.ExpectBegin() + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). + WithArgs(alloc.Tx). + WillReturnRows( + sqlmock.NewRows( + []string{ + "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", + }, + ). + AddRow( + alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), + ), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). + WithArgs(alloc.ID). + WillReturnRows( + sqlmock.NewRows([]string{"id", "allocation_id"}). + AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), + ) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, filePathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "chunk_size"}). + AddRow("/file.txt", "f", filePathHash, filePathHash, "content_hash", "qCj3sXXeXUAByi1ERIbcfXzWN75dyocYzyRXnkStXio=", 65536), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). + WithArgs(client.GetClientID()). + WillReturnError(gorm.ErrRecordNotFound) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). + WithArgs(client.GetClientID()). + WillReturnRows( + sqlmock.NewRows([]string{"client_id"}). + AddRow(client.GetClientID()), + ) + + aa := sqlmock.AnyArg() + + mock.ExpectExec(`UPDATE "read_markers"`). + WithArgs(client.GetClientPublicKey(), alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa, aa). + WillReturnResult(sqlmock.NewResult(0, 0)) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "marketplace_share_info" WHERE`)). + WithArgs(client.GetClientID(), filePathHash). + WillReturnError(gorm.ErrRecordNotFound) + + mock.ExpectCommit() + }, + wantCode: http.StatusBadRequest, + wantBody: "{\"error\":\"client does not have permission to download the file. share does not exist\"}\n\n", + }, + { + name: "DownloadFile_Encrypted_Permission_Allowed_shared_File", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + handlerName := handlers["/v1/file/download/{allocation}"] + url, err := router.Get(handlerName).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + remotePath := "/file.txt" + + pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) + authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") + if err != nil { + t.Fatal(err) + } + rm := &marker.ReadMarker{} + rm.ClientID = guestClient.ClientID + rm.ClientPublicKey = guestClient.ClientKey + rm.BlobberID = "" + rm.AllocationID = alloc.ID + rm.ReadCounter = 1 + rm.OwnerID = ownerClient.ClientID + rm.Signature, err = signHash(guestClient, rm.GetHash()) + if err != nil { + t.Fatal(err) + } + rmData, err := json.Marshal(rm) + require.NoError(t, err) + r, err := http.NewRequest(http.MethodGet, url.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("read_marker", string(rmData)) + r.Header.Set("path_hash", pathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) + r.Header.Set(common.ClientSignatureHeader, sign) + r.Header.Set(common.ClientHeader, guestClient.ClientID) + r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) + + return r + }(), + }, + alloc: alloc, + begin: func() { + dataToEncrypt := "data_to_encrypt" + encMsg, err := ownerScheme.Encrypt([]byte(dataToEncrypt)) + if err != nil { + t.Fatal(err) + } + + header := make([]byte, EncryptionHeaderSize) + copy(header, encMsg.MessageChecksum+encMsg.OverallChecksum) + data := append(header, encMsg.EncryptedData...) + fmt.Println("Encrypted data: ", string(data)) + setMockFileBlock(data) + }, + end: func() { + resetMockFileBlock() + }, + setupDbMock: func(mock sqlmock.Sqlmock) { + mock.ExpectBegin() + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). + WithArgs(alloc.Tx). + WillReturnRows( + sqlmock.NewRows( + []string{ + "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", + }, + ). + AddRow( + alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), + ), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). + WithArgs(alloc.ID). + WillReturnRows( + sqlmock.NewRows([]string{"id", "allocation_id"}). + AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), + ) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, filePathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "chunk_size"}). + AddRow("/file.txt", "f", filePathHash, filePathHash, "content_hash", ownerScheme.GetEncryptedKey(), 65536), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). + WithArgs(guestClient.ClientID). + WillReturnError(gorm.ErrRecordNotFound) + + guestPublicEncryptedKey, err := guestScheme.GetPublicKey() + if err != nil { + t.Fatal(err) + } + reEncryptionKey, err := ownerScheme.GetReGenKey(guestPublicEncryptedKey, "filetype:audio") + + if err != nil { + t.Fatal(err) + } + fmt.Printf("\n\nencryptedKey: %v\tgpbk: %v\treKey: %v\n\n", ownerScheme.GetEncryptedKey(), guestPublicEncryptedKey, reEncryptionKey) + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "marketplace_share_info" WHERE`)). + WithArgs(guestClient.ClientID, filePathHash). + WillReturnRows( + sqlmock.NewRows([]string{"re_encryption_key", "client_encryption_public_key"}). + AddRow(reEncryptionKey, guestPublicEncryptedKey), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). + WithArgs(guestClient.ClientID). + WillReturnRows( + sqlmock.NewRows([]string{"client_id"}). + AddRow(guestClient.ClientID), + ) + + aa := sqlmock.AnyArg() + + mock.ExpectExec(`UPDATE "read_markers"`). + WithArgs(guestClient.ClientKey, alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa, aa). + WillReturnResult(sqlmock.NewResult(0, 0)) + + mock.ExpectCommit() + }, + wantCode: http.StatusOK, + wantBody: "", + }, + { + name: "DownloadFile_Encrypted_InSharedFolder_Permission_Allowed_shared_File", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + handlerName := handlers["/v1/file/download/{allocation}"] + url, err := router.Get(handlerName).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + remotePath := "/" + pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") + authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") + if err != nil { + t.Fatal(err) + } + rm := &marker.ReadMarker{} + rm.ClientID = guestClient.ClientID + rm.ClientPublicKey = guestClient.ClientKey + rm.BlobberID = "" + rm.AllocationID = alloc.ID + rm.ReadCounter = 1 + rm.OwnerID = ownerClient.ClientID + rm.Signature, err = signHash(guestClient, rm.GetHash()) + if err != nil { + t.Fatal(err) + } + + rmData, err := json.Marshal(rm) + require.NoError(t, err) + + r, err := http.NewRequest(http.MethodGet, url.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("path_hash", filePathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) + r.Header.Set("read_marker", string(rmData)) + r.Header.Set(common.ClientSignatureHeader, sign) + r.Header.Set(common.ClientHeader, guestClient.ClientID) + r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) + + return r + }(), + }, + alloc: alloc, + begin: func() { + dataToEncrypt := "data_to_encrypt" + encMsg, err := ownerScheme.Encrypt([]byte(dataToEncrypt)) + if err != nil { + t.Fatal(err) + } + + header := make([]byte, EncryptionHeaderSize) + copy(header, encMsg.MessageChecksum+encMsg.OverallChecksum) + data := append(header, encMsg.EncryptedData...) + setMockFileBlock(data) + }, + end: func() { + resetMockFileBlock() + }, + setupDbMock: func(mock sqlmock.Sqlmock) { + mock.ExpectBegin() + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). + WithArgs(alloc.Tx). + WillReturnRows( + sqlmock.NewRows( + []string{ + "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", + }, + ). + AddRow( + alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), + ), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). + WithArgs(alloc.ID). + WillReturnRows( + sqlmock.NewRows([]string{"id", "allocation_id"}). + AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), + ) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, filePathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path", "chunk_size"}). + AddRow("/file.txt", "f", filePathHash, filePathHash, "content_hash", ownerScheme.GetEncryptedKey(), "/", fileref.CHUNK_SIZE), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). + WithArgs(guestClient.ClientID). + WillReturnError(gorm.ErrRecordNotFound) + + rootPathHash := fileref.GetReferenceLookup(alloc.Tx, "/") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, rootPathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path"}). + AddRow("/", "d", rootPathHash, rootPathHash, "content_hash", "", "."), + ) + + gpbk, err := guestScheme.GetPublicKey() + if err != nil { + t.Fatal(err) + } + + reEncryptionKey, _ := ownerScheme.GetReGenKey(gpbk, "filetype:audio") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "marketplace_share_info" WHERE`)). + WithArgs(guestClient.ClientID, rootPathHash). + WillReturnRows( + sqlmock.NewRows([]string{"re_encryption_key", "client_encryption_public_key"}). + AddRow(reEncryptionKey, gpbk), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). + WithArgs(guestClient.ClientID). + WillReturnRows( + sqlmock.NewRows([]string{"client_id"}). + AddRow(guestClient.ClientID), + ) + + aa := sqlmock.AnyArg() + + mock.ExpectExec(`UPDATE "read_markers"`). + WithArgs(guestClient.ClientKey, alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa, aa). + WillReturnResult(sqlmock.NewResult(0, 0)) + + mock.ExpectCommit() + }, + wantCode: http.StatusOK, + wantBody: "", + }, + { + name: "DownloadFile_Encrypted_InSharedFolderSubdirectory_Permission_Allowed_shared_File", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + handlerName := handlers["/v1/file/download/{allocation}"] + url, err := router.Get(handlerName).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + remotePath := "/folder1" + pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1/subfolder1/file.txt") + authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") + if err != nil { + t.Fatal(err) + } + rm := &marker.ReadMarker{} + rm.ClientID = guestClient.ClientID + rm.ClientPublicKey = guestClient.ClientKey + rm.BlobberID = "" + rm.AllocationID = alloc.ID + rm.ReadCounter = 1 + rm.OwnerID = alloc.OwnerID + rm.Signature, err = signHash(guestClient, rm.GetHash()) + if err != nil { + t.Fatal(err) + } + + rmData, err := json.Marshal(rm) + require.NoError(t, err) + + r, err := http.NewRequest(http.MethodGet, url.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("path_hash", filePathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) + r.Header.Set("read_marker", string(rmData)) + r.Header.Set(common.ClientSignatureHeader, sign) + r.Header.Set(common.ClientHeader, guestClient.ClientID) + r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) + + return r + }(), + }, + alloc: alloc, + begin: func() { + dataToEncrypt := "data_to_encrypt" + encMsg, err := ownerScheme.Encrypt([]byte(dataToEncrypt)) + if err != nil { + t.Fatal(err) + } + + header := make([]byte, EncryptionHeaderSize) + copy(header, encMsg.MessageChecksum+encMsg.OverallChecksum) + data := append(header, encMsg.EncryptedData...) + setMockFileBlock(data) + }, + end: func() { + resetMockFileBlock() + }, + setupDbMock: func(mock sqlmock.Sqlmock) { + mock.ExpectBegin() + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). + WithArgs(alloc.Tx). + WillReturnRows( + sqlmock.NewRows( + []string{ + "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", + }, + ). + AddRow( + alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), + ), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). + WithArgs(alloc.ID). + WillReturnRows( + sqlmock.NewRows([]string{"id", "allocation_id"}). + AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), + ) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1/subfolder1/file.txt") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, filePathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path", "chunk_size"}). + AddRow("/folder1/subfolder1/file.txt", "f", filePathHash, filePathHash, "content_hash", ownerScheme.GetEncryptedKey(), "/folder1/subfolder1", filestore.CHUNK_SIZE), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). + WithArgs(guestClient.ClientID). + WillReturnError(gorm.ErrRecordNotFound) + + rootPathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, rootPathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path"}). + AddRow("/folder1", "d", rootPathHash, rootPathHash, "content_hash", "", "."), + ) + + gpbk, err := guestScheme.GetPublicKey() + if err != nil { + t.Fatal(err) + } + + reEncryptionKey, _ := ownerScheme.GetReGenKey(gpbk, "filetype:audio") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "marketplace_share_info" WHERE`)). + WithArgs(guestClient.ClientID, rootPathHash). + WillReturnRows( + sqlmock.NewRows([]string{"re_encryption_key", "client_encryption_public_key"}). + AddRow(reEncryptionKey, gpbk), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). + WithArgs(guestClient.ClientID). + WillReturnRows( + sqlmock.NewRows([]string{"client_id"}). + AddRow(guestClient.ClientID), + ) + + aa := sqlmock.AnyArg() + + mock.ExpectExec(`UPDATE "read_markers"`). + WithArgs(guestClient.ClientKey, alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa, aa). + WillReturnResult(sqlmock.NewResult(0, 0)) + + mock.ExpectCommit() + }, + wantCode: http.StatusOK, + wantBody: "", + }, + { + name: "DownloadFile_Encrypted_InSharedFolder_WrongFilePath_Permission_Rejected_shared_File", + args: args{ + w: httptest.NewRecorder(), + r: func() *http.Request { + handlerName := handlers["/v1/file/download/{allocation}"] + url, err := router.Get(handlerName).URL("allocation", alloc.Tx) + if err != nil { + t.Fatal() + } + + remotePath := "/folder1" + pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder2/subfolder1/file.txt") + authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") + if err != nil { + t.Fatal(err) + } + rm := &marker.ReadMarker{} + rm.ClientID = guestClient.ClientID + rm.ClientPublicKey = guestClient.ClientKey + rm.BlobberID = "" + rm.AllocationID = alloc.ID + rm.ReadCounter = 1 + rm.OwnerID = alloc.OwnerID + rm.Signature, err = signHash(guestClient, rm.GetHash()) + if err != nil { + t.Fatal(err) + } + + rmData, err := json.Marshal(rm) + require.NoError(t, err) + + r, err := http.NewRequest(http.MethodGet, url.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("read_marker", string(rmData)) + r.Header.Set("path_hash", filePathHash) + r.Header.Set("block_num", fmt.Sprintf("%d", 1)) + r.Header.Set("auth_token", authTicket) + r.Header.Set(common.ClientSignatureHeader, sign) + r.Header.Set(common.ClientHeader, guestClient.ClientID) + r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) + + return r + }(), + }, + alloc: alloc, + begin: func() { + dataToEncrypt := "data_to_encrypt" + encMsg, err := ownerScheme.Encrypt([]byte(dataToEncrypt)) + if err != nil { + t.Fatal(err) + } + + header := make([]byte, EncryptionHeaderSize) + copy(header, encMsg.MessageChecksum+encMsg.OverallChecksum) + data := append(header, encMsg.EncryptedData...) + setMockFileBlock(data) + }, + end: func() { + resetMockFileBlock() + }, + setupDbMock: func(mock sqlmock.Sqlmock) { + mock.ExpectBegin() + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). + WithArgs(alloc.Tx). + WillReturnRows( + sqlmock.NewRows( + []string{ + "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", + }, + ). + AddRow( + alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), + ), + ) + + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). + WithArgs(alloc.ID). + WillReturnRows( + sqlmock.NewRows([]string{"id", "allocation_id"}). + AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), + ) + + filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder2/subfolder1/file.txt") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, filePathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path", "chunk_size"}). + AddRow("/file.txt", "f", filePathHash, filePathHash, "content_hash", ownerScheme.GetEncryptedKey(), "/folder2/subfolder1", fileref.CHUNK_SIZE), + ) + + rootPathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1") + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). + WithArgs(alloc.ID, rootPathHash). + WillReturnRows( + sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path"}). + AddRow("/folder1", "d", rootPathHash, rootPathHash, "content_hash", "", "/"), + ) + + }, + wantCode: http.StatusBadRequest, + wantBody: "{\"code\":\"download_file\",\"error\":\"download_file: cannot verify auth ticket: invalid_parameters: Auth ticket is not valid for the resource being requested\"}\n\n", + }, + } + + tests := append(positiveTests, negativeTests...) + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + mock := datastore.MockTheStore(t) + test.setupDbMock(mock) + + if test.begin != nil { + test.begin() + } + router.ServeHTTP(test.args.w, test.args.r) + if test.end != nil { + test.end() + } + + fmt.Printf("\nResponse body: %v", test.args.w.Body.String()) + assert.Equal(t, test.wantCode, test.args.w.Result().StatusCode) + if test.wantCode != http.StatusOK || test.wantBody != "" { + assert.Equal(t, test.wantBody, test.args.w.Body.String()) + } + }) + } + + curDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if err := os.RemoveAll(curDir + "/tmp"); err != nil { + t.Fatal(err) + } +} diff --git a/code/go/0chain.net/blobbercore/handler/handler_test.go b/code/go/0chain.net/blobbercore/handler/handler_test.go index 9af46dee8..f09bd17d8 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_test.go @@ -17,7 +17,6 @@ import ( "github.com/0chain/gosdk/core/zcncrypto" "github.com/0chain/gosdk/zboxcore/client" - zencryption "github.com/0chain/gosdk/zboxcore/encryption" "github.com/0chain/gosdk/zboxcore/fileref" "github.com/0chain/gosdk/zboxcore/marker" "github.com/0chain/gosdk/zcncore" @@ -88,15 +87,6 @@ func signHash(client *client.Client, hash string) (string, error) { return retSignature, nil } -func getEncryptionScheme(mnemonic string) (zencryption.EncryptionScheme, error) { - encscheme := zencryption.NewEncryptionScheme() - if _, err := encscheme.Initialize(mnemonic); err != nil { - return nil, err - } - encscheme.InitForEncryption("filetype:audio") - return encscheme, nil -} - func init() { resetMockFileBlock() common.ConfigRateLimits() @@ -328,25 +318,13 @@ func TestHandlers_Requiring_Signature(t *testing.T) { require.NoError(t, client.PopulateClients([]string{clientJson, guestClientJson}, "bls0chain")) clients := client.GetClients() - ownerClient, guestClient := clients[0], clients[1] - - ownerScheme, err := getEncryptionScheme(ownerClient.Mnemonic) - if err != nil { - t.Fatal(err) - } - - guestScheme, err := getEncryptionScheme(guestClient.Mnemonic) - if err != nil { - t.Fatal(err) - } - // require.NoError(t, client.PopulateClient(clientJson, "bls0chain")) - // setupEncryptionScheme() + ownerClient := clients[0] router, handlers := setupHandlers() sch := zcncrypto.NewSignatureScheme("bls0chain") //sch.Mnemonic = "expose culture dignity plastic digital couple promote best pool error brush upgrade correct art become lobster nature moment obtain trial multiply arch miss toe" - _, err = sch.RecoverKeys("expose culture dignity plastic digital couple promote best pool error brush upgrade correct art become lobster nature moment obtain trial multiply arch miss toe") + _, err := sch.RecoverKeys("expose culture dignity plastic digital couple promote best pool error brush upgrade correct art become lobster nature moment obtain trial multiply arch miss toe") if err != nil { t.Fatal(err) } @@ -1495,845 +1473,6 @@ func TestHandlers_Requiring_Signature(t *testing.T) { wantCode: http.StatusOK, wantBody: "{\"message\":\"Path not found\",\"status\":404}\n", }, - { - name: "DownloadFile_Record_Not_Found", - args: args{ - w: httptest.NewRecorder(), - r: func() *http.Request { - handlerName := handlers["/v1/file/download/{allocation}"] - url, err := router.Get(handlerName).URL("allocation", alloc.Tx) - if err != nil { - t.Fatal() - } - - remotePath := "/file.txt" - - rm := &marker.ReadMarker{} - rm.ClientID = ownerClient.ClientID - rm.ClientPublicKey = ownerClient.ClientKey - rm.BlobberID = "" - rm.AllocationID = alloc.ID - rm.OwnerID = ownerClient.ClientID - rm.Signature, err = signHash(ownerClient, rm.GetHash()) - if err != nil { - t.Fatal(err) - } - rmData, err := json.Marshal(rm) - require.NoError(t, err) - r, err := http.NewRequest(http.MethodGet, url.String(), nil) - if err != nil { - require.NoError(t, err) - } - - hash := encryption.Hash(alloc.Tx) - sign, err := sch.Sign(hash) - if err != nil { - t.Fatal(err) - } - - r.Header.Set("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("read_marker", string(rmData)) - r.Header.Set(common.ClientSignatureHeader, sign) - r.Header.Set(common.ClientHeader, alloc.OwnerID) - r.Header.Set(common.ClientKeyHeader, alloc.OwnerPublicKey) - - return r - }(), - }, - alloc: alloc, - setupDbMock: func(mock sqlmock.Sqlmock) { - mock.ExpectBegin() - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). - WithArgs(alloc.Tx). - WillReturnRows( - sqlmock.NewRows( - []string{ - "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", - }, - ). - AddRow( - alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), - ), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). - WithArgs(alloc.ID). - WillReturnRows( - sqlmock.NewRows([]string{"id", "allocation_id"}). - AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), - ) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, filePathHash).WillReturnError(gorm.ErrRecordNotFound) - - }, - wantCode: http.StatusBadRequest, - wantBody: "{\"code\":\"download_file\",\"error\":\"download_file: invalid file path: record not found\"}\n\n", - }, - { - name: "DownloadFile_Unencrypted_return_file", - args: args{ - w: httptest.NewRecorder(), - r: func() *http.Request { - handlerName := handlers["/v1/file/download/{allocation}"] - url, err := router.Get(handlerName).URL("allocation", alloc.Tx) - if err != nil { - t.Fatal() - } - - remotePath := "/file.txt" - - rm := &marker.ReadMarker{} - rm.ClientID = ownerClient.ClientID - rm.ClientPublicKey = ownerClient.ClientKey - rm.BlobberID = "" - rm.AllocationID = alloc.ID - rm.ReadCounter = 1 - rm.OwnerID = ownerClient.ClientID - rm.Signature, err = signHash(ownerClient, rm.GetHash()) - if err != nil { - t.Fatal(err) - } - rmData, err := json.Marshal(rm) - require.NoError(t, err) - r, err := http.NewRequest(http.MethodPost, url.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("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("read_marker", string(rmData)) - r.Header.Set(common.ClientSignatureHeader, sign) - r.Header.Set(common.ClientHeader, alloc.OwnerID) - r.Header.Set(common.ClientKeyHeader, alloc.OwnerPublicKey) - - return r - }(), - }, - alloc: alloc, - setupDbMock: func(mock sqlmock.Sqlmock) { - mock.ExpectBegin() - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). - WithArgs(alloc.Tx). - WillReturnRows( - sqlmock.NewRows( - []string{ - "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", - }, - ). - AddRow( - alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), - ), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). - WithArgs(alloc.ID). - WillReturnRows( - sqlmock.NewRows([]string{"id", "allocation_id"}). - AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), - ) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, filePathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "lookup_hash", "content_hash"}). - AddRow("/file.txt", "f", filePathHash, "abcd"), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). - WithArgs(ownerClient.ClientID). - WillReturnError(gorm.ErrRecordNotFound) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). - WithArgs(ownerClient.ClientID). - WillReturnRows( - sqlmock.NewRows([]string{"client_id"}). - AddRow(ownerClient.ClientID), - ) - - aa := sqlmock.AnyArg() - - mock.ExpectExec(`(UPDATE "read_markers" SET)(.+)`). - WithArgs(ownerClient.ClientKey, alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa). - WillReturnResult(sqlmock.NewResult(0, 0)) - - mock.ExpectCommit() - }, - wantCode: http.StatusOK, - wantBody: "\"bW9jaw==\"\n", //base64encoded for mock string - }, - { - name: "DownloadFile_Encrypted_Permission_Denied_Unshared_File", - args: args{ - w: httptest.NewRecorder(), - r: func() *http.Request { - handlerName := handlers["/v1/file/download/{allocation}"] - url, err := router.Get(handlerName).URL("allocation", alloc.Tx) - if err != nil { - t.Fatal() - } - - remotePath := "/file.txt" - - pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) - authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, ownerClient.Keys[0].PublicKey) - if err != nil { - t.Fatal(err) - } - - rm := &marker.ReadMarker{} - rm.ClientID = guestClient.ClientID - rm.ClientPublicKey = guestClient.ClientKey - rm.BlobberID = "" - rm.AllocationID = alloc.ID - rm.ReadCounter = 1 - rm.OwnerID = ownerClient.ClientID - rm.Signature, err = signHash(guestClient, rm.GetHash()) - if err != nil { - t.Fatal(err) - } - rmData, err := json.Marshal(rm) - require.NoError(t, err) - r, err := http.NewRequest(http.MethodPost, url.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("read_marker", string(rmData)) - r.Header.Set("path_hash", pathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) - r.Header.Set(common.ClientSignatureHeader, sign) - r.Header.Set(common.ClientHeader, guestClient.ClientID) - r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) - - return r - }(), - }, - alloc: alloc, - setupDbMock: func(mock sqlmock.Sqlmock) { - mock.ExpectBegin() - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). - WithArgs(alloc.Tx). - WillReturnRows( - sqlmock.NewRows( - []string{ - "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", - }, - ). - AddRow( - alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), - ), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). - WithArgs(alloc.ID). - WillReturnRows( - sqlmock.NewRows([]string{"id", "allocation_id"}). - AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), - ) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, filePathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "chunk_size"}). - AddRow("/file.txt", "f", filePathHash, filePathHash, "content_hash", "qCj3sXXeXUAByi1ERIbcfXzWN75dyocYzyRXnkStXio=", 65536), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). - WithArgs(client.GetClientID()). - WillReturnError(gorm.ErrRecordNotFound) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). - WithArgs(client.GetClientID()). - WillReturnRows( - sqlmock.NewRows([]string{"client_id"}). - AddRow(client.GetClientID()), - ) - - aa := sqlmock.AnyArg() - - mock.ExpectExec(`UPDATE "read_markers"`). - WithArgs(client.GetClientPublicKey(), alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa, aa). - WillReturnResult(sqlmock.NewResult(0, 0)) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "marketplace_share_info" WHERE`)). - WithArgs(client.GetClientID(), filePathHash). - WillReturnError(gorm.ErrRecordNotFound) - - mock.ExpectCommit() - }, - wantCode: http.StatusBadRequest, - wantBody: "{\"error\":\"client does not have permission to download the file. share does not exist\"}\n\n", - }, - { - name: "DownloadFile_Encrypted_Permission_Allowed_shared_File", - args: args{ - w: httptest.NewRecorder(), - r: func() *http.Request { - handlerName := handlers["/v1/file/download/{allocation}"] - url, err := router.Get(handlerName).URL("allocation", alloc.Tx) - if err != nil { - t.Fatal() - } - - remotePath := "/file.txt" - - pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) - authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") - if err != nil { - t.Fatal(err) - } - rm := &marker.ReadMarker{} - rm.ClientID = guestClient.ClientID - rm.ClientPublicKey = guestClient.ClientKey - rm.BlobberID = "" - rm.AllocationID = alloc.ID - rm.ReadCounter = 1 - rm.OwnerID = ownerClient.ClientID - rm.Signature, err = signHash(guestClient, rm.GetHash()) - if err != nil { - t.Fatal(err) - } - rmData, err := json.Marshal(rm) - require.NoError(t, err) - r, err := http.NewRequest(http.MethodPost, url.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("read_marker", string(rmData)) - r.Header.Set("path_hash", pathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) - r.Header.Set(common.ClientSignatureHeader, sign) - r.Header.Set(common.ClientHeader, guestClient.ClientID) - r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) - - return r - }(), - }, - alloc: alloc, - begin: func() { - dataToEncrypt := "data_to_encrypt" - encMsg, err := ownerScheme.Encrypt([]byte(dataToEncrypt)) - if err != nil { - t.Fatal(err) - } - - header := make([]byte, EncryptionHeaderSize) - copy(header, encMsg.MessageChecksum+encMsg.OverallChecksum) - data := append(header, encMsg.EncryptedData...) - fmt.Println("Encrypted data: ", string(data)) - setMockFileBlock(data) - }, - end: func() { - resetMockFileBlock() - }, - setupDbMock: func(mock sqlmock.Sqlmock) { - mock.ExpectBegin() - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). - WithArgs(alloc.Tx). - WillReturnRows( - sqlmock.NewRows( - []string{ - "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", - }, - ). - AddRow( - alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), - ), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). - WithArgs(alloc.ID). - WillReturnRows( - sqlmock.NewRows([]string{"id", "allocation_id"}). - AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), - ) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, filePathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "chunk_size"}). - AddRow("/file.txt", "f", filePathHash, filePathHash, "content_hash", ownerScheme.GetEncryptedKey(), 65536), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). - WithArgs(guestClient.ClientID). - WillReturnError(gorm.ErrRecordNotFound) - - guestPublicEncryptedKey, err := guestScheme.GetPublicKey() - if err != nil { - t.Fatal(err) - } - reEncryptionKey, err := ownerScheme.GetReGenKey(guestPublicEncryptedKey, "filetype:audio") - - if err != nil { - t.Fatal(err) - } - fmt.Printf("\n\nencryptedKey: %v\tgpbk: %v\treKey: %v\n\n", ownerScheme.GetEncryptedKey(), guestPublicEncryptedKey, reEncryptionKey) - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "marketplace_share_info" WHERE`)). - WithArgs(guestClient.ClientID, filePathHash). - WillReturnRows( - sqlmock.NewRows([]string{"re_encryption_key", "client_encryption_public_key"}). - AddRow(reEncryptionKey, guestPublicEncryptedKey), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). - WithArgs(guestClient.ClientID). - WillReturnRows( - sqlmock.NewRows([]string{"client_id"}). - AddRow(guestClient.ClientID), - ) - - aa := sqlmock.AnyArg() - - mock.ExpectExec(`UPDATE "read_markers"`). - WithArgs(guestClient.ClientKey, alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa, aa). - WillReturnResult(sqlmock.NewResult(0, 0)) - - mock.ExpectCommit() - }, - wantCode: http.StatusOK, - wantBody: "", - }, - { - name: "DownloadFile_Encrypted_InSharedFolder_Permission_Allowed_shared_File", - args: args{ - w: httptest.NewRecorder(), - r: func() *http.Request { - handlerName := handlers["/v1/file/download/{allocation}"] - url, err := router.Get(handlerName).URL("allocation", alloc.Tx) - if err != nil { - t.Fatal() - } - - remotePath := "/" - pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") - authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") - if err != nil { - t.Fatal(err) - } - rm := &marker.ReadMarker{} - rm.ClientID = guestClient.ClientID - rm.ClientPublicKey = guestClient.ClientKey - rm.BlobberID = "" - rm.AllocationID = alloc.ID - rm.ReadCounter = 1 - rm.OwnerID = ownerClient.ClientID - rm.Signature, err = signHash(guestClient, rm.GetHash()) - if err != nil { - t.Fatal(err) - } - - rmData, err := json.Marshal(rm) - require.NoError(t, err) - - r, err := http.NewRequest(http.MethodPost, url.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("path_hash", filePathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) - r.Header.Set("read_marker", string(rmData)) - r.Header.Set(common.ClientSignatureHeader, sign) - r.Header.Set(common.ClientHeader, guestClient.ClientID) - r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) - - return r - }(), - }, - alloc: alloc, - begin: func() { - dataToEncrypt := "data_to_encrypt" - encMsg, err := ownerScheme.Encrypt([]byte(dataToEncrypt)) - if err != nil { - t.Fatal(err) - } - - header := make([]byte, EncryptionHeaderSize) - copy(header, encMsg.MessageChecksum+encMsg.OverallChecksum) - data := append(header, encMsg.EncryptedData...) - setMockFileBlock(data) - }, - end: func() { - resetMockFileBlock() - }, - setupDbMock: func(mock sqlmock.Sqlmock) { - mock.ExpectBegin() - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). - WithArgs(alloc.Tx). - WillReturnRows( - sqlmock.NewRows( - []string{ - "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", - }, - ). - AddRow( - alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), - ), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). - WithArgs(alloc.ID). - WillReturnRows( - sqlmock.NewRows([]string{"id", "allocation_id"}). - AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), - ) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/file.txt") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, filePathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path", "chunk_size"}). - AddRow("/file.txt", "f", filePathHash, filePathHash, "content_hash", ownerScheme.GetEncryptedKey(), "/", fileref.CHUNK_SIZE), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). - WithArgs(guestClient.ClientID). - WillReturnError(gorm.ErrRecordNotFound) - - rootPathHash := fileref.GetReferenceLookup(alloc.Tx, "/") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, rootPathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path"}). - AddRow("/", "d", rootPathHash, rootPathHash, "content_hash", "", "."), - ) - - gpbk, err := guestScheme.GetPublicKey() - if err != nil { - t.Fatal(err) - } - - reEncryptionKey, _ := ownerScheme.GetReGenKey(gpbk, "filetype:audio") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "marketplace_share_info" WHERE`)). - WithArgs(guestClient.ClientID, rootPathHash). - WillReturnRows( - sqlmock.NewRows([]string{"re_encryption_key", "client_encryption_public_key"}). - AddRow(reEncryptionKey, gpbk), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). - WithArgs(guestClient.ClientID). - WillReturnRows( - sqlmock.NewRows([]string{"client_id"}). - AddRow(guestClient.ClientID), - ) - - aa := sqlmock.AnyArg() - - mock.ExpectExec(`UPDATE "read_markers"`). - WithArgs(guestClient.ClientKey, alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa, aa). - WillReturnResult(sqlmock.NewResult(0, 0)) - - mock.ExpectCommit() - }, - wantCode: http.StatusOK, - wantBody: "", - }, - { - name: "DownloadFile_Encrypted_InSharedFolderSubdirectory_Permission_Allowed_shared_File", - args: args{ - w: httptest.NewRecorder(), - r: func() *http.Request { - handlerName := handlers["/v1/file/download/{allocation}"] - url, err := router.Get(handlerName).URL("allocation", alloc.Tx) - if err != nil { - t.Fatal() - } - - remotePath := "/folder1" - pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1/subfolder1/file.txt") - authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") - if err != nil { - t.Fatal(err) - } - rm := &marker.ReadMarker{} - rm.ClientID = guestClient.ClientID - rm.ClientPublicKey = guestClient.ClientKey - rm.BlobberID = "" - rm.AllocationID = alloc.ID - rm.ReadCounter = 1 - rm.OwnerID = alloc.OwnerID - rm.Signature, err = signHash(guestClient, rm.GetHash()) - if err != nil { - t.Fatal(err) - } - - rmData, err := json.Marshal(rm) - require.NoError(t, err) - - r, err := http.NewRequest(http.MethodPost, url.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("path_hash", filePathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) - r.Header.Set("read_marker", string(rmData)) - r.Header.Set(common.ClientSignatureHeader, sign) - r.Header.Set(common.ClientHeader, guestClient.ClientID) - r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) - - return r - }(), - }, - alloc: alloc, - begin: func() { - dataToEncrypt := "data_to_encrypt" - encMsg, err := ownerScheme.Encrypt([]byte(dataToEncrypt)) - if err != nil { - t.Fatal(err) - } - - header := make([]byte, EncryptionHeaderSize) - copy(header, encMsg.MessageChecksum+encMsg.OverallChecksum) - data := append(header, encMsg.EncryptedData...) - setMockFileBlock(data) - }, - end: func() { - resetMockFileBlock() - }, - setupDbMock: func(mock sqlmock.Sqlmock) { - mock.ExpectBegin() - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). - WithArgs(alloc.Tx). - WillReturnRows( - sqlmock.NewRows( - []string{ - "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", - }, - ). - AddRow( - alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), - ), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). - WithArgs(alloc.ID). - WillReturnRows( - sqlmock.NewRows([]string{"id", "allocation_id"}). - AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), - ) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1/subfolder1/file.txt") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, filePathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path", "chunk_size"}). - AddRow("/folder1/subfolder1/file.txt", "f", filePathHash, filePathHash, "content_hash", ownerScheme.GetEncryptedKey(), "/folder1/subfolder1", filestore.CHUNK_SIZE), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "collaborators" WHERE`)). - WithArgs(guestClient.ClientID). - WillReturnError(gorm.ErrRecordNotFound) - - rootPathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, rootPathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path"}). - AddRow("/folder1", "d", rootPathHash, rootPathHash, "content_hash", "", "."), - ) - - gpbk, err := guestScheme.GetPublicKey() - if err != nil { - t.Fatal(err) - } - - reEncryptionKey, _ := ownerScheme.GetReGenKey(gpbk, "filetype:audio") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "marketplace_share_info" WHERE`)). - WithArgs(guestClient.ClientID, rootPathHash). - WillReturnRows( - sqlmock.NewRows([]string{"re_encryption_key", "client_encryption_public_key"}). - AddRow(reEncryptionKey, gpbk), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "read_markers" WHERE`)). - WithArgs(guestClient.ClientID). - WillReturnRows( - sqlmock.NewRows([]string{"client_id"}). - AddRow(guestClient.ClientID), - ) - - aa := sqlmock.AnyArg() - - mock.ExpectExec(`UPDATE "read_markers"`). - WithArgs(guestClient.ClientKey, alloc.ID, alloc.OwnerID, aa, aa, aa, aa, aa, aa, aa, aa). - WillReturnResult(sqlmock.NewResult(0, 0)) - - mock.ExpectCommit() - }, - wantCode: http.StatusOK, - wantBody: "", - }, - { - name: "DownloadFile_Encrypted_InSharedFolder_WrongFilePath_Permission_Rejected_shared_File", - args: args{ - w: httptest.NewRecorder(), - r: func() *http.Request { - handlerName := handlers["/v1/file/download/{allocation}"] - url, err := router.Get(handlerName).URL("allocation", alloc.Tx) - if err != nil { - t.Fatal() - } - - remotePath := "/folder1" - pathHash := fileref.GetReferenceLookup(alloc.Tx, remotePath) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder2/subfolder1/file.txt") - authTicket, err := GetAuthTicketForEncryptedFile(ownerClient, alloc.ID, remotePath, pathHash, guestClient.ClientID, "") - if err != nil { - t.Fatal(err) - } - rm := &marker.ReadMarker{} - rm.ClientID = guestClient.ClientID - rm.ClientPublicKey = guestClient.ClientKey - rm.BlobberID = "" - rm.AllocationID = alloc.ID - rm.ReadCounter = 1 - rm.OwnerID = alloc.OwnerID - rm.Signature, err = signHash(guestClient, rm.GetHash()) - if err != nil { - t.Fatal(err) - } - - rmData, err := json.Marshal(rm) - require.NoError(t, err) - - r, err := http.NewRequest(http.MethodPost, url.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("read_marker", string(rmData)) - r.Header.Set("path_hash", filePathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) - r.Header.Set(common.ClientSignatureHeader, sign) - r.Header.Set(common.ClientHeader, guestClient.ClientID) - r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) - - return r - }(), - }, - alloc: alloc, - begin: func() { - dataToEncrypt := "data_to_encrypt" - encMsg, err := ownerScheme.Encrypt([]byte(dataToEncrypt)) - if err != nil { - t.Fatal(err) - } - - header := make([]byte, EncryptionHeaderSize) - copy(header, encMsg.MessageChecksum+encMsg.OverallChecksum) - data := append(header, encMsg.EncryptedData...) - setMockFileBlock(data) - }, - end: func() { - resetMockFileBlock() - }, - setupDbMock: func(mock sqlmock.Sqlmock) { - mock.ExpectBegin() - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "allocations" WHERE`)). - WithArgs(alloc.Tx). - WillReturnRows( - sqlmock.NewRows( - []string{ - "id", "tx", "expiration_date", "owner_public_key", "owner_id", "blobber_size", - }, - ). - AddRow( - alloc.ID, alloc.Tx, alloc.Expiration, alloc.OwnerPublicKey, alloc.OwnerID, int64(1<<30), - ), - ) - - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "terms" WHERE`)). - WithArgs(alloc.ID). - WillReturnRows( - sqlmock.NewRows([]string{"id", "allocation_id"}). - AddRow(alloc.Terms[0].ID, alloc.Terms[0].AllocationID), - ) - - filePathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder2/subfolder1/file.txt") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, filePathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path", "chunk_size"}). - AddRow("/file.txt", "f", filePathHash, filePathHash, "content_hash", ownerScheme.GetEncryptedKey(), "/folder2/subfolder1", fileref.CHUNK_SIZE), - ) - - rootPathHash := fileref.GetReferenceLookup(alloc.Tx, "/folder1") - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "reference_objects" WHERE`)). - WithArgs(alloc.ID, rootPathHash). - WillReturnRows( - sqlmock.NewRows([]string{"path", "type", "path_hash", "lookup_hash", "content_hash", "encrypted_key", "parent_path"}). - AddRow("/folder1", "d", rootPathHash, rootPathHash, "content_hash", "", "/"), - ) - - }, - wantCode: http.StatusBadRequest, - wantBody: "{\"code\":\"download_file\",\"error\":\"download_file: cannot verify auth ticket: invalid_parameters: Auth ticket is not valid for the resource being requested\"}\n\n", - }, } tests := append(positiveTests, negativeTests...) From 8c98207f9b53fd3c99ff953423d03330aa7404ee Mon Sep 17 00:00:00 2001 From: Pradip Parmar Date: Sun, 27 Feb 2022 00:37:43 +0530 Subject: [PATCH 10/12] lint fix Signed-off-by: Pradip Parmar --- .../0chain.net/blobbercore/handler/handler_download_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/code/go/0chain.net/blobbercore/handler/handler_download_test.go b/code/go/0chain.net/blobbercore/handler/handler_download_test.go index 6a49282cc..88fa003c9 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_download_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_download_test.go @@ -91,12 +91,6 @@ func TestHandlers_Download_Requiring_Signature(t *testing.T) { alloc.OwnerPublicKey = ownerClient.Keys[0].PublicKey alloc.OwnerID = ownerClient.ClientID - const ( - path = "/path" - newName = "new name" - connectionID = "connection id" - ) - type ( args struct { w *httptest.ResponseRecorder From faa13cffb09be594a4f8596ac9613aa1902c8bc9 Mon Sep 17 00:00:00 2001 From: Lz Date: Sun, 27 Feb 2022 23:00:12 +0800 Subject: [PATCH 11/12] fix(download): fixed key naming issue on download request header --- ..._request.go => download_request_header.go} | 49 ++++++++----------- 1 file changed, 21 insertions(+), 28 deletions(-) rename code/go/0chain.net/blobbercore/handler/{download_request.go => download_request_header.go} (60%) diff --git a/code/go/0chain.net/blobbercore/handler/download_request.go b/code/go/0chain.net/blobbercore/handler/download_request_header.go similarity index 60% rename from code/go/0chain.net/blobbercore/handler/download_request.go rename to code/go/0chain.net/blobbercore/handler/download_request_header.go index 08611796f..1503fd28a 100644 --- a/code/go/0chain.net/blobbercore/handler/download_request.go +++ b/code/go/0chain.net/blobbercore/handler/download_request_header.go @@ -11,8 +11,8 @@ import ( "github.com/0chain/errors" ) -// DownloadRequest metedata of download request -type DownloadRequest struct { +// DownloadRequestHeader metedata of download request +type DownloadRequestHeader struct { req *http.Request allocationID string PathHash string @@ -25,7 +25,7 @@ type DownloadRequest struct { DownloadMode string } -func FromDownloadRequest(allocationID string, req *http.Request) (*DownloadRequest, error) { +func FromDownloadRequest(allocationID string, req *http.Request) (*DownloadRequestHeader, error) { if allocationID == "" { return nil, errors.Throw(common.ErrInvalidParameter, "allocationID") } @@ -34,7 +34,7 @@ func FromDownloadRequest(allocationID string, req *http.Request) (*DownloadReque return nil, errors.Throw(common.ErrInvalidParameter, "req") } - dr := &DownloadRequest{ + dr := &DownloadRequestHeader{ allocationID: allocationID, req: req, } @@ -47,16 +47,16 @@ func FromDownloadRequest(allocationID string, req *http.Request) (*DownloadReque return dr, nil } -func (dr *DownloadRequest) Parse() error { +func (dr *DownloadRequestHeader) Parse() error { if dr.req == nil { return errors.Throw(common.ErrInvalidParameter, "req") } - pathHash := dr.Get("path_hash") - path := dr.Get("path") + pathHash := dr.Get("X-Path-Hash") + path := dr.Get("X-Path") if pathHash == "" { if path == "" { - return errors.Throw(common.ErrInvalidParameter, "path") + return errors.Throw(common.ErrInvalidParameter, "X-Path") } pathHash = reference.GetReferenceLookup(dr.allocationID, path) } @@ -64,52 +64,45 @@ func (dr *DownloadRequest) Parse() error { dr.PathHash = pathHash dr.Path = path - blockNum := dr.GetInt64("block_num", -1) + blockNum := dr.GetInt64("X-Block-Num", -1) if blockNum <= 0 { - return errors.Throw(common.ErrInvalidParameter, "block_num") + return errors.Throw(common.ErrInvalidParameter, "X-Block-Num") } dr.BlockNum = blockNum - numBlocks := dr.GetInt64("num_blocks", 1) + numBlocks := dr.GetInt64("X-Num-Blocks", 1) if numBlocks <= 0 { - return errors.Throw(common.ErrInvalidParameter, "num_blocks") + return errors.Throw(common.ErrInvalidParameter, "X-Num-Blocks") } dr.NumBlocks = numBlocks - readMarker := dr.Get("read_marker") + readMarker := dr.Get("X-Read-Marker") if readMarker == "" { - return errors.Throw(common.ErrInvalidParameter, "read_marker") + return errors.Throw(common.ErrInvalidParameter, "X-Read-Marker") } err := json.Unmarshal([]byte(readMarker), &dr.ReadMarker) if err != nil { - return errors.Throw(common.ErrInvalidParameter, "read_marker") + return errors.Throw(common.ErrInvalidParameter, "X-Read-Marker") } - dr.AuthToken = dr.Get("auth_token") + dr.AuthToken = dr.Get("X-Auth-Token") - dr.RxPay = dr.Get("rx_pay") == "true" - dr.DownloadMode = dr.Get("content") + dr.RxPay = dr.Get("X-Rxpay") == "true" + dr.DownloadMode = dr.Get("X-Mode") return nil } -func (dr *DownloadRequest) Get(key string) string { +func (dr *DownloadRequestHeader) Get(key string) string { if dr.req == nil { return "" } - v := dr.req.Header.Get(key) - - if v == "" { - v = dr.req.FormValue(key) - } - - return v - + return dr.req.Header.Get(key) } -func (dr *DownloadRequest) GetInt64(key string, defaultValue int64) int64 { +func (dr *DownloadRequestHeader) GetInt64(key string, defaultValue int64) int64 { v := dr.Get(key) i, err := strconv.ParseInt(v, 10, 64) if err != nil { From 5b1cc62f65dca0571ab3c6d39c723ef8270545c3 Mon Sep 17 00:00:00 2001 From: Lz Date: Mon, 28 Feb 2022 00:01:23 +0800 Subject: [PATCH 12/12] fix(download): fixed tests --- .../0chain.net/blobbercore/convert/convert.go | 16 +++--- .../handler/handler_download_test.go | 52 +++++++++---------- .../handler/object_operation_handler_test.go | 16 +++--- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/code/go/0chain.net/blobbercore/convert/convert.go b/code/go/0chain.net/blobbercore/convert/convert.go index 7766e766f..0db96ed93 100644 --- a/code/go/0chain.net/blobbercore/convert/convert.go +++ b/code/go/0chain.net/blobbercore/convert/convert.go @@ -488,13 +488,13 @@ func DownloadFileGRPCToHTTP(req *blobbergrpc.DownloadFileRequest) (*http.Request return nil, err } - r.Header.Set("path", req.Path) - r.Header.Set("path_hash", req.PathHash) - r.Header.Set("rx_pay", req.RxPay) - r.Header.Set("block_num", req.BlockNum) - r.Header.Set("num_blocks", req.NumBlocks) - r.Header.Set("read_marker", req.ReadMarker) - r.Header.Set("auth_token", req.AuthToken) - r.Header.Set("content", req.Content) + r.Header.Set("X-Path", req.Path) + r.Header.Set("X-Path-Hash", req.PathHash) + r.Header.Set("X-Rxpay", req.RxPay) + r.Header.Set("X-Block-Num", req.BlockNum) + r.Header.Set("X-Num-Blocks", req.NumBlocks) + r.Header.Set("X-Read-Marker", req.ReadMarker) + r.Header.Set("X-Auth-Token", req.AuthToken) + r.Header.Set("X-Mode", req.Content) return r, nil } diff --git a/code/go/0chain.net/blobbercore/handler/handler_download_test.go b/code/go/0chain.net/blobbercore/handler/handler_download_test.go index 88fa003c9..1fe163206 100644 --- a/code/go/0chain.net/blobbercore/handler/handler_download_test.go +++ b/code/go/0chain.net/blobbercore/handler/handler_download_test.go @@ -238,9 +238,9 @@ func TestHandlers_Download_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("read_marker", string(rmData)) + r.Header.Set("X-Path-Hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) + r.Header.Set("X-Block-Num", fmt.Sprintf("%d", 1)) + r.Header.Set("X-Read-Marker", string(rmData)) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, alloc.OwnerID) r.Header.Set(common.ClientKeyHeader, alloc.OwnerPublicKey) @@ -317,9 +317,9 @@ func TestHandlers_Download_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("path_hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("read_marker", string(rmData)) + r.Header.Set("X-Path-Hash", fileref.GetReferenceLookup(alloc.Tx, remotePath)) + r.Header.Set("X-Block-Num", fmt.Sprintf("%d", 1)) + r.Header.Set("X-Read-Marker", string(rmData)) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, alloc.OwnerID) r.Header.Set(common.ClientKeyHeader, alloc.OwnerPublicKey) @@ -424,10 +424,10 @@ func TestHandlers_Download_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("read_marker", string(rmData)) - r.Header.Set("path_hash", pathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) + r.Header.Set("X-Read-Marker", string(rmData)) + r.Header.Set("X-Path-Hash", pathHash) + r.Header.Set("X-Block-Num", fmt.Sprintf("%d", 1)) + r.Header.Set("X-Auth-Token", authTicket) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) @@ -536,10 +536,10 @@ func TestHandlers_Download_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("read_marker", string(rmData)) - r.Header.Set("path_hash", pathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) + r.Header.Set("X-Read-Marker", string(rmData)) + r.Header.Set("X-Path-Hash", pathHash) + r.Header.Set("X-Block-Num", fmt.Sprintf("%d", 1)) + r.Header.Set("X-Auth-Token", authTicket) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) @@ -679,10 +679,10 @@ func TestHandlers_Download_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("path_hash", filePathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) - r.Header.Set("read_marker", string(rmData)) + r.Header.Set("X-Path-Hash", filePathHash) + r.Header.Set("X-Block-Num", fmt.Sprintf("%d", 1)) + r.Header.Set("X-Auth-Token", authTicket) + r.Header.Set("X-Read-Marker", string(rmData)) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) @@ -825,10 +825,10 @@ func TestHandlers_Download_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("path_hash", filePathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) - r.Header.Set("read_marker", string(rmData)) + r.Header.Set("X-Path-Hash", filePathHash) + r.Header.Set("X-Block-Num", fmt.Sprintf("%d", 1)) + r.Header.Set("X-Auth-Token", authTicket) + r.Header.Set("X-Read-Marker", string(rmData)) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) @@ -971,10 +971,10 @@ func TestHandlers_Download_Requiring_Signature(t *testing.T) { t.Fatal(err) } - r.Header.Set("read_marker", string(rmData)) - r.Header.Set("path_hash", filePathHash) - r.Header.Set("block_num", fmt.Sprintf("%d", 1)) - r.Header.Set("auth_token", authTicket) + r.Header.Set("X-Read-Marker", string(rmData)) + r.Header.Set("X-Path-Hash", filePathHash) + r.Header.Set("X-Block-Num", fmt.Sprintf("%d", 1)) + r.Header.Set("X-Auth-Token", authTicket) r.Header.Set(common.ClientSignatureHeader, sign) r.Header.Set(common.ClientHeader, guestClient.ClientID) r.Header.Set(common.ClientKeyHeader, guestClient.ClientKey) diff --git a/code/go/0chain.net/blobbercore/handler/object_operation_handler_test.go b/code/go/0chain.net/blobbercore/handler/object_operation_handler_test.go index 467cbd915..99b09f632 100644 --- a/code/go/0chain.net/blobbercore/handler/object_operation_handler_test.go +++ b/code/go/0chain.net/blobbercore/handler/object_operation_handler_test.go @@ -124,14 +124,14 @@ func TestDownloadFile(t *testing.T) { require.NoError(t, err) rmData, err := json.Marshal(rm) require.NoError(t, err) - req.Header.Set("path_hash", p.inData.pathHash) - req.Header.Set("path", p.inData.remotefilepath) + req.Header.Set("X-Path-Hash", p.inData.pathHash) + req.Header.Set("X-Path", p.inData.remotefilepath) if p.inData.rxPay { - req.Header.Set("rx_pay", "true") + req.Header.Set("X-Rxpay", "true") } - req.Header.Set("block_num", fmt.Sprintf("%d", p.inData.blockNum)) - req.Header.Set("num_blocks", fmt.Sprintf("%d", p.inData.numBlocks)) - req.Header.Set("read_marker", string(rmData)) + req.Header.Set("X-Block-Num", fmt.Sprintf("%d", p.inData.blockNum)) + req.Header.Set("X-Num-Blocks", fmt.Sprintf("%d", p.inData.numBlocks)) + req.Header.Set("X-Read-Marker", string(rmData)) if p.useAuthTicket { authTicket := &marker.AuthTicket{ AllocationID: p.inData.allocationID, @@ -145,10 +145,10 @@ func TestDownloadFile(t *testing.T) { require.NoError(t, authTicket.Sign()) require.NoError(t, client.PopulateClient(mockClientWallet, "bls0chain")) authTicketBytes, _ := json.Marshal(authTicket) - req.Header.Set("auth_token", string(authTicketBytes)) + req.Header.Set("X-Auth-Token", string(authTicketBytes)) } if len(p.inData.contentMode) > 0 { - req.Header.Set("content", p.inData.contentMode) + req.Header.Set("X-Mode", p.inData.contentMode) } return rm }