-
Notifications
You must be signed in to change notification settings - Fork 348
/
deleteobjects.go
97 lines (91 loc) · 3.13 KB
/
deleteobjects.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package operations
import (
"errors"
"fmt"
"net/http"
"github.com/treeverse/lakefs/pkg/auth"
"github.com/treeverse/lakefs/pkg/catalog"
gerrors "github.com/treeverse/lakefs/pkg/gateway/errors"
"github.com/treeverse/lakefs/pkg/gateway/path"
"github.com/treeverse/lakefs/pkg/gateway/serde"
"github.com/treeverse/lakefs/pkg/graveler"
"github.com/treeverse/lakefs/pkg/permissions"
)
type DeleteObjects struct{}
func (controller *DeleteObjects) RequiredPermissions(_ *http.Request, _ string) (permissions.Node, error) {
return permissions.Node{}, nil
}
func (controller *DeleteObjects) Handle(w http.ResponseWriter, req *http.Request, o *RepoOperation) {
o.Incr("delete_objects")
decodedXML := &serde.Delete{}
err := DecodeXMLBody(req.Body, decodedXML)
if err != nil {
_ = o.EncodeError(w, req, gerrors.Codes.ToAPIErr(gerrors.ErrBadRequest))
return
}
// delete all the files and collect responses
errs := make([]serde.DeleteError, 0)
responses := make([]serde.Deleted, 0)
for _, obj := range decodedXML.Object {
resolvedPath, err := path.ResolvePath(obj.Key)
if err != nil {
errs = append(errs, serde.DeleteError{
Code: "ErrDeletingKey",
Key: obj.Key,
Message: fmt.Sprintf("error deleting object: %s", err),
})
continue
}
// authorize this object deletion
authResp, err := o.Auth.Authorize(req.Context(), &auth.AuthorizationRequest{
Username: o.Principal,
RequiredPermissions: permissions.Node{
Permission: permissions.Permission{
Action: permissions.DeleteObjectAction,
Resource: permissions.ObjectArn(o.Repository.Name, resolvedPath.Path),
}},
})
if err != nil || !authResp.Allowed {
errs = append(errs, serde.DeleteError{
Code: "AccessDenied",
Key: obj.Key,
Message: "Access Denied",
})
}
lg := o.Log(req).WithField("key", obj.Key)
err = o.Catalog.DeleteEntry(req.Context(), o.Repository.Name, resolvedPath.Ref, resolvedPath.Path)
switch {
case errors.Is(err, catalog.ErrNotFound):
lg.Debug("tried to delete a non-existent object (OK)")
case errors.Is(err, graveler.ErrWriteToProtectedBranch):
_ = o.EncodeError(w, req, gerrors.Codes.ToAPIErr(gerrors.ErrWriteToProtectedBranch))
case errors.Is(err, catalog.ErrPathRequiredValue):
// issue #1706 - https://github.com/treeverse/lakeFS/issues/1706
// Spark trying to delete the path "main/", which we map to branch "main" with an empty path.
// Spark expects it to succeed (not deleting anything is a success), instead of returning an error.
lg.Debug("tried to delete with an empty branch")
case err != nil:
lg.WithError(err).Error("failed deleting object")
errs = append(errs, serde.DeleteError{
Code: "ErrDeletingKey",
Key: obj.Key,
Message: fmt.Sprintf("error deleting object: %s", err),
})
continue
default:
lg.Debug("object set for deletion")
}
if !decodedXML.Quiet {
responses = append(responses, serde.Deleted{Key: obj.Key})
}
}
// construct response
resp := serde.DeleteResult{}
if len(errs) > 0 {
resp.Error = errs
}
if !decodedXML.Quiet && len(responses) > 0 {
resp.Deleted = responses
}
o.EncodeResponse(w, req, resp, http.StatusOK)
}