github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/sys/it/impl_blob_test.go (about)

     1  /*
     2   * Copyright (c) 2022-present unTill Pro, Ltd.
     3   */
     4  
     5  package sys_it
     6  
     7  import (
     8  	"fmt"
     9  	"log"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/voedger/voedger/pkg/istructs"
    15  	payloads "github.com/voedger/voedger/pkg/itokens-payloads"
    16  	coreutils "github.com/voedger/voedger/pkg/utils"
    17  	it "github.com/voedger/voedger/pkg/vit"
    18  )
    19  
    20  func TestBasicUsage_BLOBProcessors(t *testing.T) {
    21  	require := require.New(t)
    22  	vit := it.NewVIT(t, &it.SharedConfig_App1)
    23  	defer vit.TearDown()
    24  
    25  	as, err := vit.AppStructs(istructs.AppQName_test1_app1)
    26  	require.NoError(err)
    27  	systemPrincipal, err := payloads.GetSystemPrincipalTokenApp(as.AppTokens())
    28  	require.NoError(err)
    29  
    30  	expBLOB := []byte{1, 2, 3, 4, 5}
    31  
    32  	ws := vit.WS(istructs.AppQName_test1_app1, "test_ws")
    33  
    34  	// write
    35  	blobID := vit.UploadBLOB(istructs.AppQName_test1_app1, ws.WSID, "test", coreutils.ApplicationXBinary, expBLOB,
    36  		coreutils.WithAuthorizeBy(systemPrincipal),
    37  		coreutils.WithHeaders("Content-Type", "application/x-www-form-urlencoded"), // has name+mimeType query params -> any Content-Type except "multipart/form-data" is allowed
    38  	)
    39  	log.Println(blobID)
    40  
    41  	// read, authorize over headers
    42  	resp := vit.ReadBLOB(istructs.AppQName_test1_app1, ws.WSID, blobID,
    43  		coreutils.WithAuthorizeBy(systemPrincipal),
    44  	)
    45  	actBLOB := []byte(resp.Body)
    46  	require.Equal("application/x-binary", resp.HTTPResp.Header["Content-Type"][0])
    47  	require.Equal(`attachment;filename="test"`, resp.HTTPResp.Header["Content-Disposition"][0])
    48  	require.Equal(expBLOB, actBLOB)
    49  
    50  	// read, authorize over unescaped cookies
    51  	resp = vit.ReadBLOB(istructs.AppQName_test1_app1, ws.WSID, blobID,
    52  		coreutils.WithCookies(coreutils.Authorization, "Bearer "+systemPrincipal),
    53  	)
    54  	actBLOB = []byte(resp.Body)
    55  	require.Equal("application/x-binary", resp.HTTPResp.Header["Content-Type"][0])
    56  	require.Equal(`attachment;filename="test"`, resp.HTTPResp.Header["Content-Disposition"][0])
    57  	require.Equal(expBLOB, actBLOB)
    58  
    59  	// read, authorize over escaped cookies
    60  	resp = vit.ReadBLOB(istructs.AppQName_test1_app1, ws.WSID, blobID,
    61  		coreutils.WithCookies(coreutils.Authorization, "Bearer%20"+systemPrincipal),
    62  	)
    63  	actBLOB = []byte(resp.Body)
    64  	require.Equal("application/x-binary", resp.HTTPResp.Header["Content-Type"][0])
    65  	require.Equal(`attachment;filename="test"`, resp.HTTPResp.Header["Content-Disposition"][0])
    66  	require.Equal(expBLOB, actBLOB)
    67  
    68  	// read, POST
    69  	resp = vit.ReadBLOB(istructs.AppQName_test1_app1, ws.WSID, blobID,
    70  		coreutils.WithAuthorizeBy(systemPrincipal),
    71  	)
    72  	actBLOB = []byte(resp.Body)
    73  	require.Equal("application/x-binary", resp.HTTPResp.Header["Content-Type"][0])
    74  	require.Equal(`attachment;filename="test"`, resp.HTTPResp.Header["Content-Disposition"][0])
    75  	require.Equal(expBLOB, actBLOB)
    76  
    77  }
    78  
    79  func TestBlobberErrors(t *testing.T) {
    80  	require := require.New(t)
    81  	vit := it.NewVIT(t, &it.SharedConfig_App1)
    82  	defer vit.TearDown()
    83  
    84  	ws := vit.WS(istructs.AppQName_test1_app1, "test_ws")
    85  
    86  	as, err := vit.AppStructs(istructs.AppQName_test1_app1)
    87  	require.NoError(err)
    88  	systemPrincipal, err := payloads.GetSystemPrincipalTokenApp(as.AppTokens())
    89  	require.NoError(err)
    90  
    91  	t.Run("401 unauthorized on no authorization token in neither headers nor cookies", func(t *testing.T) {
    92  		vit.UploadBLOB(istructs.AppQName_test1_app1, ws.WSID, "test", coreutils.ApplicationXBinary, []byte{},
    93  			coreutils.Expect401(),
    94  		)
    95  	})
    96  
    97  	t.Run("403 forbidden on blob size quota exceeded", func(t *testing.T) {
    98  		bigBLOB := make([]byte, 150)
    99  		vit.UploadBLOB(istructs.AppQName_test1_app1, ws.WSID, "test", coreutils.ApplicationXBinary, bigBLOB,
   100  			coreutils.WithAuthorizeBy(systemPrincipal),
   101  			coreutils.Expect403(),
   102  		)
   103  	})
   104  
   105  	t.Run("404 not found on querying an unexsting blob", func(t *testing.T) {
   106  		vit.ReadBLOB(istructs.AppQName_test1_app1, ws.WSID, 1,
   107  			coreutils.WithAuthorizeBy(systemPrincipal),
   108  			coreutils.Expect404(),
   109  		).Println()
   110  	})
   111  
   112  	t.Run("400 on wrong Content-Type and name+mimeType query params", func(t *testing.T) {
   113  		t.Run("neither Content-Type nor name+mimeType query params are not provided", func(t *testing.T) {
   114  			vit.POST(fmt.Sprintf(`blob/test1/app1/%d`, ws.WSID), "blobContent",
   115  				coreutils.WithAuthorizeBy(systemPrincipal),
   116  				coreutils.Expect400(),
   117  			).Println()
   118  		})
   119  		t.Run("no name+mimeType query params and non-(mutipart/form-data) Content-Type", func(t *testing.T) {
   120  			vit.POST(fmt.Sprintf(`blob/test1/app1/%d`, ws.WSID), "blobContent",
   121  				coreutils.WithAuthorizeBy(systemPrincipal),
   122  				coreutils.WithHeaders("Content-Type", "application/x-www-form-urlencoded"),
   123  				coreutils.Expect400(),
   124  			).Println()
   125  		})
   126  		t.Run("both name+mimeType query params and Conten-Type are specified", func(t *testing.T) {
   127  			vit.POST(fmt.Sprintf(`blob/test1/app1/%d?name=test&mimeType=application/x-binary`, ws.WSID), "blobContent",
   128  				coreutils.WithAuthorizeBy(systemPrincipal),
   129  				coreutils.WithHeaders("Content-Type", "multipart/form-data"),
   130  				coreutils.Expect400(),
   131  			).Println()
   132  		})
   133  		t.Run("boundary of multipart/form-data is not specified", func(t *testing.T) {
   134  			vit.POST(fmt.Sprintf(`blob/test1/app1/%d`, ws.WSID), "blobContent",
   135  				coreutils.WithAuthorizeBy(systemPrincipal),
   136  				coreutils.WithHeaders("Content-Type", "multipart/form-data"),
   137  				coreutils.Expect400(),
   138  			).Println()
   139  		})
   140  	})
   141  }
   142  
   143  func TestBlobMultipartUpload(t *testing.T) {
   144  	require := require.New(t)
   145  	vit := it.NewVIT(t, &it.SharedConfig_App1)
   146  	defer vit.TearDown()
   147  
   148  	ws := vit.WS(istructs.AppQName_test1_app1, "test_ws")
   149  
   150  	blobs := []coreutils.BLOB{
   151  		{
   152  			Content: []byte{1, 2, 3, 4, 5},
   153  			Name:    "blob1",
   154  		},
   155  		{
   156  			Content: []byte{6, 7, 8, 9, 10},
   157  			Name:    "blob2",
   158  		},
   159  	}
   160  
   161  	as, err := vit.AppStructs(istructs.AppQName_test1_app1)
   162  	require.NoError(err)
   163  	systemPrincipalToken, err := payloads.GetSystemPrincipalTokenApp(as.AppTokens())
   164  	require.NoError(err)
   165  	blobIDs := vit.UploadBLOBs(istructs.AppQName_test1_app1, ws.WSID, blobs,
   166  		coreutils.WithAuthorizeBy(systemPrincipalToken))
   167  
   168  	// read blob1
   169  	actualBLOB1 := vit.GetBLOB(istructs.AppQName_test1_app1, ws.WSID, blobIDs[0], systemPrincipalToken)
   170  	require.Equal("application/x-binary", actualBLOB1.MimeType)
   171  	require.Equal(`blob1`, actualBLOB1.Name)
   172  	require.Equal(blobs[0].Content, actualBLOB1.Content)
   173  
   174  	// read blob2
   175  	actualBLOB2 := vit.GetBLOB(istructs.AppQName_test1_app1, ws.WSID, blobIDs[1], systemPrincipalToken)
   176  	require.Equal("application/x-binary", actualBLOB2.MimeType)
   177  	require.Equal(`blob2`, actualBLOB2.Name)
   178  	require.Equal(blobs[1].Content, actualBLOB2.Content)
   179  }