From f0914b8a4352d2e152f3af87195ddc2837eeca01 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Fri, 18 Mar 2022 16:04:09 +0300 Subject: [PATCH] [#377] Reuse BucketInfo in layer Signed-off-by: Denis Kirillov --- api/handler/acl.go | 78 +++++++++------ api/handler/copy.go | 31 +++--- api/handler/cors.go | 23 +---- api/handler/delete.go | 22 ++-- api/handler/get.go | 8 +- api/handler/handlers_test.go | 30 +++--- api/handler/head.go | 14 +-- api/handler/info.go | 7 +- api/handler/locking.go | 45 ++------- api/handler/locking_test.go | 8 +- api/handler/multipart_upload.go | 82 +++++---------- api/handler/notifications.go | 12 +-- api/handler/object_list.go | 23 ++--- api/handler/put.go | 71 ++++++------- api/handler/tagging.go | 60 ++++++----- api/handler/util.go | 20 ++-- api/handler/versioning.go | 14 +-- api/layer/container.go | 5 +- api/layer/layer.go | 171 +++++++++++--------------------- api/layer/multipart_upload.go | 34 +++---- api/layer/object.go | 35 +++---- api/layer/versioning.go | 23 +---- api/layer/versioning_test.go | 46 ++++----- 23 files changed, 341 insertions(+), 521 deletions(-) diff --git a/api/handler/acl.go b/api/handler/acl.go index d373382c4..46198d690 100644 --- a/api/handler/acl.go +++ b/api/handler/acl.go @@ -127,19 +127,21 @@ type astOperation struct { func (h *handler) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bucketACL, err := h.obj.GetBucketACL(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) + return + } + + bucketACL, err := h.obj.GetBucketACL(r.Context(), bktInfo) if err != nil { h.logAndSendError(w, "could not fetch bucket acl", reqInfo, err) return } - if err := checkOwner(bucketACL.Info, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - if err = api.EncodeToResponse(w, h.encodeBucketACL(bucketACL)); err != nil { h.logAndSendError(w, "something went wrong", reqInfo, err) + return } } @@ -183,27 +185,29 @@ func (h *handler) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) { return } - if err = h.updateBucketACL(r, astBucket, reqInfo.BucketName); err != nil { + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) + return + } + + if err = h.updateBucketACL(r, astBucket, bktInfo); err != nil { h.logAndSendError(w, "could not update bucket acl", reqInfo, err) return } w.WriteHeader(http.StatusOK) } -func (h *handler) updateBucketACL(r *http.Request, astChild *ast, bkt string) error { - bucketACL, err := h.obj.GetBucketACL(r.Context(), bkt) +func (h *handler) updateBucketACL(r *http.Request, astChild *ast, bktInfo *data.BucketInfo) error { + bucketACL, err := h.obj.GetBucketACL(r.Context(), bktInfo) if err != nil { return fmt.Errorf("could not get bucket eacl: %w", err) } - if err = checkOwner(bucketACL.Info, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - return fmt.Errorf("expected owner doesn't match: %w", err) - } - - parentAst := tableToAst(bucketACL.EACL, bkt) + parentAst := tableToAst(bucketACL.EACL, bktInfo.Name) for _, resource := range parentAst.Resources { if resource.Bucket == bucketACL.Info.CID.String() { - resource.Bucket = bkt + resource.Bucket = bktInfo.Name } } @@ -218,8 +222,8 @@ func (h *handler) updateBucketACL(r *http.Request, astChild *ast, bkt string) er } p := &layer.PutBucketACLParams{ - Name: bkt, - EACL: table, + BktInfo: bktInfo, + EACL: table, } if err = h.obj.PutBucketACL(r.Context(), p); err != nil { @@ -231,14 +235,16 @@ func (h *handler) updateBucketACL(r *http.Request, astChild *ast, bkt string) er func (h *handler) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bucketACL, err := h.obj.GetBucketACL(r.Context(), reqInfo.BucketName) + + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { - h.logAndSendError(w, "could not fetch bucket acl", reqInfo, err) + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := checkOwner(bucketACL.Info, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bucketACL, err := h.obj.GetBucketACL(r.Context(), bktInfo) + if err != nil { + h.logAndSendError(w, "could not fetch bucket acl", reqInfo, err) return } @@ -280,8 +286,14 @@ func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) { return } + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) + return + } + p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: versionID, } @@ -291,7 +303,7 @@ func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) { return } - if err = h.updateBucketACL(r, astObject, reqInfo.BucketName); err != nil { + if err = h.updateBucketACL(r, astObject, bktInfo); err != nil { h.logAndSendError(w, "could not update bucket acl", reqInfo, err) return } @@ -300,14 +312,16 @@ func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bucketACL, err := h.obj.GetBucketACL(r.Context(), reqInfo.BucketName) + + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { - h.logAndSendError(w, "could not fetch bucket acl", reqInfo, err) + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bucketACL.Info, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bucketACL, err := h.obj.GetBucketACL(r.Context(), bktInfo) + if err != nil { + h.logAndSendError(w, "could not fetch bucket acl", reqInfo, err) return } @@ -336,6 +350,13 @@ func checkOwner(info *data.BucketInfo, owner string) error { func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) + + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) + return + } + bktPolicy := &bucketPolicy{Bucket: reqInfo.BucketName} if err := json.NewDecoder(r.Body).Decode(bktPolicy); err != nil { h.logAndSendError(w, "could not parse bucket policy", reqInfo, err) @@ -348,11 +369,10 @@ func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request) return } - if err = h.updateBucketACL(r, astPolicy, reqInfo.BucketName); err != nil { + if err = h.updateBucketACL(r, astPolicy, bktInfo); err != nil { h.logAndSendError(w, "could not update bucket acl", reqInfo, err) return } - w.WriteHeader(http.StatusOK) } func parseACLHeaders(header http.Header, gateKey *keys.PublicKey) (*AccessControlPolicy, error) { diff --git a/api/handler/copy.go b/api/handler/copy.go index 0970da69f..459520b96 100644 --- a/api/handler/copy.go +++ b/api/handler/copy.go @@ -59,7 +59,6 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) { return } p := &layer.HeadObjectParams{ - Bucket: srcBucket, Object: srcObject, VersionID: versionID, } @@ -71,12 +70,14 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) { return } - if err = h.checkBucketOwner(r, srcBucket, r.Header.Get(api.AmzSourceExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "source expected owner doesn't match", reqInfo, err) + if p.BktInfo, err = h.getBucketAndCheckOwner(r, srcBucket, api.AmzSourceExpectedBucketOwner); err != nil { + h.logAndSendError(w, "couldn't get source bucket", reqInfo, err) return } - if err = h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + + dstBktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "couldn't get target bucket", reqInfo, err) return } @@ -100,26 +101,20 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) { } params := &layer.CopyObjectParams{ - SrcObject: info, - DstBucket: reqInfo.BucketName, - DstObject: reqInfo.ObjectName, - SrcSize: info.Size, - Header: metadata, + SrcObject: info, + DstBktInfo: dstBktInfo, + DstObject: reqInfo.ObjectName, + SrcSize: info.Size, + Header: metadata, } - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) - if err != nil { - h.logAndSendError(w, "could not get bucket", reqInfo, err) - return - } - - settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo) + settings, err := h.obj.GetBucketSettings(r.Context(), dstBktInfo) if err != nil { h.logAndSendError(w, "could not get bucket settings", reqInfo, err) return } - params.Lock, err = formObjectLock(bktInfo, settings.LockConfiguration, r.Header) + params.Lock, err = formObjectLock(dstBktInfo, settings.LockConfiguration, r.Header) if err != nil { h.logAndSendError(w, "could not form object lock", reqInfo, err) return diff --git a/api/handler/cors.go b/api/handler/cors.go index 8cbb89909..5a2321132 100644 --- a/api/handler/cors.go +++ b/api/handler/cors.go @@ -19,17 +19,12 @@ const ( func (h *handler) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - cors, err := h.obj.GetBucketCORS(r.Context(), bktInfo) if err != nil { h.logAndSendError(w, "could not get cors", reqInfo, err) @@ -45,17 +40,12 @@ func (h *handler) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) PutBucketCorsHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - p := &layer.PutCORSParams{ BktInfo: bktInfo, Reader: r.Body, @@ -72,18 +62,13 @@ func (h *handler) PutBucketCorsHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) DeleteBucketCorsHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - - if err := h.obj.DeleteBucketCORS(r.Context(), bktInfo); err != nil { + if err = h.obj.DeleteBucketCORS(r.Context(), bktInfo); err != nil { h.logAndSendError(w, "could not delete cors", reqInfo, err) } diff --git a/api/handler/delete.go b/api/handler/delete.go index 493e4b5a0..c93a9eee0 100644 --- a/api/handler/delete.go +++ b/api/handler/delete.go @@ -60,12 +60,13 @@ func (h *handler) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) { VersionID: reqInfo.URL.Query().Get(api.QueryVersionID), }} - if err := h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - deletedObjects, err := h.obj.DeleteObjects(r.Context(), reqInfo.BucketName, versionedObject) + deletedObjects, err := h.obj.DeleteObjects(r.Context(), bktInfo, versionedObject) deletedObject := deletedObjects[0] if err == nil { err = deletedObject.Error @@ -131,8 +132,9 @@ func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Re DeletedObjects: make([]DeletedObject, 0, len(toRemove)), } - if err := h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } @@ -143,7 +145,7 @@ func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Re return nil }) - deletedObjects, err := h.obj.DeleteObjects(r.Context(), reqInfo.BucketName, toRemove) + deletedObjects, err := h.obj.DeleteObjects(r.Context(), bktInfo, toRemove) if !requested.Quiet && err != nil { h.logAndSendError(w, "couldn't delete objects", reqInfo, err) return @@ -194,11 +196,13 @@ func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Re func (h *handler) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - if err := h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := h.obj.DeleteBucket(r.Context(), &layer.DeleteBucketParams{Name: reqInfo.BucketName}); err != nil { + + if err = h.obj.DeleteBucket(r.Context(), &layer.DeleteBucketParams{BktInfo: bktInfo}); err != nil { h.logAndSendError(w, "couldn't delete bucket", reqInfo, err) } w.WriteHeader(http.StatusNoContent) diff --git a/api/handler/get.go b/api/handler/get.go index eb70f76a1..7a22c553e 100644 --- a/api/handler/get.go +++ b/api/handler/get.go @@ -115,18 +115,14 @@ func (h *handler) GetObjectHandler(w http.ResponseWriter, r *http.Request) { return } - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: reqInfo.URL.Query().Get(api.QueryVersionID), } diff --git a/api/handler/handlers_test.go b/api/handler/handlers_test.go index f48929636..2d53ab14b 100644 --- a/api/handler/handlers_test.go +++ b/api/handler/handlers_test.go @@ -77,20 +77,22 @@ func createTestBucket(ctx context.Context, t *testing.T, h *handlerContext, bktN require.NoError(t, err) } -func createTestBucketWithLock(ctx context.Context, t *testing.T, h *handlerContext, bktName string, conf *data.ObjectLockConfiguration) { +func createTestBucketWithLock(ctx context.Context, t *testing.T, h *handlerContext, bktName string, conf *data.ObjectLockConfiguration) *data.BucketInfo { cnrID, err := h.MockedPool().CreateContainer(ctx, neofs.PrmContainerCreate{ Name: bktName, AdditionalAttributes: [][2]string{{layer.AttributeLockEnabled, "true"}}, }) require.NoError(t, err) + bktInfo := &data.BucketInfo{ + CID: cnrID, + Name: bktName, + ObjectLockEnabled: true, + Owner: owner.NewID(), + } + sp := &layer.PutSettingsParams{ - BktInfo: &data.BucketInfo{ - CID: cnrID, - Name: bktName, - ObjectLockEnabled: true, - Owner: owner.NewID(), - }, + BktInfo: bktInfo, Settings: &data.BucketSettings{ VersioningEnabled: true, LockConfiguration: conf, @@ -99,19 +101,21 @@ func createTestBucketWithLock(ctx context.Context, t *testing.T, h *handlerConte err = h.Layer().PutBucketSettings(ctx, sp) require.NoError(t, err) + + return bktInfo } -func createTestObject(ctx context.Context, t *testing.T, h *handlerContext, bktName, objName string) { +func createTestObject(ctx context.Context, t *testing.T, h *handlerContext, bktInfo *data.BucketInfo, objName string) { content := make([]byte, 1024) _, err := rand.Read(content) require.NoError(t, err) _, err = h.Layer().PutObject(ctx, &layer.PutObjectParams{ - Bucket: bktName, - Object: objName, - Size: int64(len(content)), - Reader: bytes.NewReader(content), - Header: make(map[string]string), + BktInfo: bktInfo, + Object: objName, + Size: int64(len(content)), + Reader: bytes.NewReader(content), + Header: make(map[string]string), }) require.NoError(t, err) } diff --git a/api/handler/head.go b/api/handler/head.go index 43cac716f..29173c821 100644 --- a/api/handler/head.go +++ b/api/handler/head.go @@ -34,18 +34,14 @@ func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) { reqInfo = api.GetReqInfo(r.Context()) ) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: reqInfo.URL.Query().Get(api.QueryVersionID), } @@ -87,15 +83,11 @@ func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) HeadBucketHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } w.Header().Set(api.ContainerID, bktInfo.CID.String()) api.WriteResponse(w, http.StatusOK, nil, api.MimeNone) diff --git a/api/handler/info.go b/api/handler/info.go index f14309542..78c257ddd 100644 --- a/api/handler/info.go +++ b/api/handler/info.go @@ -9,17 +9,12 @@ import ( func (h *handler) GetBucketLocationHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - if err = api.EncodeToResponse(w, LocationResponse{Location: bktInfo.LocationConstraint}); err != nil { h.logAndSendError(w, "couldn't encode bucket location response", reqInfo, err) } diff --git a/api/handler/locking.go b/api/handler/locking.go index 2c7aaf5d9..23f9b5294 100644 --- a/api/handler/locking.go +++ b/api/handler/locking.go @@ -28,15 +28,11 @@ const ( func (h *handler) PutBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } if !bktInfo.ObjectLockEnabled { h.logAndSendError(w, "couldn't put object locking configuration", reqInfo, @@ -77,15 +73,11 @@ func (h *handler) PutBucketObjectLockConfigHandler(w http.ResponseWriter, r *htt func (h *handler) GetBucketObjectLockConfigHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } if !bktInfo.ObjectLockEnabled { h.logAndSendError(w, "object lock disabled", reqInfo, @@ -114,15 +106,11 @@ func (h *handler) GetBucketObjectLockConfigHandler(w http.ResponseWriter, r *htt func (h *handler) PutObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } if !bktInfo.ObjectLockEnabled { h.logAndSendError(w, "object lock disabled", reqInfo, @@ -143,7 +131,7 @@ func (h *handler) PutObjectLegalHoldHandler(w http.ResponseWriter, r *http.Reque } p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: reqInfo.URL.Query().Get(api.QueryVersionID), } @@ -187,15 +175,11 @@ func (h *handler) PutObjectLegalHoldHandler(w http.ResponseWriter, r *http.Reque func (h *handler) GetObjectLegalHoldHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } if !bktInfo.ObjectLockEnabled { h.logAndSendError(w, "object lock disabled", reqInfo, @@ -204,7 +188,7 @@ func (h *handler) GetObjectLegalHoldHandler(w http.ResponseWriter, r *http.Reque } p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: reqInfo.URL.Query().Get(api.QueryVersionID), } @@ -234,16 +218,11 @@ func (h *handler) GetObjectLegalHoldHandler(w http.ResponseWriter, r *http.Reque func (h *handler) PutObjectRetentionHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - if !bktInfo.ObjectLockEnabled { h.logAndSendError(w, "object lock disabled", reqInfo, apiErrors.GetAPIError(apiErrors.ErrObjectLockConfigurationNotFound)) @@ -263,7 +242,7 @@ func (h *handler) PutObjectRetentionHandler(w http.ResponseWriter, r *http.Reque } p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: reqInfo.URL.Query().Get(api.QueryVersionID), } @@ -317,15 +296,11 @@ func checkLockInfo(lock *data.ObjectInfo, header http.Header) error { func (h *handler) GetObjectRetentionHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } if !bktInfo.ObjectLockEnabled { h.logAndSendError(w, "object lock disabled", reqInfo, @@ -334,7 +309,7 @@ func (h *handler) GetObjectRetentionHandler(w http.ResponseWriter, r *http.Reque } p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: reqInfo.URL.Query().Get(api.QueryVersionID), } diff --git a/api/handler/locking_test.go b/api/handler/locking_test.go index 07c066182..8cb19b972 100644 --- a/api/handler/locking_test.go +++ b/api/handler/locking_test.go @@ -463,10 +463,10 @@ func TestObjectLegalHold(t *testing.T) { hc := prepareHandlerContext(t) bktName := "bucket-lock-enabled" - createTestBucketWithLock(ctx, t, hc, bktName, nil) + bktInfo := createTestBucketWithLock(ctx, t, hc, bktName, nil) objName := "obj-for-legal-hold" - createTestObject(ctx, t, hc, bktName, objName) + createTestObject(ctx, t, hc, bktInfo, objName) w, r := prepareTestRequest(t, bktName, objName, nil) hc.Handler().GetObjectLegalHoldHandler(w, r) @@ -512,10 +512,10 @@ func TestObjectRetention(t *testing.T) { hc := prepareHandlerContext(t) bktName := "bucket-lock-enabled" - createTestBucketWithLock(ctx, t, hc, bktName, nil) + bktInfo := createTestBucketWithLock(ctx, t, hc, bktName, nil) objName := "obj-for-retention" - createTestObject(ctx, t, hc, bktName, objName) + createTestObject(ctx, t, hc, bktInfo, objName) w, r := prepareTestRequest(t, bktName, objName, nil) hc.Handler().GetObjectRetentionHandler(w, r) diff --git a/api/handler/multipart_upload.go b/api/handler/multipart_upload.go index deec6f855..b84bfe7d3 100644 --- a/api/handler/multipart_upload.go +++ b/api/handler/multipart_upload.go @@ -103,17 +103,12 @@ func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Re (min value of partNumber of a common part is 1) and holding data: metadata, acl, tagging */ reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - var ( hasData bool b []byte @@ -195,16 +190,12 @@ func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Re func (h *handler) UploadPartHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } var ( queryValues = r.URL.Query() uploadID = queryValues.Get(uploadIDHeaderName) @@ -239,22 +230,9 @@ func (h *handler) UploadPartHandler(w http.ResponseWriter, r *http.Request) { } func (h *handler) UploadPartCopy(w http.ResponseWriter, r *http.Request) { - reqInfo := api.GetReqInfo(r.Context()) - - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) - if err != nil { - h.logAndSendError(w, "could not get bucket info", reqInfo, err) - return - } - - if err := checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - var ( - versionID string - + versionID string + reqInfo = api.GetReqInfo(r.Context()) queryValues = reqInfo.URL.Query() uploadID = queryValues.Get(uploadIDHeaderName) additional = []zap.Field{zap.String("uploadID", uploadID), zap.String("Key", reqInfo.ObjectName)} @@ -280,8 +258,20 @@ func (h *handler) UploadPartCopy(w http.ResponseWriter, r *http.Request) { return } + srcBktInfo, err := h.getBucketAndCheckOwner(r, srcBucket, api.AmzSourceExpectedBucketOwner) + if err != nil { + h.logAndSendError(w, "could not get source bucket info", reqInfo, err) + return + } + + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get target bucket info", reqInfo, err) + return + } + srcInfo, err := h.obj.GetObjectInfo(r.Context(), &layer.HeadObjectParams{ - Bucket: srcBucket, + BktInfo: srcBktInfo, Object: srcObject, VersionID: versionID, }) @@ -318,11 +308,6 @@ func (h *handler) UploadPartCopy(w http.ResponseWriter, r *http.Request) { return } - if err = h.checkBucketOwner(r, srcBucket, r.Header.Get(api.AmzSourceExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "source expected owner doesn't match", reqInfo, err) - return - } - p := &layer.UploadCopyParams{ Info: &layer.UploadInfoParams{ UploadID: uploadID, @@ -353,17 +338,12 @@ func (h *handler) UploadPartCopy(w http.ResponseWriter, r *http.Request) { func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - var ( uploadID = r.URL.Query().Get(uploadIDHeaderName) uploadInfo = &layer.UploadInfoParams{ @@ -439,15 +419,14 @@ func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http. h.logAndSendError(w, "could not translate acl of completed multipart upload to ast", reqInfo, err, additional...) return } - if err = h.updateBucketACL(r, astObject, reqInfo.BucketName); err != nil { + if err = h.updateBucketACL(r, astObject, bktInfo); err != nil { h.logAndSendError(w, "could not update bucket acl while completing multipart upload", reqInfo, err, additional...) return } } } - _, err = h.obj.DeleteObjects(r.Context(), bktInfo.Name, []*layer.VersionedObject{{Name: initPart.Name}}) - if err != nil { + if _, err = h.obj.DeleteObjects(r.Context(), bktInfo, []*layer.VersionedObject{{Name: initPart.Name}}); err != nil { h.logAndSendError(w, "could not delete init file of multipart upload", reqInfo, err, additional...) return } @@ -472,17 +451,12 @@ func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http. func (h *handler) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - var ( queryValues = reqInfo.URL.Query() delimiter = queryValues.Get("delimiter") @@ -525,17 +499,12 @@ func (h *handler) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Req func (h *handler) ListPartsHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - var ( partNumberMarker int @@ -587,17 +556,12 @@ func (h *handler) ListPartsHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) AbortMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } - var ( queryValues = reqInfo.URL.Query() uploadID = queryValues.Get(uploadIDHeaderName) diff --git a/api/handler/notifications.go b/api/handler/notifications.go index 983024a4d..825618ad8 100644 --- a/api/handler/notifications.go +++ b/api/handler/notifications.go @@ -16,15 +16,11 @@ type NotificationConfiguration struct { func (h *handler) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } p := &layer.PutBucketNotificationConfigurationParams{ BktInfo: bktInfo, @@ -40,16 +36,12 @@ func (h *handler) PutBucketNotificationHandler(w http.ResponseWriter, r *http.Re func (h *handler) GetBucketNotificationHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } conf, err := h.obj.GetBucketNotificationConfiguration(r.Context(), bktInfo) if err != nil { h.logAndSendError(w, "could not get bucket notification configuration", reqInfo, err) diff --git a/api/handler/object_list.go b/api/handler/object_list.go index 24b551fbc..031f36663 100644 --- a/api/handler/object_list.go +++ b/api/handler/object_list.go @@ -22,8 +22,8 @@ func (h *handler) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) { return } - if err = h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + if params.BktInfo, err = h.getBucketAndCheckOwner(r, reqInfo.BucketName); err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } @@ -40,7 +40,7 @@ func (h *handler) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) { func encodeV1(p *layer.ListObjectsParamsV1, list *layer.ListObjectsInfoV1) *ListObjectsV1Response { res := &ListObjectsV1Response{ - Name: p.Bucket, + Name: p.BktInfo.Name, EncodingType: p.Encode, Marker: p.Marker, Prefix: p.Prefix, @@ -66,8 +66,8 @@ func (h *handler) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) { return } - if err = h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + if params.BktInfo, err = h.getBucketAndCheckOwner(r, reqInfo.BucketName); err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } @@ -84,7 +84,7 @@ func (h *handler) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) { func encodeV2(p *layer.ListObjectsParamsV2, list *layer.ListObjectsInfoV2) *ListObjectsV2Response { res := &ListObjectsV2Response{ - Name: p.Bucket, + Name: p.BktInfo.Name, EncodingType: p.Encode, Prefix: s3PathEncode(p.Prefix, p.Encode), KeyCount: len(list.Objects) + len(list.Prefixes), @@ -149,7 +149,6 @@ func parseListObjectArgs(reqInfo *api.ReqInfo) (*layer.ListObjectsParamsCommon, queryValues = reqInfo.URL.Query() ) - res.Bucket = reqInfo.BucketName res.Delimiter = queryValues.Get("delimiter") res.Encode = queryValues.Get("encoding-type") @@ -218,15 +217,10 @@ func (h *handler) ListBucketObjectVersionsHandler(w http.ResponseWriter, r *http return } - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) - if err != nil { + if p.BktInfo, err = h.getBucketAndCheckOwner(r, reqInfo.BucketName); err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } info, err := h.obj.ListObjectVersions(r.Context(), p) if err != nil { @@ -234,7 +228,7 @@ func (h *handler) ListBucketObjectVersionsHandler(w http.ResponseWriter, r *http return } - response := encodeListObjectVersionsToResponse(info, p.Bucket) + response := encodeListObjectVersionsToResponse(info, p.BktInfo.Name) if err = api.EncodeToResponse(w, response); err != nil { h.logAndSendError(w, "something went wrong", reqInfo, err) } @@ -258,7 +252,6 @@ func parseListObjectVersionsRequest(reqInfo *api.ReqInfo) (*layer.ListObjectVers res.Delimiter = queryValues.Get("delimiter") res.Encode = queryValues.Get("encoding-type") res.VersionIDMarker = queryValues.Get("version-id-marker") - res.Bucket = reqInfo.BucketName return &res, nil } diff --git a/api/handler/put.go b/api/handler/put.go index 6155b2299..c6725ee08 100644 --- a/api/handler/put.go +++ b/api/handler/put.go @@ -180,13 +180,9 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) { return } - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { - h.logAndSendError(w, "could not get bucket", reqInfo, err) - return - } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } @@ -202,11 +198,11 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) { } params := &layer.PutObjectParams{ - Bucket: reqInfo.BucketName, - Object: reqInfo.ObjectName, - Reader: r.Body, - Size: r.ContentLength, - Header: metadata, + BktInfo: bktInfo, + Object: reqInfo.ObjectName, + Reader: r.Body, + Size: r.ContentLength, + Header: metadata, } settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo) @@ -228,7 +224,7 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) { } if containsACLHeaders(r) { - if newEaclTable, err = h.getNewEAclTable(r, info); err != nil { + if newEaclTable, err = h.getNewEAclTable(r, bktInfo, info); err != nil { h.logAndSendError(w, "could not get new eacl table", reqInfo, err) return } @@ -243,8 +239,8 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) { if newEaclTable != nil { p := &layer.PutBucketACLParams{ - Name: reqInfo.BucketName, - EACL: newEaclTable, + BktInfo: bktInfo, + EACL: newEaclTable, } if err = h.obj.PutBucketACL(r.Context(), p); err != nil { @@ -253,7 +249,7 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) { } } - if settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo); err != nil { + if settings, err = h.obj.GetBucketSettings(r.Context(), bktInfo); err != nil { h.log.Warn("couldn't get bucket versioning", zap.String("bucket name", reqInfo.BucketName), zap.Error(err)) } else if settings.VersioningEnabled { w.Header().Set(api.AmzVersionID, info.Version()) @@ -306,12 +302,18 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) { return } + bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) + return + } + params := &layer.PutObjectParams{ - Bucket: reqInfo.BucketName, - Object: reqInfo.ObjectName, - Reader: contentReader, - Size: size, - Header: metadata, + BktInfo: bktInfo, + Object: reqInfo.ObjectName, + Reader: contentReader, + Size: size, + Header: metadata, } info, err := h.obj.PutObject(r.Context(), params) @@ -326,7 +328,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) { r.Header.Set(api.AmzGrantWrite, "") r.Header.Set(api.AmzGrantRead, "") - if newEaclTable, err = h.getNewEAclTable(r, info); err != nil { + if newEaclTable, err = h.getNewEAclTable(r, bktInfo, info); err != nil { h.logAndSendError(w, "could not get new eacl table", reqInfo, err) return } @@ -341,8 +343,8 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) { if newEaclTable != nil { p := &layer.PutBucketACLParams{ - Name: reqInfo.BucketName, - EACL: newEaclTable, + BktInfo: bktInfo, + EACL: newEaclTable, } if err = h.obj.PutBucketACL(r.Context(), p); err != nil { @@ -351,12 +353,6 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) { } } - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) - if err != nil { - h.logAndSendError(w, "could not get bucket info", reqInfo, err) - return - } - if settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo); err != nil { h.log.Warn("couldn't get bucket versioning", zap.String("bucket name", reqInfo.BucketName), zap.Error(err)) } else if settings.VersioningEnabled { @@ -446,7 +442,7 @@ func containsACLHeaders(r *http.Request) bool { r.Header.Get(api.AmzGrantFullControl) != "" || r.Header.Get(api.AmzGrantWrite) != "" } -func (h *handler) getNewEAclTable(r *http.Request, objInfo *data.ObjectInfo) (*eacl.Table, error) { +func (h *handler) getNewEAclTable(r *http.Request, bktInfo *data.BucketInfo, objInfo *data.ObjectInfo) (*eacl.Table, error) { var newEaclTable *eacl.Table gateKey, err := h.gateKey(r.Context()) if err != nil { @@ -473,7 +469,7 @@ func (h *handler) getNewEAclTable(r *http.Request, objInfo *data.ObjectInfo) (*e return nil, fmt.Errorf("could not translate policy to ast: %w", err) } - bacl, err := h.obj.GetBucketACL(r.Context(), objInfo.Bucket) + bacl, err := h.obj.GetBucketACL(r.Context(), bktInfo) if err != nil { return nil, fmt.Errorf("could not get bucket eacl: %w", err) } @@ -585,32 +581,25 @@ func (h *handler) CreateBucketHandler(w http.ResponseWriter, r *http.Request) { p.ObjectLockEnabled = isLockEnabled(r.Header) - cid, err := h.obj.CreateBucket(r.Context(), &p) + bktInfo, err := h.obj.CreateBucket(r.Context(), &p) if err != nil { h.logAndSendError(w, "could not create bucket", reqInfo, err) return } if p.ObjectLockEnabled { - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) - if err != nil { - h.logAndSendError(w, "could get bucket info", reqInfo, err) - return - } - sp := &layer.PutSettingsParams{ BktInfo: bktInfo, Settings: &data.BucketSettings{VersioningEnabled: true}, } if err = h.obj.PutBucketSettings(r.Context(), sp); err != nil { h.logAndSendError(w, "couldn't enable bucket versioning", reqInfo, err, - zap.Stringer("container_id", cid)) + zap.Stringer("container_id", bktInfo.CID)) return } } - h.log.Info("bucket is created", - zap.String("container_id", cid.String())) + h.log.Info("bucket is created", zap.Stringer("container_id", bktInfo.CID)) api.WriteSuccessResponseHeadersOnly(w) } diff --git a/api/handler/tagging.go b/api/handler/tagging.go index c019327ad..289a21f3b 100644 --- a/api/handler/tagging.go +++ b/api/handler/tagging.go @@ -30,13 +30,14 @@ func (h *handler) PutObjectTaggingHandler(w http.ResponseWriter, r *http.Request return } - if err = h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: reqInfo.URL.Query().Get("versionId"), } @@ -62,13 +63,14 @@ func (h *handler) PutObjectTaggingHandler(w http.ResponseWriter, r *http.Request func (h *handler) GetObjectTaggingHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - if err := h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, + BktInfo: bktInfo, Object: reqInfo.ObjectName, VersionID: reqInfo.URL.Query().Get("versionId"), } @@ -94,15 +96,16 @@ func (h *handler) GetObjectTaggingHandler(w http.ResponseWriter, r *http.Request func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - p := &layer.HeadObjectParams{ - Bucket: reqInfo.BucketName, - Object: reqInfo.ObjectName, - VersionID: reqInfo.URL.Query().Get("versionId"), + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) + return } - if err := h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return + p := &layer.HeadObjectParams{ + BktInfo: bktInfo, + Object: reqInfo.ObjectName, + VersionID: reqInfo.URL.Query().Get("versionId"), } objInfo, err := h.obj.GetObjectInfo(r.Context(), p) @@ -111,7 +114,7 @@ func (h *handler) DeleteObjectTaggingHandler(w http.ResponseWriter, r *http.Requ return } - if err = h.obj.DeleteObjectTagging(r.Context(), objInfo); err != nil { + if err = h.obj.DeleteObjectTagging(r.Context(), bktInfo, objInfo); err != nil { h.logAndSendError(w, "could not delete object tagging", reqInfo, err) return } @@ -127,26 +130,28 @@ func (h *handler) PutBucketTaggingHandler(w http.ResponseWriter, r *http.Request return } - if err = h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := h.obj.PutBucketTagging(r.Context(), reqInfo.BucketName, tagSet); err != nil { + if err = h.obj.PutBucketTagging(r.Context(), bktInfo, tagSet); err != nil { h.logAndSendError(w, "could not put object tagging", reqInfo, err) + return } - w.WriteHeader(http.StatusOK) } func (h *handler) GetBucketTaggingHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - if err := h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - tagSet, err := h.obj.GetBucketTagging(r.Context(), reqInfo.BucketName) + tagSet, err := h.obj.GetBucketTagging(r.Context(), bktInfo) if err != nil { h.logAndSendError(w, "could not get object tagging", reqInfo, err) return @@ -154,17 +159,22 @@ func (h *handler) GetBucketTaggingHandler(w http.ResponseWriter, r *http.Request if err = api.EncodeToResponse(w, encodeTagging(tagSet)); err != nil { h.logAndSendError(w, "something went wrong", reqInfo, err) + return } } func (h *handler) DeleteBucketTaggingHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - if err := h.checkBucketOwner(r, reqInfo.BucketName); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) + + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) + if err != nil { + h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err := h.obj.DeleteBucketTagging(r.Context(), reqInfo.BucketName); err != nil { - h.logAndSendError(w, "could not delete object tagging", reqInfo, err) + + if err = h.obj.DeleteBucketTagging(r.Context(), bktInfo); err != nil { + h.logAndSendError(w, "could not delete bucket tagging", reqInfo, err) + return } w.WriteHeader(http.StatusNoContent) } diff --git a/api/handler/util.go b/api/handler/util.go index dfbc465c1..e7cbc3afa 100644 --- a/api/handler/util.go +++ b/api/handler/util.go @@ -5,6 +5,8 @@ import ( "strconv" "strings" + "github.com/nspcc-dev/neofs-s3-gw/api/data" + "github.com/nspcc-dev/neofs-s3-gw/api" "github.com/nspcc-dev/neofs-s3-gw/api/errors" "github.com/nspcc-dev/neofs-s3-gw/api/layer" @@ -23,24 +25,24 @@ func (h *handler) logAndSendError(w http.ResponseWriter, logText string, reqInfo api.WriteErrorResponse(w, reqInfo, err) } -func (h *handler) checkBucketOwner(r *http.Request, bucket string, header ...string) error { +func (h *handler) getBucketAndCheckOwner(r *http.Request, bucket string, header ...string) (*data.BucketInfo, error) { + bktInfo, err := h.obj.GetBucketInfo(r.Context(), bucket) + if err != nil { + return nil, err + } + var expected string if len(header) == 0 { expected = r.Header.Get(api.AmzExpectedBucketOwner) } else { - expected = header[0] + expected = r.Header.Get(header[0]) } if len(expected) == 0 { - return nil + return bktInfo, nil } - bktInfo, err := h.obj.GetBucketInfo(r.Context(), bucket) - if err != nil { - return err - } - - return checkOwner(bktInfo, expected) + return bktInfo, checkOwner(bktInfo, expected) } func parseRange(s string) (*layer.RangeParams, error) { diff --git a/api/handler/versioning.go b/api/handler/versioning.go index 70bc16e3d..21f943705 100644 --- a/api/handler/versioning.go +++ b/api/handler/versioning.go @@ -21,15 +21,11 @@ func (h *handler) PutBucketVersioningHandler(w http.ResponseWriter, r *http.Requ return } - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo) if err != nil { @@ -51,24 +47,18 @@ func (h *handler) PutBucketVersioningHandler(w http.ResponseWriter, r *http.Requ if err = h.obj.PutBucketSettings(r.Context(), p); err != nil { h.logAndSendError(w, "couldn't put update versioning settings", reqInfo, err) - return } - w.WriteHeader(http.StatusOK) } // GetBucketVersioningHandler implements bucket versioning getter handler. func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Request) { reqInfo := api.GetReqInfo(r.Context()) - bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName) + bktInfo, err := h.getBucketAndCheckOwner(r, reqInfo.BucketName) if err != nil { h.logAndSendError(w, "could not get bucket info", reqInfo, err) return } - if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil { - h.logAndSendError(w, "expected owner doesn't match", reqInfo, err) - return - } settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo) if err != nil { diff --git a/api/layer/container.go b/api/layer/container.go index 89af0ea95..8a99da0d5 100644 --- a/api/layer/container.go +++ b/api/layer/container.go @@ -122,7 +122,7 @@ func (n *layer) containerList(ctx context.Context) ([]*data.BucketInfo, error) { return list, nil } -func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*cid.ID, error) { +func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*data.BucketInfo, error) { var err error bktInfo := &data.BucketInfo{ Name: p.Name, @@ -130,6 +130,7 @@ func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*ci Created: time.Now(), BasicACL: p.ACL, LocationConstraint: p.LocationConstraint, + ObjectLockEnabled: p.ObjectLockEnabled, } var attributes [][2]string @@ -169,7 +170,7 @@ func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*ci zap.Error(err)) } - return bktInfo.CID, nil + return bktInfo, nil } func (n *layer) setContainerEACLTable(ctx context.Context, idCnr *cid.ID, table *eacl.Table) error { diff --git a/api/layer/layer.go b/api/layer/layer.go index f38f324e6..fec8c09cf 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -84,7 +84,7 @@ type ( // HeadObjectParams stores object head request parameters. HeadObjectParams struct { - Bucket string + BktInfo *data.BucketInfo Object string VersionID string } @@ -97,12 +97,12 @@ type ( // PutObjectParams stores object put request parameters. PutObjectParams struct { - Bucket string - Object string - Size int64 - Reader io.Reader - Header map[string]string - Lock *data.ObjectLock + BktInfo *data.BucketInfo + Object string + Size int64 + Reader io.Reader + Header map[string]string + Lock *data.ObjectLock } // PutSettingsParams stores object copy request parameters. @@ -119,13 +119,13 @@ type ( // CopyObjectParams stores object copy request parameters. CopyObjectParams struct { - SrcObject *data.ObjectInfo - DstBucket string - DstObject string - SrcSize int64 - Header map[string]string - Range *RangeParams - Lock *data.ObjectLock + SrcObject *data.ObjectInfo + DstBktInfo *data.BucketInfo + DstObject string + SrcSize int64 + Header map[string]string + Range *RangeParams + Lock *data.ObjectLock } // CreateBucketParams stores bucket create request parameters. CreateBucketParams struct { @@ -139,12 +139,12 @@ type ( } // PutBucketACLParams stores put bucket acl request parameters. PutBucketACLParams struct { - Name string - EACL *eacl.Table + BktInfo *data.BucketInfo + EACL *eacl.Table } // DeleteBucketParams stores delete bucket request parameters. DeleteBucketParams struct { - Name string + BktInfo *data.BucketInfo } // PutSystemObjectParams stores putSystemObject parameters. @@ -159,7 +159,7 @@ type ( // ListObjectVersionsParams stores list objects versions parameters. ListObjectVersionsParams struct { - Bucket string + BktInfo *data.BucketInfo Delimiter string KeyMarker string MaxKeys int @@ -196,21 +196,21 @@ type ( ListBuckets(ctx context.Context) ([]*data.BucketInfo, error) GetBucketInfo(ctx context.Context, name string) (*data.BucketInfo, error) - GetBucketACL(ctx context.Context, name string) (*BucketACL, error) + GetBucketACL(ctx context.Context, bktInfo *data.BucketInfo) (*BucketACL, error) PutBucketACL(ctx context.Context, p *PutBucketACLParams) error - CreateBucket(ctx context.Context, p *CreateBucketParams) (*cid.ID, error) + CreateBucket(ctx context.Context, p *CreateBucketParams) (*data.BucketInfo, error) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error GetObject(ctx context.Context, p *GetObjectParams) error HeadSystemObject(ctx context.Context, bktInfo *data.BucketInfo, name string) (*data.ObjectInfo, error) GetObjectInfo(ctx context.Context, p *HeadObjectParams) (*data.ObjectInfo, error) GetObjectTagging(ctx context.Context, p *data.ObjectInfo) (map[string]string, error) - GetBucketTagging(ctx context.Context, bucket string) (map[string]string, error) + GetBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) (map[string]string, error) PutObject(ctx context.Context, p *PutObjectParams) (*data.ObjectInfo, error) PutSystemObject(ctx context.Context, p *PutSystemObjectParams) (*data.ObjectInfo, error) PutObjectTagging(ctx context.Context, p *PutTaggingParams) error - PutBucketTagging(ctx context.Context, bucket string, tagSet map[string]string) error + PutBucketTagging(ctx context.Context, bktInfo *data.BucketInfo, tagSet map[string]string) error CopyObject(ctx context.Context, p *CopyObjectParams) (*data.ObjectInfo, error) @@ -218,10 +218,10 @@ type ( ListObjectsV2(ctx context.Context, p *ListObjectsParamsV2) (*ListObjectsInfoV2, error) ListObjectVersions(ctx context.Context, p *ListObjectVersionsParams) (*ListObjectVersionsInfo, error) - DeleteObjects(ctx context.Context, bucket string, objects []*VersionedObject) ([]*VersionedObject, error) + DeleteObjects(ctx context.Context, bktInfo *data.BucketInfo, objects []*VersionedObject) ([]*VersionedObject, error) DeleteSystemObject(ctx context.Context, bktInfo *data.BucketInfo, name string) error - DeleteObjectTagging(ctx context.Context, p *data.ObjectInfo) error - DeleteBucketTagging(ctx context.Context, bucket string) error + DeleteObjectTagging(ctx context.Context, bktInfo *data.BucketInfo, objInfo *data.ObjectInfo) error + DeleteBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) error CompleteMultipartUpload(ctx context.Context, p *CompleteMultipartParams) (*data.ObjectInfo, error) UploadPart(ctx context.Context, p *UploadPartParams) (*data.ObjectInfo, error) @@ -355,31 +355,21 @@ func (n *layer) GetBucketInfo(ctx context.Context, name string) (*data.BucketInf } // GetBucketACL returns bucket acl info by name. -func (n *layer) GetBucketACL(ctx context.Context, name string) (*BucketACL, error) { - inf, err := n.GetBucketInfo(ctx, name) - if err != nil { - return nil, err - } - - eACL, err := n.GetContainerEACL(ctx, inf.CID) +func (n *layer) GetBucketACL(ctx context.Context, bktInfo *data.BucketInfo) (*BucketACL, error) { + eACL, err := n.GetContainerEACL(ctx, bktInfo.CID) if err != nil { return nil, err } return &BucketACL{ - Info: inf, + Info: bktInfo, EACL: eACL, }, nil } // PutBucketACL put bucket acl by name. func (n *layer) PutBucketACL(ctx context.Context, param *PutBucketACLParams) error { - inf, err := n.GetBucketInfo(ctx, param.Name) - if err != nil { - return err - } - - return n.setContainerEACLTable(ctx, inf.CID, param.EACL) + return n.setContainerEACLTable(ctx, param.BktInfo.CID, param.EACL) } // ListBuckets returns all user containers. Name of the bucket is a container @@ -427,27 +417,11 @@ func (n *layer) GetObject(ctx context.Context, p *GetObjectParams) error { // GetObjectInfo returns meta information about the object. func (n *layer) GetObjectInfo(ctx context.Context, p *HeadObjectParams) (*data.ObjectInfo, error) { - bkt, err := n.GetBucketInfo(ctx, p.Bucket) - if err != nil { - n.log.Error("could not fetch bucket info", zap.Error(err)) - return nil, err - } - if len(p.VersionID) == 0 { - return n.headLastVersionIfNotDeleted(ctx, bkt, p.Object) + return n.headLastVersionIfNotDeleted(ctx, p.BktInfo, p.Object) } - return n.headVersion(ctx, bkt, p) -} - -// PutObject into storage. -func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*data.ObjectInfo, error) { - bkt, err := n.GetBucketInfo(ctx, p.Bucket) - if err != nil { - return nil, err - } - - return n.objectPut(ctx, bkt, p) + return n.headVersion(ctx, p.BktInfo, p) } // GetObjectTagging from storage. @@ -467,13 +441,8 @@ func (n *layer) GetObjectTagging(ctx context.Context, oi *data.ObjectInfo) (map[ } // GetBucketTagging from storage. -func (n *layer) GetBucketTagging(ctx context.Context, bucketName string) (map[string]string, error) { - bktInfo, err := n.GetBucketInfo(ctx, bucketName) - if err != nil { - return nil, err - } - - objInfo, err := n.HeadSystemObject(ctx, bktInfo, formBucketTagObjectName(bucketName)) +func (n *layer) GetBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) (map[string]string, error) { + objInfo, err := n.HeadSystemObject(ctx, bktInfo, formBucketTagObjectName(bktInfo.Name)) if err != nil && !errors.IsS3Error(err, errors.ErrNoSuchKey) { return nil, err } @@ -518,41 +487,27 @@ func (n *layer) PutObjectTagging(ctx context.Context, p *PutTaggingParams) error } // PutBucketTagging into storage. -func (n *layer) PutBucketTagging(ctx context.Context, bucketName string, tagSet map[string]string) error { - bktInfo, err := n.GetBucketInfo(ctx, bucketName) - if err != nil { - return err - } - +func (n *layer) PutBucketTagging(ctx context.Context, bktInfo *data.BucketInfo, tagSet map[string]string) error { s := &PutSystemObjectParams{ BktInfo: bktInfo, - ObjName: formBucketTagObjectName(bucketName), + ObjName: formBucketTagObjectName(bktInfo.Name), Metadata: tagSet, Prefix: tagPrefix, Reader: nil, } - _, err = n.PutSystemObject(ctx, s) + _, err := n.PutSystemObject(ctx, s) return err } // DeleteObjectTagging from storage. -func (n *layer) DeleteObjectTagging(ctx context.Context, p *data.ObjectInfo) error { - bktInfo, err := n.GetBucketInfo(ctx, p.Bucket) - if err != nil { - return err - } - return n.DeleteSystemObject(ctx, bktInfo, p.TagsObject()) +func (n *layer) DeleteObjectTagging(ctx context.Context, bktInfo *data.BucketInfo, objInfo *data.ObjectInfo) error { + return n.DeleteSystemObject(ctx, bktInfo, objInfo.TagsObject()) } // DeleteBucketTagging from storage. -func (n *layer) DeleteBucketTagging(ctx context.Context, bucketName string) error { - bktInfo, err := n.GetBucketInfo(ctx, bucketName) - if err != nil { - return err - } - - return n.DeleteSystemObject(ctx, bktInfo, formBucketTagObjectName(bucketName)) +func (n *layer) DeleteBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) error { + return n.DeleteSystemObject(ctx, bktInfo, formBucketTagObjectName(bktInfo.Name)) } // CopyObject from one bucket into another bucket. @@ -572,11 +527,11 @@ func (n *layer) CopyObject(ctx context.Context, p *CopyObjectParams) (*data.Obje }() return n.PutObject(ctx, &PutObjectParams{ - Bucket: p.DstBucket, - Object: p.DstObject, - Size: p.SrcSize, - Reader: pr, - Header: p.Header, + BktInfo: p.DstBktInfo, + Object: p.DstObject, + Size: p.SrcSize, + Reader: pr, + Header: p.Header, }) } @@ -588,9 +543,10 @@ func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, obj *Ver ) p := &PutObjectParams{ - Object: obj.Name, - Reader: bytes.NewReader(nil), - Header: map[string]string{}, + BktInfo: bkt, + Object: obj.Name, + Reader: bytes.NewReader(nil), + Header: map[string]string{}, } versioningEnabled := n.isVersioningEnabled(ctx, bkt) @@ -637,14 +593,14 @@ func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, obj *Ver obj.Error = err return obj } - if err = n.DeleteObjectTagging(ctx, &data.ObjectInfo{ID: id, Bucket: bkt.Name, Name: obj.Name}); err != nil { + if err = n.DeleteObjectTagging(ctx, bkt, &data.ObjectInfo{ID: id, Bucket: bkt.Name, Name: obj.Name}); err != nil { obj.Error = err return obj } } n.listsCache.CleanCacheEntriesContainingObject(obj.Name, bkt.CID) - objInfo, err := n.objectPut(ctx, bkt, p) + objInfo, err := n.PutObject(ctx, p) if err != nil { obj.Error = err return obj @@ -657,20 +613,15 @@ func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, obj *Ver } // DeleteObjects from the storage. -func (n *layer) DeleteObjects(ctx context.Context, bucket string, objects []*VersionedObject) ([]*VersionedObject, error) { - bkt, err := n.GetBucketInfo(ctx, bucket) - if err != nil { - return nil, err - } - +func (n *layer) DeleteObjects(ctx context.Context, bktInfo *data.BucketInfo, objects []*VersionedObject) ([]*VersionedObject, error) { for i, obj := range objects { - objects[i] = n.deleteObject(ctx, bkt, obj) + objects[i] = n.deleteObject(ctx, bktInfo, obj) } return objects, nil } -func (n *layer) CreateBucket(ctx context.Context, p *CreateBucketParams) (*cid.ID, error) { +func (n *layer) CreateBucket(ctx context.Context, p *CreateBucketParams) (*data.BucketInfo, error) { bktInfo, err := n.GetBucketInfo(ctx, p.Name) if err != nil { if errors.IsS3Error(err, errors.ErrNoSuchBucket) { @@ -696,12 +647,7 @@ func (n *layer) ResolveBucket(ctx context.Context, name string) (*cid.ID, error) } func (n *layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error { - bucketInfo, err := n.GetBucketInfo(ctx, p.Name) - if err != nil { - return err - } - - objects, err := n.listSortedObjects(ctx, allObjectParams{Bucket: bucketInfo}) + objects, err := n.listSortedObjects(ctx, allObjectParams{Bucket: p.BktInfo}) if err != nil { return err } @@ -709,9 +655,6 @@ func (n *layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error { return errors.GetAPIError(errors.ErrBucketNotEmpty) } - n.bucketCache.Delete(bucketInfo.Name) - if err = n.deleteContainer(ctx, bucketInfo.CID); err != nil { - return err - } - return nil + n.bucketCache.Delete(p.BktInfo.Name) + return n.deleteContainer(ctx, p.BktInfo.CID) } diff --git a/api/layer/multipart_upload.go b/api/layer/multipart_upload.go index 8469c70f0..52e57c288 100644 --- a/api/layer/multipart_upload.go +++ b/api/layer/multipart_upload.go @@ -128,14 +128,14 @@ func (n *layer) UploadPart(ctx context.Context, p *UploadPartParams) (*data.Obje appendUploadHeaders(p.Header, p.Info.UploadID, p.Info.Key, p.PartNumber) params := &PutObjectParams{ - Bucket: p.Info.Bkt.Name, - Object: createUploadPartName(p.Info.UploadID, p.Info.Key, p.PartNumber), - Size: p.Size, - Reader: p.Reader, - Header: p.Header, + BktInfo: p.Info.Bkt, + Object: createUploadPartName(p.Info.UploadID, p.Info.Key, p.PartNumber), + Size: p.Size, + Reader: p.Reader, + Header: p.Header, } - return n.objectPut(ctx, p.Info.Bkt, params) + return n.PutObject(ctx, params) } func (n *layer) UploadPartCopy(ctx context.Context, p *UploadCopyParams) (*data.ObjectInfo, error) { @@ -160,12 +160,12 @@ func (n *layer) UploadPartCopy(ctx context.Context, p *UploadCopyParams) (*data. appendUploadHeaders(metadata, p.Info.UploadID, p.Info.Key, p.PartNumber) c := &CopyObjectParams{ - SrcObject: p.SrcObjInfo, - DstBucket: p.Info.Bkt.Name, - DstObject: createUploadPartName(p.Info.UploadID, p.Info.Key, p.PartNumber), - SrcSize: p.SrcObjInfo.Size, - Header: metadata, - Range: p.Range, + SrcObject: p.SrcObjInfo, + DstBktInfo: p.Info.Bkt, + DstObject: createUploadPartName(p.Info.UploadID, p.Info.Key, p.PartNumber), + SrcSize: p.SrcObjInfo.Size, + Header: metadata, + Range: p.Range, } return n.CopyObject(ctx, c) @@ -287,11 +287,11 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar r.prm.cid = p.Info.Bkt.CID - obj, err = n.objectPut(ctx, p.Info.Bkt, &PutObjectParams{ - Bucket: p.Info.Bkt.Name, - Object: p.Info.Key, - Reader: r, - Header: initMetadata, + obj, err = n.PutObject(ctx, &PutObjectParams{ + BktInfo: p.Info.Bkt, + Object: p.Info.Key, + Reader: r, + Header: initMetadata, }) if err != nil { n.log.Error("could not put a completed object (multipart upload)", diff --git a/api/layer/object.go b/api/layer/object.go index 2ae9a6e39..5fad1d14d 100644 --- a/api/layer/object.go +++ b/api/layer/object.go @@ -38,7 +38,7 @@ type ( // ListObjectsParamsCommon contains common parameters for ListObjectsV1 and ListObjectsV2. ListObjectsParamsCommon struct { - Bucket string + BktInfo *data.BucketInfo Delimiter string Encode string MaxKeys int @@ -153,12 +153,12 @@ func (n *layer) objectGet(ctx context.Context, addr *address.Address) (*object.O return res.Head, nil } -// objectPut into NeoFS, took payload from io.Reader. -func (n *layer) objectPut(ctx context.Context, bkt *data.BucketInfo, p *PutObjectParams) (*data.ObjectInfo, error) { +// PutObject stores object into NeoFS, took payload from io.Reader. +func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*data.ObjectInfo, error) { own := n.Owner(ctx) - versioningEnabled := n.isVersioningEnabled(ctx, bkt) - versions, err := n.headVersions(ctx, bkt, p.Object) + versioningEnabled := n.isVersioningEnabled(ctx, p.BktInfo) + versions, err := n.headVersions(ctx, p.BktInfo, p.Object) if err != nil && !apiErrors.IsS3Error(err, apiErrors.ErrNoSuchKey) { return nil, err } @@ -176,7 +176,7 @@ func (n *layer) objectPut(ctx context.Context, bkt *data.BucketInfo, p *PutObjec } prm := neofs.PrmObjectCreate{ - Container: *bkt.CID, + Container: *p.BktInfo.CID, Creator: *own, PayloadSize: uint64(p.Size), Filename: p.Object, @@ -206,18 +206,18 @@ func (n *layer) objectPut(ctx context.Context, bkt *data.BucketInfo, p *PutObjec objInfo := &data.ObjectInfo{ID: id, Name: p.Object} p.Lock.Objects = append(p.Lock.Objects, *id) if p.Lock.LegalHold { - if err = n.putLockObject(ctx, bkt, objInfo.LegalHoldObject(), p.Lock); err != nil { + if err = n.putLockObject(ctx, p.BktInfo, objInfo.LegalHoldObject(), p.Lock); err != nil { return nil, err } } if !p.Lock.Until.IsZero() { - if err = n.putLockObject(ctx, bkt, objInfo.RetentionObject(), p.Lock); err != nil { + if err = n.putLockObject(ctx, p.BktInfo, objInfo.RetentionObject(), p.Lock); err != nil { return nil, err } } } - meta, err := n.objectHead(ctx, bkt.CID, id) + meta, err := n.objectHead(ctx, p.BktInfo.CID, id) if err != nil { return nil, err } @@ -226,17 +226,17 @@ func (n *layer) objectPut(ctx context.Context, bkt *data.BucketInfo, p *PutObjec n.log.Error("couldn't cache an object", zap.Error(err)) } - n.listsCache.CleanCacheEntriesContainingObject(p.Object, bkt.CID) + n.listsCache.CleanCacheEntriesContainingObject(p.Object, p.BktInfo.CID) for _, id := range idsToDeleteArr { - if err = n.objectDelete(ctx, bkt.CID, id); err != nil { + if err = n.objectDelete(ctx, p.BktInfo.CID, id); err != nil { n.log.Warn("couldn't delete object", zap.Stringer("version id", id), zap.Error(err)) } if !versioningEnabled { if objVersion := versions.getVersion(id); objVersion != nil { - if err = n.DeleteObjectTagging(ctx, objVersion); err != nil { + if err = n.DeleteObjectTagging(ctx, p.BktInfo, objVersion); err != nil { n.log.Warn("couldn't delete object tagging", zap.Stringer("version id", id), zap.Error(err)) @@ -247,10 +247,10 @@ func (n *layer) objectPut(ctx context.Context, bkt *data.BucketInfo, p *PutObjec return &data.ObjectInfo{ ID: id, - CID: bkt.CID, + CID: p.BktInfo.CID, Owner: own, - Bucket: p.Bucket, + Bucket: p.BktInfo.Name, Name: p.Object, Size: p.Size, Created: time.Now(), @@ -644,16 +644,11 @@ func triageObjects(allObjects []*data.ObjectInfo) (prefixes []string, objects [] func (n *layer) listAllObjects(ctx context.Context, p ListObjectsParamsCommon) ([]*data.ObjectInfo, error) { var ( err error - bkt *data.BucketInfo allObjects []*data.ObjectInfo ) - if bkt, err = n.GetBucketInfo(ctx, p.Bucket); err != nil { - return nil, err - } - allObjects, err = n.listSortedObjects(ctx, allObjectParams{ - Bucket: bkt, + Bucket: p.BktInfo, Prefix: p.Prefix, Delimiter: p.Delimiter, }) diff --git a/api/layer/versioning.go b/api/layer/versioning.go index 9bebe362b..bf44293c5 100644 --- a/api/layer/versioning.go +++ b/api/layer/versioning.go @@ -283,18 +283,13 @@ func (v *objectVersions) getVersion(oid *oid.ID) *data.ObjectInfo { return nil } func (n *layer) PutBucketVersioning(ctx context.Context, p *PutSettingsParams) (*data.ObjectInfo, error) { - bktInfo, err := n.GetBucketInfo(ctx, p.BktInfo.Name) - if err != nil { - return nil, err - } - metadata := map[string]string{ attrSettingsVersioningEnabled: strconv.FormatBool(p.Settings.VersioningEnabled), } s := &PutSystemObjectParams{ - BktInfo: bktInfo, - ObjName: bktInfo.SettingsObjectName(), + BktInfo: p.BktInfo, + ObjName: p.BktInfo.SettingsObjectName(), Metadata: metadata, Prefix: "", Reader: nil, @@ -303,32 +298,22 @@ func (n *layer) PutBucketVersioning(ctx context.Context, p *PutSettingsParams) ( return n.PutSystemObject(ctx, s) } -func (n *layer) GetBucketVersioning(ctx context.Context, bucketName string) (*data.BucketSettings, error) { - bktInfo, err := n.GetBucketInfo(ctx, bucketName) - if err != nil { - return nil, err - } - +func (n *layer) GetBucketVersioning(ctx context.Context, bktInfo *data.BucketInfo) (*data.BucketSettings, error) { return n.GetBucketSettings(ctx, bktInfo) } func (n *layer) ListObjectVersions(ctx context.Context, p *ListObjectVersionsParams) (*ListObjectVersionsInfo, error) { var ( - versions map[string]*objectVersions allObjects = make([]*data.ObjectInfo, 0, p.MaxKeys) res = &ListObjectVersionsInfo{} reverse = true ) - bkt, err := n.GetBucketInfo(ctx, p.Bucket) + versions, err := n.getAllObjectsVersions(ctx, p.BktInfo, p.Prefix, p.Delimiter) if err != nil { return nil, err } - if versions, err = n.getAllObjectsVersions(ctx, bkt, p.Prefix, p.Delimiter); err != nil { - return nil, err - } - sortedNames := make([]string, 0, len(versions)) for k := range versions { sortedNames = append(sortedNames, k) diff --git a/api/layer/versioning_test.go b/api/layer/versioning_test.go index ed6cee3c6..ceb4a4749 100644 --- a/api/layer/versioning_test.go +++ b/api/layer/versioning_test.go @@ -13,7 +13,6 @@ import ( "github.com/nspcc-dev/neofs-s3-gw/api/layer/neofs" "github.com/nspcc-dev/neofs-s3-gw/creds/accessbox" "github.com/nspcc-dev/neofs-s3-gw/internal/neofstest" - cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/logger" "github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/object/address" @@ -25,11 +24,11 @@ import ( func (tc *testContext) putObject(content []byte) *data.ObjectInfo { objInfo, err := tc.layer.PutObject(tc.ctx, &PutObjectParams{ - Bucket: tc.bktID.String(), - Object: tc.obj, - Size: int64(len(content)), - Reader: bytes.NewReader(content), - Header: make(map[string]string), + BktInfo: tc.bktInfo, + Object: tc.obj, + Size: int64(len(content)), + Reader: bytes.NewReader(content), + Header: make(map[string]string), }) require.NoError(tc.t, err) @@ -38,7 +37,7 @@ func (tc *testContext) putObject(content []byte) *data.ObjectInfo { func (tc *testContext) getObject(objectName, versionID string, needError bool) (*data.ObjectInfo, []byte) { objInfo, err := tc.layer.GetObjectInfo(tc.ctx, &HeadObjectParams{ - Bucket: tc.bkt, + BktInfo: tc.bktInfo, Object: objectName, VersionID: versionID, }) @@ -60,7 +59,7 @@ func (tc *testContext) getObject(objectName, versionID string, needError bool) ( } func (tc *testContext) deleteObject(objectName, versionID string) { - deletedObjects, err := tc.layer.DeleteObjects(tc.ctx, tc.bkt, []*VersionedObject{ + deletedObjects, err := tc.layer.DeleteObjects(tc.ctx, tc.bktInfo, []*VersionedObject{ {Name: objectName, VersionID: versionID}, }) require.NoError(tc.t, err) @@ -72,7 +71,7 @@ func (tc *testContext) deleteObject(objectName, versionID string) { func (tc *testContext) listObjectsV1() []*data.ObjectInfo { res, err := tc.layer.ListObjectsV1(tc.ctx, &ListObjectsParamsV1{ ListObjectsParamsCommon: ListObjectsParamsCommon{ - Bucket: tc.bkt, + BktInfo: tc.bktInfo, MaxKeys: 1000, }, }) @@ -83,7 +82,7 @@ func (tc *testContext) listObjectsV1() []*data.ObjectInfo { func (tc *testContext) listObjectsV2() []*data.ObjectInfo { res, err := tc.layer.ListObjectsV2(tc.ctx, &ListObjectsParamsV2{ ListObjectsParamsCommon: ListObjectsParamsCommon{ - Bucket: tc.bkt, + BktInfo: tc.bktInfo, MaxKeys: 1000, }, }) @@ -93,7 +92,7 @@ func (tc *testContext) listObjectsV2() []*data.ObjectInfo { func (tc *testContext) listVersions() *ListObjectVersionsInfo { res, err := tc.layer.ListObjectVersions(tc.ctx, &ListObjectVersionsParams{ - Bucket: tc.bkt, + BktInfo: tc.bktInfo, MaxKeys: 1000, }) require.NoError(tc.t, err) @@ -129,8 +128,6 @@ type testContext struct { t *testing.T ctx context.Context layer Client - bkt string - bktID *cid.ID bktInfo *data.BucketInfo obj string testNeoFS *neofstest.TestNeoFS @@ -172,12 +169,10 @@ func prepareContext(t *testing.T, cachesConfig ...*CachesConfig) *testContext { return &testContext{ ctx: ctx, layer: NewLayer(l, tp, layerCfg), - bkt: bktName, - bktID: bktID, bktInfo: &data.BucketInfo{ Name: bktName, - CID: bktID, Owner: owner.NewID(), + CID: bktID, }, obj: "obj1", t: t, @@ -632,12 +627,7 @@ func TestSystemObjectsVersioning(t *testing.T) { // simulate failed deletion tc.testNeoFS.AddObject(addr.String(), objMeta) - bktInfo := &data.BucketInfo{ - Name: tc.bkt, - CID: tc.bktID, - } - - versioning, err := tc.layer.GetBucketSettings(tc.ctx, bktInfo) + versioning, err := tc.layer.GetBucketSettings(tc.ctx, tc.bktInfo) require.NoError(t, err) require.True(t, versioning.VersioningEnabled) } @@ -652,19 +642,19 @@ func TestDeleteSystemObjectsVersioning(t *testing.T) { "tag1": "val1", } - err := tc.layer.PutBucketTagging(tc.ctx, tc.bktID.String(), tagSet) + err := tc.layer.PutBucketTagging(tc.ctx, tc.bktInfo, tagSet) require.NoError(t, err) - objMeta := tc.getSystemObject(formBucketTagObjectName(tc.bktID.String())) + objMeta := tc.getSystemObject(formBucketTagObjectName(tc.bktInfo.CID.String())) tagSet["tag2"] = "val2" - err = tc.layer.PutBucketTagging(tc.ctx, tc.bkt, tagSet) + err = tc.layer.PutBucketTagging(tc.ctx, tc.bktInfo, tagSet) require.NoError(t, err) // simulate failed deletion tc.testNeoFS.AddObject(newAddress(objMeta.ContainerID(), objMeta.ID()).String(), objMeta) - tagging, err := tc.layer.GetBucketTagging(tc.ctx, tc.bkt) + tagging, err := tc.layer.GetBucketTagging(tc.ctx, tc.bktInfo) require.NoError(t, err) expectedTagSet := map[string]string{ @@ -673,8 +663,8 @@ func TestDeleteSystemObjectsVersioning(t *testing.T) { } require.Equal(t, expectedTagSet, tagging) - err = tc.layer.DeleteBucketTagging(tc.ctx, tc.bkt) + err = tc.layer.DeleteBucketTagging(tc.ctx, tc.bktInfo) require.NoError(t, err) - require.Nil(t, tc.getSystemObject(formBucketTagObjectName(tc.bkt))) + require.Nil(t, tc.getSystemObject(formBucketTagObjectName(tc.bktInfo.Name))) }