Use automatic URI encoding (#3352)

This commit is contained in:
Ramon de Klein
2024-06-05 23:48:27 +02:00
committed by GitHub
parent 72939e0cd7
commit 49c5f5a8f0
67 changed files with 398 additions and 875 deletions

View File

@@ -58,7 +58,7 @@ swagger-console:
@echo "Generating swagger server code from yaml"
@swagger generate server -A console --main-package=management --server-package=api --exclude-main -P models.Principal -f ./swagger.yml -r NOTICE
@echo "Generating typescript api"
@npx swagger-typescript-api -p ./swagger.yml -o ./web-app/src/api -n consoleApi.ts
@npx swagger-typescript-api -p ./swagger.yml -o ./web-app/src/api -n consoleApi.ts --custom-config generator.config.js
@git restore api/server.go

View File

@@ -22,7 +22,6 @@ import (
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
"github.com/minio/console/pkg/utils"
"github.com/minio/madmin-go/v3"
groupApi "github.com/minio/console/api/operations/group"
@@ -118,12 +117,7 @@ func getGroupInfoResponse(session *models.Principal, params groupApi.GroupInfoPa
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
groupName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
groupDesc, err := groupInfo(ctx, adminClient, groupName)
groupDesc, err := groupInfo(ctx, adminClient, params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -212,12 +206,7 @@ func getRemoveGroupResponse(session *models.Principal, params groupApi.RemoveGro
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
groupName, err := utils.DecodeBase64(params.Name)
if err != nil {
return ErrorWithContext(ctx, err)
}
if err := removeGroup(ctx, adminClient, groupName); err != nil {
if err := removeGroup(ctx, adminClient, params.Name); err != nil {
minioError := madmin.ToErrorResponse(err)
err2 := ErrorWithContext(ctx, err)
if minioError.Code == "XMinioAdminNoSuchGroup" {
@@ -293,11 +282,6 @@ func getUpdateGroupResponse(session *models.Principal, params groupApi.UpdateGro
}
expectedGroupUpdate := params.Body
groupName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil {
return nil, ErrorWithContext(ctx, err)
@@ -306,7 +290,7 @@ func getUpdateGroupResponse(session *models.Principal, params groupApi.UpdateGro
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
groupUpdated, err := groupUpdate(ctx, adminClient, groupName, expectedGroupUpdate)
groupUpdated, err := groupUpdate(ctx, adminClient, params.Name, expectedGroupUpdate)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}

View File

@@ -22,7 +22,6 @@ import (
"io"
"net/http"
"strings"
"unicode/utf8"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
@@ -35,14 +34,6 @@ import (
func registerInspectHandler(api *operations.ConsoleAPI) {
api.InspectInspectHandler = inspectApi.InspectHandlerFunc(func(params inspectApi.InspectParams, principal *models.Principal) middleware.Responder {
if v, err := base64.URLEncoding.DecodeString(params.File); err == nil && utf8.Valid(v) {
params.File = string(v)
}
if v, err := base64.URLEncoding.DecodeString(params.Volume); err == nil && utf8.Valid(v) {
params.Volume = string(v)
}
k, r, err := getInspectResult(principal, &params)
if err != nil {
return inspectApi.NewInspectDefault(err.Code).WithPayload(err.APIError)

View File

@@ -18,7 +18,6 @@ package api
import (
"context"
"encoding/base64"
"time"
"github.com/minio/mc/cmd"
@@ -60,20 +59,7 @@ type ObjectResponse struct {
func getObjectsOptionsFromReq(request ObjectsRequest) (*objectsListOpts, error) {
pOptions := objectsListOpts{
BucketName: request.BucketName,
Prefix: "",
}
prefix := request.Prefix
if prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
LogError("error decoding prefix: %v", err)
return nil, err
}
pOptions.Prefix = string(decodedPrefix)
Prefix: request.Prefix,
}
if request.Mode == "rewind" {

View File

@@ -26,7 +26,6 @@ import (
bucketApi "github.com/minio/console/api/operations/bucket"
policyApi "github.com/minio/console/api/operations/policy"
"github.com/minio/console/pkg/utils"
s3 "github.com/minio/minio-go/v7"
"github.com/go-openapi/runtime/middleware"
@@ -308,10 +307,6 @@ func getListPoliciesResponse(session *models.Principal, params policyApi.ListPol
func getListUsersForPolicyResponse(session *models.Principal, params policyApi.ListUsersForPolicyParams) ([]string, *CodedAPIError) {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
policy, err := utils.DecodeBase64(params.Policy)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil {
return nil, ErrorWithContext(ctx, err)
@@ -325,12 +320,12 @@ func getListUsersForPolicyResponse(session *models.Principal, params policyApi.L
}
found := false
for i := range policies {
if policies[i].Name == policy {
if policies[i].Name == params.Policy {
found = true
}
}
if !found {
return nil, ErrorWithContext(ctx, ErrPolicyNotFound, fmt.Errorf("the policy %s does not exist", policy))
return nil, ErrorWithContext(ctx, ErrPolicyNotFound, fmt.Errorf("the policy %s does not exist", params.Policy))
}
users, err := listUsers(ctx, adminClient)
if err != nil {
@@ -340,7 +335,7 @@ func getListUsersForPolicyResponse(session *models.Principal, params policyApi.L
var filteredUsers []string
for _, user := range users {
for _, upolicy := range user.Policy {
if upolicy == policy {
if upolicy == params.Policy {
filteredUsers = append(filteredUsers, user.AccessKey)
break
}
@@ -397,12 +392,7 @@ func getSAUserPolicyResponse(session *models.Principal, params policyApi.GetSAUs
}
userAdminClient := AdminClient{Client: mAdminClient}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
user, err := getUserInfo(ctx, userAdminClient, userName)
user, err := getUserInfo(ctx, userAdminClient, params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -467,10 +457,6 @@ func getListGroupsForPolicyResponse(session *models.Principal, params policyApi.
}
// create a minioClient interface implementation
// defining the client to be used
policy, err := utils.DecodeBase64(params.Policy)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
adminClient := AdminClient{Client: mAdmin}
policies, err := listPolicies(ctx, adminClient)
if err != nil {
@@ -478,12 +464,12 @@ func getListGroupsForPolicyResponse(session *models.Principal, params policyApi.
}
found := false
for i := range policies {
if policies[i].Name == policy {
if policies[i].Name == params.Policy {
found = true
}
}
if !found {
return nil, ErrorWithContext(ctx, ErrPolicyNotFound, fmt.Errorf("the policy %s does not exist", policy))
return nil, ErrorWithContext(ctx, ErrPolicyNotFound, fmt.Errorf("the policy %s does not exist", params.Policy))
}
groups, err := adminClient.listGroups(ctx)
@@ -499,7 +485,7 @@ func getListGroupsForPolicyResponse(session *models.Principal, params policyApi.
}
groupPolicies := strings.Split(info.Policy, ",")
for _, groupPolicy := range groupPolicies {
if groupPolicy == policy {
if groupPolicy == params.Policy {
filteredGroups = append(filteredGroups, group)
}
}
@@ -524,10 +510,6 @@ func getRemovePolicyResponse(session *models.Principal, params policyApi.RemoveP
if params.Name == "" {
return ErrorWithContext(ctx, ErrPolicyNameNotInRequest)
}
policyName, err := utils.DecodeBase64(params.Name)
if err != nil {
return ErrorWithContext(ctx, err)
}
mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil {
return ErrorWithContext(ctx, err)
@@ -536,7 +518,7 @@ func getRemovePolicyResponse(session *models.Principal, params policyApi.RemoveP
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
if err := removePolicy(ctx, adminClient, policyName); err != nil {
if err := removePolicy(ctx, adminClient, params.Name); err != nil {
return ErrorWithContext(ctx, err)
}
return nil
@@ -623,11 +605,7 @@ func getPolicyInfoResponse(session *models.Principal, params policyApi.PolicyInf
// create a MinIO Admin Client interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
policyName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
policy, err := policyInfo(ctx, adminClient, policyName)
policy, err := policyInfo(ctx, adminClient, params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}

View File

@@ -22,8 +22,6 @@ import (
"sort"
"strings"
"github.com/minio/console/pkg/utils"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
@@ -257,17 +255,13 @@ func getRemoveUserResponse(session *models.Principal, params userApi.RemoveUserP
if err != nil {
return ErrorWithContext(ctx, err)
}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return ErrorWithContext(ctx, err)
}
if session.AccountAccessKey == userName {
if session.AccountAccessKey == params.Name {
return ErrorWithContext(ctx, ErrAvoidSelfAccountDelete)
}
// create a minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
if err := removeUser(ctx, adminClient, userName); err != nil {
if err := removeUser(ctx, adminClient, params.Name); err != nil {
return ErrorWithContext(ctx, err)
}
return nil
@@ -295,12 +289,7 @@ func getUserInfoResponse(session *models.Principal, params userApi.GetUserInfoPa
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
user, err := getUserInfo(ctx, adminClient, userName)
user, err := getUserInfo(ctx, adminClient, params.Name)
if err != nil {
// User doesn't exist, return 404
if madmin.ToErrorResponse(err).Code == "XMinioAdminNoSuchUser" {
@@ -335,7 +324,7 @@ func getUserInfoResponse(session *models.Principal, params userApi.GetUserInfoPa
}
userInformation := &models.User{
AccessKey: userName,
AccessKey: params.Name,
MemberOf: user.MemberOf,
Policy: policies,
Status: string(user.Status),
@@ -446,12 +435,7 @@ func getUpdateUserGroupsResponse(session *models.Principal, params userApi.Updat
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
user, err := updateUserGroups(ctx, adminClient, userName, params.Body.Groups)
user, err := updateUserGroups(ctx, adminClient, params.Name, params.Body.Groups)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -486,18 +470,14 @@ func getUpdateUserResponse(session *models.Principal, params userApi.UpdateUserI
// create a minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
status := *params.Body.Status
groups := params.Body.Groups
if err := setUserStatus(ctx, adminClient, userName, status); err != nil {
if err := setUserStatus(ctx, adminClient, params.Name, status); err != nil {
return nil, ErrorWithContext(ctx, err)
}
userElem, errUG := updateUserGroups(ctx, adminClient, userName, groups)
userElem, errUG := updateUserGroups(ctx, adminClient, params.Name, groups)
if errUG != nil {
return nil, ErrorWithContext(ctx, errUG)

View File

@@ -17,7 +17,6 @@
package api
import (
b64 "encoding/base64"
"fmt"
"io"
"net/http"
@@ -45,7 +44,7 @@ func registerPublicObjectsHandlers(api *operations.ConsoleAPI) {
func getDownloadPublicObjectResponse(params public.DownloadSharedObjectParams) (middleware.Responder, *CodedAPIError) {
ctx := params.HTTPRequest.Context()
inputURLDecoded, err := b64toMinIOStringURL(params.URL)
inputURLDecoded, err := checkMinIOStringURL(params.URL)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -91,23 +90,19 @@ func getDownloadPublicObjectResponse(params public.DownloadSharedObjectParams) (
}), nil
}
// b64toMinIOStringURL decodes url and validates is a MinIO url endpoint
func b64toMinIOStringURL(inputEncodedURL string) (*string, error) {
inputURLDecoded, err := b64.URLEncoding.DecodeString(inputEncodedURL)
if err != nil {
return nil, err
}
// checkMinIOStringURL decodes url and validates is a MinIO url endpoint
func checkMinIOStringURL(inputURL string) (*string, error) {
// Validate input URL
inputURL, err := xnet.ParseHTTPURL(string(inputURLDecoded))
parsedURL, err := xnet.ParseHTTPURL(inputURL)
if err != nil {
return nil, err
}
// Ensure incoming url points to MinIO Server
minIOHost := getMinIOEndpoint()
if inputURL.Host != minIOHost {
if parsedURL.Host != minIOHost {
return nil, ErrForbidden
}
return swag.String(string(inputURLDecoded)), nil
return swag.String(inputURL), nil
}
func url2BucketAndObject(u *url.URL) (bucketName, objectName string) {

View File

@@ -23,7 +23,7 @@ import (
"github.com/stretchr/testify/assert"
)
func Test_b64toMinIOStringURL(t *testing.T) {
func Test_checkMinIOStringURL(t *testing.T) {
tAssert := assert.New(t)
type args struct {
encodedURL string
@@ -37,7 +37,7 @@ func Test_b64toMinIOStringURL(t *testing.T) {
{
test: "valid encoded minIO URL returns decoded URL string", // http://localhost:9000/...
args: args{
encodedURL: "aHR0cDovL2xvY2FsaG9zdDo5MDAwL2J1Y2tldDEyMy9BdWRpbyUyMGljb24lMjgxJTI5LnN2Zz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPVVCTzFMMUM3VTg3UDFCUDI1MVRTJTJGMjAyNDA0MDUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNDA1VDIxMDEzM1omWC1BbXotRXhwaXJlcz00MzIwMCZYLUFtei1TZWN1cml0eS1Ub2tlbj1leUpoYkdjaU9pSklVelV4TWlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKaFkyTmxjM05MWlhraU9pSlZRazh4VERGRE4xVTROMUF4UWxBeU5URlVVeUlzSW1WNGNDSTZNVGN4TWpNNU5EQTRPU3dpY0dGeVpXNTBJam9pYldsdWFXOWhaRzFwYmlKOS5WLUtEZ3JMTVVCbG5KSEtYNlZ4SGw5LUFfLVBGRVdvazJkcFRxLTQ2YmxMbUxzdWVUeHNoVmFZNERad0dmb200VFQ1azhwaFVmZ2pjUWFuc25icmtlQSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmdmVyc2lvbklkPW51bGwmWC1BbXotU2lnbmF0dXJlPTA3Y2FkM2ViMmE2NzIyYjViYWVkMDljNmYxZmU0YTcwMWJmMTJmNDhlMTYyOGI5ZDQ1YzAxMWQ1OTU1Njc4NDU=",
encodedURL: "http://localhost:9000/bucket123/Audio%20icon%281%29.svg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=UBO1L1C7U87P1BP251TS%2F20240405%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240405T210133Z&X-Amz-Expires=43200&X-Amz-Security-Token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJVQk8xTDFDN1U4N1AxQlAyNTFUUyIsImV4cCI6MTcxMjM5NDA4OSwicGFyZW50IjoibWluaW9hZG1pbiJ9.V-KDgrLMUBlnJHKX6VxHl9-A_-PFEWok2dpTq-46blLmLsueTxshVaY4DZwGfom4TT5k8phUfgjcQansnbrkeA&X-Amz-SignedHeaders=host&versionId=null&X-Amz-Signature=07cad3eb2a6722b5baed09c6f1fe4a701bf12f48e1628b9d45c011d595567845",
},
wantError: nil,
expected: swag.String("http://localhost:9000/bucket123/Audio%20icon%281%29.svg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=UBO1L1C7U87P1BP251TS%2F20240405%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240405T210133Z&X-Amz-Expires=43200&X-Amz-Security-Token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJVQk8xTDFDN1U4N1AxQlAyNTFUUyIsImV4cCI6MTcxMjM5NDA4OSwicGFyZW50IjoibWluaW9hZG1pbiJ9.V-KDgrLMUBlnJHKX6VxHl9-A_-PFEWok2dpTq-46blLmLsueTxshVaY4DZwGfom4TT5k8phUfgjcQansnbrkeA&X-Amz-SignedHeaders=host&versionId=null&X-Amz-Signature=07cad3eb2a6722b5baed09c6f1fe4a701bf12f48e1628b9d45c011d595567845"),
@@ -45,7 +45,7 @@ func Test_b64toMinIOStringURL(t *testing.T) {
{
test: "valid encoded url but not coming from MinIO server returns forbidden error", // http://non-minio-host:9000/...
args: args{
encodedURL: "aHR0cDovL25vbi1taW5pby1ob3N0OjkwMDAvYnVja2V0MTIzL0F1ZGlvJTIwaWNvbiUyODElMjkuc3ZnP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9VUJPMUwxQzdVODdQMUJQMjUxVFMlMkYyMDI0MDQwNSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA0MDVUMjEwMTMzWiZYLUFtei1FeHBpcmVzPTQzMjAwJlgtQW16LVNlY3VyaXR5LVRva2VuPWV5SmhiR2NpT2lKSVV6VXhNaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpoWTJObGMzTkxaWGtpT2lKVlFrOHhUREZETjFVNE4xQXhRbEF5TlRGVVV5SXNJbVY0Y0NJNk1UY3hNak01TkRBNE9Td2ljR0Z5Wlc1MElqb2liV2x1YVc5aFpHMXBiaUo5LlYtS0RnckxNVUJsbkpIS1g2VnhIbDktQV8tUEZFV29rMmRwVHEtNDZibExtTHN1ZVR4c2hWYVk0RFp3R2ZvbTRUVDVrOHBoVWZnamNRYW5zbmJya2VBJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZ2ZXJzaW9uSWQ9bnVsbCZYLUFtei1TaWduYXR1cmU9MDdjYWQzZWIyYTY3MjJiNWJhZWQwOWM2ZjFmZTRhNzAxYmYxMmY0OGUxNjI4YjlkNDVjMDExZDU5NTU2Nzg0NQ==",
encodedURL: "http://non-minio-host:9000/bucket123/Audio%20icon%281%29.svg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=UBO1L1C7U87P1BP251TS%2F20240405%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240405T210133Z&X-Amz-Expires=43200&X-Amz-Security-Token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJVQk8xTDFDN1U4N1AxQlAyNTFUUyIsImV4cCI6MTcxMjM5NDA4OSwicGFyZW50IjoibWluaW9hZG1pbiJ9.V-KDgrLMUBlnJHKX6VxHl9-A_-PFEWok2dpTq-46blLmLsueTxshVaY4DZwGfom4TT5k8phUfgjcQansnbrkeA&X-Amz-SignedHeaders=host&versionId=null&X-Amz-Signature=07cad3eb2a6722b5baed09c6f1fe4a701bf12f48e1628b9d45c011d595567845",
},
wantError: swag.String("403 Forbidden"),
expected: nil,
@@ -53,7 +53,7 @@ func Test_b64toMinIOStringURL(t *testing.T) {
{
test: "valid encoded url but not coming from MinIO server port returns forbidden error", // other port http://localhost:8902/...
args: args{
encodedURL: "aHR0cDovL2xvY2FsaG9zdDo4OTAyL2J1Y2tldDEyMy9BdWRpbyUyMGljb24lMjgxJTI5LnN2Zz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPVVCTzFMMUM3VTg3UDFCUDI1MVRTJTJGMjAyNDA0MDUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNDA1VDIxMDEzM1omWC1BbXotRXhwaXJlcz00MzIwMCZYLUFtei1TZWN1cml0eS1Ub2tlbj1leUpoYkdjaU9pSklVelV4TWlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKaFkyTmxjM05MWlhraU9pSlZRazh4VERGRE4xVTROMUF4UWxBeU5URlVVeUlzSW1WNGNDSTZNVGN4TWpNNU5EQTRPU3dpY0dGeVpXNTBJam9pYldsdWFXOWhaRzFwYmlKOS5WLUtEZ3JMTVVCbG5KSEtYNlZ4SGw5LUFfLVBGRVdvazJkcFRxLTQ2YmxMbUxzdWVUeHNoVmFZNERad0dmb200VFQ1azhwaFVmZ2pjUWFuc25icmtlQSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmdmVyc2lvbklkPW51bGwmWC1BbXotU2lnbmF0dXJlPTA3Y2FkM2ViMmE2NzIyYjViYWVkMDljNmYxZmU0YTcwMWJmMTJmNDhlMTYyOGI5ZDQ1YzAxMWQ1OTU1Njc4NDU=",
encodedURL: "http://localhost:8902/bucket123/Audio%20icon%281%29.svg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=UBO1L1C7U87P1BP251TS%2F20240405%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240405T210133Z&X-Amz-Expires=43200&X-Amz-Security-Token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJVQk8xTDFDN1U4N1AxQlAyNTFUUyIsImV4cCI6MTcxMjM5NDA4OSwicGFyZW50IjoibWluaW9hZG1pbiJ9.V-KDgrLMUBlnJHKX6VxHl9-A_-PFEWok2dpTq-46blLmLsueTxshVaY4DZwGfom4TT5k8phUfgjcQansnbrkeA&X-Amz-SignedHeaders=host&versionId=null&X-Amz-Signature=07cad3eb2a6722b5baed09c6f1fe4a701bf12f48e1628b9d45c011d595567845",
},
wantError: swag.String("403 Forbidden"),
expected: nil,
@@ -61,7 +61,7 @@ func Test_b64toMinIOStringURL(t *testing.T) {
{
test: "valid url but with invalid schema returns error",
args: args{
encodedURL: "cG9zdGdyZXM6Ly9wb3N0Z3JlczoxMjM0NTZAMTI3LjAuMC4xOjU0MzIvZHVtbXk=", // postgres://postgres:123456@127.0.0.1:5432/dummy
encodedURL: "postgres://postgres:123456@127.0.0.1:5432/dummy", // postgres://postgres:123456@127.0.0.1:5432/dummy
},
wantError: swag.String("unexpected scheme found postgres"),
@@ -70,16 +70,16 @@ func Test_b64toMinIOStringURL(t *testing.T) {
{
test: "invalid url returns error",
args: args{
encodedURL: "YXNkc2Fkc2Rh", // asdsadsda
encodedURL: "asdsadsda", // asdsadsda
},
wantError: swag.String("unexpected scheme found "),
expected: nil,
},
{
test: "encoded url is url safe decoded",
test: "plain url",
args: args{
encodedURL: "aHR0cHM6Ly9sb2NhbGhvc3Q6OTAwMC9jZXN0ZXN0L0F1ZGlvJTIwaWNvbi5zdmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTY=",
encodedURL: "https://localhost:9000/cestest/Audio%20icon.svg?X-Amz-Algorithm=AWS4-HMAC-SHA256",
},
wantError: nil,
expected: swag.String("https://localhost:9000/cestest/Audio%20icon.svg?X-Amz-Algorithm=AWS4-HMAC-SHA256"),
@@ -88,20 +88,20 @@ func Test_b64toMinIOStringURL(t *testing.T) {
for _, tt := range tests {
t.Run(tt.test, func(_ *testing.T) {
url, err := b64toMinIOStringURL(tt.args.encodedURL)
url, err := checkMinIOStringURL(tt.args.encodedURL)
if tt.wantError != nil {
if err != nil {
if err.Error() != *tt.wantError {
t.Errorf("b64toMinIOStringURL() error: `%v`, wantErr: `%s`, input: `%s`", err, *tt.wantError, tt.args.encodedURL)
t.Errorf("checkMinIOStringURL() error: `%v`, wantErr: `%s`, input: `%s`", err, *tt.wantError, tt.args.encodedURL)
return
}
} else {
t.Errorf("b64toMinIOStringURL() error: `%v`, wantErr: `%s`, input: `%s`", err, *tt.wantError, tt.args.encodedURL)
t.Errorf("checkMinIOStringURL() error: `%v`, wantErr: `%s`, input: `%s`", err, *tt.wantError, tt.args.encodedURL)
return
}
} else {
if err != nil {
t.Errorf("b64toMinIOStringURL() error: `%s`, wantErr: `%v`, input: `%s`", err, tt.wantError, tt.args.encodedURL)
t.Errorf("checkMinIOStringURL() error: `%s`, wantErr: `%v`, input: `%s`", err, tt.wantError, tt.args.encodedURL)
return
}
tAssert.Equal(*tt.expected, *url)

View File

@@ -27,7 +27,6 @@ import (
saApi "github.com/minio/console/api/operations/service_account"
userApi "github.com/minio/console/api/operations/user"
"github.com/minio/console/models"
"github.com/minio/console/pkg/utils"
"github.com/minio/madmin-go/v3"
iampolicy "github.com/minio/pkg/v3/policy"
)
@@ -199,10 +198,6 @@ func getCreateAUserServiceAccountResponse(session *models.Principal, params user
// create a MinIO user Admin Client interface implementation
// defining the client to be used
userAdminClient := AdminClient{Client: userAdmin}
name, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
var expiry *time.Time
if params.Body.Expiry != "" {
@@ -212,7 +207,7 @@ func getCreateAUserServiceAccountResponse(session *models.Principal, params user
}
expiry = &parsedExpiry
}
saCreds, err := createAUserServiceAccount(ctx, userAdminClient, params.Body.Policy, name, params.Body.Name, params.Body.Description, expiry, params.Body.Comment)
saCreds, err := createAUserServiceAccount(ctx, userAdminClient, params.Body.Policy, params.Name, params.Body.Name, params.Body.Description, expiry, params.Body.Comment)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -233,14 +228,10 @@ func getCreateAUserServiceAccountCredsResponse(session *models.Principal, params
// defining the client to be used
userAdminClient := AdminClient{Client: userAdmin}
serviceAccount := params.Body
user, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
if user == serviceAccount.AccessKey {
if params.Name == serviceAccount.AccessKey {
return nil, ErrorWithContext(ctx, errors.New("Access Key already in use"))
}
accounts, err := userAdminClient.listServiceAccounts(ctx, user)
accounts, err := userAdminClient.listServiceAccounts(ctx, params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -258,7 +249,7 @@ func getCreateAUserServiceAccountCredsResponse(session *models.Principal, params
}
expiry = &parsedExpiry
}
saCreds, err := createAUserServiceAccountCreds(ctx, userAdminClient, serviceAccount.Policy, user, serviceAccount.AccessKey, serviceAccount.SecretKey, serviceAccount.Name, serviceAccount.Description, expiry, serviceAccount.Comment)
saCreds, err := createAUserServiceAccountCreds(ctx, userAdminClient, serviceAccount.Policy, params.Name, serviceAccount.AccessKey, serviceAccount.SecretKey, serviceAccount.Name, serviceAccount.Description, expiry, serviceAccount.Comment)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -366,10 +357,6 @@ func getUserServiceAccountsResponse(ctx context.Context, session *models.Princip
// create a MinIO user Admin Client interface implementation
// defining the client to be used
userAdminClient := AdminClient{Client: userAdmin}
user, err = utils.DecodeBase64(user)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
serviceAccounts, err := getUserServiceAccounts(ctx, userAdminClient, user)
if err != nil {
return nil, ErrorWithContext(ctx, err)
@@ -386,10 +373,6 @@ func deleteServiceAccount(ctx context.Context, userClient MinioAdmin, accessKey
func getDeleteServiceAccountResponse(session *models.Principal, params saApi.DeleteServiceAccountParams) *CodedAPIError {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
accessKey, err := utils.DecodeBase64(params.AccessKey)
if err != nil {
return ErrorWithContext(ctx, err)
}
userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil {
return ErrorWithContext(ctx, err)
@@ -397,7 +380,7 @@ func getDeleteServiceAccountResponse(session *models.Principal, params saApi.Del
// create a MinIO user Admin Client interface implementation
// defining the client to be used
userAdminClient := AdminClient{Client: userAdmin}
if err := deleteServiceAccount(ctx, userAdminClient, accessKey); err != nil {
if err := deleteServiceAccount(ctx, userAdminClient, params.AccessKey); err != nil {
return ErrorWithContext(ctx, err)
}
return nil
@@ -441,10 +424,6 @@ func getServiceAccountDetails(ctx context.Context, userClient MinioAdmin, access
func getServiceAccountInfo(session *models.Principal, params saApi.GetServiceAccountParams) (*models.ServiceAccount, *CodedAPIError) {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
accessKey, err := utils.DecodeBase64(params.AccessKey)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil {
return nil, ErrorWithContext(ctx, err)
@@ -453,7 +432,7 @@ func getServiceAccountInfo(session *models.Principal, params saApi.GetServiceAcc
// defining the client to be used
userAdminClient := AdminClient{Client: userAdmin}
serviceAccount, err := getServiceAccountDetails(ctx, userAdminClient, accessKey)
serviceAccount, err := getServiceAccountDetails(ctx, userAdminClient, params.AccessKey)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -481,10 +460,6 @@ func updateServiceAccountDetails(ctx context.Context, userClient MinioAdmin, acc
func updateSetServiceAccountResponse(session *models.Principal, params saApi.UpdateServiceAccountParams) *CodedAPIError {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
accessKey, err := utils.DecodeBase64(params.AccessKey)
if err != nil {
return ErrorWithContext(ctx, err)
}
policy := *params.Body.Policy
userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil {
@@ -502,7 +477,7 @@ func updateSetServiceAccountResponse(session *models.Principal, params saApi.Upd
}
expiry = &parsedExpiry
}
err = updateServiceAccountDetails(ctx, userAdminClient, accessKey, policy, expiry, params.Body.Name, params.Body.Description, params.Body.Status, params.Body.SecretKey)
err = updateServiceAccountDetails(ctx, userAdminClient, params.AccessKey, policy, expiry, params.Body.Name, params.Body.Description, params.Body.Status, params.Body.SecretKey)
if err != nil {
return ErrorWithContext(ctx, err)
}

View File

@@ -18,7 +18,6 @@ package api
import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
@@ -1014,12 +1013,7 @@ func getBucketRewindResponse(session *models.Principal, params bucketApi.GetBuck
defer cancel()
prefix := ""
if params.Prefix != nil {
encodedPrefix := SanitizeEncodedPrefix(*params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
prefix = *params.Prefix
}
s3Client, err := newS3BucketClient(session, params.BucketName, prefix, getClientIP(params.HTTPRequest))
if err != nil {

View File

@@ -18,8 +18,6 @@ package api
import (
"context"
"encoding/base64"
b64 "encoding/base64"
"errors"
"fmt"
"io"
@@ -79,19 +77,8 @@ func registerObjectsHandlers(api *operations.ConsoleAPI) {
// download object
api.ObjectDownloadObjectHandler = objectApi.DownloadObjectHandlerFunc(func(params objectApi.DownloadObjectParams, session *models.Principal) middleware.Responder {
isFolder := false
ctx := params.HTTPRequest.Context()
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
apiErr := ErrorWithContext(ctx, err)
return objectApi.NewDownloadObjectDefault(400).WithPayload(apiErr.APIError)
}
prefix = string(decodedPrefix)
}
folders := strings.Split(prefix, "/")
folders := strings.Split(params.Prefix, "/")
if folders[len(folders)-1] == "" {
isFolder = true
}
@@ -197,12 +184,7 @@ func getListObjectsResponse(session *models.Principal, params objectApi.ListObje
var withVersions bool
var withMetadata bool
if params.Prefix != nil {
encodedPrefix := SanitizeEncodedPrefix(*params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
prefix = *params.Prefix
}
if params.Recursive != nil {
recursive = *params.Recursive
@@ -417,19 +399,10 @@ func parseRange(s string, size int64) ([]httpRange, error) {
func getDownloadObjectResponse(session *models.Principal, params objectApi.DownloadObjectParams) (middleware.Responder, *CodedAPIError) {
ctx := params.HTTPRequest.Context()
var prefix string
mClient, err := newMinioClient(session, getClientIP(params.HTTPRequest))
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
opts := minio.GetObjectOptions{}
@@ -437,7 +410,7 @@ func getDownloadObjectResponse(session *models.Principal, params objectApi.Downl
opts.VersionID = *params.VersionID
}
resp, err := mClient.GetObject(ctx, params.BucketName, prefix, opts)
resp, err := mClient.GetObject(ctx, params.BucketName, params.Prefix, opts)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -446,19 +419,11 @@ func getDownloadObjectResponse(session *models.Principal, params objectApi.Downl
defer resp.Close()
isPreview := params.Preview != nil && *params.Preview
// override filename is set
decodeOverride, err := base64.StdEncoding.DecodeString(*params.OverrideFileName)
if err != nil {
fmtError := ErrorWithContext(ctx, fmt.Errorf("unable to decode OverrideFileName: %v", err))
http.Error(rw, fmtError.APIError.DetailedMessage, http.StatusBadRequest)
return
}
overrideName := string(decodeOverride)
overrideName := *params.OverrideFileName
// indicate it's a download / inline content to the browser, and the size of the object
var filename string
prefixElements := strings.Split(prefix, "/")
prefixElements := strings.Split(params.Prefix, "/")
if len(prefixElements) > 0 && overrideName == "" {
if prefixElements[len(prefixElements)-1] == "" {
filename = prefixElements[len(prefixElements)-2]
@@ -475,7 +440,7 @@ func getDownloadObjectResponse(session *models.Principal, params objectApi.Downl
stat, err := resp.Stat()
if err != nil {
minErr := minio.ToErrorResponse(err)
fmtError := ErrorWithContext(ctx, fmt.Errorf("failed to get Stat() response from server for %s (version %s): %v", prefix, opts.VersionID, minErr.Error()))
fmtError := ErrorWithContext(ctx, fmt.Errorf("failed to get Stat() response from server for %s (version %s): %v", params.Prefix, opts.VersionID, minErr.Error()))
http.Error(rw, fmtError.APIError.DetailedMessage, http.StatusInternalServerError)
return
}
@@ -537,18 +502,9 @@ func getDownloadObjectResponse(session *models.Principal, params objectApi.Downl
func getDownloadFolderResponse(session *models.Principal, params objectApi.DownloadObjectParams) (middleware.Responder, *CodedAPIError) {
ctx := params.HTTPRequest.Context()
var prefix string
mClient, err := newMinioClient(session, getClientIP(params.HTTPRequest))
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
folders := strings.Split(prefix, "/")
folders := strings.Split(params.Prefix, "/")
if err != nil {
return nil, ErrorWithContext(ctx, err)
@@ -558,7 +514,7 @@ func getDownloadFolderResponse(session *models.Principal, params objectApi.Downl
ctx: ctx,
client: minioClient,
bucketName: params.BucketName,
prefix: prefix,
prefix: params.Prefix,
recursive: true,
withVersions: false,
withMetadata: false,
@@ -579,7 +535,7 @@ func getDownloadFolderResponse(session *models.Principal, params objectApi.Downl
defer zipw.Close()
for i, obj := range objects {
name := folder + objects[i].Name[len(prefix)-1:]
name := folder + objects[i].Name[len(params.Prefix)-1:]
object, err := mClient.GetObject(ctx, params.BucketName, obj.Name, minio.GetObjectOptions{})
if err != nil {
// Ignore errors, move to next
@@ -609,20 +565,8 @@ func getDownloadFolderResponse(session *models.Principal, params objectApi.Downl
defer resp.Close()
// indicate it's a download / inline content to the browser, and the size of the object
var prefixPath string
var filename string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
fmtError := ErrorWithContext(ctx, fmt.Errorf("unable to parse encoded prefix %s: %v", encodedPrefix, err))
http.Error(rw, fmtError.APIError.DetailedMessage, http.StatusInternalServerError)
return
}
prefixPath = string(decodedPrefix)
}
prefixElements := strings.Split(prefixPath, "/")
prefixElements := strings.Split(params.Prefix, "/")
if len(prefixElements) > 0 {
if prefixElements[len(prefixElements)-1] == "" {
filename = prefixElements[len(prefixElements)-2]
@@ -775,16 +719,7 @@ func getMultipleFilesDownloadResponse(session *models.Principal, params objectAp
func getDeleteObjectResponse(session *models.Principal, params objectApi.DeleteObjectParams) *CodedAPIError {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
s3Client, err := newS3BucketClient(session, params.BucketName, prefix, getClientIP(params.HTTPRequest))
s3Client, err := newS3BucketClient(session, params.BucketName, params.Prefix, getClientIP(params.HTTPRequest))
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -817,7 +752,7 @@ func getDeleteObjectResponse(session *models.Principal, params objectApi.DeleteO
return ErrorWithContext(ctx, err)
}
err = deleteObjects(ctx, mcClient, params.BucketName, prefix, version, rec, allVersions, nonCurrentVersions, bypass)
err = deleteObjects(ctx, mcClient, params.BucketName, params.Prefix, version, rec, allVersions, nonCurrentVersions, bypass)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1008,12 +943,7 @@ func getUploadObjectResponse(session *models.Principal, params objectApi.PostBuc
func uploadFiles(ctx context.Context, client MinioClient, params objectApi.PostBucketsBucketNameObjectsUploadParams) error {
var prefix string
if params.Prefix != nil {
encodedPrefix := SanitizeEncodedPrefix(*params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return err
}
prefix = string(decodedPrefix)
prefix = *params.Prefix
// trim any leading '/', since that is not expected
// for any object.
prefix = strings.TrimPrefix(prefix, "/")
@@ -1058,16 +988,7 @@ func uploadFiles(ctx context.Context, client MinioClient, params objectApi.PostB
func getShareObjectResponse(session *models.Principal, params objectApi.ShareObjectParams) (*string, *CodedAPIError) {
ctx := params.HTTPRequest.Context()
clientIP := utils.ClientIPFromContext(ctx)
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
s3Client, err := newS3BucketClient(session, params.BucketName, prefix, clientIP)
s3Client, err := newS3BucketClient(session, params.BucketName, params.Prefix, clientIP)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -1086,7 +1007,7 @@ func getShareObjectResponse(session *models.Principal, params objectApi.ShareObj
return url, nil
}
func getShareObjectURL(ctx context.Context, client MCClient, r *http.Request, versionID string, duration string) (url *string, err error) {
func getShareObjectURL(ctx context.Context, client MCClient, r *http.Request, versionID string, duration string) (*string, error) {
// default duration 7d if not defined
if strings.TrimSpace(duration) == "" {
duration = "168h"
@@ -1100,9 +1021,8 @@ func getShareObjectURL(ctx context.Context, client MCClient, r *http.Request, ve
return nil, pErr.Cause
}
encodedMinIOURL := b64.URLEncoding.EncodeToString([]byte(minioURL))
requestURL := getRequestURLWithScheme(r)
objURL := fmt.Sprintf("%s/api/v1/download-shared-object/%s", requestURL, encodedMinIOURL)
objURL := fmt.Sprintf("%s/api/v1/download-shared-object/%s", requestURL, url.PathEscape(minioURL))
return &objURL, nil
}
@@ -1129,16 +1049,7 @@ func getSetObjectLegalHoldResponse(session *models.Principal, params objectApi.P
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = setObjectLegalHold(ctx, minioClient, params.BucketName, prefix, params.VersionID, *params.Body.Status)
err = setObjectLegalHold(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID, *params.Body.Status)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1164,16 +1075,7 @@ func getSetObjectRetentionResponse(session *models.Principal, params objectApi.P
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = setObjectRetention(ctx, minioClient, params.BucketName, params.VersionID, prefix, params.Body)
err = setObjectRetention(ctx, minioClient, params.BucketName, params.VersionID, params.Prefix, params.Body)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1216,16 +1118,7 @@ func deleteObjectRetentionResponse(session *models.Principal, params objectApi.D
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = deleteObjectRetention(ctx, minioClient, params.BucketName, prefix, params.VersionID)
err = deleteObjectRetention(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1250,16 +1143,7 @@ func getPutObjectTagsResponse(session *models.Principal, params objectApi.PutObj
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = putObjectTags(ctx, minioClient, params.BucketName, prefix, params.VersionID, params.Body.Tags)
err = putObjectTags(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID, params.Body.Tags)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1287,18 +1171,7 @@ func getPutObjectRestoreResponse(session *models.Principal, params objectApi.Put
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = restoreObject(ctx, minioClient, params.BucketName, prefix, params.VersionID)
err = restoreObject(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1342,23 +1215,12 @@ func getObjectMetadataResponse(session *models.Principal, params objectApi.GetOb
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
var versionID string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
if params.VersionID != nil {
versionID = *params.VersionID
}
objectInfo, err := getObjectInfo(ctx, minioClient, params.BucketName, prefix, versionID)
objectInfo, err := getObjectInfo(ctx, minioClient, params.BucketName, params.Prefix, versionID)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}

View File

@@ -942,7 +942,7 @@ func Test_shareObject(t *testing.T) {
},
wantError: nil,
expected: "http://localhost:9090/api/v1/download-shared-object/aHR0cDovL3NvbWV1cmw=",
expected: "http://localhost:9090/api/v1/download-shared-object/http:%2F%2Fsomeurl",
},
{
test: "return https scheme if url uses TLS",
@@ -959,7 +959,7 @@ func Test_shareObject(t *testing.T) {
},
wantError: nil,
expected: "https://localhost:9090/api/v1/download-shared-object/aHR0cDovL3NvbWV1cmw=",
expected: "https://localhost:9090/api/v1/download-shared-object/http:%2F%2Fsomeurl",
},
{
test: "returns invalid expire duration if expiration is invalid",
@@ -990,7 +990,7 @@ func Test_shareObject(t *testing.T) {
},
},
wantError: nil,
expected: "http://localhost:9090/api/v1/download-shared-object/aHR0cDovL3NvbWV1cmw=",
expected: "http://localhost:9090/api/v1/download-shared-object/http:%2F%2Fsomeurl",
},
{
test: "return error if sharefunc returns error",
@@ -1022,7 +1022,7 @@ func Test_shareObject(t *testing.T) {
},
},
wantError: nil,
expected: "http://localhost:9090/api/v1/download-shared-object/aHR0cHM6Ly8xMjcuMC4wLjE6OTAwMC9jZXN0ZXN0L0F1ZGlvJTIwaWNvbi5zdmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTY=",
expected: "http://localhost:9090/api/v1/download-shared-object/https:%2F%2F127.0.0.1:9000%2Fcestest%2FAudio%2520icon.svg%3FX-Amz-Algorithm=AWS4-HMAC-SHA256",
},
{
test: "returns redirect url with share link if redirect url env variable set",
@@ -1041,7 +1041,7 @@ func Test_shareObject(t *testing.T) {
},
},
wantError: nil,
expected: "http://proxy-url.com:9012/console/subpath/api/v1/download-shared-object/aHR0cDovL3NvbWV1cmw=",
expected: "http://proxy-url.com:9012/console/subpath/api/v1/download-shared-object/http:%2F%2Fsomeurl",
},
{
test: "returns redirect url with share link if redirect url env variable set with trailing slash",
@@ -1060,7 +1060,7 @@ func Test_shareObject(t *testing.T) {
},
},
wantError: nil,
expected: "http://proxy-url.com:9012/console/subpath/api/v1/download-shared-object/aHR0cDovL3NvbWV1cmw=",
expected: "http://proxy-url.com:9012/console/subpath/api/v1/download-shared-object/http:%2F%2Fsomeurl",
},
}
@@ -1077,7 +1077,7 @@ func Test_shareObject(t *testing.T) {
return
}
} else {
tAssert.Equal(*url, tt.expected)
tAssert.Equal(tt.expected, *url)
}
})
}

View File

@@ -211,11 +211,6 @@ func ValidateEncodedStyles(encodedStyles string) error {
return nil
}
// SanitizeEncodedPrefix replaces spaces for + since those are lost when you do GET parameters
func SanitizeEncodedPrefix(rawPrefix string) string {
return strings.ReplaceAll(rawPrefix, " ", "+")
}
var safeMimeTypes = []string{
"image/jpeg",
"image/apng",

View File

@@ -153,37 +153,6 @@ func TestExpireSessionCookie(t *testing.T) {
}
}
func TestSanitizeEncodedPrefix(t *testing.T) {
type args struct {
rawPrefix string
}
tests := []struct {
name string
args args
want string
}{
{
name: "replace spaces with +",
args: args{
rawPrefix: "hello world",
},
want: "hello+world",
},
{
name: "replace spaces with +",
args: args{
rawPrefix: " hello-world ",
},
want: "+++hello-world+++",
},
}
for _, tt := range tests {
t.Run(tt.name, func(_ *testing.T) {
assert.Equalf(t, tt.want, SanitizeEncodedPrefix(tt.args.rawPrefix), "SanitizeEncodedPrefix(%v)", tt.args.rawPrefix)
})
}
}
func Test_isSafeToPreview(t *testing.T) {
type args struct {
str string
@@ -293,27 +262,3 @@ func TestValidateEncodedStyles(t *testing.T) {
})
}
}
func TestSanitizeEncodedPrefix1(t *testing.T) {
type args struct {
rawPrefix string
}
tests := []struct {
name string
args args
want string
}{
{
name: "input sanitized",
args: args{
rawPrefix: "x y",
},
want: "x+y",
},
}
for _, tt := range tests {
t.Run(tt.name, func(_ *testing.T) {
assert.Equalf(t, tt.want, SanitizeEncodedPrefix(tt.args.rawPrefix), "SanitizeEncodedPrefix(%v)", tt.args.rawPrefix)
})
}
}

5
generator.config.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
hooks: {
onInsertPathParam: (paramName) => `encodeURIComponent(${paramName})`,
},
};

View File

@@ -18,7 +18,6 @@ package integration
import (
"bytes"
b64 "encoding/base64"
"encoding/json"
"fmt"
"io"
@@ -36,14 +35,6 @@ import (
var token string
func encodeBase64(fileName string) string {
/*
Helper function to encode in base64 the file name so we can get the path
*/
path := b64.StdEncoding.EncodeToString([]byte(fileName))
return path
}
func inspectHTTPResponse(httpResponse *http.Response) string {
/*
Helper function to inspect the content of a HTTP response.

View File

@@ -18,11 +18,11 @@ package integration
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"testing"
"time"
@@ -114,7 +114,7 @@ func Test_GetGroupAPI(t *testing.T) {
{
name: "Get Group - Valid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("getgroup1")),
api: "getgroup1",
},
expectedStatus: 200,
expectedError: nil,
@@ -122,7 +122,7 @@ func Test_GetGroupAPI(t *testing.T) {
{
name: "Get Group - Invalid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("askfjalkd")),
api: "askfjalkd",
},
expectedStatus: 500,
expectedError: nil,
@@ -140,7 +140,7 @@ func Test_GetGroupAPI(t *testing.T) {
requestDataJSON, _ := json.Marshal(requestDataPolicy)
requestDataBody := bytes.NewReader(requestDataJSON)
request, err := http.NewRequest(
"GET", fmt.Sprintf("http://localhost:9090/api/v1/group/%s", tt.args.api), requestDataBody)
"GET", fmt.Sprintf("http://localhost:9090/api/v1/group/%s", url.PathEscape(tt.args.api)), requestDataBody)
if err != nil {
log.Println(err)
return
@@ -224,7 +224,7 @@ func Test_PutGroupsAPI(t *testing.T) {
{
name: "Put Group - Valid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("putgroup1")),
api: "putgroup1",
members: []string{"member3"},
status: "enabled",
},
@@ -234,7 +234,7 @@ func Test_PutGroupsAPI(t *testing.T) {
{
name: "Put Group - Invalid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("gdgfdfgd")),
api: "gdgfdfgd",
members: []string{"member3"},
status: "enabled",
},
@@ -257,7 +257,7 @@ func Test_PutGroupsAPI(t *testing.T) {
requestDataJSON, _ := json.Marshal(requestDataPolicy)
requestDataBody := bytes.NewReader(requestDataJSON)
request, err := http.NewRequest(
"PUT", fmt.Sprintf("http://localhost:9090/api/v1/group/%s", tt.args.api), requestDataBody)
"PUT", fmt.Sprintf("http://localhost:9090/api/v1/group/%s", url.PathEscape(tt.args.api)), requestDataBody)
if err != nil {
log.Println(err)
return
@@ -294,7 +294,7 @@ func Test_DeleteGroupAPI(t *testing.T) {
{
name: "Delete Group - Valid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("grouptests1")),
api: "grouptests1",
},
verb: "DELETE",
expectedStatus: 204,
@@ -303,7 +303,7 @@ func Test_DeleteGroupAPI(t *testing.T) {
{
name: "Delete Group - Invalid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("grouptests12345")),
api: "grouptests12345",
},
verb: "DELETE",
expectedStatus: 404,
@@ -312,7 +312,7 @@ func Test_DeleteGroupAPI(t *testing.T) {
{
name: "Access Group After Delete - Invalid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("grouptests1")),
api: "grouptests1",
},
verb: "GET",
expectedStatus: 500,
@@ -331,7 +331,7 @@ func Test_DeleteGroupAPI(t *testing.T) {
requestDataJSON, _ := json.Marshal(requestDataPolicy)
requestDataBody := bytes.NewReader(requestDataJSON)
request, err := http.NewRequest(
tt.verb, fmt.Sprintf("http://localhost:9090/api/v1/group/%s", tt.args.api), requestDataBody)
tt.verb, fmt.Sprintf("http://localhost:9090/api/v1/group/%s", url.PathEscape(tt.args.api)), requestDataBody)
if err != nil {
log.Println(err)
return

View File

@@ -19,12 +19,12 @@ package integration
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"net/url"
"strings"
"testing"
"time"
@@ -90,7 +90,7 @@ func TestObjectGet(t *testing.T) {
{
name: "Preview Object",
args: args{
encodedPrefix: base64.StdEncoding.EncodeToString([]byte("myobject")),
encodedPrefix: "myobject",
},
expectedStatus: 200,
expectedError: nil,
@@ -98,7 +98,7 @@ func TestObjectGet(t *testing.T) {
{
name: "Preview image",
args: args{
encodedPrefix: base64.StdEncoding.EncodeToString([]byte("myobject.jpg")),
encodedPrefix: "myobject.jpg",
},
expectedStatus: 200,
expectedError: nil,
@@ -106,7 +106,7 @@ func TestObjectGet(t *testing.T) {
{
name: "Get Range of bytes",
args: args{
encodedPrefix: base64.StdEncoding.EncodeToString([]byte("myobject.jpg")),
encodedPrefix: "myobject.jpg",
bytesRange: "bytes=1-4",
},
expectedStatus: 206,
@@ -115,7 +115,7 @@ func TestObjectGet(t *testing.T) {
{
name: "Get Range of bytes empty start",
args: args{
encodedPrefix: base64.StdEncoding.EncodeToString([]byte("myobject.jpg")),
encodedPrefix: "myobject.jpg",
bytesRange: "bytes=-4",
},
expectedStatus: 206,
@@ -124,7 +124,7 @@ func TestObjectGet(t *testing.T) {
{
name: "Get Invalid Range of bytes",
args: args{
encodedPrefix: base64.StdEncoding.EncodeToString([]byte("myobject.jpg")),
encodedPrefix: "myobject.jpg",
bytesRange: "bytes=9-12",
},
expectedStatus: 500,
@@ -133,7 +133,7 @@ func TestObjectGet(t *testing.T) {
{
name: "Get Larger Range of bytes empty start",
args: args{
encodedPrefix: base64.StdEncoding.EncodeToString([]byte("myobject.jpg")),
encodedPrefix: "myobject.jpg",
bytesRange: "bytes=-12",
},
expectedStatus: 206,
@@ -142,29 +142,12 @@ func TestObjectGet(t *testing.T) {
{
name: "Get invalid seek start Range of bytes",
args: args{
encodedPrefix: base64.StdEncoding.EncodeToString([]byte("myobject.jpg")),
encodedPrefix: "myobject.jpg",
bytesRange: "bytes=12-16",
},
expectedStatus: 500,
expectedError: nil,
},
{
name: "Bad Preview Object",
args: args{
encodedPrefix: "garble",
},
expectedStatus: 400,
expectedError: nil,
},
{
name: "Bad Version Preview Object",
args: args{
encodedPrefix: base64.StdEncoding.EncodeToString([]byte("myobject")),
versionID: "garble",
},
expectedStatus: 500,
expectedError: nil,
},
}
for _, tt := range tests {
@@ -172,7 +155,7 @@ func TestObjectGet(t *testing.T) {
client := &http.Client{
Timeout: 3 * time.Second,
}
destination := fmt.Sprintf("/api/v1/buckets/%s/objects/download?preview=true&prefix=%s&version_id=%s", bucketName, tt.args.encodedPrefix, tt.args.versionID)
destination := fmt.Sprintf("/api/v1/buckets/%s/objects/download?preview=true&prefix=%s&version_id=%s", url.PathEscape(bucketName), url.QueryEscape(tt.args.encodedPrefix), url.QueryEscape(tt.args.versionID))
finalURL := fmt.Sprintf("http://localhost:9090%s", destination)
request, err := http.NewRequest("GET", finalURL, nil)
if err != nil {
@@ -198,7 +181,7 @@ func TestObjectGet(t *testing.T) {
}
func downloadMultipleFiles(bucketName string, objects []string) (*http.Response, error) {
requestURL := fmt.Sprintf("http://localhost:9090/api/v1/buckets/%s/objects/download-multiple", bucketName)
requestURL := fmt.Sprintf("http://localhost:9090/api/v1/buckets/%s/objects/download-multiple", url.PathEscape(bucketName))
postReqParams, _ := json.Marshal(objects)
reqBody := bytes.NewReader(postReqParams)

View File

@@ -18,12 +18,12 @@ package integration
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"testing"
"time"
@@ -179,6 +179,31 @@ func Test_AddPolicyAPI(t *testing.T) {
expectedStatus: 400,
expectedError: nil,
},
{
name: "Create Policy - Reserved character in name",
args: args{
api: "/policies",
name: "space/test?",
policy: swag.String(`
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}`),
},
expectedStatus: 201,
expectedError: nil,
},
}
for _, tt := range tests {
@@ -491,7 +516,7 @@ func Test_ListPoliciesAPI(t *testing.T) {
func Test_GetPolicyAPI(t *testing.T) {
assert := assert.New(t)
AddPolicy("getpolicytest", `
AddPolicy("test/policy?", `
{
"Version": "2012-10-17",
"Statement": [
@@ -520,7 +545,7 @@ func Test_GetPolicyAPI(t *testing.T) {
{
name: "Get Policies - Invalid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("test3")),
api: "test3",
},
expectedStatus: 500,
expectedError: nil,
@@ -528,7 +553,7 @@ func Test_GetPolicyAPI(t *testing.T) {
{
name: "Get Policies - Valid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("getpolicytest")),
api: "test/policy?",
},
expectedStatus: 200,
expectedError: nil,
@@ -542,7 +567,7 @@ func Test_GetPolicyAPI(t *testing.T) {
}
request, err := http.NewRequest(
"GET", fmt.Sprintf("http://localhost:9090/api/v1/policy/%s", tt.args.api), nil)
"GET", fmt.Sprintf("http://localhost:9090/api/v1/policy/%s", url.PathEscape(tt.args.api)), nil)
if err != nil {
log.Println(err)
return
@@ -595,7 +620,7 @@ func Test_PolicyListUsersAPI(t *testing.T) {
{
name: "List Users for Policy - Valid",
args: args{
api: "/policies/" + base64.StdEncoding.EncodeToString([]byte("policylistusers")) + "/users",
api: "/policies/" + url.PathEscape("policylistusers") + "/users",
},
expectedStatus: 200,
expectedError: nil,
@@ -603,7 +628,7 @@ func Test_PolicyListUsersAPI(t *testing.T) {
{
name: "List Users for Policy - Invalid",
args: args{
api: "/policies/" + base64.StdEncoding.EncodeToString([]byte("test2")) + "/users",
api: "/policies/" + url.PathEscape("test2") + "/users",
},
expectedStatus: 404,
expectedError: nil,
@@ -674,7 +699,7 @@ func Test_PolicyListGroupsAPI(t *testing.T) {
{
name: "List Users for Policy - Valid",
args: args{
api: "/policies/" + base64.StdEncoding.EncodeToString([]byte("policylistgroups")) + "/groups",
api: "/policies/" + url.PathEscape("policylistgroups") + "/groups",
},
expectedStatus: 200,
expectedError: nil,
@@ -682,7 +707,7 @@ func Test_PolicyListGroupsAPI(t *testing.T) {
{
name: "List Users for Policy - Invalid",
args: args{
api: "/policies/" + base64.StdEncoding.EncodeToString([]byte("test3")) + "/groups",
api: "/policies/" + url.PathEscape("test3") + "/groups",
},
expectedStatus: 404,
expectedError: nil,
@@ -751,7 +776,7 @@ func Test_DeletePolicyAPI(t *testing.T) {
{
name: "Delete Policies - Valid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("testdelete")),
api: "testdelete",
method: "DELETE",
},
expectedStatus: 204,
@@ -760,7 +785,7 @@ func Test_DeletePolicyAPI(t *testing.T) {
{
name: "Get Policy After Delete - Invalid",
args: args{
api: base64.StdEncoding.EncodeToString([]byte("testdelete")),
api: "testdelete",
method: "GET",
},
expectedStatus: 500,
@@ -775,7 +800,7 @@ func Test_DeletePolicyAPI(t *testing.T) {
}
request, err := http.NewRequest(
tt.args.method, fmt.Sprintf("http://localhost:9090/api/v1/policy/%s", tt.args.api), nil)
tt.args.method, fmt.Sprintf("http://localhost:9090/api/v1/policy/%s", url.PathEscape(tt.args.api)), nil)
if err != nil {
log.Println(err)
return
@@ -804,11 +829,6 @@ func Test_GetAUserPolicyAPI(t *testing.T) {
log.Println(err)
return
}
// encode usernames to pass to api
bName := []byte("getuserpolicyuser")
fName := []byte("failname")
encodedName := base64.URLEncoding.EncodeToString(bName)
encodedFailName := base64.URLEncoding.EncodeToString(fName)
type args struct {
api string
@@ -822,7 +842,7 @@ func Test_GetAUserPolicyAPI(t *testing.T) {
{
name: "Get User Policy - Invalid",
args: args{
api: "/user/" + encodedFailName + "/policies",
api: "/user/" + url.PathEscape("failname") + "/policies",
},
expectedStatus: 401,
expectedError: nil,
@@ -830,7 +850,7 @@ func Test_GetAUserPolicyAPI(t *testing.T) {
{
name: "Get User Policy - Valid",
args: args{
api: "/user/" + encodedName + "/policies",
api: "/user/" + url.PathEscape("getuserpolicyuser") + "/policies",
},
expectedStatus: 200,
expectedError: nil,

View File

@@ -18,11 +18,11 @@ package integration
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"testing"
"time"
@@ -92,7 +92,7 @@ func TestAddServiceAccount(t *testing.T) {
// {{baseUrl}}/user?name=proident velit
// Investiga como se borra en el browser.
request, err = http.NewRequest(
"DELETE", "http://localhost:9090/api/v1/service-accounts/"+base64.StdEncoding.EncodeToString([]byte("testuser1")), nil)
"DELETE", "http://localhost:9090/api/v1/service-accounts/"+url.PathEscape("testuser1"), nil)
if err != nil {
log.Println(err)
return

View File

@@ -21,13 +21,13 @@ package integration
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"strconv"
"strings"
@@ -396,7 +396,7 @@ func UploadAnObject(bucketName, fileName string) (*http.Response, error) {
contentType + boundaryEnd
arrayOfBytes := []byte(file)
requestDataBody := bytes.NewReader(arrayOfBytes)
apiURL := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects/upload" + "?prefix=" + base64.StdEncoding.EncodeToString([]byte(fileName))
apiURL := "http://localhost:9090/api/v1/buckets/" + url.PathEscape(bucketName) + "/objects/upload" + "?prefix=" + url.QueryEscape(fileName)
request, err := http.NewRequest(
"POST",
apiURL,
@@ -423,9 +423,8 @@ func DeleteObject(bucketName, path string, recursive, allVersions bool) (*http.R
DELETE:
{{baseUrl}}/buckets/bucketName/objects?path=Y2VzYXJpby50eHQ=&recursive=false&all_versions=false
*/
prefixEncoded := base64.StdEncoding.EncodeToString([]byte(path))
url := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects?prefix=" +
prefixEncoded + "&recursive=" + strconv.FormatBool(recursive) + "&all_versions=" +
url := "http://localhost:9090/api/v1/buckets/" + url.PathEscape(bucketName) + "/objects?prefix=" +
url.QueryEscape(path) + "&recursive=" + strconv.FormatBool(recursive) + "&all_versions=" +
strconv.FormatBool(allVersions)
request, err := http.NewRequest(
"DELETE",
@@ -444,13 +443,13 @@ func DeleteObject(bucketName, path string, recursive, allVersions bool) (*http.R
return response, err
}
func ListObjects(bucketName, prefix, withVersions string) (*http.Response, error) {
func ListObjects(bucketName, prefix string, withVersions bool) (*http.Response, error) {
/*
Helper function to list objects in a bucket.
GET: {{baseUrl}}/buckets/:bucket_name/objects
*/
request, err := http.NewRequest("GET",
"http://localhost:9090/api/v1/buckets/"+bucketName+"/objects?prefix="+prefix+"&with_versions="+withVersions,
"http://localhost:9090/api/v1/buckets/"+url.PathEscape(bucketName)+"/objects?prefix="+url.QueryEscape(prefix)+"&with_versions="+strconv.FormatBool(withVersions),
nil)
if err != nil {
log.Println(err)
@@ -753,8 +752,8 @@ func TestPutObjectsLegalholdStatus(t *testing.T) {
// Variables
assert := assert.New(t)
bucketName := "testputobjectslegalholdstatus"
objName := "testputobjectslegalholdstatus.txt" // // encoded base64 of testputobjectslegalholdstatus.txt = dGVzdHB1dG9iamVjdHNsZWdhbGhvbGRzdGF0dXMudHh0
objectNameEncoded := "dGVzdHB1dG9iamVjdHNsZWdhbGhvbGRzdGF0dXMudHh0"
objName := "testputobjectslegalholdstatus.txt"
objectNameEncoded := url.QueryEscape(objName)
status := "enabled"
// 1. Create bucket
@@ -782,7 +781,7 @@ func TestPutObjectsLegalholdStatus(t *testing.T) {
}
// Get versionID
listResponse, _ := ListObjects(bucketName, "", "true")
listResponse, _ := ListObjects(bucketName, "", true)
bodyBytes, _ := io.ReadAll(listResponse.Body)
listObjs := models.ListObjectsResponse{}
err := json.Unmarshal(bodyBytes, &listObjs)
@@ -807,13 +806,6 @@ func TestPutObjectsLegalholdStatus(t *testing.T) {
versionID: validVersionID,
},
},
{
name: "Invalid VersionID when putting object's legal hold status",
expectedStatus: 500,
args: args{
versionID: "*&^###Test1ThisMightBeInvalid555",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(_ *testing.T) {
@@ -1036,7 +1028,7 @@ func TestDeleteObjectsRetentionStatus(t *testing.T) {
assert := assert.New(t)
bucketName := "testdeleteobjectslegalholdstatus"
fileName := "testdeleteobjectslegalholdstatus.txt"
validPrefix := encodeBase64(fileName)
validPrefix := url.QueryEscape(fileName)
// 1. Create bucket
if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) {
@@ -1063,7 +1055,7 @@ func TestDeleteObjectsRetentionStatus(t *testing.T) {
}
// Get versionID
listResponse, _ := ListObjects(bucketName, validPrefix, "true")
listResponse, _ := ListObjects(bucketName, validPrefix, true)
bodyBytes, _ := io.ReadAll(listResponse.Body)
listObjs := models.ListObjectsResponse{}
err := json.Unmarshal(bodyBytes, &listObjs)
@@ -1204,7 +1196,7 @@ func TestRestoreObjectToASelectedVersion(t *testing.T) {
assert := assert.New(t)
bucketName := "testrestoreobjectstoselectedversion"
fileName := "testrestoreobjectstoselectedversion.txt"
validPrefix := encodeBase64(fileName)
validPrefix := url.QueryEscape(fileName)
// 1. Create bucket
if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) {
@@ -1231,7 +1223,7 @@ func TestRestoreObjectToASelectedVersion(t *testing.T) {
}
// 3. Get versionID
listResponse, _ := ListObjects(bucketName, validPrefix, "true")
listResponse, _ := ListObjects(bucketName, validPrefix, true)
bodyBytes, _ := io.ReadAll(listResponse.Body)
listObjs := models.ListObjectsResponse{}
err := json.Unmarshal(bodyBytes, &listObjs)
@@ -1348,7 +1340,7 @@ func TestGetsTheMetadataOfAnObject(t *testing.T) {
assert := assert.New(t)
bucketName := "testgetsthemetadataofanobject"
fileName := "testshareobjectonurl.txt"
validPrefix := encodeBase64(fileName)
validPrefix := url.QueryEscape(fileName)
tags := make(map[string]string)
tags["tag"] = "testputobjecttagbucketonetagone"
@@ -1421,7 +1413,7 @@ func TestPutObjectsRetentionStatus(t *testing.T) {
assert := assert.New(t)
bucketName := "testputobjectsretentionstatus"
fileName := "testputobjectsretentionstatus.txt"
prefix := encodeBase64(fileName)
prefix := url.QueryEscape(fileName)
// 1. Create bucket
if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) {
@@ -1448,7 +1440,7 @@ func TestPutObjectsRetentionStatus(t *testing.T) {
}
// Get versionID
listResponse, _ := ListObjects(bucketName, prefix, "true")
listResponse, _ := ListObjects(bucketName, prefix, true)
bodyBytes, _ := io.ReadAll(listResponse.Body)
listObjs := models.ListObjectsResponse{}
err := json.Unmarshal(bodyBytes, &listObjs)
@@ -1470,14 +1462,7 @@ func TestPutObjectsRetentionStatus(t *testing.T) {
name: "Valid VersionID when putting object's retention status",
expectedStatus: 200,
args: args{
versionID: validVersionID,
},
},
{
name: "Invalid VersionID when putting object's retention status",
expectedStatus: 500,
args: args{
versionID: "*&^###Test1ThisMightBeInvalid555",
versionID: url.QueryEscape(validVersionID),
},
},
}
@@ -1516,7 +1501,7 @@ func TestShareObjectOnURL(t *testing.T) {
assert := assert.New(t)
bucketName := "testshareobjectonurl"
fileName := "testshareobjectonurl.txt"
validPrefix := encodeBase64(fileName)
validPrefix := url.QueryEscape(fileName)
tags := make(map[string]string)
tags["tag"] = "testputobjecttagbucketonetagone"
versionID := "null"
@@ -1556,13 +1541,6 @@ func TestShareObjectOnURL(t *testing.T) {
prefix: validPrefix,
},
},
{
name: "Share file with invalid prefix",
expectedStatus: 500,
args: args{
prefix: "invalidprefix",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(_ *testing.T) {
@@ -1613,7 +1591,7 @@ func TestListObjects(t *testing.T) {
}
// 3. List the object
listResponse, listError := ListObjects(bucketName, "", "false")
listResponse, listError := ListObjects(bucketName, "", false)
assert.Nil(listError)
if listError != nil {
log.Println(listError)
@@ -1676,7 +1654,7 @@ func TestDeleteObject(t *testing.T) {
}
// 4. List the objects in the bucket and make sure the object is gone
listResponse, listError := ListObjects(bucketName, "", "false")
listResponse, listError := ListObjects(bucketName, "", false)
assert.Nil(listError)
if listError != nil {
log.Println(listError)
@@ -1738,7 +1716,7 @@ func TestDownloadObject(t *testing.T) {
assert := assert.New(t)
bucketName := "testdownloadobjbucketone"
fileName := "testdownloadobjectfilenameone"
path := encodeBase64(fileName)
path := url.QueryEscape(fileName)
workingDirectory, getWdErr := os.Getwd()
if getWdErr != nil {
assert.Fail("Couldn't get the directory")
@@ -1852,7 +1830,7 @@ func TestDeleteMultipleObjects(t *testing.T) {
}
// 4. List the objects, empty list is expected!
listResponse, listError := ListObjects(bucketName, "", "false")
listResponse, listError := ListObjects(bucketName, "", false)
assert.Nil(listError)
if listError != nil {
log.Println(listError)
@@ -1878,7 +1856,7 @@ func TestPutObjectTag(t *testing.T) {
assert := assert.New(t)
bucketName := "testputobjecttagbucketone"
fileName := "testputobjecttagbucketone.txt"
path := encodeBase64(fileName)
path := url.QueryEscape(fileName)
tags := make(map[string]string)
tags["tag"] = "testputobjecttagbucketonetagone"
versionID := "null"
@@ -1918,7 +1896,7 @@ func TestPutObjectTag(t *testing.T) {
}
// 4. Verify the object's tag is set
listResponse, listError := ListObjects(bucketName, path, "false")
listResponse, listError := ListObjects(bucketName, path, false)
assert.Nil(listError)
if listError != nil {
log.Println(listError)

View File

@@ -18,12 +18,12 @@ package integration
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"strconv"
"strings"
"testing"
@@ -63,7 +63,6 @@ func AddUser(accessKey, secretKey string, groups, policies []string) (*http.Resp
}
func DeleteUser(userName string) (*http.Response, error) {
userName = base64.StdEncoding.EncodeToString([]byte(userName))
/*
This is an atomic function to delete user and can be reused across
different functions.
@@ -72,7 +71,7 @@ func DeleteUser(userName string) (*http.Response, error) {
Timeout: 3 * time.Second,
}
request, err := http.NewRequest(
"DELETE", "http://localhost:9090/api/v1/user/"+userName, nil)
"DELETE", "http://localhost:9090/api/v1/user/"+url.PathEscape(userName), nil)
if err != nil {
log.Println(err)
}
@@ -104,7 +103,6 @@ func ListUsers(offset, limit string) (*http.Response, error) {
}
func GetUserInformation(userName string) (*http.Response, error) {
userName = base64.StdEncoding.EncodeToString([]byte(userName))
/*
Helper function to get user information via API:
{{baseUrl}}/user?name=proident velit
@@ -114,7 +112,7 @@ func GetUserInformation(userName string) (*http.Response, error) {
}
request, err := http.NewRequest(
"GET",
"http://localhost:9090/api/v1/user/"+userName,
"http://localhost:9090/api/v1/user/"+url.PathEscape(userName),
nil)
if err != nil {
log.Println(err)
@@ -126,7 +124,6 @@ func GetUserInformation(userName string) (*http.Response, error) {
}
func UpdateUserInformation(name, status string, groups []string) (*http.Response, error) {
name = base64.StdEncoding.EncodeToString([]byte(name))
/*
Helper function to update user information:
PUT: {{baseUrl}}/user?name=proident velit
@@ -149,7 +146,7 @@ func UpdateUserInformation(name, status string, groups []string) (*http.Response
requestDataJSON, _ := json.Marshal(requestDataAdd)
requestDataBody := bytes.NewReader(requestDataJSON)
request, err := http.NewRequest(
"PUT", "http://localhost:9090/api/v1/user/"+name, requestDataBody)
"PUT", "http://localhost:9090/api/v1/user/"+url.PathEscape(name), requestDataBody)
if err != nil {
log.Println(err)
}
@@ -160,7 +157,6 @@ func UpdateUserInformation(name, status string, groups []string) (*http.Response
}
func RemoveUser(name string) (*http.Response, error) {
name = base64.StdEncoding.EncodeToString([]byte(name))
/*
Helper function to remove user.
DELETE: {{baseUrl}}/user?name=proident velit
@@ -169,7 +165,7 @@ func RemoveUser(name string) (*http.Response, error) {
Timeout: 3 * time.Second,
}
request, err := http.NewRequest(
"DELETE", "http://localhost:9090/api/v1/user/"+name, nil)
"DELETE", "http://localhost:9090/api/v1/user/"+url.PathEscape(name), nil)
if err != nil {
log.Println(err)
}
@@ -180,7 +176,6 @@ func RemoveUser(name string) (*http.Response, error) {
}
func UpdateGroupsForAUser(userName string, groups []string) (*http.Response, error) {
userName = base64.StdEncoding.EncodeToString([]byte(userName))
/*
Helper function to update groups for a user
PUT: {{baseUrl}}/user/groups?name=username
@@ -201,7 +196,7 @@ func UpdateGroupsForAUser(userName string, groups []string) (*http.Response, err
requestDataBody := bytes.NewReader(requestDataJSON)
request, err := http.NewRequest(
"PUT",
"http://localhost:9090/api/v1/user/"+userName+"/groups",
"http://localhost:9090/api/v1/user/"+url.PathEscape(userName)+"/groups",
requestDataBody,
)
if err != nil {
@@ -214,7 +209,6 @@ func UpdateGroupsForAUser(userName string, groups []string) (*http.Response, err
}
func CreateServiceAccountForUser(userName, policy string) (*http.Response, error) {
userName = base64.StdEncoding.EncodeToString([]byte(userName))
/*
Helper function to Create Service Account for user
POST: api/v1/user/username/service-accounts
@@ -232,7 +226,7 @@ func CreateServiceAccountForUser(userName, policy string) (*http.Response, error
requestDataBody := bytes.NewReader(requestDataJSON)
request, err := http.NewRequest(
"POST",
"http://localhost:9090/api/v1/user/"+userName+"/service-accounts",
"http://localhost:9090/api/v1/user/"+url.PathEscape(userName)+"/service-accounts",
requestDataBody,
)
if err != nil {
@@ -245,7 +239,6 @@ func CreateServiceAccountForUser(userName, policy string) (*http.Response, error
}
func CreateServiceAccountForUserWithCredentials(userName, policy, accessKey, secretKey string) (*http.Response, error) {
userName = base64.StdEncoding.EncodeToString([]byte(userName))
// Helper function to test "Create Service Account for User With Credentials" end point.
client := &http.Client{
Timeout: 3 * time.Second,
@@ -259,7 +252,7 @@ func CreateServiceAccountForUserWithCredentials(userName, policy, accessKey, sec
requestDataBody := bytes.NewReader(requestDataJSON)
request, err := http.NewRequest(
"POST",
"http://localhost:9090/api/v1/user/"+userName+"/service-account-credentials",
"http://localhost:9090/api/v1/user/"+url.PathEscape(userName)+"/service-account-credentials",
requestDataBody,
)
if err != nil {
@@ -272,7 +265,6 @@ func CreateServiceAccountForUserWithCredentials(userName, policy, accessKey, sec
}
func ReturnsAListOfServiceAccountsForAUser(userName string) (*http.Response, error) {
userName = base64.StdEncoding.EncodeToString([]byte(userName))
/*
Helper function to return a list of service accounts for a user.
GET: {{baseUrl}}/user/:name/service-accounts
@@ -282,7 +274,7 @@ func ReturnsAListOfServiceAccountsForAUser(userName string) (*http.Response, err
}
request, err := http.NewRequest(
"GET",
"http://localhost:9090/api/v1/user/"+userName+"/service-accounts",
"http://localhost:9090/api/v1/user/"+url.PathEscape(userName)+"/service-accounts",
nil,
)
if err != nil {

View File

@@ -18,18 +18,8 @@ package utils
import (
"context"
"encoding/base64"
)
// DecodeBase64 : decoded base64 input into utf-8 text
func DecodeBase64(s string) (string, error) {
decodedInput, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return "", err
}
return string(decodedInput), nil
}
// Key used for Get/SetReqInfo
type key string

View File

@@ -18,6 +18,7 @@ package utils
import (
"context"
"net/url"
"testing"
)
@@ -34,7 +35,7 @@ func TestDecodeInput(t *testing.T) {
{
name: "chinese characters",
args: args{
s: "5bCP6aO85by+5bCP6aO85by+5bCP6aO85by+L+Wwj+mjvOW8vuWwj+mjvOW8vuWwj+mjvOW8vg==",
s: "%E5%B0%8F%E9%A3%BC%E5%BC%BE%E5%B0%8F%E9%A3%BC%E5%BC%BE%E5%B0%8F%E9%A3%BC%E5%BC%BE%2F%E5%B0%8F%E9%A3%BC%E5%BC%BE%E5%B0%8F%E9%A3%BC%E5%BC%BE%E5%B0%8F%E9%A3%BC%E5%BC%BE",
},
want: "小飼弾小飼弾小飼弾/小飼弾小飼弾小飼弾",
wantErr: false,
@@ -42,7 +43,7 @@ func TestDecodeInput(t *testing.T) {
{
name: "spaces and & symbol",
args: args{
s: "YSBhIC0gYSBhICYgYSBhIC0gYSBhIGE=",
s: "a%20a%20-%20a%20a%20%26%20a%20a%20-%20a%20a%20a",
},
want: "a a - a a & a a - a a a",
wantErr: false,
@@ -50,7 +51,7 @@ func TestDecodeInput(t *testing.T) {
{
name: "the infamous fly me to the moon",
args: args{
s: "MDIlMjAtJTIwRkxZJTIwTUUlMjBUTyUyMFRIRSUyME1PT04lMjA=",
s: "02%2520-%2520FLY%2520ME%2520TO%2520THE%2520MOON%2520",
},
want: "02%20-%20FLY%20ME%20TO%20THE%20MOON%20",
wantErr: false,
@@ -58,7 +59,7 @@ func TestDecodeInput(t *testing.T) {
{
name: "random symbols",
args: args{
s: "IUAjJCVeJiooKV8r",
s: "!%40%23%24%25%5E%26*()_%2B",
},
want: "!@#$%^&*()_+",
wantErr: false,
@@ -66,7 +67,7 @@ func TestDecodeInput(t *testing.T) {
{
name: "name with / symbols",
args: args{
s: "dGVzdC90ZXN0Mi/lsI/po7zlvL7lsI/po7zlvL7lsI/po7zlvL4uanBn",
s: "test%2Ftest2%2F%E5%B0%8F%E9%A3%BC%E5%BC%BE%E5%B0%8F%E9%A3%BC%E5%BC%BE%E5%B0%8F%E9%A3%BC%E5%BC%BE.jpg",
},
want: "test/test2/小飼弾小飼弾小飼弾.jpg",
wantErr: false,
@@ -74,7 +75,7 @@ func TestDecodeInput(t *testing.T) {
{
name: "decoding fails",
args: args{
s: "this should fail",
s: "%%this should fail%%",
},
want: "",
wantErr: true,
@@ -82,7 +83,7 @@ func TestDecodeInput(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(_ *testing.T) {
got, err := DecodeBase64(tt.args.s)
got, err := url.QueryUnescape(tt.args.s)
if (err != nil) != tt.wantErr {
t.Errorf("DecodeBase64() error = %v, wantErr %v", err, tt.wantErr)
return

View File

@@ -1,26 +1,13 @@
rules:
- id: js-func-encode-uri-Component
patterns:
- pattern: encodeURIComponent($X)
- pattern-not-inside: |
export const encodeURLString = (...) => {
...
};
message: Use encodeURLString() instead of encodeURIComponent()
languages:
- typescript
- javascript
severity: WARNING
fix: encodeURLString($X)
- id: js-func-encode-uri
patterns:
- pattern: encodeURI($X)
message: Use encodeURLString() instead of encodeURI()
message: Use encodeURIComponent() instead of encodeURI()
languages:
- typescript
- javascript
severity: WARNING
fix: encodeURLString($X)
fix: encodeURIComponent($X)
- id: js-dangerous-func-document-write
patterns:
- pattern: document.write(...)

View File

@@ -1987,7 +1987,7 @@ export class Api<
*/
bucketInfo: (name: string, params: RequestParams = {}) =>
this.request<Bucket, ApiError>({
path: `/buckets/${name}`,
path: `/buckets/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -2005,7 +2005,7 @@ export class Api<
*/
deleteBucket: (name: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/buckets/${name}`,
path: `/buckets/${encodeURIComponent(name)}`,
method: "DELETE",
secure: true,
...params,
@@ -2025,7 +2025,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<GetBucketRetentionConfig, ApiError>({
path: `/buckets/${bucketName}/retention`,
path: `/buckets/${encodeURIComponent(bucketName)}/retention`,
method: "GET",
secure: true,
format: "json",
@@ -2047,7 +2047,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/retention`,
path: `/buckets/${encodeURIComponent(bucketName)}/retention`,
method: "PUT",
body: body,
secure: true,
@@ -2080,7 +2080,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<ListObjectsResponse, ApiError>({
path: `/buckets/${bucketName}/objects`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects`,
method: "GET",
query: query,
secure: true,
@@ -2110,7 +2110,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/objects`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects`,
method: "DELETE",
query: query,
secure: true,
@@ -2136,7 +2136,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/delete-objects`,
path: `/buckets/${encodeURIComponent(bucketName)}/delete-objects`,
method: "POST",
query: query,
body: files,
@@ -2163,7 +2163,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/objects/upload`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/upload`,
method: "POST",
query: query,
body: data,
@@ -2187,7 +2187,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<File, ApiError>({
path: `/buckets/${bucketName}/objects/download-multiple`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/download-multiple`,
method: "POST",
body: objectList,
secure: true,
@@ -2217,7 +2217,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<File, ApiError>({
path: `/buckets/${bucketName}/objects/download`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/download`,
method: "GET",
query: query,
secure: true,
@@ -2243,7 +2243,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<IamEntity, ApiError>({
path: `/buckets/${bucketName}/objects/share`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/share`,
method: "GET",
query: query,
secure: true,
@@ -2270,7 +2270,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/objects/legalhold`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/legalhold`,
method: "PUT",
query: query,
body: body,
@@ -2298,7 +2298,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/objects/retention`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/retention`,
method: "PUT",
query: query,
body: body,
@@ -2325,7 +2325,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/objects/retention`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/retention`,
method: "DELETE",
query: query,
secure: true,
@@ -2351,7 +2351,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/objects/tags`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/tags`,
method: "PUT",
query: query,
body: body,
@@ -2378,7 +2378,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/objects/restore`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/restore`,
method: "PUT",
query: query,
secure: true,
@@ -2403,7 +2403,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<Metadata, ApiError>({
path: `/buckets/${bucketName}/objects/metadata`,
path: `/buckets/${encodeURIComponent(bucketName)}/objects/metadata`,
method: "GET",
query: query,
secure: true,
@@ -2426,7 +2426,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/tags`,
path: `/buckets/${encodeURIComponent(bucketName)}/tags`,
method: "PUT",
body: body,
secure: true,
@@ -2449,7 +2449,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<Bucket, ApiError>({
path: `/buckets/${name}/set-policy`,
path: `/buckets/${encodeURIComponent(name)}/set-policy`,
method: "PUT",
body: body,
secure: true,
@@ -2469,7 +2469,7 @@ export class Api<
*/
getBucketQuota: (name: string, params: RequestParams = {}) =>
this.request<BucketQuota, ApiError>({
path: `/buckets/${name}/quota`,
path: `/buckets/${encodeURIComponent(name)}/quota`,
method: "GET",
secure: true,
format: "json",
@@ -2491,7 +2491,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<Bucket, ApiError>({
path: `/buckets/${name}/quota`,
path: `/buckets/${encodeURIComponent(name)}/quota`,
method: "PUT",
body: body,
secure: true,
@@ -2526,7 +2526,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<ListBucketEventsResponse, ApiError>({
path: `/buckets/${bucketName}/events`,
path: `/buckets/${encodeURIComponent(bucketName)}/events`,
method: "GET",
query: query,
secure: true,
@@ -2549,7 +2549,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/events`,
path: `/buckets/${encodeURIComponent(bucketName)}/events`,
method: "POST",
body: body,
secure: true,
@@ -2573,7 +2573,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/events/${arn}`,
path: `/buckets/${encodeURIComponent(bucketName)}/events/${encodeURIComponent(arn)}`,
method: "DELETE",
body: body,
secure: true,
@@ -2592,7 +2592,7 @@ export class Api<
*/
getBucketReplication: (bucketName: string, params: RequestParams = {}) =>
this.request<BucketReplicationResponse, ApiError>({
path: `/buckets/${bucketName}/replication`,
path: `/buckets/${encodeURIComponent(bucketName)}/replication`,
method: "GET",
secure: true,
format: "json",
@@ -2614,7 +2614,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<BucketReplicationRule, ApiError>({
path: `/buckets/${bucketName}/replication/${ruleId}`,
path: `/buckets/${encodeURIComponent(bucketName)}/replication/${encodeURIComponent(ruleId)}`,
method: "GET",
secure: true,
format: "json",
@@ -2637,7 +2637,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/replication/${ruleId}`,
path: `/buckets/${encodeURIComponent(bucketName)}/replication/${encodeURIComponent(ruleId)}`,
method: "PUT",
body: body,
secure: true,
@@ -2660,7 +2660,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/replication/${ruleId}`,
path: `/buckets/${encodeURIComponent(bucketName)}/replication/${encodeURIComponent(ruleId)}`,
method: "DELETE",
secure: true,
...params,
@@ -2680,7 +2680,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/delete-all-replication-rules`,
path: `/buckets/${encodeURIComponent(bucketName)}/delete-all-replication-rules`,
method: "DELETE",
secure: true,
...params,
@@ -2701,7 +2701,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/delete-selected-replication-rules`,
path: `/buckets/${encodeURIComponent(bucketName)}/delete-selected-replication-rules`,
method: "DELETE",
body: rules,
secure: true,
@@ -2720,7 +2720,7 @@ export class Api<
*/
getBucketVersioning: (bucketName: string, params: RequestParams = {}) =>
this.request<BucketVersioningResponse, ApiError>({
path: `/buckets/${bucketName}/versioning`,
path: `/buckets/${encodeURIComponent(bucketName)}/versioning`,
method: "GET",
secure: true,
format: "json",
@@ -2742,7 +2742,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/versioning`,
path: `/buckets/${encodeURIComponent(bucketName)}/versioning`,
method: "PUT",
body: body,
secure: true,
@@ -2764,7 +2764,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<BucketObLockingResponse, ApiError>({
path: `/buckets/${bucketName}/object-locking`,
path: `/buckets/${encodeURIComponent(bucketName)}/object-locking`,
method: "GET",
secure: true,
format: "json",
@@ -2786,7 +2786,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/encryption/enable`,
path: `/buckets/${encodeURIComponent(bucketName)}/encryption/enable`,
method: "POST",
body: body,
secure: true,
@@ -2805,7 +2805,7 @@ export class Api<
*/
disableBucketEncryption: (bucketName: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/encryption/disable`,
path: `/buckets/${encodeURIComponent(bucketName)}/encryption/disable`,
method: "POST",
secure: true,
...params,
@@ -2822,7 +2822,7 @@ export class Api<
*/
getBucketEncryptionInfo: (bucketName: string, params: RequestParams = {}) =>
this.request<BucketEncryptionInfo, ApiError>({
path: `/buckets/${bucketName}/encryption/info`,
path: `/buckets/${encodeURIComponent(bucketName)}/encryption/info`,
method: "GET",
secure: true,
format: "json",
@@ -2840,7 +2840,7 @@ export class Api<
*/
getBucketLifecycle: (bucketName: string, params: RequestParams = {}) =>
this.request<BucketLifecycleResponse, ApiError>({
path: `/buckets/${bucketName}/lifecycle`,
path: `/buckets/${encodeURIComponent(bucketName)}/lifecycle`,
method: "GET",
secure: true,
format: "json",
@@ -2862,7 +2862,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/lifecycle`,
path: `/buckets/${encodeURIComponent(bucketName)}/lifecycle`,
method: "POST",
body: body,
secure: true,
@@ -2909,7 +2909,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/lifecycle/${lifecycleId}`,
path: `/buckets/${encodeURIComponent(bucketName)}/lifecycle/${encodeURIComponent(lifecycleId)}`,
method: "PUT",
body: body,
secure: true,
@@ -2932,7 +2932,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/buckets/${bucketName}/lifecycle/${lifecycleId}`,
path: `/buckets/${encodeURIComponent(bucketName)}/lifecycle/${encodeURIComponent(lifecycleId)}`,
method: "DELETE",
secure: true,
...params,
@@ -2956,7 +2956,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<RewindResponse, ApiError>({
path: `/buckets/${bucketName}/rewind/${date}`,
path: `/buckets/${encodeURIComponent(bucketName)}/rewind/${encodeURIComponent(date)}`,
method: "GET",
query: query,
secure: true,
@@ -3119,7 +3119,7 @@ export class Api<
*/
getServiceAccount: (accessKey: string, params: RequestParams = {}) =>
this.request<ServiceAccount, ApiError>({
path: `/service-accounts/${accessKey}`,
path: `/service-accounts/${encodeURIComponent(accessKey)}`,
method: "GET",
secure: true,
format: "json",
@@ -3141,7 +3141,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/service-accounts/${accessKey}`,
path: `/service-accounts/${encodeURIComponent(accessKey)}`,
method: "PUT",
body: body,
secure: true,
@@ -3160,7 +3160,7 @@ export class Api<
*/
deleteServiceAccount: (accessKey: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/service-accounts/${accessKey}`,
path: `/service-accounts/${encodeURIComponent(accessKey)}`,
method: "DELETE",
secure: true,
...params,
@@ -3278,7 +3278,7 @@ export class Api<
*/
getUserInfo: (name: string, params: RequestParams = {}) =>
this.request<User, ApiError>({
path: `/user/${name}`,
path: `/user/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -3300,7 +3300,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<User, ApiError>({
path: `/user/${name}`,
path: `/user/${encodeURIComponent(name)}`,
method: "PUT",
body: body,
secure: true,
@@ -3320,7 +3320,7 @@ export class Api<
*/
removeUser: (name: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/user/${name}`,
path: `/user/${encodeURIComponent(name)}`,
method: "DELETE",
secure: true,
...params,
@@ -3341,7 +3341,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<User, ApiError>({
path: `/user/${name}/groups`,
path: `/user/${encodeURIComponent(name)}/groups`,
method: "PUT",
body: body,
secure: true,
@@ -3379,7 +3379,7 @@ export class Api<
*/
getSaUserPolicy: (name: string, params: RequestParams = {}) =>
this.request<AUserPolicyResponse, ApiError>({
path: `/user/${name}/policies`,
path: `/user/${encodeURIComponent(name)}/policies`,
method: "GET",
secure: true,
format: "json",
@@ -3397,7 +3397,7 @@ export class Api<
*/
listAUserServiceAccounts: (name: string, params: RequestParams = {}) =>
this.request<ServiceAccounts, ApiError>({
path: `/user/${name}/service-accounts`,
path: `/user/${encodeURIComponent(name)}/service-accounts`,
method: "GET",
secure: true,
format: "json",
@@ -3419,7 +3419,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<ServiceAccountCreds, ApiError>({
path: `/user/${name}/service-accounts`,
path: `/user/${encodeURIComponent(name)}/service-accounts`,
method: "POST",
body: body,
secure: true,
@@ -3442,7 +3442,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<ServiceAccountCreds, ApiError>({
path: `/user/${name}/service-account-credentials`,
path: `/user/${encodeURIComponent(name)}/service-account-credentials`,
method: "POST",
body: body,
secure: true,
@@ -3535,7 +3535,7 @@ export class Api<
*/
groupInfo: (name: string, params: RequestParams = {}) =>
this.request<Group, ApiError>({
path: `/group/${name}`,
path: `/group/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -3553,7 +3553,7 @@ export class Api<
*/
removeGroup: (name: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/group/${name}`,
path: `/group/${encodeURIComponent(name)}`,
method: "DELETE",
secure: true,
...params,
@@ -3574,7 +3574,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<Group, ApiError>({
path: `/group/${name}`,
path: `/group/${encodeURIComponent(name)}`,
method: "PUT",
body: body,
secure: true,
@@ -3648,7 +3648,7 @@ export class Api<
*/
listUsersForPolicy: (policy: string, params: RequestParams = {}) =>
this.request<SelectedUsers, ApiError>({
path: `/policies/${policy}/users`,
path: `/policies/${encodeURIComponent(policy)}/users`,
method: "GET",
secure: true,
format: "json",
@@ -3666,7 +3666,7 @@ export class Api<
*/
listGroupsForPolicy: (policy: string, params: RequestParams = {}) =>
this.request<SelectedUsers, ApiError>({
path: `/policies/${policy}/groups`,
path: `/policies/${encodeURIComponent(policy)}/groups`,
method: "GET",
secure: true,
format: "json",
@@ -3700,7 +3700,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<ListPoliciesResponse, ApiError>({
path: `/bucket-policy/${bucket}`,
path: `/bucket-policy/${encodeURIComponent(bucket)}`,
method: "GET",
query: query,
secure: true,
@@ -3724,7 +3724,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<boolean, ApiError>({
path: `/bucket/${bucket}/access-rules`,
path: `/bucket/${encodeURIComponent(bucket)}/access-rules`,
method: "PUT",
body: prefixaccess,
secure: true,
@@ -3759,7 +3759,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<ListAccessRulesResponse, ApiError>({
path: `/bucket/${bucket}/access-rules`,
path: `/bucket/${encodeURIComponent(bucket)}/access-rules`,
method: "GET",
query: query,
secure: true,
@@ -3782,7 +3782,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<boolean, ApiError>({
path: `/bucket/${bucket}/access-rules`,
path: `/bucket/${encodeURIComponent(bucket)}/access-rules`,
method: "DELETE",
body: prefix,
secure: true,
@@ -3818,7 +3818,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<SelectedUsers, ApiError>({
path: `/bucket-users/${bucket}`,
path: `/bucket-users/${encodeURIComponent(bucket)}`,
method: "GET",
query: query,
secure: true,
@@ -3838,7 +3838,7 @@ export class Api<
*/
policyInfo: (name: string, params: RequestParams = {}) =>
this.request<Policy, ApiError>({
path: `/policy/${name}`,
path: `/policy/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -3856,7 +3856,7 @@ export class Api<
*/
removePolicy: (name: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/policy/${name}`,
path: `/policy/${encodeURIComponent(name)}`,
method: "DELETE",
secure: true,
...params,
@@ -3907,7 +3907,7 @@ export class Api<
*/
configInfo: (name: string, params: RequestParams = {}) =>
this.request<Configuration[], ApiError>({
path: `/configs/${name}`,
path: `/configs/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -3929,7 +3929,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<SetConfigResponse, ApiError>({
path: `/configs/${name}`,
path: `/configs/${encodeURIComponent(name)}`,
method: "PUT",
body: body,
secure: true,
@@ -3949,7 +3949,7 @@ export class Api<
*/
resetConfig: (name: string, params: RequestParams = {}) =>
this.request<SetConfigResponse, ApiError>({
path: `/configs/${name}/reset`,
path: `/configs/${encodeURIComponent(name)}/reset`,
method: "POST",
secure: true,
format: "json",
@@ -4264,7 +4264,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<WidgetDetails, ApiError>({
path: `/admin/info/widgets/${widgetId}`,
path: `/admin/info/widgets/${encodeURIComponent(widgetId)}`,
method: "GET",
query: query,
secure: true,
@@ -4511,7 +4511,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<Tier, ApiError>({
path: `/admin/tiers/${type}/${name}`,
path: `/admin/tiers/${encodeURIComponent(type)}/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -4534,7 +4534,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/admin/tiers/${type}/${name}/credentials`,
path: `/admin/tiers/${encodeURIComponent(type)}/${encodeURIComponent(name)}/credentials`,
method: "PUT",
body: body,
secure: true,
@@ -4635,7 +4635,7 @@ export class Api<
*/
remoteBucketDetails: (name: string, params: RequestParams = {}) =>
this.request<RemoteBucket, ApiError>({
path: `/remote-buckets/${name}`,
path: `/remote-buckets/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -4657,7 +4657,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/remote-buckets/${sourceBucketName}/${arn}`,
path: `/remote-buckets/${encodeURIComponent(sourceBucketName)}/${encodeURIComponent(arn)}`,
method: "DELETE",
secure: true,
...params,
@@ -4831,7 +4831,7 @@ export class Api<
*/
kmsKeyStatus: (name: string, params: RequestParams = {}) =>
this.request<KmsKeyStatusResponse, ApiError>({
path: `/kms/keys/${name}`,
path: `/kms/keys/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -4849,7 +4849,7 @@ export class Api<
*/
kmsDeleteKey: (name: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/kms/keys/${name}`,
path: `/kms/keys/${encodeURIComponent(name)}`,
method: "DELETE",
secure: true,
...params,
@@ -4870,7 +4870,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/kms/keys/${name}/import`,
path: `/kms/keys/${encodeURIComponent(name)}/import`,
method: "POST",
body: body,
secure: true,
@@ -4933,7 +4933,7 @@ export class Api<
*/
kmsGetPolicy: (name: string, params: RequestParams = {}) =>
this.request<KmsGetPolicyResponse, ApiError>({
path: `/kms/policies/${name}`,
path: `/kms/policies/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -4951,7 +4951,7 @@ export class Api<
*/
kmsDeletePolicy: (name: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/kms/policies/${name}`,
path: `/kms/policies/${encodeURIComponent(name)}`,
method: "DELETE",
secure: true,
...params,
@@ -4972,7 +4972,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<void, ApiError>({
path: `/kms/policies/${name}/assign`,
path: `/kms/policies/${encodeURIComponent(name)}/assign`,
method: "POST",
body: body,
secure: true,
@@ -4991,7 +4991,7 @@ export class Api<
*/
kmsDescribePolicy: (name: string, params: RequestParams = {}) =>
this.request<KmsDescribePolicyResponse, ApiError>({
path: `/kms/policies/${name}/describe`,
path: `/kms/policies/${encodeURIComponent(name)}/describe`,
method: "GET",
secure: true,
format: "json",
@@ -5009,7 +5009,7 @@ export class Api<
*/
kmsDeleteIdentity: (name: string, params: RequestParams = {}) =>
this.request<void, ApiError>({
path: `/kms/identities/${name}`,
path: `/kms/identities/${encodeURIComponent(name)}`,
method: "DELETE",
secure: true,
...params,
@@ -5026,7 +5026,7 @@ export class Api<
*/
kmsDescribeIdentity: (name: string, params: RequestParams = {}) =>
this.request<KmsDescribeIdentityResponse, ApiError>({
path: `/kms/identities/${name}/describe`,
path: `/kms/identities/${encodeURIComponent(name)}/describe`,
method: "GET",
secure: true,
format: "json",
@@ -5092,7 +5092,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<SetIDPResponse, ApiError>({
path: `/idp/${type}`,
path: `/idp/${encodeURIComponent(type)}`,
method: "POST",
body: body,
secure: true,
@@ -5112,7 +5112,7 @@ export class Api<
*/
listConfigurations: (type: string, params: RequestParams = {}) =>
this.request<IdpListConfigurationsResponse, ApiError>({
path: `/idp/${type}`,
path: `/idp/${encodeURIComponent(type)}`,
method: "GET",
secure: true,
format: "json",
@@ -5134,7 +5134,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<IdpServerConfiguration, ApiError>({
path: `/idp/${type}/${name}`,
path: `/idp/${encodeURIComponent(type)}/${encodeURIComponent(name)}`,
method: "GET",
secure: true,
format: "json",
@@ -5156,7 +5156,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<SetIDPResponse, ApiError>({
path: `/idp/${type}/${name}`,
path: `/idp/${encodeURIComponent(type)}/${encodeURIComponent(name)}`,
method: "DELETE",
secure: true,
format: "json",
@@ -5179,7 +5179,7 @@ export class Api<
params: RequestParams = {},
) =>
this.request<SetIDPResponse, ApiError>({
path: `/idp/${type}/${name}`,
path: `/idp/${encodeURIComponent(type)}/${encodeURIComponent(name)}`,
method: "PUT",
body: body,
secure: true,
@@ -5290,7 +5290,7 @@ export class Api<
*/
downloadSharedObject: (url: string, params: RequestParams = {}) =>
this.request<File, ApiError>({
path: `/download-shared-object/${url}`,
path: `/download-shared-object/${encodeURIComponent(url)}`,
method: "GET",
...params,
}),

View File

@@ -467,38 +467,6 @@ export const representationNumber = (number: number | undefined) => {
/** Ref https://developer.mozilla.org/en-US/docs/Glossary/Base64 */
const base64ToBytes = (base64: any): Uint8Array => {
const binString: any = atob(base64);
// @ts-ignore
return Uint8Array.from(binString, (m) => m.codePointAt(0));
};
const bytesToBase64 = (bytes: any) => {
const binString = Array.from(bytes, (x: any) => String.fromCodePoint(x)).join(
"",
);
return btoa(binString);
};
export const encodeURLString = (name: string | null) => {
if (!name) {
return "";
}
try {
return bytesToBase64(new TextEncoder().encode(name));
} catch (err) {
return "";
}
};
export const decodeURLString = (text: string) => {
try {
return new TextDecoder().decode(base64ToBytes(text));
} catch (err) {
return text;
}
};
export const performDownload = (blob: Blob, fileName: string) => {
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);

View File

@@ -17,7 +17,6 @@
import React, { Fragment, useState } from "react";
import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog";
import { ConfirmDeleteIcon } from "mds";
import { encodeURLString } from "../../../common/utils";
import { setErrorSnackMessage } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import { api } from "api";
@@ -47,7 +46,7 @@ const DeleteServiceAccount = ({
const onConfirmDelete = () => {
setLoadingDelete(true);
api.serviceAccounts
.deleteServiceAccount(encodeURLString(selectedServiceAccount))
.deleteServiceAccount(selectedServiceAccount)
.then((_) => {
closeDeleteModalAndRefresh(true);
})

View File

@@ -29,7 +29,6 @@ import { errorToHandler } from "api/errors";
import CodeMirrorWrapper from "../Common/FormComponents/CodeMirrorWrapper/CodeMirrorWrapper";
import { ApiError } from "api/consoleApi";
import { useAppDispatch } from "store";
import { encodeURLString } from "common/utils";
import { setErrorSnackMessage, setModalErrorSnackMessage } from "systemSlice";
import ModalWrapper from "../Common/ModalWrapper/ModalWrapper";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
@@ -57,10 +56,9 @@ const EditServiceAccount = ({
useEffect(() => {
if (!loading && selectedAccessKey !== "") {
const sourceAccKey = encodeURLString(selectedAccessKey);
setLoading(true);
api.serviceAccounts
.getServiceAccount(sourceAccKey)
.getServiceAccount(selectedAccessKey || "")
.then((res) => {
setLoading(false);
const saInfo = res.data;
@@ -87,7 +85,7 @@ const EditServiceAccount = ({
const setPolicy = (event: React.FormEvent, newPolicy: string) => {
event.preventDefault();
api.serviceAccounts
.updateServiceAccount(encodeURLString(selectedAccessKey), {
.updateServiceAccount(selectedAccessKey || "", {
policy: newPolicy,
description: description,
expiry: expiry,

View File

@@ -29,7 +29,6 @@ import {
hasPermission,
SecureComponent,
} from "../../../../common/SecureComponent";
import { encodeURLString } from "../../../../common/utils";
import { setErrorSnackMessage, setHelpName } from "../../../../systemSlice";
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
import { useAppDispatch } from "../../../../store";
@@ -85,7 +84,7 @@ const AccessDetails = () => {
type: "view",
disableButtonFunction: () => !viewPolicy,
onClick: (policy: any) => {
navigate(`${IAM_PAGES.POLICIES}/${encodeURLString(policy.name)}`);
navigate(`${IAM_PAGES.POLICIES}/${encodeURIComponent(policy.name)}`);
},
},
];
@@ -95,7 +94,7 @@ const AccessDetails = () => {
type: "view",
disableButtonFunction: () => !viewUser,
onClick: (user: any) => {
navigate(`${IAM_PAGES.USERS}/${encodeURLString(user)}`);
navigate(`${IAM_PAGES.USERS}/${encodeURIComponent(user)}`);
},
},
];

View File

@@ -20,7 +20,6 @@ import { useLocation, useParams } from "react-router-dom";
import { api } from "api";
import { AppState, useAppDispatch } from "../../../../store";
import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions";
import { decodeURLString, encodeURLString } from "../../../../common/utils";
import {
resetMessages,
setIsVersioned,
@@ -77,8 +76,11 @@ const BrowserHandler = () => {
const records = useSelector((state: AppState) => state.objectBrowser.records);
const bucketName = params.bucketName || "";
const pathSegment = location.pathname.split(`/browser/${bucketName}/`);
const internalPaths = pathSegment.length === 2 ? pathSegment[1] : "";
const pathSegment = location.pathname.split(
`/browser/${encodeURIComponent(bucketName)}/`,
);
const internalPaths =
pathSegment.length === 2 ? decodeURIComponent(pathSegment[1]) : "";
const initWSRequest = useCallback(
(path: string) => {
@@ -105,18 +107,13 @@ const BrowserHandler = () => {
// Common path load
const pathLoad = useCallback(
(forceLoad: boolean = false) => {
const decodedInternalPaths = decodeURLString(internalPaths);
// We exit Versions mode in case of path change
dispatch(setVersionsModeEnabled({ status: false }));
let searchPath = decodedInternalPaths;
let searchPath = internalPaths;
if (!decodedInternalPaths.endsWith("/") && decodedInternalPaths !== "") {
searchPath = `${decodedInternalPaths
.split("/")
.slice(0, -1)
.join("/")}/`;
if (!internalPaths.endsWith("/") && internalPaths !== "") {
searchPath = `${internalPaths.split("/").slice(0, -1).join("/")}/`;
}
if (searchPath === "/") {
@@ -151,11 +148,9 @@ const BrowserHandler = () => {
// Object Details handler
useEffect(() => {
const decodedIPaths = decodeURLString(internalPaths);
dispatch(setLoadingVersioning(true));
if (decodedIPaths.endsWith("/") || decodedIPaths === "") {
if (internalPaths.endsWith("/") || internalPaths === "") {
dispatch(setObjectDetailsView(false));
dispatch(setSelectedObjectView(null));
dispatch(setLoadingLocking(true));
@@ -163,11 +158,7 @@ const BrowserHandler = () => {
dispatch(setLoadingObjectInfo(true));
dispatch(setObjectDetailsView(true));
dispatch(setLoadingVersions(true));
dispatch(
setSelectedObjectView(
`${decodedIPaths ? `${encodeURLString(decodedIPaths)}` : ``}`,
),
);
dispatch(setSelectedObjectView(internalPaths || ""));
}
}, [bucketName, internalPaths, rewindDate, rewindEnabled, dispatch]);

View File

@@ -27,7 +27,6 @@ import {
} from "mds";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
import { encodeURLString } from "../../../../../../common/utils";
import { BucketObjectItem } from "./types";
import { AppState, useAppDispatch } from "../../../../../../store";
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
@@ -101,7 +100,7 @@ const CreatePathModal = ({
folderPath = folderPath.slice(1); //trim '/'
}
const newPath = `/browser/${bucketName}/${encodeURLString(
const newPath = `/browser/${encodeURIComponent(bucketName)}/${encodeURIComponent(
`${folderPath}${cleanPathURL}/`,
)}`;

View File

@@ -26,7 +26,6 @@ import { IAM_SCOPES } from "../../../../../../common/SecureComponent/permissions
import { useSelector } from "react-redux";
import { BucketVersioningResponse } from "api/consoleApi";
import { api } from "../../../../../../api";
import { encodeURLString } from "../../../../../../common/utils";
interface IDeleteObjectProps {
closeDeleteModalAndRefresh: (refresh: boolean) => void;
@@ -92,7 +91,7 @@ const DeleteObject = ({
const firstObject = selectedObjects[0];
api.buckets
.deleteObject(selectedBucket, {
prefix: encodeURLString(firstObject),
prefix: firstObject,
all_versions: deleteVersions,
bypass: bypassGovernance,
recursive: firstObject.endsWith("/"), //if it is just a prefix

View File

@@ -16,7 +16,6 @@
import React, { Fragment, useEffect, useState } from "react";
import { decodeURLString } from "../../../../../../common/utils";
import { ConfirmDeleteIcon, Switch, Grid, InputBox } from "mds";
import ConfirmDialog from "../../../../Common/ModalWrapper/ConfirmDialog";
import { setErrorSnackMessage } from "../../../../../../systemSlice";
@@ -102,7 +101,7 @@ const DeleteNonCurrentVersions = ({
confirmationContent={
<Fragment>
Are you sure you want to delete all the non-current versions for:{" "}
<b>{decodeURLString(selectedObject)}</b>? <br />
<b>{selectedObject}</b>? <br />
{canBypass && (
<Fragment>
<div

View File

@@ -16,7 +16,6 @@
import React, { Fragment, useState } from "react";
import { ErrorResponseHandler } from "../../../../../../common/types";
import { decodeURLString } from "../../../../../../common/utils";
import ConfirmDialog from "../../../../Common/ModalWrapper/ConfirmDialog";
import useApi from "../../../../Common/Hooks/useApi";
import { ConfirmDeleteIcon, Switch } from "mds";
@@ -76,13 +75,12 @@ const DeleteObject = ({
return null;
}
const onConfirmDelete = () => {
const decodedSelectedObject = decodeURLString(selectedObject);
const recursive = decodedSelectedObject.endsWith("/");
const recursive = selectedObject.endsWith("/");
invokeDeleteApi(
"DELETE",
`/api/v1/buckets/${selectedBucket}/objects?prefix=${selectedObject}${
`/api/v1/buckets/${encodeURIComponent(selectedBucket)}/objects?prefix=${encodeURIComponent(selectedObject)}${
selectedVersion !== ""
? `&version_id=${selectedVersion}`
? `&version_id=${encodeURIComponent(selectedVersion)}`
: `&recursive=${recursive}&all_versions=${deleteVersions}`
}${bypassGovernance ? "&bypass=true" : ""}`,
);
@@ -100,7 +98,7 @@ const DeleteObject = ({
confirmationContent={
<Fragment>
Are you sure you want to delete: <br />
<b>{decodeURLString(selectedObject)}</b>{" "}
<b>{selectedObject}</b>{" "}
{selectedVersion !== "" ? (
<Fragment>
<br />

View File

@@ -24,9 +24,7 @@ import {
Box,
} from "mds";
import {
decodeURLString,
deleteCookie,
encodeURLString,
getCookieValue,
performDownload,
} from "../../../../../../common/utils";
@@ -63,11 +61,8 @@ const InspectObject = ({
};
const performInspect = async () => {
const file = encodeURLString(inspectPath + "/xl.meta");
const volume = encodeURLString(volumeName);
let basename = document.baseURI.replace(window.location.origin, "");
const urlOfInspectApi = `${window.location.origin}${basename}/api/v1/admin/inspect?volume=${volume}&file=${file}&encrypt=${isEncrypt}`;
const urlOfInspectApi = `${window.location.origin}${basename}/api/v1/admin/inspect?volume=${encodeURIComponent(volumeName)}&file=${encodeURIComponent(inspectPath + "/xl.meta")}&encrypt=${isEncrypt}`;
makeRequest(urlOfInspectApi)
.then(async (res) => {
@@ -126,8 +121,7 @@ const InspectObject = ({
onSubmit(e);
}}
>
Would you like to encrypt <b>{decodeURLString(inspectPath)}</b>?{" "}
<br />
Would you like to encrypt <b>{inspectPath}</b>? <br />
<Switch
label={"Encrypt"}
indicatorLabels={["Yes", "No"]}

View File

@@ -48,11 +48,7 @@ import { useSelector } from "react-redux";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import { useDropzone } from "react-dropzone";
import { DateTime } from "luxon";
import {
decodeURLString,
encodeURLString,
niceBytesInt,
} from "../../../../../../common/utils";
import { niceBytesInt } from "../../../../../../common/utils";
import BrowserBreadcrumbs from "../../../../ObjectBrowser/BrowserBreadcrumbs";
import { AllowedPreviews, previewObjectType } from "../utils";
import { ErrorResponseHandler } from "../../../../../../common/types";
@@ -235,10 +231,10 @@ const ListObjects = () => {
const bucketName = params.bucketName || "";
const pathSegment = location.pathname.split(`/browser/${bucketName}/`);
const internalPaths = pathSegment.length === 2 ? pathSegment[1] : "";
const internalPaths =
pathSegment.length === 2 ? decodeURIComponent(pathSegment[1]) : "";
const pageTitle = decodeURLString(internalPaths);
const currentPath = pageTitle.split("/").filter((i: string) => i !== "");
const currentPath = internalPaths.split("/").filter((i: string) => i !== "");
let uploadPath = [bucketName];
if (currentPath.length > 0) {
@@ -316,12 +312,11 @@ const ListObjects = () => {
const fetchMetadata = useCallback(() => {
const objectName = selectedObjects[0];
const encodedPath = encodeURLString(objectName);
if (!isMetaDataLoaded && encodedPath) {
if (!isMetaDataLoaded && objectName) {
api.buckets
.getObjectMetadata(bucketName, {
prefix: encodedPath,
prefix: objectName,
})
.then((res) => {
let metadata = get(res.data, "objectMetadata", {});
@@ -511,8 +506,6 @@ const ListObjects = () => {
const blobFile = new Blob([file], { type: file.type });
let encodedPath = "";
const filePath = get(file, "path", "");
const fileWebkitRelativePath = get(file, "webkitRelativePath", "");
@@ -552,17 +545,15 @@ const ListObjects = () => {
}
if (prefixPath !== "") {
uploadUrl = `${uploadUrl}?prefix=${encodeURLString(
uploadUrl = `${uploadUrl}?prefix=${encodeURIComponent(
prefixPath + fileName,
)}`;
} else {
uploadUrl = `${uploadUrl}?prefix=${encodeURLString(fileName)}`;
uploadUrl = `${uploadUrl}?prefix=${encodeURIComponent(fileName)}`;
}
encodedPath = encodeURLString(prefixPath);
const identity = encodeURLString(
`${bucketName}-${encodedPath}-${new Date().getTime()}-${Math.random()}`,
const identity = encodeURIComponent(
`${bucketName}-${prefixPath}-${new Date().getTime()}-${Math.random()}`,
);
let xhr = new XMLHttpRequest();
@@ -666,7 +657,7 @@ const ListObjects = () => {
done: false,
instanceID: identity,
percentage: 0,
prefix: `${decodeURLString(encodedPath)}${fileName}`,
prefix: `${prefixPath}${fileName}`,
type: "upload",
waitingForFile: false,
failed: false,
@@ -812,8 +803,7 @@ const ListObjects = () => {
if (detailsOpen && selectedInternalPaths !== null) {
// We change URL to be the contained folder
const decodedPath = decodeURLString(internalPaths);
const splitURLS = decodedPath.split("/");
const splitURLS = internalPaths.split("/");
// We remove the last section of the URL as it should be a file
splitURLS.pop();
@@ -824,7 +814,9 @@ const ListObjects = () => {
URLItem = `${splitURLS.join("/")}/`;
}
navigate(`/browser/${bucketName}/${encodeURLString(URLItem)}`);
navigate(
`/browser/${encodeURIComponent(bucketName)}/${encodeURIComponent(URLItem)}`,
);
}
dispatch(setObjectDetailsView(false));
@@ -1222,7 +1214,7 @@ const ListObjects = () => {
>
<BrowserBreadcrumbs
bucketName={bucketName}
internalPaths={pageTitle}
internalPaths={internalPaths}
additionalOptions={
!isVersioningApplied || rewindEnabled ? null : (
<Checkbox

View File

@@ -19,7 +19,6 @@ import { listModeColumns, rewindModeColumns } from "./ListObjectsHelpers";
import { useSelector } from "react-redux";
import { AppState, useAppDispatch } from "../../../../../../store";
import { selFeatures } from "../../../../consoleSlice";
import { encodeURLString } from "../../../../../../common/utils";
import {
setLoadingVersions,
setObjectDetailsView,
@@ -111,18 +110,13 @@ const ListObjectsTable = () => {
const openPath = (object: BucketObject) => {
const idElement = object.name || "";
const newPath = `/browser/${bucketName}${
idElement ? `/${encodeURLString(idElement)}` : ``
const newPath = `/browser/${encodeURIComponent(bucketName)}${
idElement ? `/${encodeURIComponent(idElement)}` : ``
}`;
// for anonymous start download
if (anonymousMode && !object.name?.endsWith("/")) {
downloadObject(
dispatch,
bucketName,
`${encodeURLString(idElement)}`,
object,
);
downloadObject(dispatch, bucketName, idElement, object);
return;
}
dispatch(setSelectedObjects([]));
@@ -133,11 +127,7 @@ const ListObjectsTable = () => {
dispatch(setObjectDetailsView(true));
dispatch(setLoadingVersions(true));
}
dispatch(
setSelectedObjectView(
`${idElement ? `${encodeURLString(idElement)}` : ``}`,
),
);
dispatch(setSelectedObjectView(idElement));
};
const tableActions: ItemActions[] = [
{

View File

@@ -41,7 +41,6 @@ import { downloadObject } from "../../../../ObjectBrowser/utils";
import { BucketObject, BucketVersioningResponse } from "api/consoleApi";
import { AllowedPreviews, previewObjectType } from "../utils";
import {
decodeURLString,
niceBytes,
niceBytesInt,
niceDaysInt,
@@ -130,7 +129,7 @@ const ObjectDetailPanel = ({
const [metaData, setMetaData] = useState<any | null>(null);
const [loadMetadata, setLoadingMetadata] = useState<boolean>(false);
const internalPathsDecoded = decodeURLString(internalPaths) || "";
const internalPathsDecoded = internalPaths || "";
const allPathData = internalPathsDecoded.split("/");
const currentItem = allPathData.pop() || "";

View File

@@ -19,7 +19,6 @@ import { Box, RecoverIcon } from "mds";
import { BucketObject } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
import { encodeURLString } from "../../../../../../common/utils";
import ConfirmDialog from "../../../../Common/ModalWrapper/ConfirmDialog";
import { setErrorSnackMessage } from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
@@ -48,7 +47,7 @@ const RestoreFileVersion = ({
api.buckets
.putObjectRestore(bucketName, {
prefix: encodeURLString(objectPath),
prefix: objectPath,
version_id: versionToRestore.version_id || "",
})
.then(() => {

View File

@@ -21,7 +21,6 @@ import { BucketObject, ObjectLegalHoldStatus } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
import { encodeURLString } from "../../../../../../common/utils";
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
@@ -59,7 +58,7 @@ const SetLegalHoldModal = ({
.putObjectLegalHold(
bucketName,
{
prefix: encodeURLString(objectName),
prefix: objectName,
version_id: versionId || "",
},
{

View File

@@ -20,7 +20,6 @@ import { useSelector } from "react-redux";
import { BucketObject, ObjectRetentionMode } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
import { encodeURLString } from "common/utils";
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
import { twoDigitDate } from "../../../../Common/FormComponents/DateSelector/utils";
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
@@ -106,7 +105,7 @@ const SetRetention = ({
.putObjectRetention(
bucketName,
{
prefix: encodeURLString(selectedObject),
prefix: selectedObject,
version_id: versionId || "",
},
{
@@ -130,7 +129,7 @@ const SetRetention = ({
) => {
api.buckets
.deleteObjectRetention(bucketName, {
prefix: encodeURLString(selectedObject),
prefix: selectedObject,
version_id: versionId || "",
})
.then(() => {

View File

@@ -28,10 +28,7 @@ import {
import CopyToClipboard from "react-copy-to-clipboard";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import DaysSelector from "../../../../Common/FormComponents/DaysSelector/DaysSelector";
import {
encodeURLString,
niceTimeFromSeconds,
} from "../../../../../../common/utils";
import { niceTimeFromSeconds } from "../../../../../../common/utils";
import {
selDistSet,
setModalErrorSnackMessage,
@@ -90,7 +87,7 @@ const ShareFile = ({
if (distributedSetup) {
api.buckets
.listObjects(bucketName, {
prefix: encodeURLString(dataObject.name || ""),
prefix: dataObject.name || "",
with_versions: distributedSetup,
})
.then((res) => {
@@ -138,7 +135,7 @@ const ShareFile = ({
if (diffDate > 0) {
api.buckets
.shareObject(bucketName, {
prefix: encodeURLString(dataObject.name || ""),
prefix: dataObject.name || "",
version_id: versionID,
expires: selectedDate !== "" ? `${diffDate}s` : "",
})

View File

@@ -32,7 +32,6 @@ import {
import { BucketObject } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
import { encodeURLString } from "common/utils";
import { useSelector } from "react-redux";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
@@ -71,8 +70,6 @@ const AddTagModal = ({
const [deleteKey, setDeleteKey] = useState<string>("");
const [deleteLabel, setDeleteLabel] = useState<string>("");
const selectedObject = encodeURLString(actualInfo.name || "");
const currentTags = actualInfo.tags;
const currTagKeys = Object.keys(currentTags || {});
@@ -96,7 +93,7 @@ const AddTagModal = ({
api.buckets
.putObjectTags(
bucketName,
{ prefix: selectedObject, version_id: verID },
{ prefix: actualInfo.name || "", version_id: verID },
{ tags: newTagList },
)
.then(() => {
@@ -118,7 +115,7 @@ const AddTagModal = ({
api.buckets
.putObjectTags(
bucketName,
{ prefix: selectedObject, version_id: verID },
{ prefix: actualInfo.name || "", version_id: verID },
{ tags: cleanObject },
)
.then(() => {

View File

@@ -31,7 +31,7 @@ import {
} from "mds";
import ShareFile from "./ShareFile";
import { decodeURLString, niceBytesInt } from "../../../../../../common/utils";
import { niceBytesInt } from "../../../../../../common/utils";
import RestoreFileVersion from "./RestoreFileVersion";
import { AppState, useAppDispatch } from "../../../../../../store";
@@ -128,11 +128,9 @@ const VersionsNavigator = ({
.then((res) => {
const result = get(res.data, "objects", []);
const decodedInternalPaths = decodeURLString(internalPaths);
// Filter the results prefixes as API can return more files than expected.
const filteredPrefixes = result.filter(
(item: BucketObject) => item.name === decodedInternalPaths,
(item: BucketObject) => item.name === internalPaths,
);
if (distributedSetup) {
@@ -356,7 +354,7 @@ const VersionsNavigator = ({
{delSelectedVOpen && (
<DeleteSelectedVersions
selectedBucket={bucketName}
selectedObject={decodeURLString(internalPaths)}
selectedObject={internalPaths}
deleteOpen={delSelectedVOpen}
selectedVersions={selectedItems}
closeDeleteModalAndRefresh={closeSelectedVersions}
@@ -383,7 +381,7 @@ const VersionsNavigator = ({
<Grid item xs={12}>
<BrowserBreadcrumbs
bucketName={bucketName}
internalPaths={decodeURLString(internalPaths)}
internalPaths={internalPaths}
hidePathButton={true}
/>
</Grid>

View File

@@ -18,7 +18,6 @@ import React, { Fragment, useCallback, useEffect, useState } from "react";
import { ProgressBar, Grid, Box, InformativeMessage } from "mds";
import get from "lodash/get";
import { AllowedPreviews, previewObjectType } from "../utils";
import { encodeURLString } from "../../../../../../common/utils";
import { api } from "../../../../../../api";
import PreviewPDF from "./PreviewPDF";
import { downloadObject } from "../../../../ObjectBrowser/utils";
@@ -47,10 +46,9 @@ const PreviewFile = ({
const fetchMetadata = useCallback(() => {
if (!isMetaDataLoaded) {
const encodedPath = encodeURLString(objectName);
api.buckets
.getObjectMetadata(bucketName, {
prefix: encodedPath,
prefix: objectName,
versionID: actualInfo.version_id || "",
})
.then((res) => {
@@ -78,9 +76,8 @@ const PreviewFile = ({
let path = "";
if (actualInfo) {
const encodedPath = encodeURLString(actualInfo.name || "");
let basename = document.baseURI.replace(window.location.origin, "");
path = `${window.location.origin}${basename}api/v1/buckets/${bucketName}/objects/download?preview=true&prefix=${encodedPath}`;
path = `${window.location.origin}${basename}api/v1/buckets/${encodeURIComponent(bucketName)}/objects/download?preview=true&prefix=${encodeURIComponent(actualInfo.name || "")}`;
if (actualInfo.version_id) {
path = path.concat(`&version_id=${actualInfo.version_id}`);
}

View File

@@ -15,7 +15,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { BucketObjectItem } from "./ListObjects/types";
import { decodeURLString, encodeURLString } from "../../../../../common/utils";
import { removeTrace } from "../../../ObjectBrowser/transferManager";
import store from "../../../../../store";
import { ContentType, PermissionResource } from "api/consoleApi";
@@ -66,7 +65,7 @@ export const downloadSelectedAsZip = async (
};
const isFolder = (objectPath: string) => {
return decodeURLString(objectPath).endsWith("/");
return objectPath.endsWith("/");
};
export const download = (
@@ -88,9 +87,9 @@ export const download = (
let path = `${
window.location.origin
}${basename}api/v1/buckets/${bucketName}/objects/download?prefix=${objectPath}${
}${basename}api/v1/buckets/${encodeURIComponent(bucketName)}/objects/download?prefix=${encodeURIComponent(objectPath)}${
overrideFileName !== null && overrideFileName.trim() !== ""
? `&override_file_name=${encodeURLString(overrideFileName || "")}`
? `&override_file_name=${encodeURIComponent(overrideFileName || "")}`
: ""
}`;
if (versionID) {

View File

@@ -17,7 +17,6 @@
import React, { useState } from "react";
import { AddMembersToGroupIcon, Button, FormLayout, Grid, ReadBox } from "mds";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
import { encodeURLString } from "../../../common/utils";
import { setModalErrorSnackMessage } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import { api } from "api";
@@ -48,7 +47,7 @@ const AddGroupMember = ({
function addMembersToGroup() {
return api.group
.updateGroup(encodeURLString(selectedGroup), {
.updateGroup(selectedGroup, {
members: selectedUsers,
status: groupStatus,
})

View File

@@ -16,7 +16,6 @@
import React, { Fragment, useState } from "react";
import { ConfirmDeleteIcon } from "mds";
import { encodeURLString } from "../../../common/utils";
import { setErrorSnackMessage } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog";
@@ -46,7 +45,7 @@ const DeleteGroup = ({
for (let group of selectedGroups) {
setLoadingDelete(true);
api.group
.removeGroup(encodeURLString(group))
.removeGroup(group)
.then((_) => {
closeDeleteModalAndRefresh(true);
})

View File

@@ -51,7 +51,6 @@ import {
} from "../../../common/SecureComponent";
import { errorToHandler } from "../../../api/errors";
import withSuspense from "../Common/Components/withSuspense";
import { encodeURLString } from "../../../common/utils";
import { setErrorSnackMessage, setHelpName } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
@@ -163,7 +162,7 @@ const Groups = () => {
);
const viewAction = (group: any) => {
navigate(`${IAM_PAGES.GROUPS}/${encodeURLString(group)}`);
navigate(`${IAM_PAGES.GROUPS}/${encodeURIComponent(group)}`);
};
const tableActions = [

View File

@@ -53,7 +53,6 @@ import {
hasPermission,
SecureComponent,
} from "../../../common/SecureComponent";
import { decodeURLString, encodeURLString } from "../../../common/utils";
import { setHelpName, setModalErrorSnackMessage } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import { setSelectedPolicies } from "../Users/AddUsersSlice";
@@ -82,8 +81,6 @@ const GroupsDetails = () => {
const [memberFilter, setMemberFilter] = useState<string>("");
const [currentTab, setCurrentTab] = useState<string>("members");
const groupName = decodeURLString(params.groupName || "");
const { members = [], policy = "", status: groupEnabled } = groupDetails;
const filteredMembers = members.filter((elementItem) =>
@@ -102,11 +99,11 @@ const GroupsDetails = () => {
}, []);
useEffect(() => {
if (groupName) {
if (params.groupName) {
fetchGroupInfo();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [groupName]);
}, [params.groupName]);
const groupPolicies = formatPolicy(policy);
const isGroupEnabled = groupEnabled === "enabled";
@@ -138,7 +135,7 @@ const GroupsDetails = () => {
function fetchGroupInfo() {
if (getGroupDetails) {
api.group
.groupInfo(encodeURLString(groupName))
.groupInfo(params.groupName || "")
.then((res) => {
setGroupDetails(res.data);
})
@@ -151,7 +148,7 @@ const GroupsDetails = () => {
function toggleGroupStatus(nextStatus: boolean) {
return api.group
.updateGroup(encodeURLString(groupName), {
.updateGroup(params.groupName || "", {
members: members,
status: nextStatus ? "enabled" : "disabled",
})
@@ -242,7 +239,9 @@ const GroupsDetails = () => {
{
type: "view",
onClick: (userName) => {
navigate(`${IAM_PAGES.USERS}/${encodeURLString(userName)}`);
navigate(
`${IAM_PAGES.USERS}/${encodeURIComponent(userName)}`,
);
},
isDisabled: !viewUser,
},
@@ -312,7 +311,9 @@ const GroupsDetails = () => {
{
type: "view",
onClick: (policy) => {
navigate(`${IAM_PAGES.POLICIES}/${encodeURLString(policy)}`);
navigate(
`${IAM_PAGES.POLICIES}/${encodeURIComponent(policy)}`,
);
},
isDisabled: !canViewPolicy,
},
@@ -332,7 +333,7 @@ const GroupsDetails = () => {
{policyOpen ? (
<SetPolicy
open={policyOpen}
selectedGroups={[groupName]}
selectedGroups={[params.groupName || ""]}
selectedUser={null}
closeModalAndRefresh={() => {
setPolicyOpen(false);
@@ -344,7 +345,7 @@ const GroupsDetails = () => {
{usersOpen ? (
<AddGroupMember
selectedGroup={groupName}
selectedGroup={params.groupName}
onSaveClick={() => {}}
title={memberActionText}
groupStatus={groupEnabled}
@@ -360,7 +361,7 @@ const GroupsDetails = () => {
{deleteOpen && (
<DeleteGroup
deleteOpen={deleteOpen}
selectedGroups={[groupName]}
selectedGroups={[params.groupName || ""]}
closeDeleteModalAndRefresh={(isDelSuccess: boolean) => {
setDeleteOpen(false);
if (isDelSuccess) {
@@ -388,7 +389,7 @@ const GroupsDetails = () => {
<GroupsIcon width={40} />
</Fragment>
}
title={groupName}
title={params.groupName || ""}
subTitle={null}
bottomBorder
actions={

View File

@@ -19,7 +19,7 @@ import { useSelector } from "react-redux";
import CopyToClipboard from "react-copy-to-clipboard";
import styled from "styled-components";
import { Link, useNavigate } from "react-router-dom";
import { encodeURLString, safeDecodeURIComponent } from "../../../common/utils";
import { safeDecodeURIComponent } from "../../../common/utils";
import {
Button,
CopyIcon,
@@ -137,8 +137,8 @@ const BrowserBreadcrumbs = ({
let breadcrumbsMap = splitPaths.map((objectItem: string, index: number) => {
const subSplit = `${splitPaths.slice(0, index + 1).join("/")}/`;
const route = `/browser/${bucketName}/${
subSplit ? `${encodeURLString(subSplit)}` : ``
const route = `/browser/${encodeURIComponent(bucketName)}/${
subSplit ? `${encodeURIComponent(subSplit)}` : ``
}`;
if (index === lastBreadcrumbsIndex && objectItem === versionedFile) {
@@ -222,7 +222,7 @@ const BrowserBreadcrumbs = ({
navigate(
`/browser/${bucketName}${
prevPath.length > 0
? `/${encodeURLString(`${prevPath.join("/")}/`)}`
? `/${encodeURIComponent(`${prevPath.join("/")}/`)}`
: ""
}`,
);

View File

@@ -16,7 +16,7 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import { AppState } from "../../../store";
import { encodeURLString, getClientOS } from "../../../common/utils";
import { getClientOS } from "../../../common/utils";
import { BucketObjectItem } from "../Buckets/ListBuckets/Objects/ListObjects/types";
import { makeid, storeCallForObjectWithID } from "./transferManager";
import {
@@ -46,7 +46,7 @@ export const downloadSelected = createAsyncThunk(
const state = getState() as AppState;
const downloadObject = (object: BucketObjectItem) => {
const identityDownload = encodeURLString(
const identityDownload = encodeURIComponent(
`${bucketName}-${object.name}-${new Date().getTime()}-${Math.random()}`,
);
@@ -54,7 +54,7 @@ export const downloadSelected = createAsyncThunk(
const downloadCall = download(
bucketName,
encodeURLString(object.name),
object.name,
object.version_id,
object.size,
null,

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { encodeURLString, getClientOS } from "../../../common/utils";
import { getClientOS } from "../../../common/utils";
import { makeid, storeCallForObjectWithID } from "./transferManager";
import { download } from "../Buckets/ListBuckets/Objects/utils";
import {
@@ -35,7 +35,7 @@ export const downloadObject = (
internalPaths: string,
object: BucketObject,
) => {
const identityDownload = encodeURLString(
const identityDownload = encodeURIComponent(
`${bucketName}-${object.name}-${new Date().getTime()}-${Math.random()}`,
);

View File

@@ -22,7 +22,6 @@ import { useAppDispatch } from "../../../store";
import { api } from "api";
import { ApiError, HttpResponse } from "api/consoleApi";
import { errorToHandler } from "api/errors";
import { encodeURLString } from "common/utils";
interface IDeletePolicyProps {
closeDeleteModalAndRefresh: (refresh: boolean) => void;
@@ -47,7 +46,7 @@ const DeletePolicy = ({
const onConfirmDelete = () => {
setLoadingDelete(true);
api.policy
.removePolicy(encodeURLString(selectedPolicy))
.removePolicy(selectedPolicy)
.then((_) => {
closeDeleteModalAndRefresh(true);
})

View File

@@ -42,7 +42,6 @@ import {
SecureComponent,
} from "../../../common/SecureComponent";
import { Policy } from "../../../api/consoleApi";
import { encodeURLString } from "../../../common/utils";
import { setErrorSnackMessage, setHelpName } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import { api } from "../../../api";
@@ -142,7 +141,7 @@ const ListPolicies = () => {
};
const viewAction = (policy: any) => {
navigate(`${IAM_PAGES.POLICIES}/${encodeURLString(policy.name)}`);
navigate(`${IAM_PAGES.POLICIES}/${encodeURIComponent(policy.name)}`);
};
const tableActions = [

View File

@@ -59,7 +59,6 @@ import {
import withSuspense from "../Common/Components/withSuspense";
import PolicyView from "./PolicyView";
import { decodeURLString, encodeURLString } from "../../../common/utils";
import {
setErrorSnackMessage,
setHelpName,
@@ -89,7 +88,7 @@ const PolicyDetails = () => {
const [groupList, setGroupList] = useState<string[]>([]);
const [addLoading, setAddLoading] = useState<boolean>(false);
const policyName = decodeURLString(params.policyName || "");
const policyName = params.policyName || "";
const [policyDefinition, setPolicyDefinition] = useState<string>("");
const [loadingPolicy, setLoadingPolicy] = useState<boolean>(true);
@@ -183,7 +182,7 @@ const PolicyDetails = () => {
if (loadingUsers) {
if (displayUsers && !ldapIsEnabled) {
api.policies
.listUsersForPolicy(encodeURLString(policyName))
.listUsersForPolicy(policyName)
.then((result) => {
setUserList(result.data ?? []);
setLoadingUsers(false);
@@ -202,7 +201,7 @@ const PolicyDetails = () => {
if (loadingGroups) {
if (displayGroups && !ldapIsEnabled) {
api.policies
.listGroupsForPolicy(encodeURLString(policyName))
.listGroupsForPolicy(policyName)
.then((result) => {
setGroupList(result.data ?? []);
setLoadingGroups(false);
@@ -220,7 +219,7 @@ const PolicyDetails = () => {
if (loadingPolicy) {
if (displayPolicy) {
api.policy
.policyInfo(encodeURLString(policyName))
.policyInfo(policyName)
.then((result) => {
if (result.data) {
setPolicy(result.data);
@@ -283,7 +282,7 @@ const PolicyDetails = () => {
};
const userViewAction = (user: any) => {
navigate(`${IAM_PAGES.USERS}/${encodeURLString(user)}`);
navigate(`${IAM_PAGES.USERS}/${encodeURIComponent(user)}`);
};
const userTableActions = [
{
@@ -298,7 +297,7 @@ const PolicyDetails = () => {
);
const groupViewAction = (group: any) => {
navigate(`${IAM_PAGES.GROUPS}/${encodeURLString(group)}`);
navigate(`${IAM_PAGES.GROUPS}/${encodeURIComponent(group)}`);
};
const groupTableActions = [

View File

@@ -20,7 +20,6 @@ import { useSelector } from "react-redux";
import { Button, FormLayout, ReadBox, Grid, ProgressBar } from "mds";
import { ErrorResponseHandler } from "../../../common/types";
import { encodeURLString } from "../../../common/utils";
import { setModalErrorSnackMessage } from "../../../systemSlice";
import { AppState, useAppDispatch } from "../../../store";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
@@ -83,7 +82,7 @@ const SetPolicy = ({
const fetchGroupInformation = () => {
if (selectedGroups?.length === 1) {
api
.invoke("GET", `/api/v1/group/${encodeURLString(selectedGroups[0])}`)
.invoke("GET", `/api/v1/group/${encodeURIComponent(selectedGroups[0])}`)
.then((res: any) => {
const groupPolicy: String = get(res, "policy", "");
setActualPolicy(groupPolicy.split(","));

View File

@@ -31,7 +31,6 @@ import { useNavigate } from "react-router-dom";
import { useSelector } from "react-redux";
import {
deleteCookie,
encodeURLString,
getCookieValue,
performDownload,
} from "../../../common/utils";
@@ -143,11 +142,8 @@ const Inspect = () => {
};
const performInspect = async () => {
const file = encodeURLString(inspectPath);
const volume = encodeURLString(volumeName);
let basename = document.baseURI.replace(window.location.origin, "");
const urlOfInspectApi = `${basename}/api/v1/admin/inspect?volume=${volume}&file=${file}&encrypt=${isEncrypt}`;
const urlOfInspectApi = `${basename}/api/v1/admin/inspect?volume=${encodeURIComponent(volumeName)}&file=${encodeURIComponent(inspectPath)}&encrypt=${isEncrypt}`;
makeRequest(urlOfInspectApi)
.then(async (res) => {

View File

@@ -35,11 +35,7 @@ import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
import { NewServiceAccount } from "../Common/CredentialsPrompt/types";
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
import { ErrorResponseHandler } from "../../../common/types";
import {
decodeURLString,
encodeURLString,
getRandomString,
} from "../../../common/utils";
import { getRandomString } from "../../../common/utils";
import { setErrorSnackMessage, setHelpName } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import CodeMirrorWrapper from "../Common/FormComponents/CodeMirrorWrapper/CodeMirrorWrapper";
@@ -64,7 +60,7 @@ const AddServiceAccount = () => {
useState<NewServiceAccount | null>(null);
const [policyJSON, setPolicyJSON] = useState<string>("");
const userName = decodeURLString(params.userName || "");
const userName = params.userName || "";
const [name, setName] = useState<string>("");
const [description, setDescription] = useState<string>("");
@@ -77,7 +73,7 @@ const AddServiceAccount = () => {
api
.invoke(
"POST",
`/api/v1/user/${encodeURLString(
`/api/v1/user/${encodeURIComponent(
userName,
)}/service-account-credentials`,
{
@@ -120,7 +116,7 @@ const AddServiceAccount = () => {
useEffect(() => {
if (isRestrictedByPolicy) {
api
.invoke("GET", `/api/v1/user/${encodeURLString(userName)}/policies`)
.invoke("GET", `/api/v1/user/${encodeURIComponent(userName)}/policies`)
.then((res) => {
setPolicyJSON(JSON.stringify(JSON.parse(res.policy), null, 4));
@@ -144,7 +140,7 @@ const AddServiceAccount = () => {
const closeCredentialsModal = () => {
setNewServiceAccount(null);
navigate(`${IAM_PAGES.USERS}/${encodeURLString(userName)}`);
navigate(`${IAM_PAGES.USERS}/${encodeURIComponent(userName)}`);
};
useEffect(() => {
@@ -169,7 +165,7 @@ const AddServiceAccount = () => {
label={
<BackLink
onClick={() =>
navigate(`${IAM_PAGES.USERS}/${encodeURLString(userName)}`)
navigate(`${IAM_PAGES.USERS}/${encodeURIComponent(userName)}`)
}
label={"User Details - " + userName}
/>

View File

@@ -26,7 +26,6 @@ import {
} from "mds";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
import { ErrorResponseHandler } from "../../../common/types";
import { encodeURLString } from "../../../common/utils";
import { setModalErrorSnackMessage } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import api from "../../../common/api";
@@ -57,7 +56,7 @@ const ChangeUserGroups = ({
}
api
.invoke("GET", `/api/v1/user/${encodeURLString(selectedUser)}`)
.invoke("GET", `/api/v1/user/${encodeURIComponent(selectedUser)}`)
.then((res) => {
setAddLoading(false);
setAccessKey(res.accessKey);
@@ -89,7 +88,7 @@ const ChangeUserGroups = ({
setAddLoading(true);
if (selectedUser !== null) {
api
.invoke("PUT", `/api/v1/user/${encodeURLString(selectedUser)}`, {
.invoke("PUT", `/api/v1/user/${encodeURIComponent(selectedUser)}`, {
status: enabled ? "enabled" : "disabled",
groups: selectedGroups,
})

View File

@@ -18,7 +18,6 @@ import React, { Fragment, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { setErrorSnackMessage } from "../../../systemSlice";
import { ConfirmDeleteIcon, DataTable, InformativeMessage, Loader } from "mds";
import { encodeURLString } from "../../../common/utils";
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog";
import { useAppDispatch } from "../../../store";
@@ -78,7 +77,7 @@ const DeleteUser = ({
));
const viewAction = (selectionElement: any): void => {
navigate(
`${IAM_PAGES.USERS}/${encodeURLString(selectionElement.userName)}`,
`${IAM_PAGES.USERS}/${encodeURIComponent(selectionElement.userName)}`,
);
onClose();
};
@@ -101,7 +100,7 @@ const DeleteUser = ({
closeDeleteModalAndRefresh(true);
} else {
api.user
.removeUser(encodeURLString(user))
.removeUser(user)
.then((res) => {
closeDeleteModalAndRefresh(true);
navigate(`${IAM_PAGES.USERS}`);

View File

@@ -34,7 +34,6 @@ import { User, UsersList } from "./types";
import { usersSort } from "../../../utils/sortFunctions";
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
import { ErrorResponseHandler } from "../../../common/types";
import { encodeURLString } from "../../../common/utils";
import {
addUserToGroupPermissions,
CONSOLE_UI_RESOURCE,
@@ -148,7 +147,7 @@ const ListUsers = () => {
const viewAction = (selectionElement: any): void => {
navigate(
`${IAM_PAGES.USERS}/${encodeURLString(selectionElement.accessKey)}`,
`${IAM_PAGES.USERS}/${encodeURIComponent(selectionElement.accessKey)}`,
);
};

View File

@@ -35,7 +35,6 @@ import {
} from "mds";
import { IPolicyItem } from "./types";
import { ErrorResponseHandler } from "../../../common/types";
import { decodeURLString, encodeURLString } from "../../../common/utils";
import { setHelpName, setModalErrorSnackMessage } from "../../../systemSlice";
import {
assignGroupPermissions,
@@ -91,7 +90,7 @@ const UserDetails = () => {
const disableEnabled =
hasPermission(CONSOLE_UI_RESOURCE, disableUserPermissions) && enabled;
const userName = decodeURLString(params.userName || "");
const userName = params.userName || "";
const changeUserPassword = () => {
setChangeUserPasswordModalOpen(true);
@@ -121,7 +120,7 @@ const UserDetails = () => {
}
setLoading(true);
api
.invoke("GET", `/api/v1/user/${encodeURLString(userName)}`)
.invoke("GET", `/api/v1/user/${encodeURIComponent(userName)}`)
.then((res) => {
setAddLoading(false);
const memberOf = res.memberOf || [];
@@ -162,7 +161,7 @@ const UserDetails = () => {
}
setAddLoading(true);
api
.invoke("PUT", `/api/v1/user/${encodeURLString(userName)}`, {
.invoke("PUT", `/api/v1/user/${encodeURIComponent(userName)}`, {
status: isEnabled ? "enabled" : "disabled",
groups: selectedGroups,
})
@@ -192,7 +191,7 @@ const UserDetails = () => {
};
const groupViewAction = (group: any) => {
navigate(`${IAM_PAGES.GROUPS}/${encodeURLString(group.group)}`);
navigate(`${IAM_PAGES.GROUPS}/${encodeURIComponent(group.group)}`);
};
const groupTableActions = [
@@ -493,7 +492,7 @@ const UserDetails = () => {
type: "view",
onClick: (policy: IPolicyItem) => {
navigate(
`${IAM_PAGES.POLICIES}/${encodeURLString(
`${IAM_PAGES.POLICIES}/${encodeURIComponent(
policy.policy,
)}`,
);

View File

@@ -31,7 +31,6 @@ import {
IAM_SCOPES,
} from "../../../common/SecureComponent/permissions";
import { SecureComponent } from "../../../common/SecureComponent";
import { encodeURLString } from "../../../common/utils";
import {
setErrorSnackMessage,
setHelpName,
@@ -75,7 +74,10 @@ const UserServiceAccountsPanel = ({
useEffect(() => {
if (loading) {
api
.invoke("GET", `/api/v1/user/${encodeURLString(user)}/service-accounts`)
.invoke(
"GET",
`/api/v1/user/${encodeURIComponent(user)}/service-accounts`,
)
.then((res: ServiceAccounts) => {
setLoading(false);
const sortedRows = res.sort(usersSort);
@@ -233,7 +235,7 @@ const UserServiceAccountsPanel = ({
icon={<AddIcon />}
onClick={() => {
navigate(
`/identity/users/new-user-sa/${encodeURLString(user)}`,
`/identity/users/new-user-sa/${encodeURIComponent(user)}`,
);
}}
disabled={!hasPolicy}

View File

@@ -34,7 +34,6 @@ import {
WebsocketRequest,
WebsocketResponse,
} from "../screens/Console/Buckets/ListBuckets/Objects/ListObjects/types";
import { decodeURLString, encodeURLString } from "../common/utils";
import { permissionItems } from "../screens/Console/Buckets/ListBuckets/Objects/utils";
import { setErrorSnackMessage } from "../systemSlice";
@@ -108,11 +107,9 @@ export const objectBrowserWSMiddleware = (
let pathPrefix = "";
if (internalPathsPrefix) {
const decodedPath = decodeURLString(internalPathsPrefix);
pathPrefix = decodedPath.endsWith("/")
? decodedPath
: decodedPath + "/";
pathPrefix = internalPathsPrefix.endsWith("/")
? internalPathsPrefix
: internalPathsPrefix + "/";
}
const permitItems = permissionItems(
@@ -202,7 +199,7 @@ export const objectBrowserWSMiddleware = (
const request: WebsocketRequest = {
bucket_name: dataPayload.bucketName,
prefix: encodeURLString(dataPayload.path),
prefix: dataPayload.path,
mode: dataPayload.rewindMode ? "rewind" : "objects",
date: dataPayload.date,
request_id: newRequestID,

View File

@@ -54,7 +54,7 @@ test
const uploadButton = elements.uploadButton;
await t
.useRole(roles.bucketWritePrefixOnly)
.navigateTo("http://localhost:9090/browser/testcafe/d3JpdGU=")
.navigateTo("http://localhost:9090/browser/testcafe/write")
.click(uploadButton)
.expect(
Selector("div")