diff --git a/api/handler/acl_test.go b/api/handler/acl_test.go index 1818936..40f17ba 100644 --- a/api/handler/acl_test.go +++ b/api/handler/acl_test.go @@ -1349,7 +1349,7 @@ func createAccessBox(t *testing.T) *accessbox.Box { } func createBucket(t *testing.T, tc *handlerContext, bktName string, box *accessbox.Box) *data.BucketInfo { - w, r := prepareTestRequest(t, bktName, "", nil) + w, r := prepareTestRequest(tc, bktName, "", nil) ctx := context.WithValue(r.Context(), api.BoxData, box) r = r.WithContext(ctx) tc.Handler().CreateBucketHandler(w, r) @@ -1361,7 +1361,7 @@ func createBucket(t *testing.T, tc *handlerContext, bktName string, box *accessb } func putBucketACL(t *testing.T, tc *handlerContext, bktName string, box *accessbox.Box, header map[string]string) { - w, r := prepareTestRequest(t, bktName, "", nil) + w, r := prepareTestRequest(tc, bktName, "", nil) for key, val := range header { r.Header.Set(key, val) } diff --git a/api/handler/atttributes_test.go b/api/handler/atttributes_test.go index 67a72ce..0678053 100644 --- a/api/handler/atttributes_test.go +++ b/api/handler/atttributes_test.go @@ -2,7 +2,6 @@ package handler import ( "bytes" - "context" "net/http" "net/url" "testing" @@ -13,33 +12,32 @@ import ( ) func TestGetObjectPartsAttributes(t *testing.T) { - ctx := context.Background() hc := prepareHandlerContext(t) bktName := "bucket-get-attributes" objName, objMultipartName := "object", "object-multipart" - createTestBucket(ctx, t, hc, bktName) + createTestBucket(hc, bktName) body := bytes.NewReader([]byte("content")) - w, r := prepareTestPayloadRequest(bktName, objName, body) + w, r := prepareTestPayloadRequest(hc, bktName, objName, body) hc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) + w, r = prepareTestRequest(hc, bktName, objName, nil) r.Header.Set(api.AmzObjectAttributes, objectParts) hc.Handler().GetObjectAttributesHandler(w, r) result := &GetObjectAttributesResponse{} parseTestResponse(t, w, result) require.Nil(t, result.ObjectParts) - w, r = prepareTestRequest(t, bktName, objMultipartName, nil) + w, r = prepareTestRequest(hc, bktName, objMultipartName, nil) hc.Handler().CreateMultipartUploadHandler(w, r) multipartUpload := &InitiateMultipartUploadResponse{} parseTestResponse(t, w, multipartUpload) body2 := bytes.NewReader([]byte("content2")) - w, r = prepareTestPayloadRequest(bktName, objMultipartName, body2) + w, r = prepareTestPayloadRequest(hc, bktName, objMultipartName, body2) query := make(url.Values) query.Add(uploadIDHeaderName, multipartUpload.UploadID) query.Add(partNumberHeaderName, "1") @@ -54,14 +52,14 @@ func TestGetObjectPartsAttributes(t *testing.T) { PartNumber: 1, }}, } - w, r = prepareTestRequest(t, bktName, objMultipartName, completeUpload) + w, r = prepareTestRequest(hc, bktName, objMultipartName, completeUpload) query = make(url.Values) query.Add(uploadIDHeaderName, multipartUpload.UploadID) r.URL.RawQuery = query.Encode() hc.Handler().CompleteMultipartUploadHandler(w, r) assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objMultipartName, nil) + w, r = prepareTestRequest(hc, bktName, objMultipartName, nil) r.Header.Set(api.AmzObjectAttributes, objectParts) hc.Handler().GetObjectAttributesHandler(w, r) result = &GetObjectAttributesResponse{} diff --git a/api/handler/copy_test.go b/api/handler/copy_test.go index 316d360..1d5cba7 100644 --- a/api/handler/copy_test.go +++ b/api/handler/copy_test.go @@ -22,7 +22,7 @@ func TestCopyWithTaggingDirective(t *testing.T) { bktName, objName := "bucket-for-copy", "object-from-copy" objToCopy, objToCopy2 := "object-to-copy", "object-to-copy-2" - createBucketAndObject(t, tc, bktName, objName) + createBucketAndObject(tc, bktName, objName) putObjectTagging(t, tc, bktName, objName, map[string]string{"key": "val"}) @@ -47,7 +47,7 @@ func TestCopyToItself(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-copy", "object-for-copy" - createBucketAndObject(t, tc, bktName, objName) + createBucketAndObject(tc, bktName, objName) copyMeta := CopyMeta{MetadataDirective: replaceDirective} @@ -64,7 +64,7 @@ func TestCopyToItself(t *testing.T) { } func copyObject(t *testing.T, tc *handlerContext, bktName, fromObject, toObject string, copyMeta CopyMeta, statusCode int) { - w, r := prepareTestRequest(t, bktName, toObject, nil) + w, r := prepareTestRequest(tc, bktName, toObject, nil) r.Header.Set(api.AmzCopySource, bktName+"/"+fromObject) r.Header.Set(api.AmzMetadataDirective, copyMeta.MetadataDirective) @@ -95,7 +95,7 @@ func putObjectTagging(t *testing.T, tc *handlerContext, bktName, objName string, }) } - w, r := prepareTestRequest(t, bktName, objName, body) + w, r := prepareTestRequest(tc, bktName, objName, body) tc.Handler().PutObjectTaggingHandler(w, r) assertStatus(t, w, http.StatusOK) } @@ -104,7 +104,7 @@ func getObjectTagging(t *testing.T, tc *handlerContext, bktName, objName, versio query := make(url.Values) query.Add(api.QueryVersionID, version) - w, r := prepareTestFullRequest(t, bktName, objName, query, nil) + w, r := prepareTestFullRequest(tc, bktName, objName, query, nil) tc.Handler().GetObjectTaggingHandler(w, r) assertStatus(t, w, http.StatusOK) diff --git a/api/handler/delete_test.go b/api/handler/delete_test.go index 386b8d3..8c1b993 100644 --- a/api/handler/delete_test.go +++ b/api/handler/delete_test.go @@ -35,7 +35,7 @@ func TestDeleteObject(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-removal", "object-to-delete" - bktInfo, objInfo := createBucketAndObject(t, tc, bktName, objName) + bktInfo, objInfo := createBucketAndObject(tc, bktName, objName) checkFound(t, tc, bktName, objName, emptyVersion) deleteObject(t, tc, bktName, objName, emptyVersion) @@ -61,7 +61,7 @@ func TestDeleteDeletedObject(t *testing.T) { t.Run("unversioned bucket", func(t *testing.T) { bktName, objName := "bucket-unversioned-removal", "object-to-delete" - createBucketAndObject(t, tc, bktName, objName) + createBucketAndObject(tc, bktName, objName) versionID, isDeleteMarker := deleteObject(t, tc, bktName, objName, emptyVersion) require.Empty(t, versionID) @@ -116,7 +116,7 @@ func TestDeleteObjectUnversioned(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-removal-unversioned", "object-to-delete-unversioned" - bktInfo, objInfo := createBucketAndObject(t, tc, bktName, objName) + bktInfo, objInfo := createBucketAndObject(tc, bktName, objName) checkFound(t, tc, bktName, objName, emptyVersion) deleteObject(t, tc, bktName, objName, emptyVersion) @@ -151,7 +151,7 @@ func TestDeleteObjectCombined(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-removal", "object-to-delete" - bktInfo, objInfo := createBucketAndObject(t, tc, bktName, objName) + bktInfo, objInfo := createBucketAndObject(tc, bktName, objName) putBucketVersioning(t, tc, bktName, true) @@ -168,7 +168,7 @@ func TestDeleteObjectSuspended(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-removal", "object-to-delete" - bktInfo, objInfo := createBucketAndObject(t, tc, bktName, objName) + bktInfo, objInfo := createBucketAndObject(tc, bktName, objName) putBucketVersioning(t, tc, bktName, true) @@ -188,7 +188,7 @@ func TestDeleteMarkers(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-removal", "object-to-delete" - createTestBucket(tc.Context(), t, tc, bktName) + createTestBucket(tc, bktName) putBucketVersioning(t, tc, bktName, true) checkNotFound(t, tc, bktName, objName, emptyVersion) @@ -243,21 +243,21 @@ func TestDeleteObjectCheckMarkerReturn(t *testing.T) { require.Equal(t, deleteMarkerVersion, deleteMarkerVersion2) } -func createBucketAndObject(t *testing.T, tc *handlerContext, bktName, objName string) (*data.BucketInfo, *data.ObjectInfo) { - bktInfo := createTestBucket(tc.Context(), t, tc, bktName) +func createBucketAndObject(tc *handlerContext, bktName, objName string) (*data.BucketInfo, *data.ObjectInfo) { + bktInfo := createTestBucket(tc, bktName) - objInfo := createTestObject(tc.Context(), t, tc, bktInfo, objName) + objInfo := createTestObject(tc, bktInfo, objName) return bktInfo, objInfo } func createVersionedBucketAndObject(t *testing.T, tc *handlerContext, bktName, objName string) (*data.BucketInfo, *data.ObjectInfo) { - createTestBucket(tc.Context(), t, tc, bktName) + createTestBucket(tc, bktName) bktInfo, err := tc.Layer().GetBucketInfo(tc.Context(), bktName) require.NoError(t, err) putBucketVersioning(t, tc, bktName, true) - objInfo := createTestObject(tc.Context(), t, tc, bktInfo, objName) + objInfo := createTestObject(tc, bktInfo, objName) return bktInfo, objInfo } @@ -267,7 +267,7 @@ func putBucketVersioning(t *testing.T, tc *handlerContext, bktName string, enabl if enabled { cfg.Status = "Enabled" } - w, r := prepareTestRequest(t, bktName, "", cfg) + w, r := prepareTestRequest(tc, bktName, "", cfg) tc.Handler().PutBucketVersioningHandler(w, r) assertStatus(t, w, http.StatusOK) } @@ -276,7 +276,7 @@ func deleteObject(t *testing.T, tc *handlerContext, bktName, objName, version st query := make(url.Values) query.Add(api.QueryVersionID, version) - w, r := prepareTestFullRequest(t, bktName, objName, query, nil) + w, r := prepareTestFullRequest(tc, bktName, objName, query, nil) tc.Handler().DeleteObjectHandler(w, r) assertStatus(t, w, http.StatusNoContent) @@ -284,7 +284,7 @@ func deleteObject(t *testing.T, tc *handlerContext, bktName, objName, version st } func deleteBucket(t *testing.T, tc *handlerContext, bktName string, code int) { - w, r := prepareTestRequest(t, bktName, "", nil) + w, r := prepareTestRequest(tc, bktName, "", nil) tc.Handler().DeleteBucketHandler(w, r) assertStatus(t, w, code) } @@ -293,7 +293,7 @@ func checkNotFound(t *testing.T, tc *handlerContext, bktName, objName, version s query := make(url.Values) query.Add(api.QueryVersionID, version) - w, r := prepareTestFullRequest(t, bktName, objName, query, nil) + w, r := prepareTestFullRequest(tc, bktName, objName, query, nil) tc.Handler().HeadObjectHandler(w, r) assertStatus(t, w, http.StatusNotFound) } @@ -302,13 +302,13 @@ func checkFound(t *testing.T, tc *handlerContext, bktName, objName, version stri query := make(url.Values) query.Add(api.QueryVersionID, version) - w, r := prepareTestFullRequest(t, bktName, objName, query, nil) + w, r := prepareTestFullRequest(tc, bktName, objName, query, nil) tc.Handler().HeadObjectHandler(w, r) assertStatus(t, w, http.StatusOK) } func listVersions(t *testing.T, tc *handlerContext, bktName string) *ListObjectsVersionsResponse { - w, r := prepareTestRequest(t, bktName, "", nil) + w, r := prepareTestRequest(tc, bktName, "", nil) tc.Handler().ListBucketObjectVersionsHandler(w, r) assertStatus(t, w, http.StatusOK) res := &ListObjectsVersionsResponse{} @@ -318,13 +318,13 @@ func listVersions(t *testing.T, tc *handlerContext, bktName string) *ListObjects func putObject(t *testing.T, tc *handlerContext, bktName, objName string) { body := bytes.NewReader([]byte("content")) - w, r := prepareTestPayloadRequest(bktName, objName, body) + w, r := prepareTestPayloadRequest(tc, bktName, objName, body) tc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) } func createSuspendedBucket(t *testing.T, tc *handlerContext, bktName string) *data.BucketInfo { - createTestBucket(tc.Context(), t, tc, bktName) + createTestBucket(tc, bktName) bktInfo, err := tc.Layer().GetBucketInfo(tc.Context(), bktName) require.NoError(t, err) putBucketVersioning(t, tc, bktName, false) diff --git a/api/handler/encryption_test.go b/api/handler/encryption_test.go index 40cc1b9..1932c23 100644 --- a/api/handler/encryption_test.go +++ b/api/handler/encryption_test.go @@ -27,7 +27,7 @@ func TestSimpleGetEncrypted(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-sse-c", "object-to-encrypt" - bktInfo := createTestBucket(tc.Context(), t, tc, bktName) + bktInfo := createTestBucket(tc, bktName) content := "content" putEncryptedObject(t, tc, bktName, objName, content) @@ -48,7 +48,7 @@ func TestGetEncryptedRange(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-sse-c", "object-to-encrypt" - createTestBucket(tc.Context(), t, tc, bktName) + createTestBucket(tc, bktName) var sb strings.Builder for i := 0; i < 1<<16+11; i++ { @@ -89,7 +89,7 @@ func TestGetEncryptedRange(t *testing.T) { func TestS3EncryptionSSECMultipartUpload(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-sse-c-multipart-s3-tests", "multipart_enc" - createTestBucket(tc.Context(), t, tc, bktName) + createTestBucket(tc, bktName) objLen := 30 * 1024 * 1024 partSize := objLen / 6 @@ -168,7 +168,7 @@ func multipartUploadEncrypted(t *testing.T, tc *handlerContext, bktName, objName } func createMultipartUpload(t *testing.T, tc *handlerContext, bktName, objName string, headers map[string]string) *InitiateMultipartUploadResponse { - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(tc, bktName, objName, nil) setEncryptHeaders(r) setHeaders(r, headers) tc.Handler().CreateMultipartUploadHandler(w, r) @@ -190,7 +190,7 @@ func completeMultipartUpload(t *testing.T, tc *handlerContext, bktName, objName, }) } - w, r := prepareTestFullRequest(t, bktName, objName, query, complete) + w, r := prepareTestFullRequest(tc, bktName, objName, query, complete) tc.Handler().CompleteMultipartUploadHandler(w, r) assertStatus(t, w, http.StatusOK) } @@ -204,7 +204,7 @@ func uploadPart(t *testing.T, tc *handlerContext, bktName, objName, uploadID str query.Set(uploadIDQuery, uploadID) query.Set(partNumberQuery, strconv.Itoa(num)) - w, r := prepareTestRequestWithQuery(bktName, objName, query, partBody) + w, r := prepareTestRequestWithQuery(tc, bktName, objName, query, partBody) setEncryptHeaders(r) tc.Handler().UploadPartHandler(w, r) assertStatus(t, w, http.StatusOK) @@ -218,9 +218,9 @@ func TestMultipartEncrypted(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-sse-c-multipart", "object-to-encrypt-multipart" - createTestBucket(tc.Context(), t, tc, bktName) + createTestBucket(tc, bktName) - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(tc, bktName, objName, nil) setEncryptHeaders(r) tc.Handler().CreateMultipartUploadHandler(w, r) multipartInitInfo := &InitiateMultipartUploadResponse{} @@ -233,7 +233,7 @@ func TestMultipartEncrypted(t *testing.T) { query := make(url.Values) query.Set(uploadIDQuery, multipartInitInfo.UploadID) query.Set(partNumberQuery, "1") - w, r = prepareTestRequestWithQuery(bktName, objName, query, part1) + w, r = prepareTestRequestWithQuery(tc, bktName, objName, query, part1) setEncryptHeaders(r) tc.Handler().UploadPartHandler(w, r) assertStatus(t, w, http.StatusOK) @@ -243,7 +243,7 @@ func TestMultipartEncrypted(t *testing.T) { query = make(url.Values) query.Set(uploadIDQuery, multipartInitInfo.UploadID) query.Set(partNumberQuery, "2") - w, r = prepareTestRequestWithQuery(bktName, objName, query, part2) + w, r = prepareTestRequestWithQuery(tc, bktName, objName, query, part2) setEncryptHeaders(r) tc.Handler().UploadPartHandler(w, r) assertStatus(t, w, http.StatusOK) @@ -257,7 +257,7 @@ func TestMultipartEncrypted(t *testing.T) { {ETag: part2ETag, PartNumber: 2}, }, } - w, r = prepareTestFullRequest(t, bktName, objName, query, complete) + w, r = prepareTestFullRequest(tc, bktName, objName, query, complete) tc.Handler().CompleteMultipartUploadHandler(w, r) assertStatus(t, w, http.StatusOK) @@ -271,14 +271,14 @@ func TestMultipartEncrypted(t *testing.T) { func putEncryptedObject(t *testing.T, tc *handlerContext, bktName, objName, content string) { body := bytes.NewReader([]byte(content)) - w, r := prepareTestPayloadRequest(bktName, objName, body) + w, r := prepareTestPayloadRequest(tc, bktName, objName, body) setEncryptHeaders(r) tc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) } func getEncryptedObject(t *testing.T, tc *handlerContext, bktName, objName string) ([]byte, http.Header) { - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(tc, bktName, objName, nil) setEncryptHeaders(r) tc.Handler().GetObjectHandler(w, r) assertStatus(t, w, http.StatusOK) @@ -288,7 +288,7 @@ func getEncryptedObject(t *testing.T, tc *handlerContext, bktName, objName strin } func getEncryptedObjectRange(t *testing.T, tc *handlerContext, bktName, objName string, start, end int) []byte { - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(tc, bktName, objName, nil) setEncryptHeaders(r) r.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", start, end)) tc.Handler().GetObjectHandler(w, r) diff --git a/api/handler/get_test.go b/api/handler/get_test.go index ffe05d3..f439b24 100644 --- a/api/handler/get_test.go +++ b/api/handler/get_test.go @@ -152,7 +152,7 @@ func TestGetRange(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-range", "object-to-range" - createTestBucket(tc.Context(), t, tc, bktName) + createTestBucket(tc, bktName) content := "123456789abcdef" putObjectContent(t, tc, bktName, objName, content) @@ -172,13 +172,13 @@ func TestGetRange(t *testing.T) { func putObjectContent(t *testing.T, tc *handlerContext, bktName, objName, content string) { body := bytes.NewReader([]byte(content)) - w, r := prepareTestPayloadRequest(bktName, objName, body) + w, r := prepareTestPayloadRequest(tc, bktName, objName, body) tc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) } func getObjectRange(t *testing.T, tc *handlerContext, bktName, objName string, start, end int) []byte { - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(tc, bktName, objName, nil) r.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", start, end)) tc.Handler().GetObjectHandler(w, r) assertStatus(t, w, http.StatusPartialContent) diff --git a/api/handler/handlers_test.go b/api/handler/handlers_test.go index f6a53bd..afda347 100644 --- a/api/handler/handlers_test.go +++ b/api/handler/handlers_test.go @@ -22,12 +22,13 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/user" - usertest "github.com/nspcc-dev/neofs-sdk-go/user/test" "github.com/stretchr/testify/require" "go.uber.org/zap" ) type handlerContext struct { + owner user.ID + t *testing.T h *handler tp *layer.TestNeoFS context context.Context @@ -61,6 +62,9 @@ func prepareHandlerContext(t *testing.T) *handlerContext { return tp.ContainerID(name) }) + var owner user.ID + user.IDFromKey(&owner, key.PrivateKey.PublicKey) + layerCfg := &layer.Config{ Caches: layer.DefaultCachesConfigs(zap.NewExample()), AnonKey: layer.AnonymousKey{Key: key}, @@ -77,31 +81,33 @@ func prepareHandlerContext(t *testing.T) *handlerContext { } return &handlerContext{ + owner: owner, + t: t, h: h, tp: tp, - context: context.Background(), + context: context.WithValue(context.Background(), api.BoxData, newTestAccessBox(t, key)), } } -func createTestBucket(ctx context.Context, t *testing.T, h *handlerContext, bktName string) *data.BucketInfo { - _, err := h.MockedPool().CreateContainer(ctx, layer.PrmContainerCreate{ - Creator: *usertest.ID(), +func createTestBucket(hc *handlerContext, bktName string) *data.BucketInfo { + _, err := hc.MockedPool().CreateContainer(hc.Context(), layer.PrmContainerCreate{ + Creator: hc.owner, Name: bktName, }) - require.NoError(t, err) + require.NoError(hc.t, err) - bktInfo, err := h.Layer().GetBucketInfo(ctx, bktName) - require.NoError(t, err) + bktInfo, err := hc.Layer().GetBucketInfo(hc.Context(), bktName) + require.NoError(hc.t, err) return bktInfo } -func createTestBucketWithLock(ctx context.Context, t *testing.T, h *handlerContext, bktName string, conf *data.ObjectLockConfiguration) *data.BucketInfo { - cnrID, err := h.MockedPool().CreateContainer(ctx, layer.PrmContainerCreate{ - Creator: *usertest.ID(), +func createTestBucketWithLock(hc *handlerContext, bktName string, conf *data.ObjectLockConfiguration) *data.BucketInfo { + cnrID, err := hc.MockedPool().CreateContainer(hc.Context(), layer.PrmContainerCreate{ + Creator: hc.owner, Name: bktName, AdditionalAttributes: [][2]string{{layer.AttributeLockEnabled, "true"}}, }) - require.NoError(t, err) + require.NoError(hc.t, err) var ownerID user.ID @@ -120,61 +126,61 @@ func createTestBucketWithLock(ctx context.Context, t *testing.T, h *handlerConte }, } - err = h.Layer().PutBucketSettings(ctx, sp) - require.NoError(t, err) + err = hc.Layer().PutBucketSettings(hc.Context(), sp) + require.NoError(hc.t, err) return bktInfo } -func createTestObject(ctx context.Context, t *testing.T, h *handlerContext, bktInfo *data.BucketInfo, objName string) *data.ObjectInfo { +func createTestObject(hc *handlerContext, bktInfo *data.BucketInfo, objName string) *data.ObjectInfo { content := make([]byte, 1024) _, err := rand.Read(content) - require.NoError(t, err) + require.NoError(hc.t, err) header := map[string]string{ object.AttributeTimestamp: strconv.FormatInt(time.Now().UTC().Unix(), 10), } - objInfo, err := h.Layer().PutObject(ctx, &layer.PutObjectParams{ + objInfo, err := hc.Layer().PutObject(hc.Context(), &layer.PutObjectParams{ BktInfo: bktInfo, Object: objName, Size: int64(len(content)), Reader: bytes.NewReader(content), Header: header, }) - require.NoError(t, err) + require.NoError(hc.t, err) return objInfo } -func prepareTestRequest(t *testing.T, bktName, objName string, body interface{}) (*httptest.ResponseRecorder, *http.Request) { - return prepareTestFullRequest(t, bktName, objName, make(url.Values), body) +func prepareTestRequest(hc *handlerContext, bktName, objName string, body interface{}) (*httptest.ResponseRecorder, *http.Request) { + return prepareTestFullRequest(hc, bktName, objName, make(url.Values), body) } -func prepareTestFullRequest(t *testing.T, bktName, objName string, query url.Values, body interface{}) (*httptest.ResponseRecorder, *http.Request) { +func prepareTestFullRequest(hc *handlerContext, bktName, objName string, query url.Values, body interface{}) (*httptest.ResponseRecorder, *http.Request) { rawBody, err := xml.Marshal(body) - require.NoError(t, err) + require.NoError(hc.t, err) - return prepareTestRequestWithQuery(bktName, objName, query, rawBody) + return prepareTestRequestWithQuery(hc, bktName, objName, query, rawBody) } -func prepareTestRequestWithQuery(bktName, objName string, query url.Values, body []byte) (*httptest.ResponseRecorder, *http.Request) { +func prepareTestRequestWithQuery(hc *handlerContext, bktName, objName string, query url.Values, body []byte) (*httptest.ResponseRecorder, *http.Request) { w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(body)) r.URL.RawQuery = query.Encode() reqInfo := api.NewReqInfo(w, r, api.ObjectRequest{Bucket: bktName, Object: objName}) - r = r.WithContext(api.SetReqInfo(r.Context(), reqInfo)) + r = r.WithContext(api.SetReqInfo(hc.Context(), reqInfo)) return w, r } -func prepareTestPayloadRequest(bktName, objName string, payload io.Reader) (*httptest.ResponseRecorder, *http.Request) { +func prepareTestPayloadRequest(hc *handlerContext, bktName, objName string, payload io.Reader) (*httptest.ResponseRecorder, *http.Request) { w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, defaultURL, payload) reqInfo := api.NewReqInfo(w, r, api.ObjectRequest{Bucket: bktName, Object: objName}) - r = r.WithContext(api.SetReqInfo(r.Context(), reqInfo)) + r = r.WithContext(api.SetReqInfo(hc.Context(), reqInfo)) return w, r } diff --git a/api/handler/head_test.go b/api/handler/head_test.go index ff6f3e7..c6552cd 100644 --- a/api/handler/head_test.go +++ b/api/handler/head_test.go @@ -6,81 +6,101 @@ import ( "testing" "time" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neofs-s3-gw/api" + "github.com/nspcc-dev/neofs-s3-gw/creds/accessbox" + "github.com/nspcc-dev/neofs-sdk-go/bearer" + "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/stretchr/testify/require" ) func TestConditionalHead(t *testing.T) { - ctx := context.Background() tc := prepareHandlerContext(t) - bktName := "bucket-for-conditional" - createTestBucket(ctx, t, tc, bktName) - bktInfo, err := tc.Layer().GetBucketInfo(ctx, bktName) - require.NoError(t, err) + bktName, objName := "bucket-for-conditional", "object" + _, objInfo := createBucketAndObject(tc, bktName, objName) - objName := "object" - objInfo := createTestObject(ctx, t, tc, bktInfo, objName) - - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(tc, bktName, objName, nil) tc.Handler().HeadObjectHandler(w, r) assertStatus(t, w, http.StatusOK) - etag := w.Result().Header.Get(api.ETag) - lastModified := w.Result().Header.Get(api.LastModified) - _ = lastModified - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfMatch, etag) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) + headers := map[string]string{api.IfMatch: etag} + headObject(t, tc, bktName, objName, headers, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfMatch, "etag") - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusPreconditionFailed) + headers = map[string]string{api.IfMatch: "etag"} + headObject(t, tc, bktName, objName, headers, http.StatusPreconditionFailed) - w, r = prepareTestRequest(t, bktName, objName, nil) - unmodifiedSince := objInfo.Created.Add(time.Minute) - r.Header.Set(api.IfUnmodifiedSince, unmodifiedSince.Format(http.TimeFormat)) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) + headers = map[string]string{api.IfUnmodifiedSince: objInfo.Created.Add(time.Minute).Format(http.TimeFormat)} + headObject(t, tc, bktName, objName, headers, http.StatusOK) var zeroTime time.Time - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfUnmodifiedSince, zeroTime.UTC().Format(http.TimeFormat)) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusPreconditionFailed) + headers = map[string]string{api.IfUnmodifiedSince: zeroTime.UTC().Format(http.TimeFormat)} + headObject(t, tc, bktName, objName, headers, http.StatusPreconditionFailed) - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfMatch, etag) - r.Header.Set(api.IfUnmodifiedSince, zeroTime.UTC().Format(http.TimeFormat)) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) + headers = map[string]string{ + api.IfMatch: etag, + api.IfUnmodifiedSince: zeroTime.UTC().Format(http.TimeFormat), + } + headObject(t, tc, bktName, objName, headers, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfNoneMatch, etag) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusNotModified) + headers = map[string]string{api.IfNoneMatch: etag} + headObject(t, tc, bktName, objName, headers, http.StatusNotModified) - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfNoneMatch, "etag") - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) + headers = map[string]string{api.IfNoneMatch: "etag"} + headObject(t, tc, bktName, objName, headers, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfModifiedSince, zeroTime.UTC().Format(http.TimeFormat)) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) + headers = map[string]string{api.IfModifiedSince: zeroTime.UTC().Format(http.TimeFormat)} + headObject(t, tc, bktName, objName, headers, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfModifiedSince, time.Now().Add(time.Minute).UTC().Format(http.TimeFormat)) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusNotModified) + headers = map[string]string{api.IfModifiedSince: time.Now().Add(time.Minute).UTC().Format(http.TimeFormat)} + headObject(t, tc, bktName, objName, headers, http.StatusNotModified) - w, r = prepareTestRequest(t, bktName, objName, nil) - r.Header.Set(api.IfNoneMatch, etag) - r.Header.Set(api.IfModifiedSince, zeroTime.UTC().Format(http.TimeFormat)) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusNotModified) + headers = map[string]string{ + api.IfNoneMatch: etag, + api.IfModifiedSince: zeroTime.UTC().Format(http.TimeFormat), + } + headObject(t, tc, bktName, objName, headers, http.StatusNotModified) +} + +func headObject(t *testing.T, tc *handlerContext, bktName, objName string, headers map[string]string, status int) { + w, r := prepareTestRequest(tc, bktName, objName, nil) + + for key, val := range headers { + r.Header.Set(key, val) + } + + tc.Handler().HeadObjectHandler(w, r) + assertStatus(t, w, status) +} + +func TestInvalidAccessThroughCache(t *testing.T) { + tc := prepareHandlerContext(t) + bktName, objName := "bucket-for-cache", "obj-for-cache" + createBucketAndObject(tc, bktName, objName) + + headObject(t, tc, bktName, objName, nil, http.StatusOK) + + w, r := prepareTestRequest(tc, bktName, objName, nil) + tc.Handler().HeadObjectHandler(w, r.WithContext(context.WithValue(r.Context(), api.BoxData, newTestAccessBox(t, nil)))) + assertStatus(t, w, http.StatusForbidden) +} + +func newTestAccessBox(t *testing.T, key *keys.PrivateKey) *accessbox.Box { + var err error + if key == nil { + key, err = keys.NewPrivateKey() + require.NoError(t, err) + } + + var btoken bearer.Token + btoken.SetEACLTable(*eacl.NewTable()) + err = btoken.Sign(key.PrivateKey) + require.NoError(t, err) + + return &accessbox.Box{ + Gate: &accessbox.GateData{ + BearerToken: &btoken, + }, + } } diff --git a/api/handler/locking_test.go b/api/handler/locking_test.go index f1a1fca..3737cff 100644 --- a/api/handler/locking_test.go +++ b/api/handler/locking_test.go @@ -245,13 +245,13 @@ func TestPutBucketLockConfigurationHandler(t *testing.T) { hc := prepareHandlerContext(t) bktLockDisabled := "bucket-lock-disabled" - createTestBucket(ctx, t, hc, bktLockDisabled) + createTestBucket(hc, bktLockDisabled) bktLockEnabled := "bucket-lock-enabled" - createTestBucketWithLock(ctx, t, hc, bktLockEnabled, nil) + createTestBucketWithLock(hc, bktLockEnabled, nil) bktLockEnabledWithOldConfig := "bucket-lock-enabled-old-conf" - createTestBucketWithLock(ctx, t, hc, bktLockEnabledWithOldConfig, + createTestBucketWithLock(hc, bktLockEnabledWithOldConfig, &data.ObjectLockConfiguration{ Rule: &data.ObjectLockRule{ DefaultRetention: &data.DefaultRetention{ @@ -331,14 +331,13 @@ func TestPutBucketLockConfigurationHandler(t *testing.T) { } func TestGetBucketLockConfigurationHandler(t *testing.T) { - ctx := context.Background() hc := prepareHandlerContext(t) bktLockDisabled := "bucket-lock-disabled" - createTestBucket(ctx, t, hc, bktLockDisabled) + createTestBucket(hc, bktLockDisabled) bktLockEnabled := "bucket-lock-enabled" - createTestBucketWithLock(ctx, t, hc, bktLockEnabled, nil) + createTestBucketWithLock(hc, bktLockEnabled, nil) oldConfig := &data.ObjectLockConfiguration{ Rule: &data.ObjectLockRule{ @@ -349,7 +348,7 @@ func TestGetBucketLockConfigurationHandler(t *testing.T) { }, } bktLockEnabledWithOldConfig := "bucket-lock-enabled-old-conf" - createTestBucketWithLock(ctx, t, hc, bktLockEnabledWithOldConfig, oldConfig) + createTestBucketWithLock(hc, bktLockEnabledWithOldConfig, oldConfig) for _, tc := range []struct { name string @@ -416,44 +415,43 @@ func assertS3Error(t *testing.T, w *httptest.ResponseRecorder, expectedError api } func TestObjectLegalHold(t *testing.T) { - ctx := context.Background() hc := prepareHandlerContext(t) bktName := "bucket-lock-enabled" - bktInfo := createTestBucketWithLock(ctx, t, hc, bktName, nil) + bktInfo := createTestBucketWithLock(hc, bktName, nil) objName := "obj-for-legal-hold" - createTestObject(ctx, t, hc, bktInfo, objName) + createTestObject(hc, bktInfo, objName) - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(hc, bktName, objName, nil) hc.Handler().GetObjectLegalHoldHandler(w, r) assertLegalHold(t, w, legalHoldOff) - w, r = prepareTestRequest(t, bktName, objName, &data.LegalHold{Status: legalHoldOn}) + w, r = prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: legalHoldOn}) hc.Handler().PutObjectLegalHoldHandler(w, r) - require.Equal(t, http.StatusOK, w.Code) + assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) + w, r = prepareTestRequest(hc, bktName, objName, nil) hc.Handler().GetObjectLegalHoldHandler(w, r) assertLegalHold(t, w, legalHoldOn) // to make sure put hold is an idempotent operation - w, r = prepareTestRequest(t, bktName, objName, &data.LegalHold{Status: legalHoldOn}) + w, r = prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: legalHoldOn}) hc.Handler().PutObjectLegalHoldHandler(w, r) - require.Equal(t, http.StatusOK, w.Code) + assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, &data.LegalHold{Status: legalHoldOff}) + w, r = prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: legalHoldOff}) hc.Handler().PutObjectLegalHoldHandler(w, r) - require.Equal(t, http.StatusOK, w.Code) + assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) + w, r = prepareTestRequest(hc, bktName, objName, nil) hc.Handler().GetObjectLegalHoldHandler(w, r) assertLegalHold(t, w, legalHoldOff) // to make sure put hold is an idempotent operation - w, r = prepareTestRequest(t, bktName, objName, &data.LegalHold{Status: legalHoldOff}) + w, r = prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: legalHoldOff}) hc.Handler().PutObjectLegalHoldHandler(w, r) - require.Equal(t, http.StatusOK, w.Code) + assertStatus(t, w, http.StatusOK) } func assertLegalHold(t *testing.T, w *httptest.ResponseRecorder, status string) { @@ -465,44 +463,43 @@ func assertLegalHold(t *testing.T, w *httptest.ResponseRecorder, status string) } func TestObjectRetention(t *testing.T) { - ctx := context.Background() hc := prepareHandlerContext(t) bktName := "bucket-lock-enabled" - bktInfo := createTestBucketWithLock(ctx, t, hc, bktName, nil) + bktInfo := createTestBucketWithLock(hc, bktName, nil) objName := "obj-for-retention" - createTestObject(ctx, t, hc, bktInfo, objName) + createTestObject(hc, bktInfo, objName) - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(hc, bktName, objName, nil) hc.Handler().GetObjectRetentionHandler(w, r) assertS3Error(t, w, apiErrors.GetAPIError(apiErrors.ErrNoSuchKey)) retention := &data.Retention{Mode: governanceMode, RetainUntilDate: time.Now().Add(time.Minute).UTC().Format(time.RFC3339)} - w, r = prepareTestRequest(t, bktName, objName, retention) + w, r = prepareTestRequest(hc, bktName, objName, retention) hc.Handler().PutObjectRetentionHandler(w, r) assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) + w, r = prepareTestRequest(hc, bktName, objName, nil) hc.Handler().GetObjectRetentionHandler(w, r) assertRetention(t, w, retention) retention = &data.Retention{Mode: governanceMode, RetainUntilDate: time.Now().UTC().Add(time.Minute).Format(time.RFC3339)} - w, r = prepareTestRequest(t, bktName, objName, retention) + w, r = prepareTestRequest(hc, bktName, objName, retention) hc.Handler().PutObjectRetentionHandler(w, r) assertS3Error(t, w, apiErrors.GetAPIError(apiErrors.ErrInternalError)) retention = &data.Retention{Mode: complianceMode, RetainUntilDate: time.Now().Add(time.Minute).UTC().Format(time.RFC3339)} - w, r = prepareTestRequest(t, bktName, objName, retention) + w, r = prepareTestRequest(hc, bktName, objName, retention) r.Header.Set(api.AmzBypassGovernanceRetention, strconv.FormatBool(true)) hc.Handler().PutObjectRetentionHandler(w, r) assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) + w, r = prepareTestRequest(hc, bktName, objName, nil) hc.Handler().GetObjectRetentionHandler(w, r) assertRetention(t, w, retention) - w, r = prepareTestRequest(t, bktName, objName, retention) + w, r = prepareTestRequest(hc, bktName, objName, retention) r.Header.Set(api.AmzBypassGovernanceRetention, strconv.FormatBool(true)) hc.Handler().PutObjectRetentionHandler(w, r) assertS3Error(t, w, apiErrors.GetAPIError(apiErrors.ErrInternalError)) @@ -518,7 +515,6 @@ func assertRetention(t *testing.T, w *httptest.ResponseRecorder, retention *data } func TestPutObjectWithLock(t *testing.T) { - ctx := context.Background() hc := prepareHandlerContext(t) bktName := "bucket-lock-enabled" @@ -531,15 +527,15 @@ func TestPutObjectWithLock(t *testing.T) { }, }, } - createTestBucketWithLock(ctx, t, hc, bktName, lockConfig) + createTestBucketWithLock(hc, bktName, lockConfig) objDefault := "obj-default-retention" - w, r := prepareTestRequest(t, bktName, objDefault, nil) + w, r := prepareTestRequest(hc, bktName, objDefault, nil) hc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objDefault, nil) + w, r = prepareTestRequest(hc, bktName, objDefault, nil) hc.Handler().GetObjectRetentionHandler(w, r) expectedRetention := &data.Retention{ Mode: governanceMode, @@ -547,12 +543,12 @@ func TestPutObjectWithLock(t *testing.T) { } assertRetentionApproximate(t, w, expectedRetention, 1) - w, r = prepareTestRequest(t, bktName, objDefault, nil) + w, r = prepareTestRequest(hc, bktName, objDefault, nil) hc.Handler().GetObjectLegalHoldHandler(w, r) assertLegalHold(t, w, legalHoldOff) objOverride := "obj-override-retention" - w, r = prepareTestRequest(t, bktName, objOverride, nil) + w, r = prepareTestRequest(hc, bktName, objOverride, nil) r.Header.Set(api.AmzObjectLockMode, complianceMode) r.Header.Set(api.AmzObjectLockLegalHold, legalHoldOn) r.Header.Set(api.AmzBypassGovernanceRetention, "true") @@ -560,7 +556,7 @@ func TestPutObjectWithLock(t *testing.T) { hc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objOverride, nil) + w, r = prepareTestRequest(hc, bktName, objOverride, nil) hc.Handler().GetObjectRetentionHandler(w, r) expectedRetention = &data.Retention{ Mode: complianceMode, @@ -568,7 +564,7 @@ func TestPutObjectWithLock(t *testing.T) { } assertRetentionApproximate(t, w, expectedRetention, 1) - w, r = prepareTestRequest(t, bktName, objOverride, nil) + w, r = prepareTestRequest(hc, bktName, objOverride, nil) hc.Handler().GetObjectLegalHoldHandler(w, r) assertLegalHold(t, w, legalHoldOn) } @@ -577,7 +573,7 @@ func TestPutLockErrors(t *testing.T) { hc := prepareHandlerContext(t) bktName, objName := "bucket-lock-enabled", "object" - createTestBucketWithLock(hc.Context(), t, hc, bktName, nil) + createTestBucketWithLock(hc, bktName, nil) headers := map[string]string{api.AmzObjectLockMode: complianceMode} putObjectWithLockFailed(t, hc, bktName, objName, headers, apiErrors.ErrObjectLockInvalidHeaders) @@ -611,7 +607,7 @@ func TestPutLockErrors(t *testing.T) { } func putObjectWithLockFailed(t *testing.T, hc *handlerContext, bktName, objName string, headers map[string]string, errCode apiErrors.ErrorCode) { - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(hc, bktName, objName, nil) for key, val := range headers { r.Header.Set(key, val) @@ -622,7 +618,7 @@ func putObjectWithLockFailed(t *testing.T, hc *handlerContext, bktName, objName } func putObjectRetentionFailed(t *testing.T, hc *handlerContext, bktName, objName string, retention *data.Retention, errCode apiErrors.ErrorCode) { - w, r := prepareTestRequest(t, bktName, objName, retention) + w, r := prepareTestRequest(hc, bktName, objName, retention) hc.Handler().PutObjectRetentionHandler(w, r) assertS3Error(t, w, apiErrors.GetAPIError(errCode)) } diff --git a/api/handler/object_list_test.go b/api/handler/object_list_test.go index 439edb3..1762f30 100644 --- a/api/handler/object_list_test.go +++ b/api/handler/object_list_test.go @@ -2,7 +2,6 @@ package handler import ( "bytes" - "context" "net/http" "net/url" "strconv" @@ -43,30 +42,29 @@ func TestParseContinuationToken(t *testing.T) { } func TestListObjectNullVersions(t *testing.T) { - ctx := context.Background() hc := prepareHandlerContext(t) bktName := "bucket-versioning-enabled" - createTestBucket(ctx, t, hc, bktName) + createTestBucket(hc, bktName) objName := "object" body := bytes.NewReader([]byte("content")) - w, r := prepareTestPayloadRequest(bktName, objName, body) + w, r := prepareTestPayloadRequest(hc, bktName, objName, body) hc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) versioning := &VersioningConfiguration{Status: "Enabled"} - w, r = prepareTestRequest(t, bktName, objName, versioning) + w, r = prepareTestRequest(hc, bktName, objName, versioning) hc.Handler().PutBucketVersioningHandler(w, r) assertStatus(t, w, http.StatusOK) body2 := bytes.NewReader([]byte("content2")) - w, r = prepareTestPayloadRequest(bktName, objName, body2) + w, r = prepareTestPayloadRequest(hc, bktName, objName, body2) hc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(t, bktName, objName, nil) + w, r = prepareTestRequest(hc, bktName, objName, nil) hc.Handler().ListBucketObjectVersionsHandler(w, r) result := &ListObjectsVersionsResponse{} @@ -81,10 +79,10 @@ func TestS3CompatibilityBucketListV2BothContinuationTokenStartAfter(t *testing.T bktName := "bucket-for-listing" objects := []string{"bar", "baz", "foo", "quxx"} - bktInfo, _ := createBucketAndObject(t, tc, bktName, objects[0]) + bktInfo, _ := createBucketAndObject(tc, bktName, objects[0]) for _, objName := range objects[1:] { - createTestObject(tc.Context(), t, tc, bktInfo, objName) + createTestObject(tc, bktInfo, objName) } listV2Response1 := listObjectsV2(t, tc, bktName, "", "", "bar", "", 1) @@ -106,10 +104,10 @@ func TestS3BucketListDelimiterBasic(t *testing.T) { bktName := "bucket-for-listing" objects := []string{"foo/bar", "foo/bar/xyzzy", "quux/thud", "asdf"} - bktInfo, _ := createBucketAndObject(t, tc, bktName, objects[0]) + bktInfo, _ := createBucketAndObject(tc, bktName, objects[0]) for _, objName := range objects[1:] { - createTestObject(tc.Context(), t, tc, bktInfo, objName) + createTestObject(tc, bktInfo, objName) } listV1Response := listObjectsV1(t, tc, bktName, "", "/", "", -1) @@ -125,10 +123,10 @@ func TestS3BucketListV2DelimiterPrefix(t *testing.T) { bktName := "bucket-for-listingv2" objects := []string{"asdf", "boo/bar", "boo/baz/xyzzy", "cquux/thud", "cquux/bla"} - bktInfo, _ := createBucketAndObject(t, tc, bktName, objects[0]) + bktInfo, _ := createBucketAndObject(tc, bktName, objects[0]) for _, objName := range objects[1:] { - createTestObject(tc.Context(), t, tc, bktInfo, objName) + createTestObject(tc, bktInfo, objName) } var empty []string @@ -158,7 +156,7 @@ func listObjectsV2(t *testing.T, tc *handlerContext, bktName, prefix, delimiter, query.Add("continuation-token", continuationToken) } - w, r := prepareTestFullRequest(t, bktName, "", query, nil) + w, r := prepareTestFullRequest(tc, bktName, "", query, nil) tc.Handler().ListObjectsV2Handler(w, r) assertStatus(t, w, http.StatusOK) res := &ListObjectsV2Response{} @@ -208,7 +206,7 @@ func listObjectsV1(t *testing.T, tc *handlerContext, bktName, prefix, delimiter, query.Add("marker", marker) } - w, r := prepareTestFullRequest(t, bktName, "", query, nil) + w, r := prepareTestFullRequest(tc, bktName, "", query, nil) tc.Handler().ListObjectsV1Handler(w, r) assertStatus(t, w, http.StatusOK) res := &ListObjectsV1Response{} diff --git a/api/handler/put_test.go b/api/handler/put_test.go index c0309a8..b0057f3 100644 --- a/api/handler/put_test.go +++ b/api/handler/put_test.go @@ -111,9 +111,9 @@ func TestPutObjectOverrideCopiesNumber(t *testing.T) { tc := prepareHandlerContext(t) bktName, objName := "bucket-for-copies-number", "object-for-copies-number" - bktInfo := createTestBucket(tc.Context(), t, tc, bktName) + bktInfo := createTestBucket(tc, bktName) - w, r := prepareTestRequest(t, bktName, objName, nil) + w, r := prepareTestRequest(tc, bktName, objName, nil) r.Header.Set(api.MetadataPrefix+strings.ToUpper(layer.AttributeNeofsCopiesNumber), "1") tc.Handler().PutObjectHandler(w, r) diff --git a/api/layer/neofs_mock.go b/api/layer/neofs_mock.go index d5b674b..cc0fa8a 100644 --- a/api/layer/neofs_mock.go +++ b/api/layer/neofs_mock.go @@ -11,6 +11,9 @@ import ( "time" objectv2 "github.com/nspcc-dev/neofs-api-go/v2/object" + "github.com/nspcc-dev/neofs-s3-gw/api" + "github.com/nspcc-dev/neofs-s3-gw/creds/accessbox" + "github.com/nspcc-dev/neofs-sdk-go/bearer" "github.com/nspcc-dev/neofs-sdk-go/checksum" "github.com/nspcc-dev/neofs-sdk-go/container" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" @@ -127,7 +130,7 @@ func (t *TestNeoFS) UserContainers(_ context.Context, _ user.ID) ([]cid.ID, erro return res, nil } -func (t *TestNeoFS) ReadObject(_ context.Context, prm PrmObjectRead) (*ObjectPart, error) { +func (t *TestNeoFS) ReadObject(ctx context.Context, prm PrmObjectRead) (*ObjectPart, error) { var addr oid.Address addr.SetContainer(prm.Container) addr.SetObject(prm.Object) @@ -135,6 +138,11 @@ func (t *TestNeoFS) ReadObject(_ context.Context, prm PrmObjectRead) (*ObjectPar sAddr := addr.EncodeToString() if obj, ok := t.objects[sAddr]; ok { + owner := getOwner(ctx) + if !obj.OwnerID().Equals(owner) { + return nil, ErrAccessDenied + } + payload := obj.Payload() if prm.PayloadRange[0]+prm.PayloadRange[1] > 0 { @@ -151,7 +159,7 @@ func (t *TestNeoFS) ReadObject(_ context.Context, prm PrmObjectRead) (*ObjectPar return nil, fmt.Errorf("object not found %s", addr) } -func (t *TestNeoFS) CreateObject(_ context.Context, prm PrmObjectCreate) (oid.ID, error) { +func (t *TestNeoFS) CreateObject(ctx context.Context, prm PrmObjectCreate) (oid.ID, error) { b := make([]byte, 32) if _, err := io.ReadFull(rand.Reader, b); err != nil { return oid.ID{}, err @@ -181,6 +189,7 @@ func (t *TestNeoFS) CreateObject(_ context.Context, prm PrmObjectCreate) (oid.ID obj.SetPayloadSize(prm.PayloadSize) obj.SetAttributes(attrs...) obj.SetCreationEpoch(t.currentEpoch) + obj.SetOwnerID(&prm.Creator) t.currentEpoch++ if len(prm.Locks) > 0 { @@ -209,12 +218,19 @@ func (t *TestNeoFS) CreateObject(_ context.Context, prm PrmObjectCreate) (oid.ID return objID, nil } -func (t *TestNeoFS) DeleteObject(_ context.Context, prm PrmObjectDelete) error { +func (t *TestNeoFS) DeleteObject(ctx context.Context, prm PrmObjectDelete) error { var addr oid.Address addr.SetContainer(prm.Container) addr.SetObject(prm.Object) - delete(t.objects, addr.EncodeToString()) + if obj, ok := t.objects[addr.EncodeToString()]; ok { + owner := getOwner(ctx) + if !obj.OwnerID().Equals(owner) { + return ErrAccessDenied + } + + delete(t.objects, addr.EncodeToString()) + } return nil } @@ -260,3 +276,11 @@ func (t *TestNeoFS) ContainerEACL(_ context.Context, cnrID cid.ID) (*eacl.Table, return table, nil } + +func getOwner(ctx context.Context) user.ID { + if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil && bd.Gate.BearerToken != nil { + return bearer.ResolveIssuer(*bd.Gate.BearerToken) + } + + return user.ID{} +} diff --git a/api/layer/versioning_test.go b/api/layer/versioning_test.go index b8958be..899b923 100644 --- a/api/layer/versioning_test.go +++ b/api/layer/versioning_test.go @@ -12,7 +12,7 @@ import ( bearertest "github.com/nspcc-dev/neofs-sdk-go/bearer/test" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" - usertest "github.com/nspcc-dev/neofs-sdk-go/user/test" + "github.com/nspcc-dev/neofs-sdk-go/user" "github.com/stretchr/testify/require" "go.uber.org/zap" ) @@ -159,6 +159,9 @@ func prepareContext(t *testing.T, cachesConfig ...*CachesConfig) *testContext { config = cachesConfig[0] } + var owner user.ID + user.IDFromKey(&owner, key.PrivateKey.PublicKey) + layerCfg := &Config{ Caches: config, AnonKey: AnonymousKey{Key: key}, @@ -170,7 +173,7 @@ func prepareContext(t *testing.T, cachesConfig ...*CachesConfig) *testContext { layer: NewLayer(logger, tp, layerCfg), bktInfo: &data.BucketInfo{ Name: bktName, - Owner: *usertest.ID(), + Owner: owner, CID: bktID, }, obj: "obj1",