From 5529fb914e2e49f1cc01a6fe237a38f3474bb0ce Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Tue, 31 May 2022 10:55:57 +0300 Subject: [PATCH] [#452] Fix lock tests Signed-off-by: Denis Kirillov --- api/handler/locking.go | 26 +++++-------- api/handler/locking_test.go | 76 +++++++++---------------------------- 2 files changed, 27 insertions(+), 75 deletions(-) diff --git a/api/handler/locking.go b/api/handler/locking.go index a7eba03a..c9c31ce0 100644 --- a/api/handler/locking.go +++ b/api/handler/locking.go @@ -221,22 +221,6 @@ func (h *handler) PutObjectRetentionHandler(w http.ResponseWriter, r *http.Reque } } -func checkLockInfo(lock *data.ObjectInfo, header http.Header) error { - if lock == nil { - return nil - } - - if lock.Headers[layer.AttributeComplianceMode] != "" { - return fmt.Errorf("it's forbidden to change compliance lock mode") - } - - if bypass, err := strconv.ParseBool(header.Get(api.AmzBypassGovernanceRetention)); err != nil || !bypass { - return fmt.Errorf("cannot bypass governance mode") - } - - return nil -} - func (h *handler) GetObjectRetentionHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) @@ -358,6 +342,16 @@ func formObjectLock(bktInfo *data.BucketInfo, defaultConfig *data.ObjectLockConf objectLock.Retention.Until = retentionDate } + if objectLock.Retention != nil { + if bypassStr := header.Get(api.AmzBypassGovernanceRetention); len(bypassStr) > 0 { + bypass, err := strconv.ParseBool(bypassStr) + if err != nil { + return nil, fmt.Errorf("couldn't parse bypass governance header: %w", err) + } + objectLock.Retention.ByPassedGovernance = bypass + } + } + return objectLock, nil } diff --git a/api/handler/locking_test.go b/api/handler/locking_test.go index d5576a12..752e9369 100644 --- a/api/handler/locking_test.go +++ b/api/handler/locking_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/xml" + "io" "net/http" "net/http/httptest" "strconv" @@ -13,7 +14,6 @@ import ( "github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api/data" apiErrors "github.com/nspcc-dev/neofs-s3-gw/api/errors" - "github.com/nspcc-dev/neofs-s3-gw/api/layer" "github.com/stretchr/testify/require" ) @@ -153,57 +153,6 @@ func assertObjectLocks(t *testing.T, expected, actual *data.ObjectLock) { } } -func TestCheckLockObject(t *testing.T) { - for _, tc := range []struct { - name string - isCompliance bool - header http.Header - expectedError bool - }{ - { - name: "error governance bypass", - header: map[string][]string{ - api.AmzBypassGovernanceRetention: {strconv.FormatBool(false)}, - }, - expectedError: true, - }, - { - name: "error invalid governance bypass", - header: map[string][]string{ - api.AmzBypassGovernanceRetention: {"t r u e"}, - }, - expectedError: true, - }, - { - name: "error failed change compliance mode", - isCompliance: true, - expectedError: true, - }, - { - name: "valid", - header: map[string][]string{ - api.AmzBypassGovernanceRetention: {strconv.FormatBool(true)}, - }, - }, - } { - t.Run(tc.name, func(t *testing.T) { - header := make(map[string]string) - if tc.isCompliance { - header[layer.AttributeComplianceMode] = strconv.FormatBool(true) - } - - lockInfo := &data.ObjectInfo{Headers: header} - err := checkLockInfo(lockInfo, tc.header) - if tc.expectedError { - require.Error(t, err) - return - } - - require.NoError(t, err) - }) - } -} - func TestLockConfiguration(t *testing.T) { for _, tc := range []struct { name string @@ -530,25 +479,25 @@ func TestObjectRetention(t *testing.T) { hc.Handler().GetObjectRetentionHandler(w, r) assertS3Error(t, w, apiErrors.GetAPIError(apiErrors.ErrNoSuchKey)) - retention := &data.Retention{Mode: governanceMode, RetainUntilDate: time.Now().Format(time.RFC3339)} + retention := &data.Retention{Mode: governanceMode, RetainUntilDate: time.Now().UTC().Format(time.RFC3339)} w, r = prepareTestRequest(t, bktName, objName, retention) hc.Handler().PutObjectRetentionHandler(w, r) - require.Equal(t, http.StatusOK, w.Code) + assertStatus(t, w, http.StatusOK) w, r = prepareTestRequest(t, bktName, objName, nil) hc.Handler().GetObjectRetentionHandler(w, r) assertRetention(t, w, retention) - retention = &data.Retention{Mode: governanceMode, RetainUntilDate: time.Now().Format(time.RFC3339)} + retention = &data.Retention{Mode: governanceMode, RetainUntilDate: time.Now().UTC().Format(time.RFC3339)} w, r = prepareTestRequest(t, bktName, objName, retention) hc.Handler().PutObjectRetentionHandler(w, r) assertS3Error(t, w, apiErrors.GetAPIError(apiErrors.ErrInternalError)) - retention = &data.Retention{Mode: complianceMode, RetainUntilDate: time.Now().Format(time.RFC3339)} + retention = &data.Retention{Mode: complianceMode, RetainUntilDate: time.Now().UTC().Format(time.RFC3339)} w, r = prepareTestRequest(t, bktName, objName, retention) r.Header.Set(api.AmzBypassGovernanceRetention, strconv.FormatBool(true)) hc.Handler().PutObjectRetentionHandler(w, r) - require.Equal(t, http.StatusOK, w.Code) + assertStatus(t, w, http.StatusOK) w, r = prepareTestRequest(t, bktName, objName, nil) hc.Handler().GetObjectRetentionHandler(w, r) @@ -589,7 +538,7 @@ func TestPutObjectWithLock(t *testing.T) { w, r := prepareTestRequest(t, bktName, objDefault, nil) hc.Handler().PutObjectHandler(w, r) - require.Equal(t, http.StatusOK, w.Code) + assertStatus(t, w, http.StatusOK) w, r = prepareTestRequest(t, bktName, objDefault, nil) hc.Handler().GetObjectRetentionHandler(w, r) @@ -607,9 +556,10 @@ func TestPutObjectWithLock(t *testing.T) { w, r = prepareTestRequest(t, bktName, objOverride, nil) r.Header.Set(api.AmzObjectLockMode, complianceMode) r.Header.Set(api.AmzObjectLockLegalHold, legalHoldOn) + r.Header.Set(api.AmzBypassGovernanceRetention, "true") r.Header.Set(api.AmzObjectLockRetainUntilDate, time.Now().Add(2*24*time.Hour).Format(time.RFC3339)) hc.Handler().PutObjectHandler(w, r) - require.Equal(t, http.StatusOK, w.Code) + assertStatus(t, w, http.StatusOK) w, r = prepareTestRequest(t, bktName, objOverride, nil) hc.Handler().GetObjectRetentionHandler(w, r) @@ -639,3 +589,11 @@ func assertRetentionApproximate(t *testing.T, w *httptest.ResponseRecorder, rete require.InDelta(t, expectedUntil.Unix(), actualUntil.Unix(), delta) } + +func assertStatus(t *testing.T, w *httptest.ResponseRecorder, status int) { + if w.Code != status { + resp, err := io.ReadAll(w.Result().Body) + require.NoError(t, err) + require.Fail(t, string(resp)) + } +}