improve versioning status display and delete with versions when versioning is suspended (#2689)
This commit is contained in:
committed by
GitHub
parent
c700ee491e
commit
b8e14ee269
@@ -2289,16 +2289,21 @@ func TestBucketVersioning(t *testing.T) {
|
||||
200, getVersioningResult.StatusCode, "Status Code is incorrect")
|
||||
}
|
||||
bodyBytes, _ := ioutil.ReadAll(getVersioningResult.Body)
|
||||
structBucketRepl := models.BucketVersioningResponse{}
|
||||
structBucketRepl := models.BucketVersioningResponse{
|
||||
ExcludeFolders: false,
|
||||
ExcludedPrefixes: nil,
|
||||
MFADelete: "",
|
||||
Status: "",
|
||||
}
|
||||
err = json.Unmarshal(bodyBytes, &structBucketRepl)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
assert.Nil(err)
|
||||
}
|
||||
assert.Equal(
|
||||
structBucketRepl.IsVersioned,
|
||||
true,
|
||||
structBucketRepl.IsVersioned,
|
||||
structBucketRepl.Status,
|
||||
"Enabled",
|
||||
structBucketRepl.Status,
|
||||
)
|
||||
|
||||
fmt.Println("Versioned bucket creation test status:", response.Status)
|
||||
@@ -3045,7 +3050,7 @@ func TestSetBucketVersioning(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
// 2. Set versioning as False
|
||||
// 2. Set versioning as False i.e Suspend versioning
|
||||
response, err := SetBucketVersioning(bucket, false, nil, nil)
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
@@ -3069,13 +3074,18 @@ func TestSetBucketVersioning(t *testing.T) {
|
||||
200, getVersioningResult.StatusCode, "Status Code is incorrect")
|
||||
}
|
||||
bodyBytes, _ := ioutil.ReadAll(getVersioningResult.Body)
|
||||
result := models.BucketVersioningResponse{}
|
||||
result := models.BucketVersioningResponse{
|
||||
ExcludeFolders: false,
|
||||
ExcludedPrefixes: nil,
|
||||
MFADelete: "",
|
||||
Status: "",
|
||||
}
|
||||
err = json.Unmarshal(bodyBytes, &result)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
assert.Nil(err)
|
||||
}
|
||||
assert.Equal(false, result.IsVersioned, result)
|
||||
assert.Equal("Suspended", result.Status, result)
|
||||
}
|
||||
|
||||
func EnableBucketEncryption(bucketName, encType, kmsKeyID string) (*http.Response, error) {
|
||||
|
||||
@@ -24,7 +24,9 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
@@ -34,17 +36,90 @@ import (
|
||||
// swagger:model bucketVersioningResponse
|
||||
type BucketVersioningResponse struct {
|
||||
|
||||
// is versioned
|
||||
IsVersioned bool `json:"is_versioned,omitempty"`
|
||||
// exclude folders
|
||||
ExcludeFolders bool `json:"ExcludeFolders,omitempty"`
|
||||
|
||||
// excluded prefixes
|
||||
ExcludedPrefixes []*BucketVersioningResponseExcludedPrefixesItems0 `json:"ExcludedPrefixes"`
|
||||
|
||||
// m f a delete
|
||||
MFADelete string `json:"MFADelete,omitempty"`
|
||||
|
||||
// status
|
||||
Status string `json:"Status,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this bucket versioning response
|
||||
func (m *BucketVersioningResponse) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateExcludedPrefixes(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this bucket versioning response based on context it is used
|
||||
func (m *BucketVersioningResponse) validateExcludedPrefixes(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.ExcludedPrefixes) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(m.ExcludedPrefixes); i++ {
|
||||
if swag.IsZero(m.ExcludedPrefixes[i]) { // not required
|
||||
continue
|
||||
}
|
||||
|
||||
if m.ExcludedPrefixes[i] != nil {
|
||||
if err := m.ExcludedPrefixes[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("ExcludedPrefixes" + "." + strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("ExcludedPrefixes" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this bucket versioning response based on the context it is used
|
||||
func (m *BucketVersioningResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.contextValidateExcludedPrefixes(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BucketVersioningResponse) contextValidateExcludedPrefixes(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
for i := 0; i < len(m.ExcludedPrefixes); i++ {
|
||||
|
||||
if m.ExcludedPrefixes[i] != nil {
|
||||
if err := m.ExcludedPrefixes[i].ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("ExcludedPrefixes" + "." + strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("ExcludedPrefixes" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -65,3 +140,40 @@ func (m *BucketVersioningResponse) UnmarshalBinary(b []byte) error {
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
// BucketVersioningResponseExcludedPrefixesItems0 bucket versioning response excluded prefixes items0
|
||||
//
|
||||
// swagger:model BucketVersioningResponseExcludedPrefixesItems0
|
||||
type BucketVersioningResponseExcludedPrefixesItems0 struct {
|
||||
|
||||
// prefix
|
||||
Prefix string `json:"Prefix,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this bucket versioning response excluded prefixes items0
|
||||
func (m *BucketVersioningResponseExcludedPrefixesItems0) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this bucket versioning response excluded prefixes items0 based on context it is used
|
||||
func (m *BucketVersioningResponseExcludedPrefixesItems0) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *BucketVersioningResponseExcludedPrefixesItems0) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *BucketVersioningResponseExcludedPrefixesItems0) UnmarshalBinary(b []byte) error {
|
||||
var res BucketVersioningResponseExcludedPrefixesItems0
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ import { decodeURLString, encodeURLString } from "../../../../common/utils";
|
||||
import { permissionItems } from "../ListBuckets/Objects/utils";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import api from "../../../../common/api";
|
||||
import { BucketObjectLocking, BucketVersioning } from "../types";
|
||||
import { BucketObjectLocking, BucketVersioningInfo } from "../types";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import OBHeader from "../../ObjectBrowser/OBHeader";
|
||||
|
||||
@@ -401,8 +401,8 @@ const BrowserHandler = () => {
|
||||
if (displayListObjects) {
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets/${bucketName}/versioning`)
|
||||
.then((res: BucketVersioning) => {
|
||||
dispatch(setIsVersioned(res.is_versioned));
|
||||
.then((res: BucketVersioningInfo) => {
|
||||
dispatch(setIsVersioned(res));
|
||||
dispatch(setLoadingVersioning(false));
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
BucketObjectLocking,
|
||||
BucketQuota,
|
||||
BucketReplication,
|
||||
BucketVersioning,
|
||||
BucketVersioningInfo,
|
||||
} from "../types";
|
||||
import { BucketList } from "../../Watch/types";
|
||||
import {
|
||||
@@ -61,6 +61,7 @@ import {
|
||||
setBucketDetailsLoad,
|
||||
} from "./bucketDetailsSlice";
|
||||
import { useAppDispatch } from "../../../../store";
|
||||
import VersioningInfo from "../VersioningInfo";
|
||||
|
||||
const SetAccessPolicy = withSuspense(
|
||||
React.lazy(() => import("./SetAccessPolicy"))
|
||||
@@ -121,7 +122,7 @@ const BucketSummary = ({ classes }: IBucketSummaryProps) => {
|
||||
const [loadingQuota, setLoadingQuota] = useState<boolean>(true);
|
||||
const [loadingReplication, setLoadingReplication] = useState<boolean>(true);
|
||||
const [loadingRetention, setLoadingRetention] = useState<boolean>(true);
|
||||
const [isVersioned, setIsVersioned] = useState<boolean>(false);
|
||||
const [versioningInfo, setVersioningInfo] = useState<BucketVersioningInfo>();
|
||||
const [quotaEnabled, setQuotaEnabled] = useState<boolean>(false);
|
||||
const [quota, setQuota] = useState<BucketQuota | null>(null);
|
||||
const [encryptionEnabled, setEncryptionEnabled] = useState<boolean>(false);
|
||||
@@ -203,8 +204,8 @@ const BucketSummary = ({ classes }: IBucketSummaryProps) => {
|
||||
if (loadingVersioning && distributedSetup) {
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets/${bucketName}/versioning`)
|
||||
.then((res: BucketVersioning) => {
|
||||
setIsVersioned(res.is_versioned);
|
||||
.then((res: BucketVersioningInfo) => {
|
||||
setVersioningInfo(res);
|
||||
setLoadingVersioning(false);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
@@ -370,6 +371,15 @@ const BucketSummary = ({ classes }: IBucketSummaryProps) => {
|
||||
loadAllBucketData();
|
||||
}
|
||||
};
|
||||
|
||||
let versioningStatus = versioningInfo?.Status;
|
||||
let versioningText = "Unversioned (Default)";
|
||||
if (versioningStatus === "Enabled") {
|
||||
versioningText = "Versioned";
|
||||
} else if (versioningStatus === "Suspended") {
|
||||
versioningText = "Suspended";
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
return (
|
||||
<Fragment>
|
||||
@@ -412,7 +422,7 @@ const BucketSummary = ({ classes }: IBucketSummaryProps) => {
|
||||
closeVersioningModalAndRefresh={closeEnableVersioning}
|
||||
modalOpen={enableVersioningOpen}
|
||||
selectedBucket={bucketName}
|
||||
versioningCurrentState={isVersioned}
|
||||
versioningInfo={versioningInfo}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -576,10 +586,27 @@ const BucketSummary = ({ classes }: IBucketSummaryProps) => {
|
||||
]}
|
||||
resourceName={bucketName}
|
||||
property={"Current Status:"}
|
||||
value={isVersioned ? "Versioned" : "Unversioned (Default)"}
|
||||
value={
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
textDecorationStyle: "normal",
|
||||
placeItems: "flex-start",
|
||||
justifyItems: "flex-start",
|
||||
gap: 3,
|
||||
}}
|
||||
>
|
||||
<div> {versioningText}</div>
|
||||
</Box>
|
||||
}
|
||||
onEdit={setBucketVersioning}
|
||||
isLoading={loadingVersioning}
|
||||
/>
|
||||
|
||||
{versioningInfo?.Status === "Enabled" ? (
|
||||
<VersioningInfo versioningState={versioningInfo} />
|
||||
) : null}
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
@@ -24,20 +24,24 @@ import { ConfirmModalIcon } from "mds";
|
||||
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { useAppDispatch } from "../../../../store";
|
||||
import { BucketVersioningInfo } from "../types";
|
||||
import VersioningInfo from "../VersioningInfo";
|
||||
|
||||
interface IVersioningEventProps {
|
||||
closeVersioningModalAndRefresh: (refresh: boolean) => void;
|
||||
modalOpen: boolean;
|
||||
selectedBucket: string;
|
||||
versioningCurrentState: boolean;
|
||||
versioningInfo: BucketVersioningInfo | undefined;
|
||||
}
|
||||
|
||||
const EnableVersioningModal = ({
|
||||
closeVersioningModalAndRefresh,
|
||||
modalOpen,
|
||||
selectedBucket,
|
||||
versioningCurrentState,
|
||||
versioningInfo = {},
|
||||
}: IVersioningEventProps) => {
|
||||
const isVersioningEnabled = versioningInfo.Status === "Enabled";
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const [versioningLoading, setVersioningLoading] = useState<boolean>(false);
|
||||
|
||||
@@ -49,7 +53,7 @@ const EnableVersioningModal = ({
|
||||
|
||||
api
|
||||
.invoke("PUT", `/api/v1/buckets/${selectedBucket}/versioning`, {
|
||||
versioning: !versioningCurrentState,
|
||||
versioning: !isVersioningEnabled,
|
||||
})
|
||||
.then(() => {
|
||||
setVersioningLoading(false);
|
||||
@@ -64,7 +68,7 @@ const EnableVersioningModal = ({
|
||||
return (
|
||||
<ConfirmDialog
|
||||
title={`Versioning on Bucket`}
|
||||
confirmText={versioningCurrentState ? "Disable" : "Enable"}
|
||||
confirmText={isVersioningEnabled ? "Suspend" : "Enable"}
|
||||
isOpen={modalOpen}
|
||||
isLoading={versioningLoading}
|
||||
titleIcon={<ConfirmModalIcon />}
|
||||
@@ -78,15 +82,24 @@ const EnableVersioningModal = ({
|
||||
confirmationContent={
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Are you sure you want to{" "}
|
||||
<strong>{versioningCurrentState ? "disable" : "enable"}</strong>{" "}
|
||||
<strong>{isVersioningEnabled ? "suspend" : "enable"}</strong>{" "}
|
||||
versioning for this bucket?
|
||||
{versioningCurrentState && (
|
||||
{isVersioningEnabled && (
|
||||
<Fragment>
|
||||
<br />
|
||||
<br />
|
||||
<strong>File versions won't be automatically deleted.</strong>
|
||||
</Fragment>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
paddingTop: "20px",
|
||||
}}
|
||||
>
|
||||
{isVersioningEnabled ? (
|
||||
<VersioningInfo versioningState={versioningInfo} />
|
||||
) : null}
|
||||
</div>
|
||||
</DialogContentText>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -28,6 +28,7 @@ import { AppState, useAppDispatch } from "../../../../../../store";
|
||||
import { hasPermission } from "../../../../../../common/SecureComponent";
|
||||
import { IAM_SCOPES } from "../../../../../../common/SecureComponent/permissions";
|
||||
import { useSelector } from "react-redux";
|
||||
import { BucketVersioningInfo } from "../../../types";
|
||||
|
||||
interface IDeleteObjectProps {
|
||||
closeDeleteModalAndRefresh: (refresh: boolean) => void;
|
||||
@@ -35,7 +36,7 @@ interface IDeleteObjectProps {
|
||||
selectedObjects: string[];
|
||||
selectedBucket: string;
|
||||
|
||||
versioning: boolean;
|
||||
versioning: BucketVersioningInfo;
|
||||
}
|
||||
|
||||
const DeleteObject = ({
|
||||
@@ -99,6 +100,9 @@ const DeleteObject = ({
|
||||
}
|
||||
};
|
||||
|
||||
const isVersionedDelete =
|
||||
versioning?.Status === "Enabled" || versioning?.Status === "Suspended";
|
||||
|
||||
return (
|
||||
<ConfirmDialog
|
||||
title={`Delete Objects`}
|
||||
@@ -112,7 +116,7 @@ const DeleteObject = ({
|
||||
<DialogContentText>
|
||||
Are you sure you want to delete the selected {selectedObjects.length}{" "}
|
||||
objects?{" "}
|
||||
{versioning && (
|
||||
{isVersionedDelete && (
|
||||
<Fragment>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
@@ -29,6 +29,8 @@ import { AppState, useAppDispatch } from "../../../../../../store";
|
||||
import { hasPermission } from "../../../../../../common/SecureComponent";
|
||||
import { IAM_SCOPES } from "../../../../../../common/SecureComponent/permissions";
|
||||
import { useSelector } from "react-redux";
|
||||
import { BucketVersioningInfo } from "../../../types";
|
||||
import { isVersionedMode } from "../../../../../../utils/validationFunctions";
|
||||
|
||||
interface IDeleteObjectProps {
|
||||
closeDeleteModalAndRefresh: (refresh: boolean) => void;
|
||||
@@ -36,7 +38,7 @@ interface IDeleteObjectProps {
|
||||
selectedObject: string;
|
||||
selectedBucket: string;
|
||||
|
||||
versioning: boolean;
|
||||
versioningInfo: BucketVersioningInfo | undefined;
|
||||
selectedVersion?: string;
|
||||
}
|
||||
|
||||
@@ -45,7 +47,7 @@ const DeleteObject = ({
|
||||
deleteOpen,
|
||||
selectedBucket,
|
||||
selectedObject,
|
||||
versioning,
|
||||
versioningInfo,
|
||||
selectedVersion = "",
|
||||
}: IDeleteObjectProps) => {
|
||||
const dispatch = useAppDispatch();
|
||||
@@ -120,22 +122,23 @@ const DeleteObject = ({
|
||||
)}
|
||||
? <br />
|
||||
<br />
|
||||
{versioning && selectedVersion === "" && (
|
||||
<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=""
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
{isVersionedMode(versioningInfo?.Status) &&
|
||||
selectedVersion === "" && (
|
||||
<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=""
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
{canBypass && (deleteVersions || selectedVersion !== "") && (
|
||||
<Fragment>
|
||||
<div
|
||||
|
||||
@@ -253,7 +253,7 @@ const ListObjects = () => {
|
||||
);
|
||||
|
||||
const isVersioned = useSelector(
|
||||
(state: AppState) => state.objectBrowser.isVersioned
|
||||
(state: AppState) => state.objectBrowser.versionInfo
|
||||
);
|
||||
const lockingEnabled = useSelector(
|
||||
(state: AppState) => state.objectBrowser.lockingEnabled
|
||||
@@ -1132,7 +1132,7 @@ const ListObjects = () => {
|
||||
internalPaths={selectedInternalPaths}
|
||||
bucketName={bucketName}
|
||||
onClosePanel={onClosePanel}
|
||||
versioning={isVersioned}
|
||||
versioningInfo={isVersioned}
|
||||
locking={lockingEnabled}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -82,6 +82,7 @@ import {
|
||||
import RenameLongFileName from "../../../../ObjectBrowser/RenameLongFilename";
|
||||
import TooltipWrapper from "../../../../Common/TooltipWrapper/TooltipWrapper";
|
||||
import { downloadObject } from "../../../../ObjectBrowser/utils";
|
||||
import { BucketVersioningInfo } from "../../../types";
|
||||
|
||||
const styles = () =>
|
||||
createStyles({
|
||||
@@ -139,7 +140,7 @@ interface IObjectDetailPanelProps {
|
||||
classes: any;
|
||||
internalPaths: string;
|
||||
bucketName: string;
|
||||
versioning: boolean;
|
||||
versioningInfo: BucketVersioningInfo;
|
||||
locking: boolean;
|
||||
onClosePanel: (hardRefresh: boolean) => void;
|
||||
}
|
||||
@@ -148,7 +149,7 @@ const ObjectDetailPanel = ({
|
||||
classes,
|
||||
internalPaths,
|
||||
bucketName,
|
||||
versioning,
|
||||
versioningInfo,
|
||||
locking,
|
||||
onClosePanel,
|
||||
}: IObjectDetailPanelProps) => {
|
||||
@@ -606,7 +607,7 @@ const ObjectDetailPanel = ({
|
||||
selectedBucket={bucketName}
|
||||
selectedObject={internalPaths}
|
||||
closeDeleteModalAndRefresh={closeDeleteModal}
|
||||
versioning={distributedSetup && versioning}
|
||||
versioningInfo={distributedSetup ? versioningInfo : undefined}
|
||||
selectedVersion={selectedVersion}
|
||||
/>
|
||||
)}
|
||||
|
||||
72
portal-ui/src/screens/Console/Buckets/VersioningInfo.tsx
Normal file
72
portal-ui/src/screens/Console/Buckets/VersioningInfo.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React from "react";
|
||||
import { Box } from "@mui/material";
|
||||
import { BucketVersioningInfo } from "./types";
|
||||
import LabelWithIcon from "./BucketDetails/SummaryItems/LabelWithIcon";
|
||||
import { DisabledIcon, EnabledIcon } from "mds";
|
||||
|
||||
const VersioningInfo = ({
|
||||
versioningState = {},
|
||||
}: {
|
||||
versioningState?: BucketVersioningInfo;
|
||||
}) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 2,
|
||||
}}
|
||||
>
|
||||
<Box sx={{ fontWeight: "medium", display: "flex", gap: 2 }}>
|
||||
{versioningState.ExcludeFolders ? (
|
||||
<LabelWithIcon
|
||||
icon={
|
||||
versioningState.ExcludeFolders ? (
|
||||
<EnabledIcon style={{ color: "green" }} />
|
||||
) : (
|
||||
<DisabledIcon />
|
||||
)
|
||||
}
|
||||
label={
|
||||
<label style={{ textDecoration: "normal" }}>
|
||||
Exclude Folders
|
||||
</label>
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
</Box>
|
||||
{versioningState.ExcludedPrefixes?.length ? (
|
||||
<Box
|
||||
sx={{
|
||||
fontWeight: "medium",
|
||||
display: "flex",
|
||||
justifyItems: "end",
|
||||
placeItems: "flex-start",
|
||||
flexDirection: "column",
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<Box>Excluded Prefixes :</Box>
|
||||
<div
|
||||
style={{
|
||||
maxHeight: "200px",
|
||||
overflowY: "auto",
|
||||
placeItems: "flex-start",
|
||||
justifyItems: "end",
|
||||
flexDirection: "column",
|
||||
display: "flex",
|
||||
}}
|
||||
>
|
||||
{versioningState.ExcludedPrefixes?.map((it) => (
|
||||
<div>
|
||||
<strong>{it.Prefix}</strong>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Box>
|
||||
) : null}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default VersioningInfo;
|
||||
@@ -81,6 +81,13 @@ export interface BucketVersioning {
|
||||
is_versioned: boolean;
|
||||
}
|
||||
|
||||
export interface BucketVersioningInfo {
|
||||
ExcludeFolders?: boolean;
|
||||
ExcludedPrefixes?: Record<"Prefix", string>[];
|
||||
MFADelete?: string;
|
||||
Status?: "Enabled" | "Suspended" | "";
|
||||
}
|
||||
|
||||
export interface BucketObjectLocking {
|
||||
object_locking_enabled: boolean;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
IRestoreLocalObjectList,
|
||||
} from "../Buckets/ListBuckets/Objects/ListObjects/types";
|
||||
import { IRetentionConfig } from "../../../common/types";
|
||||
import { BucketVersioningInfo } from "../Buckets/types";
|
||||
|
||||
const defaultRewind = {
|
||||
rewindEnabled: false,
|
||||
@@ -57,7 +58,7 @@ const initialState: ObjectBrowserState = {
|
||||
records: [],
|
||||
loadRecords: true,
|
||||
loadingVersioning: true,
|
||||
isVersioned: false,
|
||||
versionInfo: {},
|
||||
lockingEnabled: false,
|
||||
loadingLocking: false,
|
||||
selectedObjects: [],
|
||||
@@ -290,8 +291,8 @@ export const objectBrowserSlice = createSlice({
|
||||
setLoadingVersioning: (state, action: PayloadAction<boolean>) => {
|
||||
state.loadingVersioning = action.payload;
|
||||
},
|
||||
setIsVersioned: (state, action: PayloadAction<boolean>) => {
|
||||
state.isVersioned = action.payload;
|
||||
setIsVersioned: (state, action: PayloadAction<BucketVersioningInfo>) => {
|
||||
state.versionInfo = action.payload;
|
||||
},
|
||||
setLockingEnabled: (state, action: PayloadAction<boolean>) => {
|
||||
state.lockingEnabled = action.payload;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import { BucketObjectItem } from "../Buckets/ListBuckets/Objects/ListObjects/types";
|
||||
import { IRetentionConfig } from "../../../common/types";
|
||||
import { BucketVersioningInfo } from "../Buckets/types";
|
||||
|
||||
export const REWIND_SET_ENABLE = "REWIND/SET_ENABLE";
|
||||
export const REWIND_RESET_REWIND = "REWIND/RESET_REWIND";
|
||||
@@ -83,7 +84,7 @@ export interface ObjectBrowserState {
|
||||
records: BucketObjectItem[];
|
||||
loadRecords: boolean;
|
||||
loadingVersioning: boolean;
|
||||
isVersioned: boolean;
|
||||
versionInfo: BucketVersioningInfo;
|
||||
lockingEnabled: boolean;
|
||||
loadingLocking: boolean;
|
||||
selectedObjects: string[];
|
||||
|
||||
@@ -69,3 +69,7 @@ export const commonFormValidation = (fieldsValidate: IValidation[]) => {
|
||||
|
||||
return returnErrors;
|
||||
};
|
||||
|
||||
export const isVersionedMode = (status: string | undefined) => {
|
||||
return status === "Enabled" || status === "Suspended";
|
||||
};
|
||||
|
||||
@@ -2597,7 +2597,7 @@ func init() {
|
||||
"tags": [
|
||||
"Configuration"
|
||||
],
|
||||
"summary": "Uploads an Object.",
|
||||
"summary": "Uploads a file to import MinIO server config.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
@@ -5906,8 +5906,25 @@ func init() {
|
||||
"bucketVersioningResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"is_versioned": {
|
||||
"ExcludeFolders": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"ExcludedPrefixes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Prefix": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MFADelete": {
|
||||
"type": "string"
|
||||
},
|
||||
"Status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -11432,7 +11449,7 @@ func init() {
|
||||
"tags": [
|
||||
"Configuration"
|
||||
],
|
||||
"summary": "Uploads an Object.",
|
||||
"summary": "Uploads a file to import MinIO server config.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
@@ -14172,6 +14189,14 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"BucketVersioningResponseExcludedPrefixesItems0": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Prefix": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"LoginRequestFeatures": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -14867,8 +14892,20 @@ func init() {
|
||||
"bucketVersioningResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"is_versioned": {
|
||||
"ExcludeFolders": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"ExcludedPrefixes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/BucketVersioningResponseExcludedPrefixesItems0"
|
||||
}
|
||||
},
|
||||
"MFADelete": {
|
||||
"type": "string"
|
||||
},
|
||||
"Status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -51,7 +51,7 @@ func NewPostConfigsImport(ctx *middleware.Context, handler PostConfigsImportHand
|
||||
/*
|
||||
PostConfigsImport swagger:route POST /configs/import Configuration postConfigsImport
|
||||
|
||||
Uploads an Object.
|
||||
Uploads a file to import MinIO server config.
|
||||
*/
|
||||
type PostConfigsImport struct {
|
||||
Context *middleware.Context
|
||||
|
||||
@@ -357,9 +357,19 @@ func getBucketVersionedResponse(session *models.Principal, params bucketApi.GetB
|
||||
ErrorWithContext(ctx, fmt.Errorf("error versioning bucket: %v", err))
|
||||
}
|
||||
|
||||
excludedPrefixes := make([]*models.BucketVersioningResponseExcludedPrefixesItems0, len(res.ExcludedPrefixes))
|
||||
for i, v := range res.ExcludedPrefixes {
|
||||
excludedPrefixes[i] = &models.BucketVersioningResponseExcludedPrefixesItems0{
|
||||
Prefix: v.Prefix,
|
||||
}
|
||||
}
|
||||
|
||||
// serialize output
|
||||
bucketVResponse := &models.BucketVersioningResponse{
|
||||
IsVersioned: res.Status == "Enabled",
|
||||
ExcludeFolders: res.ExcludeFolders,
|
||||
ExcludedPrefixes: excludedPrefixes,
|
||||
MFADelete: res.MFADelete,
|
||||
Status: res.Status,
|
||||
}
|
||||
return bucketVResponse, nil
|
||||
}
|
||||
|
||||
@@ -4908,8 +4908,20 @@ definitions:
|
||||
bucketVersioningResponse:
|
||||
type: object
|
||||
properties:
|
||||
is_versioned:
|
||||
Status:
|
||||
type: string
|
||||
MFADelete:
|
||||
type: string
|
||||
ExcludedPrefixes:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
Prefix:
|
||||
type: string
|
||||
ExcludeFolders:
|
||||
type: boolean
|
||||
|
||||
setBucketVersioning:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in New Issue
Block a user