[#214] Add condition to update eacl

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2021-08-19 17:14:19 +03:00 committed by Angira Kekteeva
parent a0f59bb348
commit 76fc241bc1

View file

@ -6,6 +6,7 @@ import (
"net/http"
"strings"
"github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
"github.com/nspcc-dev/neofs-node/pkg/policy"
"github.com/nspcc-dev/neofs-s3-gw/api"
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
@ -30,56 +31,60 @@ type createBucketParams struct {
}
func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
var (
err error
info *layer.ObjectInfo
reqInfo = api.GetReqInfo(r.Context())
)
var newEaclTable *eacl.Table
reqInfo := api.GetReqInfo(r.Context())
objectACL, err := parseACLHeaders(r)
if err != nil {
h.logAndSendError(w, "could not parse object acl", reqInfo, err)
return
}
objectACL.Resource = reqInfo.BucketName + "/" + reqInfo.ObjectName
if containsACLHeaders(r) {
objectACL, err := parseACLHeaders(r)
if err != nil {
h.logAndSendError(w, "could not parse object acl", reqInfo, err)
return
}
objectACL.Resource = reqInfo.BucketName + "/" + reqInfo.ObjectName
bktPolicy, err := aclToPolicy(objectACL)
if err != nil {
h.logAndSendError(w, "could not translate object acl to bucket policy", reqInfo, err)
return
bktPolicy, err := aclToPolicy(objectACL)
if err != nil {
h.logAndSendError(w, "could not translate object acl to bucket policy", reqInfo, err)
return
}
astChild, err := policyToAst(bktPolicy)
if err != nil {
h.logAndSendError(w, "could not translate policy to ast", reqInfo, err)
return
}
bacl, err := h.obj.GetBucketACL(r.Context(), reqInfo.BucketName)
if err != nil {
h.logAndSendError(w, "could not get bucket eacl", reqInfo, err)
return
}
parentAst := tableToAst(bacl.EACL, reqInfo.BucketName)
for _, resource := range parentAst.Resources {
if resource.Name == bacl.Info.CID.String() {
resource.Name = reqInfo.BucketName
}
}
if resAst, updated := mergeAst(parentAst, astChild); updated {
if newEaclTable, err = astToTable(resAst, reqInfo.BucketName); err != nil {
h.logAndSendError(w, "could not translate ast to table", reqInfo, err)
return
}
}
}
astChild, err := policyToAst(bktPolicy)
if err != nil {
h.logAndSendError(w, "could not translate policy to ast", reqInfo, err)
return
}
bacl, err := h.obj.GetBucketACL(r.Context(), reqInfo.BucketName)
bktInfo, err := h.obj.GetBucketInfo(r.Context(), reqInfo.BucketName)
if err != nil {
h.logAndSendError(w, "could not get bucket eacl", reqInfo, err)
return
}
if err = checkOwner(bacl.Info, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil {
if err = checkOwner(bktInfo, r.Header.Get(api.AmzExpectedBucketOwner)); err != nil {
h.logAndSendError(w, "expected owner doesn't match", reqInfo, err)
return
}
parentAst := tableToAst(bacl.EACL, reqInfo.BucketName)
for _, resource := range parentAst.Resources {
if resource.Name == bacl.Info.CID.String() {
resource.Name = reqInfo.BucketName
}
}
resAst, updated := mergeAst(parentAst, astChild)
table, err := astToTable(resAst, reqInfo.BucketName)
if err != nil {
h.logAndSendError(w, "could not translate ast to table", reqInfo, err)
return
}
metadata := parseMetadata(r)
if contentType := r.Header.Get(api.ContentType); len(contentType) > 0 {
metadata[api.ContentType] = contentType
@ -93,15 +98,16 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
Header: metadata,
}
if info, err = h.obj.PutObject(r.Context(), params); err != nil {
info, err := h.obj.PutObject(r.Context(), params)
if err != nil {
h.logAndSendError(w, "could not upload object", reqInfo, err)
return
}
if updated {
if newEaclTable != nil {
p := &layer.PutBucketACLParams{
Name: reqInfo.BucketName,
EACL: table,
EACL: newEaclTable,
}
if err = h.obj.PutBucketACL(r.Context(), p); err != nil {
@ -114,6 +120,11 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
api.WriteSuccessResponseHeadersOnly(w)
}
func containsACLHeaders(r *http.Request) bool {
return r.Header.Get(api.AmzACL) != "" || r.Header.Get(api.AmzGrantRead) != "" ||
r.Header.Get(api.AmzGrantFullControl) != "" || r.Header.Get(api.AmzGrantWrite) != ""
}
func parseMetadata(r *http.Request) map[string]string {
res := make(map[string]string)
for k, v := range r.Header {