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)
}