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" @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 @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" @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 @git restore api/server.go

View File

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

View File

@@ -22,7 +22,6 @@ import (
"io" "io"
"net/http" "net/http"
"strings" "strings"
"unicode/utf8"
"github.com/go-openapi/runtime" "github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware" "github.com/go-openapi/runtime/middleware"
@@ -35,14 +34,6 @@ import (
func registerInspectHandler(api *operations.ConsoleAPI) { func registerInspectHandler(api *operations.ConsoleAPI) {
api.InspectInspectHandler = inspectApi.InspectHandlerFunc(func(params inspectApi.InspectParams, principal *models.Principal) middleware.Responder { 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) k, r, err := getInspectResult(principal, &params)
if err != nil { if err != nil {
return inspectApi.NewInspectDefault(err.Code).WithPayload(err.APIError) return inspectApi.NewInspectDefault(err.Code).WithPayload(err.APIError)

View File

@@ -18,7 +18,6 @@ package api
import ( import (
"context" "context"
"encoding/base64"
"time" "time"
"github.com/minio/mc/cmd" "github.com/minio/mc/cmd"
@@ -60,20 +59,7 @@ type ObjectResponse struct {
func getObjectsOptionsFromReq(request ObjectsRequest) (*objectsListOpts, error) { func getObjectsOptionsFromReq(request ObjectsRequest) (*objectsListOpts, error) {
pOptions := objectsListOpts{ pOptions := objectsListOpts{
BucketName: request.BucketName, BucketName: request.BucketName,
Prefix: "", Prefix: request.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)
} }
if request.Mode == "rewind" { if request.Mode == "rewind" {

View File

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

View File

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

View File

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

View File

@@ -23,7 +23,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func Test_b64toMinIOStringURL(t *testing.T) { func Test_checkMinIOStringURL(t *testing.T) {
tAssert := assert.New(t) tAssert := assert.New(t)
type args struct { type args struct {
encodedURL string encodedURL string
@@ -37,7 +37,7 @@ func Test_b64toMinIOStringURL(t *testing.T) {
{ {
test: "valid encoded minIO URL returns decoded URL string", // http://localhost:9000/... test: "valid encoded minIO URL returns decoded URL string", // http://localhost:9000/...
args: args{ 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, 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"), 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/... test: "valid encoded url but not coming from MinIO server returns forbidden error", // http://non-minio-host:9000/...
args: args{ 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"), wantError: swag.String("403 Forbidden"),
expected: nil, 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/... test: "valid encoded url but not coming from MinIO server port returns forbidden error", // other port http://localhost:8902/...
args: args{ 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"), wantError: swag.String("403 Forbidden"),
expected: nil, expected: nil,
@@ -61,7 +61,7 @@ func Test_b64toMinIOStringURL(t *testing.T) {
{ {
test: "valid url but with invalid schema returns error", test: "valid url but with invalid schema returns error",
args: args{ 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"), wantError: swag.String("unexpected scheme found postgres"),
@@ -70,16 +70,16 @@ func Test_b64toMinIOStringURL(t *testing.T) {
{ {
test: "invalid url returns error", test: "invalid url returns error",
args: args{ args: args{
encodedURL: "YXNkc2Fkc2Rh", // asdsadsda encodedURL: "asdsadsda", // asdsadsda
}, },
wantError: swag.String("unexpected scheme found "), wantError: swag.String("unexpected scheme found "),
expected: nil, expected: nil,
}, },
{ {
test: "encoded url is url safe decoded", test: "plain url",
args: args{ args: args{
encodedURL: "aHR0cHM6Ly9sb2NhbGhvc3Q6OTAwMC9jZXN0ZXN0L0F1ZGlvJTIwaWNvbi5zdmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTY=", encodedURL: "https://localhost:9000/cestest/Audio%20icon.svg?X-Amz-Algorithm=AWS4-HMAC-SHA256",
}, },
wantError: nil, wantError: nil,
expected: swag.String("https://localhost:9000/cestest/Audio%20icon.svg?X-Amz-Algorithm=AWS4-HMAC-SHA256"), 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 { for _, tt := range tests {
t.Run(tt.test, func(_ *testing.T) { t.Run(tt.test, func(_ *testing.T) {
url, err := b64toMinIOStringURL(tt.args.encodedURL) url, err := checkMinIOStringURL(tt.args.encodedURL)
if tt.wantError != nil { if tt.wantError != nil {
if err != nil { if err != nil {
if err.Error() != *tt.wantError { 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 return
} }
} else { } 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 return
} }
} else { } else {
if err != nil { 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 return
} }
tAssert.Equal(*tt.expected, *url) tAssert.Equal(*tt.expected, *url)

View File

@@ -27,7 +27,6 @@ import (
saApi "github.com/minio/console/api/operations/service_account" saApi "github.com/minio/console/api/operations/service_account"
userApi "github.com/minio/console/api/operations/user" userApi "github.com/minio/console/api/operations/user"
"github.com/minio/console/models" "github.com/minio/console/models"
"github.com/minio/console/pkg/utils"
"github.com/minio/madmin-go/v3" "github.com/minio/madmin-go/v3"
iampolicy "github.com/minio/pkg/v3/policy" 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 // create a MinIO user Admin Client interface implementation
// defining the client to be used // defining the client to be used
userAdminClient := AdminClient{Client: userAdmin} userAdminClient := AdminClient{Client: userAdmin}
name, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
var expiry *time.Time var expiry *time.Time
if params.Body.Expiry != "" { if params.Body.Expiry != "" {
@@ -212,7 +207,7 @@ func getCreateAUserServiceAccountResponse(session *models.Principal, params user
} }
expiry = &parsedExpiry 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 { if err != nil {
return nil, ErrorWithContext(ctx, err) return nil, ErrorWithContext(ctx, err)
} }
@@ -233,14 +228,10 @@ func getCreateAUserServiceAccountCredsResponse(session *models.Principal, params
// defining the client to be used // defining the client to be used
userAdminClient := AdminClient{Client: userAdmin} userAdminClient := AdminClient{Client: userAdmin}
serviceAccount := params.Body serviceAccount := params.Body
user, err := utils.DecodeBase64(params.Name) if params.Name == serviceAccount.AccessKey {
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
if user == serviceAccount.AccessKey {
return nil, ErrorWithContext(ctx, errors.New("Access Key already in use")) 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 { if err != nil {
return nil, ErrorWithContext(ctx, err) return nil, ErrorWithContext(ctx, err)
} }
@@ -258,7 +249,7 @@ func getCreateAUserServiceAccountCredsResponse(session *models.Principal, params
} }
expiry = &parsedExpiry 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 { if err != nil {
return nil, ErrorWithContext(ctx, err) 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 // create a MinIO user Admin Client interface implementation
// defining the client to be used // defining the client to be used
userAdminClient := AdminClient{Client: userAdmin} userAdminClient := AdminClient{Client: userAdmin}
user, err = utils.DecodeBase64(user)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
serviceAccounts, err := getUserServiceAccounts(ctx, userAdminClient, user) serviceAccounts, err := getUserServiceAccounts(ctx, userAdminClient, user)
if err != nil { if err != nil {
return nil, ErrorWithContext(ctx, err) 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 { func getDeleteServiceAccountResponse(session *models.Principal, params saApi.DeleteServiceAccountParams) *CodedAPIError {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context()) ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel() defer cancel()
accessKey, err := utils.DecodeBase64(params.AccessKey)
if err != nil {
return ErrorWithContext(ctx, err)
}
userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session) userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil { if err != nil {
return ErrorWithContext(ctx, err) return ErrorWithContext(ctx, err)
@@ -397,7 +380,7 @@ func getDeleteServiceAccountResponse(session *models.Principal, params saApi.Del
// create a MinIO user Admin Client interface implementation // create a MinIO user Admin Client interface implementation
// defining the client to be used // defining the client to be used
userAdminClient := AdminClient{Client: userAdmin} 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 ErrorWithContext(ctx, err)
} }
return nil 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) { func getServiceAccountInfo(session *models.Principal, params saApi.GetServiceAccountParams) (*models.ServiceAccount, *CodedAPIError) {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context()) ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel() defer cancel()
accessKey, err := utils.DecodeBase64(params.AccessKey)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session) userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil { if err != nil {
return nil, ErrorWithContext(ctx, err) return nil, ErrorWithContext(ctx, err)
@@ -453,7 +432,7 @@ func getServiceAccountInfo(session *models.Principal, params saApi.GetServiceAcc
// defining the client to be used // defining the client to be used
userAdminClient := AdminClient{Client: userAdmin} userAdminClient := AdminClient{Client: userAdmin}
serviceAccount, err := getServiceAccountDetails(ctx, userAdminClient, accessKey) serviceAccount, err := getServiceAccountDetails(ctx, userAdminClient, params.AccessKey)
if err != nil { if err != nil {
return nil, ErrorWithContext(ctx, err) 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 { func updateSetServiceAccountResponse(session *models.Principal, params saApi.UpdateServiceAccountParams) *CodedAPIError {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context()) ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel() defer cancel()
accessKey, err := utils.DecodeBase64(params.AccessKey)
if err != nil {
return ErrorWithContext(ctx, err)
}
policy := *params.Body.Policy policy := *params.Body.Policy
userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session) userAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
if err != nil { if err != nil {
@@ -502,7 +477,7 @@ func updateSetServiceAccountResponse(session *models.Principal, params saApi.Upd
} }
expiry = &parsedExpiry 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 { if err != nil {
return ErrorWithContext(ctx, err) return ErrorWithContext(ctx, err)
} }

View File

@@ -18,7 +18,6 @@ package api
import ( import (
"context" "context"
"encoding/base64"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@@ -1014,12 +1013,7 @@ func getBucketRewindResponse(session *models.Principal, params bucketApi.GetBuck
defer cancel() defer cancel()
prefix := "" prefix := ""
if params.Prefix != nil { if params.Prefix != nil {
encodedPrefix := SanitizeEncodedPrefix(*params.Prefix) prefix = *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, getClientIP(params.HTTPRequest)) s3Client, err := newS3BucketClient(session, params.BucketName, prefix, getClientIP(params.HTTPRequest))
if err != nil { if err != nil {

View File

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

View File

@@ -942,7 +942,7 @@ func Test_shareObject(t *testing.T) {
}, },
wantError: nil, 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", test: "return https scheme if url uses TLS",
@@ -959,7 +959,7 @@ func Test_shareObject(t *testing.T) {
}, },
wantError: nil, 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", test: "returns invalid expire duration if expiration is invalid",
@@ -990,7 +990,7 @@ func Test_shareObject(t *testing.T) {
}, },
}, },
wantError: nil, 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", test: "return error if sharefunc returns error",
@@ -1022,7 +1022,7 @@ func Test_shareObject(t *testing.T) {
}, },
}, },
wantError: nil, 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", 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, 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", 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, 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 return
} }
} else { } else {
tAssert.Equal(*url, tt.expected) tAssert.Equal(tt.expected, *url)
} }
}) })
} }

View File

@@ -211,11 +211,6 @@ func ValidateEncodedStyles(encodedStyles string) error {
return nil 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{ var safeMimeTypes = []string{
"image/jpeg", "image/jpeg",
"image/apng", "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) { func Test_isSafeToPreview(t *testing.T) {
type args struct { type args struct {
str string 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 ( import (
"bytes" "bytes"
b64 "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@@ -36,14 +35,6 @@ import (
var token string 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 { func inspectHTTPResponse(httpResponse *http.Response) string {
/* /*
Helper function to inspect the content of a HTTP response. Helper function to inspect the content of a HTTP response.

View File

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

View File

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

View File

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

View File

@@ -18,11 +18,11 @@ package integration
import ( import (
"bytes" "bytes"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"net/url"
"testing" "testing"
"time" "time"
@@ -92,7 +92,7 @@ func TestAddServiceAccount(t *testing.T) {
// {{baseUrl}}/user?name=proident velit // {{baseUrl}}/user?name=proident velit
// Investiga como se borra en el browser. // Investiga como se borra en el browser.
request, err = http.NewRequest( 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 { if err != nil {
log.Println(err) log.Println(err)
return return

View File

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

View File

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

View File

@@ -18,18 +18,8 @@ package utils
import ( import (
"context" "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 // Key used for Get/SetReqInfo
type key string type key string

View File

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

View File

@@ -1,26 +1,13 @@
rules: 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 - id: js-func-encode-uri
patterns: patterns:
- pattern: encodeURI($X) - pattern: encodeURI($X)
message: Use encodeURLString() instead of encodeURI() message: Use encodeURIComponent() instead of encodeURI()
languages: languages:
- typescript - typescript
- javascript - javascript
severity: WARNING severity: WARNING
fix: encodeURLString($X) fix: encodeURIComponent($X)
- id: js-dangerous-func-document-write - id: js-dangerous-func-document-write
patterns: patterns:
- pattern: document.write(...) - pattern: document.write(...)

View File

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

View File

@@ -467,38 +467,6 @@ export const representationNumber = (number: number | undefined) => {
/** Ref https://developer.mozilla.org/en-US/docs/Glossary/Base64 */ /** 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) => { export const performDownload = (blob: Blob, fileName: string) => {
const link = document.createElement("a"); const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob); link.href = window.URL.createObjectURL(blob);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,7 +18,6 @@ import React, { Fragment, useCallback, useEffect, useState } from "react";
import { ProgressBar, Grid, Box, InformativeMessage } from "mds"; import { ProgressBar, Grid, Box, InformativeMessage } from "mds";
import get from "lodash/get"; import get from "lodash/get";
import { AllowedPreviews, previewObjectType } from "../utils"; import { AllowedPreviews, previewObjectType } from "../utils";
import { encodeURLString } from "../../../../../../common/utils";
import { api } from "../../../../../../api"; import { api } from "../../../../../../api";
import PreviewPDF from "./PreviewPDF"; import PreviewPDF from "./PreviewPDF";
import { downloadObject } from "../../../../ObjectBrowser/utils"; import { downloadObject } from "../../../../ObjectBrowser/utils";
@@ -47,10 +46,9 @@ const PreviewFile = ({
const fetchMetadata = useCallback(() => { const fetchMetadata = useCallback(() => {
if (!isMetaDataLoaded) { if (!isMetaDataLoaded) {
const encodedPath = encodeURLString(objectName);
api.buckets api.buckets
.getObjectMetadata(bucketName, { .getObjectMetadata(bucketName, {
prefix: encodedPath, prefix: objectName,
versionID: actualInfo.version_id || "", versionID: actualInfo.version_id || "",
}) })
.then((res) => { .then((res) => {
@@ -78,9 +76,8 @@ const PreviewFile = ({
let path = ""; let path = "";
if (actualInfo) { if (actualInfo) {
const encodedPath = encodeURLString(actualInfo.name || "");
let basename = document.baseURI.replace(window.location.origin, ""); 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) { if (actualInfo.version_id) {
path = path.concat(`&version_id=${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/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
import { BucketObjectItem } from "./ListObjects/types"; import { BucketObjectItem } from "./ListObjects/types";
import { decodeURLString, encodeURLString } from "../../../../../common/utils";
import { removeTrace } from "../../../ObjectBrowser/transferManager"; import { removeTrace } from "../../../ObjectBrowser/transferManager";
import store from "../../../../../store"; import store from "../../../../../store";
import { ContentType, PermissionResource } from "api/consoleApi"; import { ContentType, PermissionResource } from "api/consoleApi";
@@ -66,7 +65,7 @@ export const downloadSelectedAsZip = async (
}; };
const isFolder = (objectPath: string) => { const isFolder = (objectPath: string) => {
return decodeURLString(objectPath).endsWith("/"); return objectPath.endsWith("/");
}; };
export const download = ( export const download = (
@@ -88,9 +87,9 @@ export const download = (
let path = `${ let path = `${
window.location.origin 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() !== "" overrideFileName !== null && overrideFileName.trim() !== ""
? `&override_file_name=${encodeURLString(overrideFileName || "")}` ? `&override_file_name=${encodeURIComponent(overrideFileName || "")}`
: "" : ""
}`; }`;
if (versionID) { if (versionID) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License // 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/>. // 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 { makeid, storeCallForObjectWithID } from "./transferManager";
import { download } from "../Buckets/ListBuckets/Objects/utils"; import { download } from "../Buckets/ListBuckets/Objects/utils";
import { import {
@@ -35,7 +35,7 @@ export const downloadObject = (
internalPaths: string, internalPaths: string,
object: BucketObject, object: BucketObject,
) => { ) => {
const identityDownload = encodeURLString( const identityDownload = encodeURIComponent(
`${bucketName}-${object.name}-${new Date().getTime()}-${Math.random()}`, `${bucketName}-${object.name}-${new Date().getTime()}-${Math.random()}`,
); );

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,7 +31,6 @@ import { useNavigate } from "react-router-dom";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { import {
deleteCookie, deleteCookie,
encodeURLString,
getCookieValue, getCookieValue,
performDownload, performDownload,
} from "../../../common/utils"; } from "../../../common/utils";
@@ -143,11 +142,8 @@ const Inspect = () => {
}; };
const performInspect = async () => { const performInspect = async () => {
const file = encodeURLString(inspectPath);
const volume = encodeURLString(volumeName);
let basename = document.baseURI.replace(window.location.origin, ""); 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) makeRequest(urlOfInspectApi)
.then(async (res) => { .then(async (res) => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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