diff --git a/portal-ui/package.json b/portal-ui/package.json
index c429e8b2a..27ff043bf 100644
--- a/portal-ui/package.json
+++ b/portal-ui/package.json
@@ -18,7 +18,7 @@
"local-storage-fallback": "^4.1.1",
"lodash": "^4.17.21",
"luxon": "^3.3.0",
- "mds": "https://github.com/minio/mds.git#v0.3.1",
+ "mds": "https://github.com/minio/mds.git#v0.3.2",
"minio": "^7.0.32",
"react": "^18.1.0",
"react-component-export-image": "^1.0.6",
diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/AddAccessRule.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/AddAccessRule.tsx
index b8e780790..2d8649cb5 100644
--- a/portal-ui/src/screens/Console/Buckets/BucketDetails/AddAccessRule.tsx
+++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/AddAccessRule.tsx
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import { Grid } from "@mui/material";
import { AddAccessRuleIcon, Button } from "mds";
@@ -30,7 +30,10 @@ import {
import api from "../../../../common/api";
import { ErrorResponseHandler } from "../../../../common/types";
import SelectWrapper from "../../Common/FormComponents/SelectWrapper/SelectWrapper";
-import { setErrorSnackMessage } from "../../../../systemSlice";
+import {
+ setErrorSnackMessage,
+ setSnackBarMessage,
+} from "../../../../systemSlice";
import { useAppDispatch } from "../../../../store";
interface IAddAccessRule {
@@ -38,6 +41,7 @@ interface IAddAccessRule {
modalOpen: boolean;
onClose: () => any;
bucket: string;
+ prefilledRoute?: string;
}
const styles = (theme: Theme) =>
@@ -51,12 +55,19 @@ const AddAccessRule = ({
onClose,
classes,
bucket,
+ prefilledRoute,
}: IAddAccessRule) => {
const dispatch = useAppDispatch();
const [prefix, setPrefix] = useState("");
const [selectedAccess, setSelectedAccess] = useState("readonly");
+ useEffect(() => {
+ if (prefilledRoute) {
+ setPrefix(prefilledRoute);
+ }
+ }, [prefilledRoute]);
+
const accessOptions = [
{ label: "readonly", value: "readonly" },
{ label: "writeonly", value: "writeonly" },
@@ -75,6 +86,7 @@ const AddAccessRule = ({
access: selectedAccess,
})
.then((res: any) => {
+ dispatch(setSnackBarMessage("Access Rule added successfully"));
onClose();
})
.catch((err: ErrorResponseHandler) => {
@@ -86,7 +98,7 @@ const AddAccessRule = ({
return (
}
>
diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/DeleteAccessRule.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/DeleteAccessRule.tsx
index 9f82971c3..b27261078 100644
--- a/portal-ui/src/screens/Console/Buckets/BucketDetails/DeleteAccessRule.tsx
+++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/DeleteAccessRule.tsx
@@ -61,7 +61,7 @@ const DeleteAccessRule = ({
return (
}
>
diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx
index ec098490b..f691e1ce9 100644
--- a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx
+++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx
@@ -28,6 +28,7 @@ import { useDropzone } from "react-dropzone";
import { Theme } from "@mui/material/styles";
import { CSSObject } from "styled-components";
import {
+ AccessRuleIcon,
BucketsIcon,
Button,
DeleteIcon,
@@ -103,6 +104,7 @@ import {
openList,
resetMessages,
resetRewind,
+ setAnonymousAccessOpen,
setDownloadRenameModal,
setLoadingObjects,
setLoadingRecords,
@@ -133,11 +135,13 @@ import TooltipWrapper from "../../../../Common/TooltipWrapper/TooltipWrapper";
import ListObjectsTable from "./ListObjectsTable";
import {
downloadSelected,
+ openAnonymousAccess,
openPreview,
openShare,
} from "../../../../ObjectBrowser/objectBrowserThunks";
import FilterObjectsSB from "../../../../ObjectBrowser/FilterObjectsSB";
+import AddAccessRule from "../../../BucketDetails/AddAccessRule";
const DeleteMultipleObjects = withSuspense(
React.lazy(() => import("./DeleteMultipleObjects"))
@@ -280,6 +284,9 @@ const ListObjects = () => {
const colorVariants = useSelector(
(state: AppState) => state.system.overrideStyles
);
+ const anonymousAccessOpen = useSelector(
+ (state: AppState) => state.objectBrowser.anonymousAccessOpen
+ );
const loadingBucket = useSelector(selBucketDetailsLoading);
const bucketInfo = useSelector(selBucketDetailsInfo);
@@ -323,6 +330,13 @@ const ListObjects = () => {
const displayDeleteObject = hasPermission(bucketName, [
IAM_SCOPES.S3_DELETE_OBJECT,
]);
+ const canSetAnonymousAccess = hasPermission(bucketName, [
+ IAM_SCOPES.S3_GET_BUCKET_POLICY,
+ IAM_SCOPES.S3_PUT_BUCKET_POLICY,
+ IAM_SCOPES.S3_GET_ACTIONS,
+ IAM_SCOPES.S3_PUT_ACTIONS,
+ ]);
+
const selectedObjects = useSelector(
(state: AppState) => state.objectBrowser.selectedObjects
);
@@ -782,6 +796,10 @@ const ListObjects = () => {
dispatch(setDownloadRenameModal(null));
};
+ const closeAddAccessRule = () => {
+ dispatch(setAnonymousAccessOpen(false));
+ };
+
let createdTime = DateTime.now();
if (bucketInfo?.creation_date) {
@@ -855,6 +873,21 @@ const ListObjects = () => {
icon: ,
tooltip: canPreviewFile ? "Preview Selected File" : "Preview unavailable",
},
+ {
+ action: () => {
+ dispatch(openAnonymousAccess());
+ },
+ label: "Anonymous Access",
+ disabled:
+ selectedObjects.length !== 1 ||
+ !selectedObjects[0].endsWith("/") ||
+ !canSetAnonymousAccess,
+ icon: ,
+ tooltip:
+ selectedObjects.length === 1 && selectedObjects[0].endsWith("/")
+ ? "Set Anonymous Access to this Folder"
+ : "Anonymous Access unavailable",
+ },
{
action: () => {
setDeleteMultipleOpen(true);
@@ -925,6 +958,14 @@ const ListObjects = () => {
}}
/>
)}
+ {anonymousAccessOpen && (
+
+ )}
{anonymousMode && (
diff --git a/portal-ui/src/screens/Console/ObjectBrowser/objectBrowserSlice.ts b/portal-ui/src/screens/Console/ObjectBrowser/objectBrowserSlice.ts
index ae7e97e9a..9851ea82a 100644
--- a/portal-ui/src/screens/Console/ObjectBrowser/objectBrowserSlice.ts
+++ b/portal-ui/src/screens/Console/ObjectBrowser/objectBrowserSlice.ts
@@ -67,6 +67,7 @@ const initialState: ObjectBrowserState = {
previewOpen: false,
shareFileModalOpen: false,
isOpeningObjectDetail: false,
+ anonymousAccessOpen: false,
retentionConfig: {
mode: "",
unit: "",
@@ -361,6 +362,9 @@ export const objectBrowserSlice = createSlice({
setLongFileOpen: (state, action: PayloadAction) => {
state.longFileOpen = action.payload;
},
+ setAnonymousAccessOpen: (state, action: PayloadAction) => {
+ state.anonymousAccessOpen = action.payload;
+ },
},
});
export const {
@@ -407,6 +411,7 @@ export const {
setRetentionConfig,
setSelectedBucket,
setLongFileOpen,
+ setAnonymousAccessOpen,
} = objectBrowserSlice.actions;
export default objectBrowserSlice.reducer;
diff --git a/portal-ui/src/screens/Console/ObjectBrowser/objectBrowserThunks.ts b/portal-ui/src/screens/Console/ObjectBrowser/objectBrowserThunks.ts
index b5367cc5d..ea7458cde 100644
--- a/portal-ui/src/screens/Console/ObjectBrowser/objectBrowserThunks.ts
+++ b/portal-ui/src/screens/Console/ObjectBrowser/objectBrowserThunks.ts
@@ -24,6 +24,7 @@ import {
cancelObjectInList,
completeObject,
failObject,
+ setAnonymousAccessOpen,
setDownloadRenameModal,
setNewObject,
setPreviewOpen,
@@ -155,3 +156,17 @@ export const openShare = createAsyncThunk(
}
}
);
+
+export const openAnonymousAccess = createAsyncThunk(
+ "objectBrowser/openAnonymousAccess",
+ async (_, { getState, dispatch }) => {
+ const state = getState() as AppState;
+
+ if (
+ state.objectBrowser.selectedObjects.length === 1 &&
+ state.objectBrowser.selectedObjects[0].endsWith("/")
+ ) {
+ dispatch(setAnonymousAccessOpen(true));
+ }
+ }
+);
diff --git a/portal-ui/src/screens/Console/ObjectBrowser/types.ts b/portal-ui/src/screens/Console/ObjectBrowser/types.ts
index b1ebf82aa..7f11f23f1 100644
--- a/portal-ui/src/screens/Console/ObjectBrowser/types.ts
+++ b/portal-ui/src/screens/Console/ObjectBrowser/types.ts
@@ -95,6 +95,7 @@ export interface ObjectBrowserState {
isOpeningObjectDetail: boolean;
retentionConfig: IRetentionConfig | null;
longFileOpen: boolean;
+ anonymousAccessOpen: boolean;
}
export interface ObjectManager {
diff --git a/portal-ui/yarn.lock b/portal-ui/yarn.lock
index 491cc5ac6..5317145cb 100644
--- a/portal-ui/yarn.lock
+++ b/portal-ui/yarn.lock
@@ -4877,10 +4877,10 @@ destroy@1.2.0:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
-detect-gpu@^5.0.15:
- version "5.0.15"
- resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.15.tgz#d375f89b246f21167859efbbd89eff60ccbcfd4d"
- integrity sha512-ImImgPRhTvo/bmtotR1KG534ZE+L6yIV9sMe4y3zOUzeInnYk/9KOBqxz9M5hKkHXhGKKjY04pMrLMb+rp3FWw==
+detect-gpu@^5.0.16:
+ version "5.0.16"
+ resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.16.tgz#a42054724f4a75d667add68ad1073c80d29ef733"
+ integrity sha512-6+o6Sy+FzgQJG7Ray0fN7B4kRGGPuyaM5FHXJ4N3sLcQhsUO9+NEw9emM7vxN7DroZGG16ZydCX6kpgDmNXyKQ==
dependencies:
webgl-constants "^1.1.1"
@@ -8316,14 +8316,14 @@ mdn-data@2.0.4:
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
-"mds@https://github.com/minio/mds.git#v0.3.1":
- version "0.3.1"
- resolved "https://github.com/minio/mds.git#8beec5b36aef3ba4c389b170a0108f301a5f29e3"
+"mds@https://github.com/minio/mds.git#v0.3.2":
+ version "0.3.2"
+ resolved "https://github.com/minio/mds.git#85654388adaec4d2624b61bee439c7d9cd5801f7"
dependencies:
"@types/styled-components" "^5.1.25"
- detect-gpu "^5.0.15"
+ detect-gpu "^5.0.16"
react-virtualized "^9.22.3"
- styled-components "^5.3.8"
+ styled-components "^5.3.9"
media-typer@0.3.0:
version "0.3.0"
@@ -11212,7 +11212,7 @@ style-loader@^3.3.1:
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.2.tgz#eaebca714d9e462c19aa1e3599057bc363924899"
integrity sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw==
-styled-components@^5.3.8, styled-components@^5.3.9:
+styled-components@^5.3.9:
version "5.3.9"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.9.tgz#641af2a8bb89904de708c71b439caa9633e8f0ba"
integrity sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==