From 45e3c0922d86ba09b767ed17866d19c00ffe6fc0 Mon Sep 17 00:00:00 2001 From: Jon Austin <62040422+jonaustin09@users.noreply.github.com> Date: Mon, 26 Jun 2023 23:29:56 +0400 Subject: [PATCH] Tag actions FE (#113) * feat: Added get-object-tagging, put-object-tagging, delete-object-tagging actions in fe --- s3api/controllers/base.go | 50 +++++++++++++++++++++++++++++++++++++++ s3response/s3response.go | 13 ++++++++++ 2 files changed, 63 insertions(+) diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index 78223d0..2c89a08 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -33,6 +33,7 @@ import ( "github.com/versity/versitygw/backend" "github.com/versity/versitygw/s3api/utils" "github.com/versity/versitygw/s3err" + "github.com/versity/versitygw/s3response" ) type S3ApiController struct { @@ -77,6 +78,24 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { return SendResponse(ctx, err) } + if ctx.Request().URI().QueryArgs().Has("tagging") { + if err := auth.VerifyACL(parsedAcl, bucket, access, "READ", isRoot); err != nil { + return SendXMLResponse(ctx, nil, err) + } + + tags, err := c.be.GetTags(bucket, key) + if err != nil { + return SendXMLResponse(ctx, nil, err) + } + resp := s3response.Tagging{TagSet: s3response.TagSet{Tags: []s3response.Tag{}}} + + for key, val := range tags { + resp.TagSet.Tags = append(resp.TagSet.Tags, s3response.Tag{Key: key, Value: val}) + } + + return SendXMLResponse(ctx, resp, nil) + } + if uploadId != "" { if maxParts < 0 || (maxParts == 0 && ctx.Query("max-parts") != "") { return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidMaxParts)) @@ -327,6 +346,28 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { return SendResponse(ctx, err) } + if ctx.Request().URI().QueryArgs().Has("tagging") { + var objTagging s3response.Tagging + err := xml.Unmarshal(ctx.Body(), &objTagging) + if err != nil { + return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest)) + } + + tags := make(map[string]string, len(objTagging.TagSet.Tags)) + + for _, tag := range objTagging.TagSet.Tags { + tags[tag.Key] = tag.Value + } + + if err := auth.VerifyACL(parsedAcl, bucket, access, "WRITE", isRoot); err != nil { + return SendResponse(ctx, err) + } + + err = c.be.SetTags(bucket, keyStart, tags) + + return SendResponse(ctx, err) + } + if uploadId != "" && partNumberStr != "" { partNumber := ctx.QueryInt("partNumber", -1) if partNumber < 1 { @@ -468,6 +509,15 @@ func (c S3ApiController) DeleteActions(ctx *fiber.Ctx) error { return SendResponse(ctx, err) } + if ctx.Request().URI().QueryArgs().Has("tagging") { + if err := auth.VerifyACL(parsedAcl, bucket, access, "WRITE", isRoot); err != nil { + return SendResponse(ctx, err) + } + + err = c.be.RemoveTags(bucket, key) + return SendResponse(ctx, err) + } + if uploadId != "" { expectedBucketOwner, requestPayer := ctx.Get("X-Amz-Expected-Bucket-Owner"), ctx.Get("X-Amz-Request-Payer") diff --git a/s3response/s3response.go b/s3response/s3response.go index fec1033..969eb6b 100644 --- a/s3response/s3response.go +++ b/s3response/s3response.go @@ -94,3 +94,16 @@ type Owner struct { ID string DisplayName string } + +type Tag struct { + Key string `xml:"Key"` + Value string `xml:"Value"` +} + +type TagSet struct { + Tags []Tag `xml:"Tag"` +} + +type Tagging struct { + TagSet TagSet `xml:"TagSet"` +}