github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/gateway/operations/deleteobject.go (about) 1 package operations 2 3 import ( 4 "errors" 5 "net/http" 6 7 "github.com/treeverse/lakefs/pkg/block" 8 gatewayerrors "github.com/treeverse/lakefs/pkg/gateway/errors" 9 "github.com/treeverse/lakefs/pkg/graveler" 10 "github.com/treeverse/lakefs/pkg/logging" 11 "github.com/treeverse/lakefs/pkg/permissions" 12 ) 13 14 type DeleteObject struct{} 15 16 func (controller *DeleteObject) RequiredPermissions(_ *http.Request, repoID, _, path string) (permissions.Node, error) { 17 return permissions.Node{ 18 Permission: permissions.Permission{ 19 Action: permissions.DeleteObjectAction, 20 Resource: permissions.ObjectArn(repoID, path), 21 }, 22 }, nil 23 } 24 25 func (controller *DeleteObject) HandleAbortMultipartUpload(w http.ResponseWriter, req *http.Request, o *PathOperation) { 26 o.Incr("abort_mpu", o.Principal, o.Repository.Name, o.Reference) 27 query := req.URL.Query() 28 uploadID := query.Get(QueryParamUploadID) 29 30 ctx := req.Context() 31 mpu, err := o.MultipartTracker.Get(ctx, uploadID) 32 if err != nil { 33 o.Log(req).WithError(err).Error("upload id not found in tracker") 34 _ = o.EncodeError(w, req, err, gatewayerrors.Codes.ToAPIErr(gatewayerrors.ErrNoSuchKey)) 35 return 36 } 37 if mpu.Path != o.Path { 38 o.Log(req).Error("could not match multipart upload with multipart tracker record") 39 _ = o.EncodeError(w, req, err, gatewayerrors.Codes.ToAPIErr(gatewayerrors.ErrNoSuchKey)) 40 return 41 } 42 43 req = req.WithContext(logging.AddFields(ctx, logging.Fields{logging.UploadIDFieldKey: uploadID})) 44 err = o.BlockStore.AbortMultiPartUpload(ctx, block.ObjectPointer{ 45 StorageNamespace: o.Repository.StorageNamespace, 46 IdentifierType: block.IdentifierTypeRelative, 47 Identifier: mpu.PhysicalAddress, 48 }, uploadID) 49 if err != nil { 50 o.Log(req).WithError(err).Error("could not abort multipart upload") 51 _ = o.EncodeError(w, req, err, gatewayerrors.Codes.ToAPIErr(gatewayerrors.ErrInternalError)) 52 return 53 } 54 55 if err := o.MultipartTracker.Delete(ctx, uploadID); err != nil { 56 o.Log(req).WithError(err).Warn("could not delete multipart record") 57 } 58 59 w.WriteHeader(http.StatusNoContent) 60 } 61 62 func (controller *DeleteObject) Handle(w http.ResponseWriter, req *http.Request, o *PathOperation) { 63 if o.HandleUnsupported(w, req, "tagging", "acl", "torrent") { 64 return 65 } 66 query := req.URL.Query() 67 if query.Has(QueryParamUploadID) { 68 controller.HandleAbortMultipartUpload(w, req, o) 69 return 70 } 71 72 o.Incr("delete_object", o.Principal, o.Repository.Name, o.Reference) 73 lg := o.Log(req).WithField("key", o.Path) 74 err := o.Catalog.DeleteEntry(req.Context(), o.Repository.Name, o.Reference, o.Path) 75 switch { 76 case errors.Is(err, graveler.ErrNotFound): 77 lg.WithError(err).Debug("could not delete object, it doesn't exist") 78 case errors.Is(err, graveler.ErrWriteToProtectedBranch): 79 _ = o.EncodeError(w, req, err, gatewayerrors.Codes.ToAPIErr(gatewayerrors.ErrWriteToProtectedBranch)) 80 return 81 case errors.Is(err, graveler.ErrReadOnlyRepository): 82 _ = o.EncodeError(w, req, err, gatewayerrors.Codes.ToAPIErr(gatewayerrors.ErrReadOnlyRepository)) 83 return 84 case err != nil: 85 lg.WithError(err).Error("could not delete object") 86 _ = o.EncodeError(w, req, err, gatewayerrors.Codes.ToAPIErr(gatewayerrors.ErrInternalError)) 87 return 88 default: 89 lg.Debug("object set for deletion") 90 } 91 w.WriteHeader(http.StatusNoContent) 92 }