From 93f871cd1f53a2b654f5fb498cccbbf987427dc6 Mon Sep 17 00:00:00 2001 From: Pavel Pogodaev Date: Fri, 19 Jul 2024 22:20:40 +0300 Subject: [PATCH] [#31] Add force bucket delete flag Signed-off-by: Pavel Pogodaev --- api/errors/errors.go | 7 +++++++ api/handler/delete.go | 13 ++++++++++++- api/headers.go | 1 + api/layer/layer.go | 4 ++-- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/api/errors/errors.go b/api/errors/errors.go index 096b25b..de9389f 100644 --- a/api/errors/errors.go +++ b/api/errors/errors.go @@ -277,6 +277,7 @@ const ( ErrEvaluatorBindingDoesNotExist ErrMissingHeaders ErrInvalidColumnIndex + ErrMissingForceBucketDeleteHeader ErrPostPolicyConditionInvalidFormat @@ -1709,6 +1710,12 @@ var errorCodes = errorCodeMap{ Description: "Some headers in the query are missing from the file. Check the file and try again.", HTTPStatusCode: http.StatusBadRequest, }, + ErrMissingForceBucketDeleteHeader: { + ErrCode: ErrMissingForceBucketDeleteHeader, + Code: "ErrMissingForceBucketDeleteHeader", + Description: "Missing X-Amz-Force-Bucket-Delete header.", + HTTPStatusCode: http.StatusBadRequest, + }, ErrInvalidColumnIndex: { ErrCode: ErrInvalidColumnIndex, Code: "InvalidColumnIndex", diff --git a/api/handler/delete.go b/api/handler/delete.go index 7fc081e..1715705 100644 --- a/api/handler/delete.go +++ b/api/handler/delete.go @@ -237,10 +237,21 @@ func (h *handler) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) { sessionToken = boxData.Gate.SessionTokenForDelete() } + skipObjCheck := false + if value, ok := r.Header[api.AmzForceBucketDelete]; !ok { + h.logAndSendError(w, "missing X-Amz-Force-Delete-Bucket", reqInfo, errors.GetAPIError(errors.ErrMissingForceBucketDeleteHeader)) + return + } else { + s := value[0] + if s == "true" { + skipObjCheck = true + } + } + if err = h.obj.DeleteBucket(r.Context(), &layer.DeleteBucketParams{ BktInfo: bktInfo, SessionToken: sessionToken, - }); err != nil { + }, skipObjCheck); err != nil { h.logAndSendError(w, "couldn't delete bucket", reqInfo, err) return } diff --git a/api/headers.go b/api/headers.go index a91149c..540d3cc 100644 --- a/api/headers.go +++ b/api/headers.go @@ -62,6 +62,7 @@ const ( AmzMaxParts = "X-Amz-Max-Parts" AmzPartNumberMarker = "X-Amz-Part-Number-Marker" AmzStorageClass = "X-Amz-Storage-Class" + AmzForceBucketDelete = "X-Amz-Force-Delete-Bucket" AmzServerSideEncryptionCustomerAlgorithm = "x-amz-server-side-encryption-customer-algorithm" AmzServerSideEncryptionCustomerKey = "x-amz-server-side-encryption-customer-key" diff --git a/api/layer/layer.go b/api/layer/layer.go index 85fb7db..9fcf0c1 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -793,7 +793,7 @@ func (n *Layer) ResolveBucket(ctx context.Context, name string) (cid.ID, error) return cnrID, nil } -func (n *Layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error { +func (n *Layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams, skipCheck bool) error { res, _, err := n.getAllObjectsVersions(ctx, commonVersionsListingParams{ BktInfo: p.BktInfo, MaxKeys: 1, @@ -802,7 +802,7 @@ func (n *Layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error { if err != nil { return err } - if len(res) != 0 { + if len(res) != 0 && !skipCheck { return errors.GetAPIError(errors.ErrBucketNotEmpty) }