mirror of
https://github.com/OpenMaxIO/openmaxio-object-browser
synced 2026-07-01 07:41:18 -07:00
add encoded filename as part of delete api url (#3141)
This commit is contained in:
committed by
GitHub
parent
607d94fef4
commit
6767bfa2d2
@@ -423,8 +423,9 @@ 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
|
||||||
*/
|
*/
|
||||||
url := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects?path=" +
|
prefixEncoded := base64.StdEncoding.EncodeToString([]byte(path))
|
||||||
path + "&recursive=" + strconv.FormatBool(recursive) + "&all_versions=" +
|
url := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects?prefix=" +
|
||||||
|
prefixEncoded + "&recursive=" + strconv.FormatBool(recursive) + "&all_versions=" +
|
||||||
strconv.FormatBool(allVersions)
|
strconv.FormatBool(allVersions)
|
||||||
request, err := http.NewRequest(
|
request, err := http.NewRequest(
|
||||||
"DELETE",
|
"DELETE",
|
||||||
@@ -1639,7 +1640,6 @@ func TestDeleteObject(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
bucketName := "testdeleteobjectbucket1"
|
bucketName := "testdeleteobjectbucket1"
|
||||||
fileName := "testdeleteobjectfile"
|
fileName := "testdeleteobjectfile"
|
||||||
path := "dGVzdGRlbGV0ZW9iamVjdGZpbGUxLnR4dA==" // fileName encoded base64
|
|
||||||
numberOfFiles := 2
|
numberOfFiles := 2
|
||||||
|
|
||||||
// 1. Create bucket
|
// 1. Create bucket
|
||||||
@@ -1662,8 +1662,9 @@ func TestDeleteObject(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
objPathFull := fileName + "1.txt" // would be encoded in DeleteObject util method.
|
||||||
// 3. Delete only one object from the bucket.
|
// 3. Delete only one object from the bucket.
|
||||||
deleteResponse, deleteError := DeleteObject(bucketName, path, false, false)
|
deleteResponse, deleteError := DeleteObject(bucketName, objPathFull, false, false)
|
||||||
assert.Nil(deleteError)
|
assert.Nil(deleteError)
|
||||||
if deleteError != nil {
|
if deleteError != nil {
|
||||||
log.Println(deleteError)
|
log.Println(deleteError)
|
||||||
|
|||||||
@@ -2092,7 +2092,7 @@ export class Api<
|
|||||||
deleteObject: (
|
deleteObject: (
|
||||||
bucketName: string,
|
bucketName: string,
|
||||||
query: {
|
query: {
|
||||||
path: string;
|
prefix: string;
|
||||||
version_id?: string;
|
version_id?: string;
|
||||||
recursive?: boolean;
|
recursive?: boolean;
|
||||||
all_versions?: boolean;
|
all_versions?: boolean;
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import { hasPermission } from "../../../../../../common/SecureComponent";
|
|||||||
import { IAM_SCOPES } from "../../../../../../common/SecureComponent/permissions";
|
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 { encodeURLString } from "../../../../../../common/utils";
|
||||||
|
|
||||||
interface IDeleteObjectProps {
|
interface IDeleteObjectProps {
|
||||||
closeDeleteModalAndRefresh: (refresh: boolean) => void;
|
closeDeleteModalAndRefresh: (refresh: boolean) => void;
|
||||||
@@ -86,13 +88,37 @@ const DeleteObject = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (toSend) {
|
if (toSend) {
|
||||||
invokeDeleteApi(
|
if (selectedObjects.length === 1) {
|
||||||
"POST",
|
const firstObject = selectedObjects[0];
|
||||||
`/api/v1/buckets/${selectedBucket}/delete-objects?all_versions=${deleteVersions}${
|
api.buckets
|
||||||
bypassGovernance ? "&bypass=true" : ""
|
.deleteObject(selectedBucket, {
|
||||||
}`,
|
prefix: encodeURLString(firstObject),
|
||||||
toSend,
|
all_versions: deleteVersions,
|
||||||
);
|
bypass: bypassGovernance,
|
||||||
|
recursive: firstObject.endsWith("/"), //if it is just a prefix
|
||||||
|
})
|
||||||
|
.then(onDelSuccess)
|
||||||
|
.catch((err) => {
|
||||||
|
dispatch(
|
||||||
|
setErrorSnackMessage({
|
||||||
|
errorMessage: `Could not delete object. ${err.statusText}. ${
|
||||||
|
retentionConfig
|
||||||
|
? "Please check retention mode and if object is WORM protected."
|
||||||
|
: ""
|
||||||
|
}`,
|
||||||
|
detailedError: "",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
invokeDeleteApi(
|
||||||
|
"POST",
|
||||||
|
`/api/v1/buckets/${selectedBucket}/delete-objects?all_versions=${deleteVersions}${
|
||||||
|
bypassGovernance ? "&bypass=true" : ""
|
||||||
|
}`,
|
||||||
|
toSend,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ const DeleteNonCurrentVersions = ({
|
|||||||
if (deleteLoading) {
|
if (deleteLoading) {
|
||||||
api.buckets
|
api.buckets
|
||||||
.deleteObject(selectedBucket, {
|
.deleteObject(selectedBucket, {
|
||||||
path: selectedObject,
|
prefix: selectedObject,
|
||||||
non_current_versions: true,
|
non_current_versions: true,
|
||||||
bypass: bypassGovernance,
|
bypass: bypassGovernance,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ const DeleteObject = ({
|
|||||||
const recursive = decodedSelectedObject.endsWith("/");
|
const recursive = decodedSelectedObject.endsWith("/");
|
||||||
invokeDeleteApi(
|
invokeDeleteApi(
|
||||||
"DELETE",
|
"DELETE",
|
||||||
`/api/v1/buckets/${selectedBucket}/objects?path=${selectedObject}${
|
`/api/v1/buckets/${selectedBucket}/objects?prefix=${selectedObject}${
|
||||||
selectedVersion !== ""
|
selectedVersion !== ""
|
||||||
? `&version_id=${selectedVersion}`
|
? `&version_id=${selectedVersion}`
|
||||||
: `&recursive=${recursive}&all_versions=${deleteVersions}`
|
: `&recursive=${recursive}&all_versions=${deleteVersions}`
|
||||||
|
|||||||
@@ -17,11 +17,8 @@
|
|||||||
import * as roles from "../utils/roles";
|
import * as roles from "../utils/roles";
|
||||||
import * as elements from "../utils/elements";
|
import * as elements from "../utils/elements";
|
||||||
import * as functions from "../utils/functions";
|
import * as functions from "../utils/functions";
|
||||||
import { bucketsElement } from "../utils/elements-menu";
|
|
||||||
import { testBucketBrowseButtonFor } from "../utils/functions";
|
import { testBucketBrowseButtonFor } from "../utils/functions";
|
||||||
import { Selector } from "testcafe";
|
import { Selector } from "testcafe";
|
||||||
import * as constants from "../utils/constants";
|
|
||||||
import { deleteAllVersions } from "../utils/elements";
|
|
||||||
|
|
||||||
fixture("For user with Bucket Read & Write permissions").page(
|
fixture("For user with Bucket Read & Write permissions").page(
|
||||||
"http://localhost:9090",
|
"http://localhost:9090",
|
||||||
@@ -45,6 +42,9 @@ test
|
|||||||
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
|
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
|
||||||
.wait(1000);
|
.wait(1000);
|
||||||
})("All versions of an object can be deleted from a bucket", async (t) => {
|
})("All versions of an object can be deleted from a bucket", async (t) => {
|
||||||
|
const versionRows = Selector(
|
||||||
|
"div.ReactVirtualized__Grid.ReactVirtualized__Table__Grid > div > div:nth-child(1)",
|
||||||
|
);
|
||||||
await t
|
await t
|
||||||
.useRole(roles.bucketReadWrite)
|
.useRole(roles.bucketReadWrite)
|
||||||
.navigateTo("http://localhost:9090/browser")
|
.navigateTo("http://localhost:9090/browser")
|
||||||
@@ -55,11 +55,7 @@ test
|
|||||||
.click(elements.deleteButton)
|
.click(elements.deleteButton)
|
||||||
.click(elements.deleteAllVersions)
|
.click(elements.deleteAllVersions)
|
||||||
.click(Selector("button:enabled").withExactText("Delete").nth(1))
|
.click(Selector("button:enabled").withExactText("Delete").nth(1))
|
||||||
.expect(
|
.expect(versionRows.exists)
|
||||||
Selector(
|
|
||||||
"div.ReactVirtualized__Grid.ReactVirtualized__Table__Grid > div > div:nth-child(1)",
|
|
||||||
).exists,
|
|
||||||
)
|
|
||||||
.notOk();
|
.notOk();
|
||||||
})
|
})
|
||||||
.after(async (t) => {
|
.after(async (t) => {
|
||||||
|
|||||||
@@ -1534,7 +1534,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"name": "path",
|
"name": "prefix",
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
@@ -10684,7 +10684,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"name": "path",
|
"name": "prefix",
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ type DeleteObjectParams struct {
|
|||||||
Required: true
|
Required: true
|
||||||
In: query
|
In: query
|
||||||
*/
|
*/
|
||||||
Path string
|
Prefix string
|
||||||
/*
|
/*
|
||||||
In: query
|
In: query
|
||||||
*/
|
*/
|
||||||
@@ -113,8 +113,8 @@ func (o *DeleteObjectParams) BindRequest(r *http.Request, route *middleware.Matc
|
|||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
qPath, qhkPath, _ := qs.GetOK("path")
|
qPrefix, qhkPrefix, _ := qs.GetOK("prefix")
|
||||||
if err := o.bindPath(qPath, qhkPath, route.Formats); err != nil {
|
if err := o.bindPrefix(qPrefix, qhkPrefix, route.Formats); err != nil {
|
||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,10 +216,10 @@ func (o *DeleteObjectParams) bindNonCurrentVersions(rawData []string, hasKey boo
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bindPath binds and validates parameter Path from query.
|
// bindPrefix binds and validates parameter Prefix from query.
|
||||||
func (o *DeleteObjectParams) bindPath(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
func (o *DeleteObjectParams) bindPrefix(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
if !hasKey {
|
if !hasKey {
|
||||||
return errors.Required("path", "query", rawData)
|
return errors.Required("prefix", "query", rawData)
|
||||||
}
|
}
|
||||||
var raw string
|
var raw string
|
||||||
if len(rawData) > 0 {
|
if len(rawData) > 0 {
|
||||||
@@ -229,10 +229,10 @@ func (o *DeleteObjectParams) bindPath(rawData []string, hasKey bool, formats str
|
|||||||
// Required: true
|
// Required: true
|
||||||
// AllowEmptyValue: false
|
// AllowEmptyValue: false
|
||||||
|
|
||||||
if err := validate.RequiredString("path", "query", raw); err != nil {
|
if err := validate.RequiredString("prefix", "query", raw); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.Path = raw
|
o.Prefix = raw
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ type DeleteObjectURL struct {
|
|||||||
AllVersions *bool
|
AllVersions *bool
|
||||||
Bypass *bool
|
Bypass *bool
|
||||||
NonCurrentVersions *bool
|
NonCurrentVersions *bool
|
||||||
Path string
|
Prefix string
|
||||||
Recursive *bool
|
Recursive *bool
|
||||||
VersionID *string
|
VersionID *string
|
||||||
|
|
||||||
@@ -107,9 +107,9 @@ func (o *DeleteObjectURL) Build() (*url.URL, error) {
|
|||||||
qs.Set("non_current_versions", nonCurrentVersionsQ)
|
qs.Set("non_current_versions", nonCurrentVersionsQ)
|
||||||
}
|
}
|
||||||
|
|
||||||
pathQ := o.Path
|
prefixQ := o.Prefix
|
||||||
if pathQ != "" {
|
if prefixQ != "" {
|
||||||
qs.Set("path", pathQ)
|
qs.Set("prefix", prefixQ)
|
||||||
}
|
}
|
||||||
|
|
||||||
var recursiveQ string
|
var recursiveQ string
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ func registerObjectsHandlers(api *operations.ConsoleAPI) {
|
|||||||
})
|
})
|
||||||
// delete object
|
// delete object
|
||||||
api.ObjectDeleteObjectHandler = objectApi.DeleteObjectHandlerFunc(func(params objectApi.DeleteObjectParams, session *models.Principal) middleware.Responder {
|
api.ObjectDeleteObjectHandler = objectApi.DeleteObjectHandlerFunc(func(params objectApi.DeleteObjectParams, session *models.Principal) middleware.Responder {
|
||||||
|
fmt.Println("ObjectDeleteObjectHandler", params.Prefix)
|
||||||
if err := getDeleteObjectResponse(session, params); err != nil {
|
if err := getDeleteObjectResponse(session, params); err != nil {
|
||||||
return objectApi.NewDeleteObjectDefault(err.Code).WithPayload(err.APIError)
|
return objectApi.NewDeleteObjectDefault(err.Code).WithPayload(err.APIError)
|
||||||
}
|
}
|
||||||
@@ -70,6 +71,8 @@ func registerObjectsHandlers(api *operations.ConsoleAPI) {
|
|||||||
})
|
})
|
||||||
// delete multiple objects
|
// delete multiple objects
|
||||||
api.ObjectDeleteMultipleObjectsHandler = objectApi.DeleteMultipleObjectsHandlerFunc(func(params objectApi.DeleteMultipleObjectsParams, session *models.Principal) middleware.Responder {
|
api.ObjectDeleteMultipleObjectsHandler = objectApi.DeleteMultipleObjectsHandlerFunc(func(params objectApi.DeleteMultipleObjectsParams, session *models.Principal) middleware.Responder {
|
||||||
|
fmt.Println("ObjectDeleteMultipleObjectsHandler", params)
|
||||||
|
|
||||||
if err := getDeleteMultiplePathsResponse(session, params); err != nil {
|
if err := getDeleteMultiplePathsResponse(session, params); err != nil {
|
||||||
return objectApi.NewDeleteMultipleObjectsDefault(err.Code).WithPayload(err.APIError)
|
return objectApi.NewDeleteMultipleObjectsDefault(err.Code).WithPayload(err.APIError)
|
||||||
}
|
}
|
||||||
@@ -764,8 +767,8 @@ func getDeleteObjectResponse(session *models.Principal, params objectApi.DeleteO
|
|||||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
var prefix string
|
var prefix string
|
||||||
if params.Path != "" {
|
if params.Prefix != "" {
|
||||||
encodedPrefix := SanitizeEncodedPrefix(params.Path)
|
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
|
||||||
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
|
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrorWithContext(ctx, err)
|
return ErrorWithContext(ctx, err)
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ paths:
|
|||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
- name: path
|
- name: prefix
|
||||||
in: query
|
in: query
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
Reference in New Issue
Block a user