diff --git a/auth/acl.go b/auth/acl.go index e98e4d8..305248e 100644 --- a/auth/acl.go +++ b/auth/acl.go @@ -46,6 +46,7 @@ type AccessControlList struct { } type AccessControlPolicy struct { AccessControlList AccessControlList `xml:"AccessControlList"` + Owner types.Owner } func ParseACL(data []byte) (ACL, error) { diff --git a/integration/tests.go b/integration/tests.go index a007b13..0827f34 100644 --- a/integration/tests.go +++ b/integration/tests.go @@ -1096,7 +1096,7 @@ func TestPutGetRemoveTags(s *S3Conf) { testname := "test put/get/remove object tags" runF(testname) - bucket := "testbucket1" + bucket := "testbucket13" err := setup(s, bucket) if err != nil { @@ -1191,7 +1191,7 @@ func TestAclActions(s *S3Conf) { testname := "test put/get acl" runF(testname) - bucket := "testbucket1" + bucket := "testbucket14" err := setup(s, bucket) if err != nil { @@ -1257,6 +1257,7 @@ func TestAclActions(s *S3Conf) { Bucket: &bucket, AccessControlPolicy: &types.AccessControlPolicy{ Grants: grants, + Owner: &types.Owner{ID: &s.awsID}, }, }) cancel() diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index 74567b9..6ba9902 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -235,8 +235,9 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error { } func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error { - bucket, acl, grantFullControl, grantRead, grantReadACP, granWrite, grantWriteACP, access, isRoot := + bucket, bucketOwner, acl, grantFullControl, grantRead, grantReadACP, granWrite, grantWriteACP, access, isRoot := ctx.Params("bucket"), + ctx.Get("X-Amz-Expected-Bucket-Owner"), ctx.Get("X-Amz-Acl"), ctx.Get("X-Amz-Grant-Full-Control"), ctx.Get("X-Amz-Grant-Read"), @@ -253,40 +254,36 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error { if len(ctx.Body()) > 0 { if grants+acl != "" { - return s3err.GetAPIError(s3err.ErrInvalidRequest) + return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidRequest)) } var accessControlPolicy auth.AccessControlPolicy err := xml.Unmarshal(ctx.Body(), &accessControlPolicy) if err != nil { - return s3err.GetAPIError(s3err.ErrInvalidRequest) + return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidRequest)) } input = &s3.PutBucketAclInput{ Bucket: &bucket, ACL: "", - AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &access}, Grants: accessControlPolicy.AccessControlList.Grants}, + AccessControlPolicy: &types.AccessControlPolicy{Owner: &accessControlPolicy.Owner, Grants: accessControlPolicy.AccessControlList.Grants}, } } if acl != "" { if acl != "private" && acl != "public-read" && acl != "public-read-write" { - return s3err.GetAPIError(s3err.ErrInvalidRequest) + return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidRequest)) } if len(ctx.Body()) > 0 || grants != "" { - return s3err.GetAPIError(s3err.ErrInvalidRequest) + return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidRequest)) } input = &s3.PutBucketAclInput{ Bucket: &bucket, ACL: types.BucketCannedACL(acl), - AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &access}}, + AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &bucketOwner}}, } } if grants != "" { - if acl != "" || len(ctx.Body()) > 0 { - return s3err.GetAPIError(s3err.ErrInvalidRequest) - } - input = &s3.PutBucketAclInput{ Bucket: &bucket, GrantFullControl: &grantFullControl, @@ -294,7 +291,8 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error { GrantReadACP: &grantReadACP, GrantWrite: &granWrite, GrantWriteACP: &grantWriteACP, - AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &access}}, + AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &bucketOwner}}, + ACL: "", } } @@ -330,7 +328,6 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { keyStart := ctx.Params("key") keyEnd := ctx.Params("*1") uploadId := ctx.Query("uploadId") - partNumberStr := ctx.Query("partNumber") access := ctx.Locals("access").(string) isRoot := ctx.Locals("isRoot").(bool) @@ -351,6 +348,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { // Other headers contentLengthStr := ctx.Get("Content-Length") + bucketOwner := ctx.Get("X-Amz-Expected-Bucket-Owner") grants := grantFullControl + grantRead + grantReadACP + granWrite + grantWriteACP @@ -403,7 +401,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { return SendResponse(ctx, err) } - if uploadId != "" && partNumberStr != "" { + if ctx.Request().URI().QueryArgs().Has("uploadId") && ctx.Request().URI().QueryArgs().Has("partNumber") { partNumber := ctx.QueryInt("partNumber", -1) if partNumber < 1 { return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidPart)) @@ -421,25 +419,57 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { return SendResponse(ctx, err) } - if grants != "" || acl != "" { - if grants != "" && acl != "" { - return errors.New("wrong api call") + if ctx.Request().URI().QueryArgs().Has("acl") { + var input *s3.PutObjectAclInput + + if len(ctx.Body()) > 0 { + if grants+acl != "" { + return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidRequest)) + } + + var accessControlPolicy auth.AccessControlPolicy + err := xml.Unmarshal(ctx.Body(), &accessControlPolicy) + if err != nil { + return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidRequest)) + } + + input = &s3.PutObjectAclInput{ + Bucket: &bucket, + Key: &keyStart, + ACL: "", + AccessControlPolicy: &types.AccessControlPolicy{Owner: &accessControlPolicy.Owner, Grants: accessControlPolicy.AccessControlList.Grants}, + } + } + if acl != "" { + if acl != "private" && acl != "public-read" && acl != "public-read-write" { + return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidRequest)) + } + if len(ctx.Body()) > 0 || grants != "" { + return SendXMLResponse(ctx, nil, s3err.GetAPIError(s3err.ErrInvalidRequest)) + } + + input = &s3.PutObjectAclInput{ + Bucket: &bucket, + Key: &keyStart, + ACL: types.ObjectCannedACL(acl), + AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &bucketOwner}}, + } + } + if grants != "" { + input = &s3.PutObjectAclInput{ + Bucket: &bucket, + Key: &keyStart, + GrantFullControl: &grantFullControl, + GrantRead: &grantRead, + GrantReadACP: &grantReadACP, + GrantWrite: &granWrite, + GrantWriteACP: &grantWriteACP, + AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &bucketOwner}}, + ACL: "", + } } - if err := auth.VerifyACL(parsedAcl, bucket, access, "WRITE_ACP", isRoot); err != nil { - return SendResponse(ctx, err) - } - - err := c.be.PutObjectAcl(&s3.PutObjectAclInput{ - Bucket: &bucket, - Key: &keyStart, - ACL: types.ObjectCannedACL(acl), - GrantFullControl: &grantFullControl, - GrantRead: &grantRead, - GrantReadACP: &grantReadACP, - GrantWrite: &granWrite, - GrantWriteACP: &grantWriteACP, - }) + err = c.be.PutObjectAcl(input) return SendResponse(ctx, err) } @@ -759,6 +789,7 @@ func SendResponse(ctx *fiber.Ctx, err error) error { func SendXMLResponse(ctx *fiber.Ctx, resp any, err error) error { if err != nil { + fmt.Println(err) serr, ok := err.(s3err.APIError) if ok { ctx.Status(serr.HTTPStatusCode) diff --git a/s3api/controllers/base_test.go b/s3api/controllers/base_test.go index 1d325ef..c766db2 100644 --- a/s3api/controllers/base_test.go +++ b/s3api/controllers/base_test.go @@ -126,6 +126,16 @@ func TestS3ApiController_ListBuckets(t *testing.T) { }) appErr.Get("/", s3ApiControllerErr.ListBuckets) + //Admin error case + admErr := fiber.New() + admErr.Use(func(ctx *fiber.Ctx) error { + ctx.Locals("access", "valid access") + ctx.Locals("isRoot", false) + ctx.Locals("isDebug", false) + return ctx.Next() + }) + admErr.Get("/", s3ApiController.ListBuckets) + tests := []struct { name string args args @@ -151,6 +161,15 @@ func TestS3ApiController_ListBuckets(t *testing.T) { wantErr: false, statusCode: 200, }, + { + name: "admin-error-case", + args: args{ + req: httptest.NewRequest(http.MethodGet, "/", nil), + }, + app: admErr, + wantErr: false, + statusCode: 500, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -172,6 +191,11 @@ func TestS3ApiController_GetActions(t *testing.T) { req *http.Request } + getPtr := func(val string) *string { + return &val + } + now := time.Now() + app := fiber.New() s3ApiController := S3ApiController{ be: &BackendMock{ @@ -188,7 +212,18 @@ func TestS3ApiController_GetActions(t *testing.T) { return &s3.GetObjectAttributesOutput{}, nil }, GetObjectFunc: func(bucket, object, acceptRange string, writer io.Writer) (*s3.GetObjectOutput, error) { - return &s3.GetObjectOutput{Metadata: nil}, nil + return &s3.GetObjectOutput{ + Metadata: map[string]string{"hello": "world"}, + ContentType: getPtr("application/xml"), + ContentEncoding: getPtr("gzip"), + ETag: getPtr("98sda7f97sa9df798sd79f8as9df"), + ContentLength: 1000, + LastModified: &now, + StorageClass: "storage class", + }, nil + }, + GetTagsFunc: func(bucket, object string) (map[string]string, error) { + return map[string]string{"hello": "world"}, nil }, }, } @@ -200,17 +235,9 @@ func TestS3ApiController_GetActions(t *testing.T) { }) app.Get("/:bucket/:key/*", s3ApiController.GetActions) - // GetObjectACL - getObjectACLReq := httptest.NewRequest(http.MethodGet, "/my-bucket/key", nil) - getObjectACLReq.Header.Set("X-Amz-Object-Attributes", "attrs") - - // GetObject error case - getObjectReq := httptest.NewRequest(http.MethodGet, "/my-bucket/key", nil) - getObjectReq.Header.Set("Range", "hello=") - - // GetObject success case - getObjectSuccessReq := httptest.NewRequest(http.MethodGet, "/my-bucket/key", nil) - getObjectReq.Header.Set("Range", "range=13-invalid") + // GetObjectAttributes success case + getObjAttrs := httptest.NewRequest(http.MethodGet, "/my-bucket/key", nil) + getObjAttrs.Header.Set("X-Amz-Object-Attributes", "hello") tests := []struct { name string @@ -220,19 +247,46 @@ func TestS3ApiController_GetActions(t *testing.T) { statusCode int }{ { - name: "Get-actions-invalid-max-parts", + name: "Get-actions-get-tags-success", app: app, args: args{ - req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=InvalidMaxParts", nil), + req: httptest.NewRequest(http.MethodGet, "/my-bucket/key/key.json?tagging", nil), + }, + wantErr: false, + statusCode: 200, + }, + { + name: "Get-actions-invalid-max-parts-string", + app: app, + args: args{ + req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=invalid", nil), }, wantErr: false, statusCode: 400, }, { - name: "Get-actions-invalid-part-number-marker", + name: "Get-actions-invalid-max-parts-negative", app: app, args: args{ - req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=200&part-number-marker=InvalidPartNumber", nil), + req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=-8", nil), + }, + wantErr: false, + statusCode: 400, + }, + { + name: "Get-actions-invalid-part-number-marker-string", + app: app, + args: args{ + req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=200&part-number-marker=invalid", nil), + }, + wantErr: false, + statusCode: 400, + }, + { + name: "Get-actions-invalid-part-number-marker-negative", + app: app, + args: args{ + req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=200&part-number-marker=-8", nil), }, wantErr: false, statusCode: 400, @@ -250,7 +304,16 @@ func TestS3ApiController_GetActions(t *testing.T) { name: "Get-actions-get-object-acl-success", app: app, args: args{ - req: getObjectACLReq, + req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?acl", nil), + }, + wantErr: false, + statusCode: 200, + }, + { + name: "Get-actions-get-object-attributes-success", + app: app, + args: args{ + req: getObjAttrs, }, wantErr: false, statusCode: 200, @@ -259,7 +322,7 @@ func TestS3ApiController_GetActions(t *testing.T) { name: "Get-actions-get-object-success", app: app, args: args{ - req: getObjectSuccessReq, + req: httptest.NewRequest(http.MethodGet, "/my-bucket/key", nil), }, wantErr: false, statusCode: 200, @@ -390,11 +453,11 @@ func TestS3ApiController_ListActions(t *testing.T) { resp, err := tt.app.Test(tt.args.req) if (err != nil) != tt.wantErr { - t.Errorf("S3ApiController.GetActions() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("S3ApiController.ListActions() error = %v, wantErr %v", err, tt.wantErr) } if resp.StatusCode != tt.statusCode { - t.Errorf("S3ApiController.GetActions() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode) + t.Errorf("S3ApiController.ListActions() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode) } }) } @@ -406,12 +469,31 @@ func TestS3ApiController_PutBucketActions(t *testing.T) { } app := fiber.New() + + // Mock valid acl acl := auth.ACL{Owner: "valid access", ACL: "public-read-write"} acldata, err := json.Marshal(acl) if err != nil { t.Errorf("Failed to parse the params: %v", err.Error()) return } + + body := ` + + + + + hell + + string + + + + hello + + + ` + s3ApiController := S3ApiController{ be: &BackendMock{ GetBucketAclFunc: func(bucket string) ([]byte, error) { @@ -434,14 +516,28 @@ func TestS3ApiController_PutBucketActions(t *testing.T) { }) app.Put("/:bucket", s3ApiController.PutBucketActions) - // Error case - errorReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", nil) - errorReq.Header.Set("X-Amz-Acl", "private") - errorReq.Header.Set("X-Amz-Grant-Read", "read") + // invalid acl case + invAclReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", nil) + invAclReq.Header.Set("X-Amz-Acl", "invalid") - // PutBucketAcl success - aclReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", nil) - aclReq.Header.Set("X-Amz-Acl", "private") + // invalid acl case 2 + errAclReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", nil) + errAclReq.Header.Set("X-Amz-Acl", "private") + errAclReq.Header.Set("X-Amz-Grant-Read", "hello") + + // PutBucketAcl incorrect bucket owner case + incorrectBucketOwner := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", nil) + incorrectBucketOwner.Header.Set("X-Amz-Acl", "private") + incorrectBucketOwner.Header.Set("X-Amz-Expected-Bucket-Owner", "invalid access") + + // PutBucketAcl acl success + aclSuccReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", nil) + aclSuccReq.Header.Set("X-Amz-Acl", "private") + aclSuccReq.Header.Set("X-Amz-Expected-Bucket-Owner", "valid access") + + // Invalid acl body case + errAclBodyReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", strings.NewReader(body)) + errAclBodyReq.Header.Set("X-Amz-Grant-Read", "hello") tests := []struct { name string @@ -451,19 +547,46 @@ func TestS3ApiController_PutBucketActions(t *testing.T) { statusCode int }{ { - name: "Put-bucket-acl-error", + name: "Put-bucket-acl-invalid-acl", app: app, args: args{ - req: errorReq, + req: invAclReq, }, wantErr: false, - statusCode: 500, + statusCode: 400, }, { - name: "Put-object-acl-success", + name: "Put-bucket-acl-incorrect-acl", app: app, args: args{ - req: aclReq, + req: errAclReq, + }, + wantErr: false, + statusCode: 400, + }, + { + name: "Put-bucket-acl-incorrect-acl-body", + app: app, + args: args{ + req: errAclBodyReq, + }, + wantErr: false, + statusCode: 400, + }, + { + name: "Put-bucket-acl-incorrect-bucket-owner", + app: app, + args: args{ + req: incorrectBucketOwner, + }, + wantErr: false, + statusCode: 403, + }, + { + name: "Put-bucket-acl-success", + app: app, + args: args{ + req: aclSuccReq, }, wantErr: false, statusCode: 200, @@ -496,15 +619,38 @@ func TestS3ApiController_PutActions(t *testing.T) { req *http.Request } + body := ` + + + + + hell + + string + + + + hello + + + ` + tagBody := ` + + + + string + string + + + + ` + app := fiber.New() s3ApiController := S3ApiController{ be: &BackendMock{ GetBucketAclFunc: func(bucket string) ([]byte, error) { return acldata, nil }, - UploadPartCopyFunc: func(*s3.UploadPartCopyInput) (*s3.UploadPartCopyOutput, error) { - return &s3.UploadPartCopyOutput{}, nil - }, PutObjectAclFunc: func(*s3.PutObjectAclInput) error { return nil }, @@ -514,6 +660,12 @@ func TestS3ApiController_PutActions(t *testing.T) { PutObjectFunc: func(*s3.PutObjectInput) (string, error) { return "Hey", nil }, + PutObjectPartFunc: func(bucket, object, uploadID string, part int, length int64, r io.Reader) (string, error) { + return "hello", nil + }, + SetTagsFunc: func(bucket, object string, tags map[string]string) error { + return nil + }, }, } app.Use(func(ctx *fiber.Ctx) error { @@ -524,19 +676,31 @@ func TestS3ApiController_PutActions(t *testing.T) { }) app.Put("/:bucket/:key/*", s3ApiController.PutActions) - //PutObjectAcl error - aclReqErr := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil) - aclReqErr.Header.Set("X-Amz-Acl", "acl") - aclReqErr.Header.Set("X-Amz-Grant-Write", "write") - - //PutObjectAcl success - aclReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil) - aclReq.Header.Set("X-Amz-Acl", "acl") - - //CopyObject success + // CopyObject success cpySrcReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil) cpySrcReq.Header.Set("X-Amz-Copy-Source", "srcBucket/srcObject") + // PutObjectAcl success + aclReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil) + aclReq.Header.Set("X-Amz-Acl", "private") + + // PutObjectAcl success grt case + aclGrtReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil) + aclGrtReq.Header.Set("X-Amz-Grant-Read", "private") + + // invalid acl case 1 + invAclReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?acl", nil) + invAclReq.Header.Set("X-Amz-Acl", "invalid") + + // invalid acl case 2 + errAclReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?acl", nil) + errAclReq.Header.Set("X-Amz-Acl", "private") + errAclReq.Header.Set("X-Amz-Grant-Read", "hello") + + // invalid body & grt case + invAclBodyGrtReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?acl", strings.NewReader(body)) + invAclBodyGrtReq.Header.Set("X-Amz-Grant-Read", "hello") + tests := []struct { name string app *fiber.App @@ -545,7 +709,7 @@ func TestS3ApiController_PutActions(t *testing.T) { statusCode int }{ { - name: "Upload-put-part-error-case", + name: "Put-object-part-error-case", app: app, args: args{ req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?uploadId=abc&partNumber=invalid", nil), @@ -554,40 +718,49 @@ func TestS3ApiController_PutActions(t *testing.T) { statusCode: 400, }, { - name: "Upload-copy-part-success", + name: "Put-object-part-success", app: app, args: args{ - req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?partNumber=3", nil), + req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?uploadId=4&partNumber=3", nil), }, wantErr: false, statusCode: 200, }, { - name: "Upload-part-success", + name: "Set-tags-success", app: app, args: args{ - req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?uploadId=234234", nil), + req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?tagging", strings.NewReader(tagBody)), }, wantErr: false, statusCode: 200, }, { - name: "Put-object-acl-error", + name: "Put-object-acl-invalid-acl", app: app, args: args{ - req: aclReqErr, + req: invAclReq, }, wantErr: false, - statusCode: 500, + statusCode: 400, }, { - name: "Put-object-acl-error", + name: "Put-object-acl-incorrect-acl", app: app, args: args{ - req: aclReqErr, + req: errAclReq, }, wantErr: false, - statusCode: 500, + statusCode: 400, + }, + { + name: "Put-object-acl-incorrect-acl-body-case", + app: app, + args: args{ + req: invAclBodyGrtReq, + }, + wantErr: false, + statusCode: 400, }, { name: "Put-object-acl-success", @@ -598,6 +771,24 @@ func TestS3ApiController_PutActions(t *testing.T) { wantErr: false, statusCode: 200, }, + { + name: "Put-object-acl-success-body-case", + app: app, + args: args{ + req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?acl", strings.NewReader(body)), + }, + wantErr: false, + statusCode: 200, + }, + { + name: "Put-object-acl-success-grt-case", + app: app, + args: args{ + req: aclGrtReq, + }, + wantErr: false, + statusCode: 200, + }, { name: "Copy-object-success", app: app, @@ -611,7 +802,7 @@ func TestS3ApiController_PutActions(t *testing.T) { name: "Put-object-success", app: app, args: args{ - req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil), + req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key/key2", nil), }, wantErr: false, statusCode: 200, @@ -658,28 +849,6 @@ func TestS3ApiController_DeleteBucket(t *testing.T) { app.Delete("/:bucket", s3ApiController.DeleteBucket) - // error case - appErr := fiber.New() - - s3ApiControllerErr := S3ApiController{ - be: &BackendMock{ - GetBucketAclFunc: func(bucket string) ([]byte, error) { - return acldata, nil - }, - DeleteBucketFunc: func(bucket string) error { - return s3err.GetAPIError(48) - }, - }, - } - - appErr.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") - ctx.Locals("isRoot", true) - ctx.Locals("isDebug", false) - return ctx.Next() - }) - appErr.Delete("/:bucket", s3ApiControllerErr.DeleteBucket) - tests := []struct { name string app *fiber.App @@ -696,15 +865,6 @@ func TestS3ApiController_DeleteBucket(t *testing.T) { wantErr: false, statusCode: 200, }, - { - name: "Delete-bucket-error", - app: appErr, - args: args{ - req: httptest.NewRequest(http.MethodDelete, "/my-bucket", nil), - }, - wantErr: false, - statusCode: 400, - }, } for _, tt := range tests { resp, err := tt.app.Test(tt.args.req) diff --git a/s3api/server_test.go b/s3api/server_test.go index a5bf975..5313e41 100644 --- a/s3api/server_test.go +++ b/s3api/server_test.go @@ -15,6 +15,7 @@ package s3api import ( + "crypto/tls" "reflect" "testing" @@ -82,15 +83,26 @@ func TestS3ApiServer_Serve(t *testing.T) { wantErr bool }{ { - name: "Return error when serving S3 api server with invalid address", + name: "Serve-invalid-address", wantErr: true, sa: &S3ApiServer{ app: fiber.New(), backend: backend.BackendUnsupported{}, - port: "Wrong address", + port: "Invalid address", router: &S3ApiRouter{}, }, }, + { + name: "Serve-invalid-address-with-certificate", + wantErr: true, + sa: &S3ApiServer{ + app: fiber.New(), + backend: backend.BackendUnsupported{}, + port: "Invalid address", + router: &S3ApiRouter{}, + cert: &tls.Certificate{}, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/s3api/utils/utils_test.go b/s3api/utils/utils_test.go index 08df618..3096cba 100644 --- a/s3api/utils/utils_test.go +++ b/s3api/utils/utils_test.go @@ -117,3 +117,39 @@ func TestGetUserMetaData(t *testing.T) { }) } } + +func Test_includeHeader(t *testing.T) { + type args struct { + hdr string + signedHdrs []string + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "include-header-falsy-case", + args: args{ + hdr: "Content-Type", + signedHdrs: []string{"X-Amz-Acl", "Content-Encoding"}, + }, + want: false, + }, + { + name: "include-header-falsy-case", + args: args{ + hdr: "Content-Type", + signedHdrs: []string{"X-Amz-Acl", "Content-Type"}, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := includeHeader(tt.args.hdr, tt.args.signedHdrs); got != tt.want { + t.Errorf("includeHeader() = %v, want %v", got, tt.want) + } + }) + } +}