Fixed Delete all object versions selector functionality (#2516)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2022-12-16 11:07:40 -06:00
committed by GitHub
parent 1f60d4a808
commit 35541ef323
5 changed files with 100 additions and 44 deletions

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useState } from "react";
import React, { Fragment, useState } from "react";
import { DialogContentText } from "@mui/material";
import { ErrorResponseHandler } from "../../../../../../common/types";
@@ -96,18 +96,42 @@ const DeleteObject = ({
Are you sure you want to delete the selected {selectedObjects.length}{" "}
objects?{" "}
{versioning && (
<FormSwitchWrapper
label={"Delete All Versions"}
indicatorLabels={["Yes", "No"]}
checked={deleteVersions}
value={"delete_versions"}
id="delete-versions"
name="delete-versions"
onChange={(e) => {
setDeleteVersions(!deleteVersions);
}}
description=""
/>
<Fragment>
<br />
<br />
<FormSwitchWrapper
label={"Delete All Versions"}
indicatorLabels={["Yes", "No"]}
checked={deleteVersions}
value={"delete_versions"}
id="delete-versions"
name="delete-versions"
onChange={(e) => {
setDeleteVersions(!deleteVersions);
}}
description=""
/>
{deleteVersions && (
<Fragment>
<div
style={{
marginTop: 10,
border: "#c83b51 1px solid",
borderRadius: 3,
padding: 5,
backgroundColor: "#c83b5120",
color: "#c83b51",
}}
>
This will remove the objects as well as all of their
versions, <br />
This action is irreversible.
</div>
<br />
Are you sure you want to continue?
</Fragment>
)}
</Fragment>
)}
</DialogContentText>
}

View File

@@ -81,7 +81,11 @@ const DeleteObject = ({
onConfirm={onConfirmDelete}
onClose={onClose}
confirmationContent={
<DialogContentText>
<DialogContentText
sx={{
width: "430px",
}}
>
Are you sure you want to delete: <br />
<b>{decodeURLString(selectedObject)}</b>{" "}
{selectedVersion !== "" ? (
@@ -98,18 +102,40 @@ const DeleteObject = ({
? <br />
<br />
{versioning && selectedVersion === "" && (
<FormSwitchWrapper
label={"Delete All Versions"}
indicatorLabels={["Yes", "No"]}
checked={deleteVersions}
value={"delete_versions"}
id="delete-versions"
name="delete-versions"
onChange={(e) => {
setDeleteVersions(!deleteVersions);
}}
description=""
/>
<Fragment>
<FormSwitchWrapper
label={"Delete All Versions"}
indicatorLabels={["Yes", "No"]}
checked={deleteVersions}
value={"delete_versions"}
id="delete-versions"
name="delete-versions"
onChange={(e) => {
setDeleteVersions(!deleteVersions);
}}
description=""
/>
{deleteVersions && (
<Fragment>
<div
style={{
marginTop: 10,
border: "#c83b51 1px solid",
borderRadius: 3,
padding: 5,
backgroundColor: "#c83b5120",
color: "#c83b51",
}}
>
This will remove the object as well as all of its versions,{" "}
<br />
This action is irreversible.
</div>
<br />
Are you sure you want to continue?
</Fragment>
)}
</Fragment>
)}
</DialogContentText>
}

View File

@@ -228,7 +228,7 @@ type MCClient interface {
addNotificationConfig(ctx context.Context, arn string, events []string, prefix, suffix string, ignoreExisting bool) *probe.Error
removeNotificationConfig(ctx context.Context, arn string, event string, prefix string, suffix string) *probe.Error
watch(ctx context.Context, options mc.WatchOptions) (*mc.WatchObject, *probe.Error)
remove(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult
remove(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult
list(ctx context.Context, opts mc.ListOptions) <-chan *mc.ClientContent
get(ctx context.Context, opts mc.GetOptions) (io.ReadCloser, *probe.Error)
shareDownload(ctx context.Context, versionID string, expires time.Duration) (string, *probe.Error)
@@ -269,8 +269,8 @@ func (c mcClient) setVersioning(ctx context.Context, status string) *probe.Error
return c.client.SetVersion(ctx, status, []string{}, false)
}
func (c mcClient) remove(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
return c.client.Remove(ctx, isIncomplete, isRemoveBucket, isBypass, false, contentCh)
func (c mcClient) remove(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
return c.client.Remove(ctx, isIncomplete, isRemoveBucket, isBypass, forceDelete, contentCh)
}
func (c mcClient) list(ctx context.Context, opts mc.ListOptions) <-chan *mc.ClientContent {

View File

@@ -664,7 +664,7 @@ func deleteObjects(ctx context.Context, client MCClient, bucket string, path str
return deleteNonCurrentVersions(ctx, client, bucket, path)
}
if recursive {
if recursive || allVersions {
return deleteMultipleObjects(ctx, client, recursive, allVersions)
}
@@ -675,10 +675,16 @@ func deleteObjects(ctx context.Context, client MCClient, bucket string, path str
//
// Use cases:
// * Remove objects recursively
func deleteMultipleObjects(ctx context.Context, client MCClient, recursive bool, allVersions bool) error {
func deleteMultipleObjects(ctx context.Context, client MCClient, recursive, allVersions bool) error {
isBypass := false
isIncomplete := false
isRemoveBucket := false
forceDelete := false
if recursive || allVersions {
forceDelete = true
}
listOpts := mc.ListOptions{
Recursive: recursive,
Incomplete: isIncomplete,
@@ -707,7 +713,7 @@ func deleteMultipleObjects(ctx context.Context, client MCClient, recursive bool,
}
}()
for result := range client.remove(ctx, isIncomplete, isRemoveBucket, isBypass, contentCh) {
for result := range client.remove(ctx, isIncomplete, isRemoveBucket, isBypass, forceDelete, contentCh) {
if result.Err != nil {
return result.Err.Cause
}
@@ -726,7 +732,7 @@ func deleteSingleObject(ctx context.Context, client MCClient, bucket, object str
isIncomplete := false
isRemoveBucket := false
resultCh := client.remove(ctx, isIncomplete, isRemoveBucket, isBypass, contentCh)
resultCh := client.remove(ctx, isIncomplete, isRemoveBucket, isBypass, false, contentCh)
for result := range resultCh {
if result.Err != nil {
return result.Err.Cause
@@ -767,7 +773,7 @@ func deleteNonCurrentVersions(ctx context.Context, client MCClient, bucket, path
}
}()
for result := range client.remove(ctx, false, false, false, contentCh) {
for result := range client.remove(ctx, false, false, false, false, contentCh) {
if result.Err != nil {
return result.Err.Cause
}

View File

@@ -49,7 +49,7 @@ var (
var (
mcListMock func(ctx context.Context, opts mc.ListOptions) <-chan *mc.ClientContent
mcRemoveMock func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult
mcRemoveMock func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult
mcGetMock func(ctx context.Context, opts mc.GetOptions) (io.ReadCloser, *probe.Error)
mcShareDownloadMock func(ctx context.Context, versionID string, expires time.Duration) (string, *probe.Error)
)
@@ -96,8 +96,8 @@ func (c s3ClientMock) list(ctx context.Context, opts mc.ListOptions) <-chan *mc.
return mcListMock(ctx, opts)
}
func (c s3ClientMock) remove(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
return mcRemoveMock(ctx, isIncomplete, isRemoveBucket, isBypass, contentCh)
func (c s3ClientMock) remove(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
return mcRemoveMock(ctx, isIncomplete, isRemoveBucket, isBypass, forceDelete, contentCh)
}
func (c s3ClientMock) get(ctx context.Context, opts mc.GetOptions) (io.ReadCloser, *probe.Error) {
@@ -595,7 +595,7 @@ func Test_deleteObjects(t *testing.T) {
recursive bool
nonCurrent bool
listFunc func(ctx context.Context, opts mc.ListOptions) <-chan *mc.ClientContent
removeFunc func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult
removeFunc func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult
}
tests := []struct {
test string
@@ -609,7 +609,7 @@ func Test_deleteObjects(t *testing.T) {
versionID: "",
recursive: false,
nonCurrent: false,
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
resultCh := make(chan mc.RemoveResult, 1)
resultCh <- mc.RemoveResult{Err: nil}
close(resultCh)
@@ -625,7 +625,7 @@ func Test_deleteObjects(t *testing.T) {
versionID: "",
recursive: false,
nonCurrent: false,
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
resultCh := make(chan mc.RemoveResult, 1)
resultCh <- mc.RemoveResult{Err: probe.NewError(errors.New("probe error"))}
close(resultCh)
@@ -641,7 +641,7 @@ func Test_deleteObjects(t *testing.T) {
versionID: "",
recursive: true,
nonCurrent: false,
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
resultCh := make(chan mc.RemoveResult, 1)
resultCh <- mc.RemoveResult{Err: nil}
close(resultCh)
@@ -665,7 +665,7 @@ func Test_deleteObjects(t *testing.T) {
versionID: "",
recursive: true,
nonCurrent: false,
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
resultCh := make(chan mc.RemoveResult, 1)
resultCh <- mc.RemoveResult{Err: probe.NewError(errors.New("probe error"))}
close(resultCh)
@@ -687,7 +687,7 @@ func Test_deleteObjects(t *testing.T) {
versionID: "",
recursive: true,
nonCurrent: true,
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
resultCh := make(chan mc.RemoveResult, 1)
resultCh <- mc.RemoveResult{Err: nil}
close(resultCh)
@@ -711,7 +711,7 @@ func Test_deleteObjects(t *testing.T) {
versionID: "",
recursive: true,
nonCurrent: true,
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
removeFunc: func(ctx context.Context, isIncomplete, isRemoveBucket, isBypass, forceDelete bool, contentCh <-chan *mc.ClientContent) <-chan mc.RemoveResult {
resultCh := make(chan mc.RemoveResult, 1)
resultCh <- mc.RemoveResult{Err: probe.NewError(errors.New("probe error"))}
close(resultCh)