diff --git a/portal-ui/src/common/SecureComponent/SecureComponent.tsx b/portal-ui/src/common/SecureComponent/SecureComponent.tsx index bbd36e8c51..08a6e98d3f 100644 --- a/portal-ui/src/common/SecureComponent/SecureComponent.tsx +++ b/portal-ui/src/common/SecureComponent/SecureComponent.tsx @@ -15,95 +15,7 @@ // along with this program. If not, see . import React, { cloneElement } from "react"; -import get from "lodash/get"; -import { store } from "../../store"; -import { hasAccessToResource } from "./permissions"; - -export const hasPermission = ( - resource: string | string[] | undefined, - scopes: string[], - matchAll?: boolean, - containsResource?: boolean -) => { - if (!resource) { - return false; - } - const state = store.getState(); - const sessionGrants = state.console.session.permissions || {}; - - const globalGrants = sessionGrants["arn:aws:s3:::*"] || []; - let resources: string[] = []; - let resourceGrants: string[] = []; - let containsResourceGrants: string[] = []; - - if (resource) { - if (Array.isArray(resource)) { - resources = [...resources, ...resource]; - } else { - resources.push(resource); - } - - // Filter wildcard items - const wildcards = Object.keys(sessionGrants).filter( - (item) => item.includes("*") && item !== "arn:aws:s3:::*" - ); - - const getMatchingWildcards = (path: string) => { - const items = wildcards.map((element) => { - const wildcardItemSection = element.split(":").slice(-1)[0]; - - const replaceWildcard = wildcardItemSection - .replace("/", "\\/") - .replace("\\/*", "($|(\\/.*?))"); - - const inRegExp = new RegExp(`${replaceWildcard}$`, "gm"); - - if(inRegExp.exec(path)) { - return element; - } - - return null; - }); - - return items.filter(itm => itm !== null); - }; - - resources.forEach((rsItem) => { - // Validation against inner paths & wildcards - let wildcardRules =getMatchingWildcards(rsItem); - - let wildcardGrants: string[] = []; - - wildcardRules.forEach((rule) => { - if(rule) { - const wcResources = get(sessionGrants, rule, []); - wildcardGrants = [...wildcardGrants, ...wcResources]; - } - }); - - const simpleResources = get(sessionGrants, rsItem, []); - const s3Resources = get(sessionGrants, `arn:aws:s3:::${rsItem}/*`, []); - - resourceGrants = [...simpleResources, ...s3Resources, ...wildcardGrants]; - - if (containsResource) { - const matchResource = `arn:aws:s3:::${rsItem}`; - - Object.entries(sessionGrants).forEach(([key, value]) => { - if (key.includes(matchResource)) { - containsResourceGrants = [...containsResourceGrants, ...value]; - } - }); - } - }); - } - - return hasAccessToResource( - [...resourceGrants, ...globalGrants, ...containsResourceGrants], - scopes, - matchAll - ); -}; +import hasPermission from "./accessControl"; interface ISecureComponentProps { errorProps?: any; diff --git a/portal-ui/src/common/SecureComponent/__tests__/accessControl.test.ts b/portal-ui/src/common/SecureComponent/__tests__/accessControl.test.ts new file mode 100644 index 0000000000..93aef080d5 --- /dev/null +++ b/portal-ui/src/common/SecureComponent/__tests__/accessControl.test.ts @@ -0,0 +1,66 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2022 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import hasPermission from "../accessControl"; +import { store } from "../../../store"; +import { SESSION_RESPONSE } from "../../../screens/Console/actions"; + +const setPolicy1 = () => { + store.dispatch({ + type: SESSION_RESPONSE, + message: { + distributedMode: true, + features: ["log-search"], + permissions: { + "arn:aws:s3:::testcafe": [ + "admin:CreateUser", + "s3:GetBucketLocation", + "s3:ListBucket", + "admin:CreateServiceAccount", + ], + "arn:aws:s3:::testcafe/*": [ + "admin:CreateServiceAccount", + "admin:CreateUser", + "s3:GetObject", + "s3:ListBucket", + ], + "arn:aws:s3:::testcafe/write/*": [ + "admin:CreateServiceAccount", + "admin:CreateUser", + "s3:PutObject", + "s3:DeleteObject", + "s3:GetObject", + "s3:ListBucket", + ], + "console-ui": ["admin:CreateServiceAccount", "admin:CreateUser"], + }, + operator: false, + status: "ok", + }, + }); +}; + +test("Upload button disabled", () => { + setPolicy1(); + expect(hasPermission("testcafe", ["s3:PutObject"])).toBe(false); +}); + +test("Upload button enabled valid prefix", () => { + setPolicy1(); + expect(hasPermission("testcafe/write", ["s3:PutObject"], false, true)).toBe( + true + ); +}); diff --git a/portal-ui/src/common/SecureComponent/accessControl.ts b/portal-ui/src/common/SecureComponent/accessControl.ts new file mode 100644 index 0000000000..41edd811f5 --- /dev/null +++ b/portal-ui/src/common/SecureComponent/accessControl.ts @@ -0,0 +1,136 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2022 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import { store } from "../../store"; +import get from "lodash/get"; +import { IAM_SCOPES } from "./permissions"; + +const hasPermission = ( + resource: string | string[] | undefined, + scopes: string[], + matchAll?: boolean, + containsResource?: boolean +) => { + if (!resource) { + return false; + } + const state = store.getState(); + const sessionGrants = state.console.session.permissions || {}; + + const globalGrants = sessionGrants["arn:aws:s3:::*"] || []; + let resources: string[] = []; + let resourceGrants: string[] = []; + let containsResourceGrants: string[] = []; + + if (resource) { + if (Array.isArray(resource)) { + resources = [...resources, ...resource]; + } else { + resources.push(resource); + } + + // Filter wildcard items + const wildcards = Object.keys(sessionGrants).filter( + (item) => item.includes("*") && item !== "arn:aws:s3:::*" + ); + + const getMatchingWildcards = (path: string) => { + const items = wildcards.map((element) => { + const wildcardItemSection = element.split(":").slice(-1)[0]; + + const replaceWildcard = wildcardItemSection + .replace("/", "\\/") + .replace("\\/*", "($|(\\/.*?))"); + + const inRegExp = new RegExp(`${replaceWildcard}$`, "gm"); + + if (inRegExp.exec(path)) { + return element; + } + + return null; + }); + + return items.filter((itm) => itm !== null); + }; + + resources.forEach((rsItem) => { + // Validation against inner paths & wildcards + let wildcardRules = getMatchingWildcards(rsItem); + + let wildcardGrants: string[] = []; + + wildcardRules.forEach((rule) => { + if (rule) { + const wcResources = get(sessionGrants, rule, []); + wildcardGrants = [...wildcardGrants, ...wcResources]; + } + }); + + const simpleResources = get(sessionGrants, rsItem, []); + const s3Resources = get(sessionGrants, `arn:aws:s3:::${rsItem}/*`, []); + + resourceGrants = [...simpleResources, ...s3Resources, ...wildcardGrants]; + + if (containsResource) { + const matchResource = `arn:aws:s3:::${rsItem}`; + + Object.entries(sessionGrants).forEach(([key, value]) => { + if (key.includes(matchResource)) { + containsResourceGrants = [...containsResourceGrants, ...value]; + } + }); + } + }); + } + + return hasAccessToResource( + [...resourceGrants, ...globalGrants, ...containsResourceGrants], + scopes, + matchAll + ); +}; + +// hasAccessToResource receives a list of user permissions to perform on a specific resource, then compares those permissions against +// a list of required permissions and return true or false depending of the level of required access (match all permissions, +// match some of the permissions) +const hasAccessToResource = ( + userPermissionsOnBucket: string[] | null | undefined, + requiredPermissions: string[] = [], + matchAll?: boolean +) => { + if (!userPermissionsOnBucket) { + return false; + } + + const s3All = userPermissionsOnBucket.includes(IAM_SCOPES.S3_ALL_ACTIONS); + const AdminAll = userPermissionsOnBucket.includes( + IAM_SCOPES.ADMIN_ALL_ACTIONS + ); + + const permissions = requiredPermissions.filter(function (n) { + return ( + userPermissionsOnBucket.indexOf(n) !== -1 || + (n.indexOf("s3:") !== -1 && s3All) || + (n.indexOf("admin:") !== -1 && AdminAll) + ); + }); + return matchAll + ? permissions.length === requiredPermissions.length + : permissions.length > 0; +}; + +export default hasPermission; diff --git a/portal-ui/src/common/SecureComponent/index.ts b/portal-ui/src/common/SecureComponent/index.ts new file mode 100644 index 0000000000..9db2d90a9a --- /dev/null +++ b/portal-ui/src/common/SecureComponent/index.ts @@ -0,0 +1,18 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2022 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +export { default as hasPermission } from "./accessControl"; +export { default as SecureComponent } from "./SecureComponent"; diff --git a/portal-ui/src/common/SecureComponent/permissions.ts b/portal-ui/src/common/SecureComponent/permissions.ts index 09d72f2a8d..31cba791d8 100644 --- a/portal-ui/src/common/SecureComponent/permissions.ts +++ b/portal-ui/src/common/SecureComponent/permissions.ts @@ -14,35 +14,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -// hasAccessToResource receives a list of user permissions to perform on a specific resource, then compares those permissions against -// a list of required permissions and return true or false depending of the level of required access (match all permissions, -// match some of the permissions) -export const hasAccessToResource = ( - userPermissionsOnBucket: string[] | null | undefined, - requiredPermissions: string[] = [], - matchAll?: boolean -) => { - if (!userPermissionsOnBucket) { - return false; - } - - const s3All = userPermissionsOnBucket.includes(IAM_SCOPES.S3_ALL_ACTIONS); - const AdminAll = userPermissionsOnBucket.includes( - IAM_SCOPES.ADMIN_ALL_ACTIONS - ); - - const permissions = requiredPermissions.filter(function (n) { - return ( - userPermissionsOnBucket.indexOf(n) !== -1 || - (n.indexOf("s3:") !== -1 && s3All) || - (n.indexOf("admin:") !== -1 && AdminAll) - ); - }); - return matchAll - ? permissions.length === requiredPermissions.length - : permissions.length > 0; -}; - export const IAM_ROLES = { BUCKET_OWNER: "BUCKET_OWNER", // upload/delete objects from the bucket BUCKET_VIEWER: "BUCKET_VIEWER", // only view objects on the bucket diff --git a/portal-ui/src/screens/Console/Account/Account.tsx b/portal-ui/src/screens/Console/Account/Account.tsx index 4c2a0849b7..4df9225848 100644 --- a/portal-ui/src/screens/Console/Account/Account.tsx +++ b/portal-ui/src/screens/Console/Account/Account.tsx @@ -49,7 +49,7 @@ import { CONSOLE_UI_RESOURCE, IAM_SCOPES, } from "../../../common/SecureComponent/permissions"; -import SecureComponent from "../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../common/SecureComponent"; import RBIconButton from "../Buckets/BucketDetails/SummaryItems/RBIconButton"; import { selectSAs } from "../Configurations/utils"; import DeleteMultipleServiceAccounts from "../Users/DeleteMultipleServiceAccounts"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/AccessDetailsPanel.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/AccessDetailsPanel.tsx index e910d86101..123003e46c 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/AccessDetailsPanel.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/AccessDetailsPanel.tsx @@ -36,9 +36,10 @@ import { IAM_SCOPES, } from "../../../../common/SecureComponent/permissions"; import PanelTitle from "../../Common/PanelTitle/PanelTitle"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../../common/SecureComponent/SecureComponent"; +} from "../../../../common/SecureComponent"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import { tableStyles } from "../../Common/FormComponents/common/styleLibrary"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/AccessRulePanel.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/AccessRulePanel.tsx index aba5f7f8cb..560c34a5b6 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/AccessRulePanel.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/AccessRulePanel.tsx @@ -39,9 +39,10 @@ import { import { BucketInfo } from "../types"; import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions"; import PanelTitle from "../../Common/PanelTitle/PanelTitle"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../../common/SecureComponent/SecureComponent"; +} from "../../../../common/SecureComponent"; import withSuspense from "../../Common/Components/withSuspense"; import RBIconButton from "./SummaryItems/RBIconButton"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/BrowserHandler.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/BrowserHandler.tsx index c1e0e2cc44..9e337000ac 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/BrowserHandler.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/BrowserHandler.tsx @@ -34,7 +34,7 @@ import PageHeader from "../../Common/PageHeader/PageHeader"; import SettingsIcon from "../../../../icons/SettingsIcon"; import { BucketInfo } from "../types"; import { setErrorSnackMessage } from "../../../../actions"; -import SecureComponent from "../../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../../common/SecureComponent"; import { IAM_PERMISSIONS, IAM_ROLES, diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketDetails.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketDetails.tsx index ec48f5c25d..f6cb05f49f 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketDetails.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketDetails.tsx @@ -44,9 +44,10 @@ import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions"; import PageLayout from "../../Common/Layout/PageLayout"; import VerticalTabs from "../../Common/VerticalTabs/VerticalTabs"; import BackLink from "../../../../common/BackLink"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../../common/SecureComponent/SecureComponent"; +} from "../../../../common/SecureComponent"; import withSuspense from "../../Common/Components/withSuspense"; import RBIconButton from "./SummaryItems/RBIconButton"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketEventsPanel.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketEventsPanel.tsx index 4648917140..4e960236cd 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketEventsPanel.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketEventsPanel.tsx @@ -36,9 +36,10 @@ import api from "../../../../common/api"; import HelpBox from "../../../../common/HelpBox"; import PanelTitle from "../../Common/PanelTitle/PanelTitle"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../../common/SecureComponent/SecureComponent"; +} from "../../../../common/SecureComponent"; import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions"; import withSuspense from "../../Common/Components/withSuspense"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketLifecyclePanel.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketLifecyclePanel.tsx index 977d754b62..07d03d53ca 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketLifecyclePanel.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketLifecyclePanel.tsx @@ -37,9 +37,10 @@ import AddLifecycleModal from "./AddLifecycleModal"; import TableWrapper from "../../Common/TableWrapper/TableWrapper"; import HelpBox from "../../../../common/HelpBox"; import PanelTitle from "../../Common/PanelTitle/PanelTitle"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../../common/SecureComponent/SecureComponent"; +} from "../../../../common/SecureComponent"; import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions"; import RBIconButton from "./SummaryItems/RBIconButton"; import DeleteBucketLifecycleRule from "./DeleteBucketLifecycleRule"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketReplicationPanel.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketReplicationPanel.tsx index 45cb59e9fb..7ee2b60926 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketReplicationPanel.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketReplicationPanel.tsx @@ -40,9 +40,10 @@ import TableWrapper from "../../Common/TableWrapper/TableWrapper"; import HelpBox from "../../../../common/HelpBox"; import PanelTitle from "../../Common/PanelTitle/PanelTitle"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../../common/SecureComponent/SecureComponent"; +} from "../../../../common/SecureComponent"; import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions"; import withSuspense from "../../Common/Components/withSuspense"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketSummaryPanel.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketSummaryPanel.tsx index 4ce982bc95..27d1c120e4 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketSummaryPanel.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/BucketSummaryPanel.tsx @@ -44,9 +44,10 @@ import { import api from "../../../../common/api"; import { setBucketDetailsLoad } from "../actions"; import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../../common/SecureComponent/SecureComponent"; +} from "../../../../common/SecureComponent"; import withSuspense from "../../Common/Components/withSuspense"; import LabelValuePair from "../../Common/UsageBarWrapper/LabelValuePair"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/SummaryItems/BucketTags.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/SummaryItems/BucketTags.tsx index 4c9e6afb07..4760779c9b 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/SummaryItems/BucketTags.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/SummaryItems/BucketTags.tsx @@ -19,7 +19,7 @@ import { ErrorResponseHandler } from "../../../../../common/types"; import useApi from "../../../Common/Hooks/useApi"; import { Box, CircularProgress } from "@mui/material"; import { IAM_SCOPES } from "../../../../../common/SecureComponent/permissions"; -import SecureComponent from "../../../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../../../common/SecureComponent"; import get from "lodash/get"; import Chip from "@mui/material/Chip"; import CloseIcon from "@mui/icons-material/Close"; diff --git a/portal-ui/src/screens/Console/Buckets/BucketDetails/SummaryItems/EditablePropertyItem.tsx b/portal-ui/src/screens/Console/Buckets/BucketDetails/SummaryItems/EditablePropertyItem.tsx index e1caec1754..0918794a31 100644 --- a/portal-ui/src/screens/Console/Buckets/BucketDetails/SummaryItems/EditablePropertyItem.tsx +++ b/portal-ui/src/screens/Console/Buckets/BucketDetails/SummaryItems/EditablePropertyItem.tsx @@ -16,7 +16,7 @@ import React from "react"; import LabelValuePair from "../../../Common/UsageBarWrapper/LabelValuePair"; -import SecureComponent from "../../../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../../../common/SecureComponent"; import ActionLink from "./ActionLink"; import { Box } from "@mui/material"; import EditActionButton from "./EditActionButton"; diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/BucketListItem.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/BucketListItem.tsx index e5f4cc5082..cef1208b8b 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/BucketListItem.tsx +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/BucketListItem.tsx @@ -33,7 +33,7 @@ import { IAM_PERMISSIONS, IAM_ROLES, } from "../../../../common/SecureComponent/permissions"; -import SecureComponent from "../../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../../common/SecureComponent"; import RBIconButton from "../BucketDetails/SummaryItems/RBIconButton"; import clsx from "clsx"; diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx index 18b95551f2..4f155eac3b 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx @@ -22,7 +22,7 @@ import withStyles from "@mui/styles/withStyles"; import { LinearProgress } from "@mui/material"; import Grid from "@mui/material/Grid"; import { Bucket, BucketList } from "../types"; -import {AddIcon, BucketsIcon, LifecycleConfigIcon} from "../../../../icons"; +import { AddIcon, BucketsIcon, LifecycleConfigIcon } from "../../../../icons"; import { AppState } from "../../../../store"; import { setErrorSnackMessage } from "../../../../actions"; import { @@ -41,7 +41,7 @@ import RefreshIcon from "../../../../icons/RefreshIcon"; import AButton from "../../Common/AButton/AButton"; import MultipleBucketsIcon from "../../../../icons/MultipleBucketsIcon"; import SelectMultipleIcon from "../../../../icons/SelectMultipleIcon"; -import SecureComponent from "../../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../../common/SecureComponent"; import { CONSOLE_UI_RESOURCE, IAM_SCOPES, @@ -259,15 +259,15 @@ const ListBuckets = ({ /> { - setLifecycleModalOpen(true); - }} - text={""} - icon={} - disabled={selectedBuckets.length === 0} - color={"primary"} - variant={"outlined"} + tooltip={"Set Lifecycle"} + onClick={() => { + setLifecycleModalOpen(true); + }} + text={""} + icon={} + disabled={selectedBuckets.length === 0} + color={"primary"} + variant={"outlined"} /> - - { + uploadFileFunction(handleCloseUpload); + }} + disabled={!uploadObjectAllowed || forceDisable} > - { - uploadFileFunction(handleCloseUpload); - }} - disabled={forceDisable} - > - - - - Upload File - - - + + + Upload File + + { + uploadFolderFunction(handleCloseUpload); + }} + disabled={!uploadFolderAllowed || forceDisable} > - { - uploadFolderFunction(handleCloseUpload); - }} - disabled={forceDisable} - > - - - - Upload Folder - - + + + + Upload Folder + ); diff --git a/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx b/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx index 2052cf2166..de7886872c 100644 --- a/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx +++ b/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx @@ -52,7 +52,7 @@ import { IAM_PAGES, IAM_SCOPES, } from "../../../../common/SecureComponent/permissions"; -import SecureComponent from "../../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../../common/SecureComponent"; import { tierTypes } from "./utils"; import RBIconButton from "../../Buckets/BucketDetails/SummaryItems/RBIconButton"; diff --git a/portal-ui/src/screens/Console/Console.tsx b/portal-ui/src/screens/Console/Console.tsx index bb4638a235..6d8bd557e5 100644 --- a/portal-ui/src/screens/Console/Console.tsx +++ b/portal-ui/src/screens/Console/Console.tsx @@ -47,7 +47,7 @@ import { IAM_SCOPES, S3_ALL_RESOURCES, } from "../../common/SecureComponent/permissions"; -import { hasPermission } from "../../common/SecureComponent/SecureComponent"; +import { hasPermission } from "../../common/SecureComponent"; import { IRouteRule } from "./Menu/types"; import LoadingComponent from "../../common/LoadingComponent"; diff --git a/portal-ui/src/screens/Console/Groups/Groups.tsx b/portal-ui/src/screens/Console/Groups/Groups.tsx index f49db04906..1f47802947 100644 --- a/portal-ui/src/screens/Console/Groups/Groups.tsx +++ b/portal-ui/src/screens/Console/Groups/Groups.tsx @@ -45,9 +45,10 @@ import { IAM_PAGES, IAM_SCOPES, } from "../../../common/SecureComponent/permissions"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../common/SecureComponent/SecureComponent"; +} from "../../../common/SecureComponent"; import withSuspense from "../Common/Components/withSuspense"; import RBIconButton from "../Buckets/BucketDetails/SummaryItems/RBIconButton"; diff --git a/portal-ui/src/screens/Console/Groups/GroupsDetails.tsx b/portal-ui/src/screens/Console/Groups/GroupsDetails.tsx index 2998fb71f3..da2254e2b3 100644 --- a/portal-ui/src/screens/Console/Groups/GroupsDetails.tsx +++ b/portal-ui/src/screens/Console/Groups/GroupsDetails.tsx @@ -41,9 +41,10 @@ import { IAM_PAGES, IAM_SCOPES, } from "../../../common/SecureComponent/permissions"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../common/SecureComponent/SecureComponent"; +} from "../../../common/SecureComponent"; import GroupDetailsHeader from "./GroupDetailsHeader"; import RBIconButton from "../Buckets/BucketDetails/SummaryItems/RBIconButton"; diff --git a/portal-ui/src/screens/Console/Heal/Heal.tsx b/portal-ui/src/screens/Console/Heal/Heal.tsx index 353bc67b40..57e752d601 100644 --- a/portal-ui/src/screens/Console/Heal/Heal.tsx +++ b/portal-ui/src/screens/Console/Heal/Heal.tsx @@ -51,7 +51,7 @@ import CheckboxWrapper from "../Common/FormComponents/CheckboxWrapper/CheckboxWr import PageHeader from "../Common/PageHeader/PageHeader"; import api from "../../../common/api"; import PageLayout from "../Common/Layout/PageLayout"; -import SecureComponent from "../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../common/SecureComponent"; import DistributedOnly from "../Common/DistributedOnly/DistributedOnly"; const styles = (theme: Theme) => diff --git a/portal-ui/src/screens/Console/License/License.tsx b/portal-ui/src/screens/Console/License/License.tsx index d1fe1d4b9e..2436326b87 100644 --- a/portal-ui/src/screens/Console/License/License.tsx +++ b/portal-ui/src/screens/Console/License/License.tsx @@ -34,7 +34,7 @@ import PageHeader from "../Common/PageHeader/PageHeader"; import LicenseModal from "./LicenseModal"; import api from "../../../common/api"; import { LicenseIcon } from "../../../icons"; -import { hasPermission } from "../../../common/SecureComponent/SecureComponent"; +import { hasPermission } from "../../../common/SecureComponent"; import { CONSOLE_UI_RESOURCE, IAM_PAGES, diff --git a/portal-ui/src/screens/Console/Logs/LogSearch/LogsSearchMain.tsx b/portal-ui/src/screens/Console/Logs/LogSearch/LogsSearchMain.tsx index 66171ceb9b..ad97055378 100644 --- a/portal-ui/src/screens/Console/Logs/LogSearch/LogsSearchMain.tsx +++ b/portal-ui/src/screens/Console/Logs/LogSearch/LogsSearchMain.tsx @@ -45,7 +45,7 @@ import { CONSOLE_UI_RESOURCE, IAM_SCOPES, } from "../../../../common/SecureComponent/permissions"; -import SecureComponent from "../../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../../common/SecureComponent"; import { SearchIcon } from "../../../../icons"; import MissingIntegration from "../../Common/MissingIntegration/MissingIntegration"; diff --git a/portal-ui/src/screens/Console/Menu/MenuItem.tsx b/portal-ui/src/screens/Console/Menu/MenuItem.tsx index 040cc62b3c..57f94f7499 100644 --- a/portal-ui/src/screens/Console/Menu/MenuItem.tsx +++ b/portal-ui/src/screens/Console/Menu/MenuItem.tsx @@ -34,7 +34,7 @@ import { MenuCollapsedIcon, MenuExpandedIcon, } from "../../../icons/SidebarMenus"; -import { hasPermission } from "../../../common/SecureComponent/SecureComponent"; +import { hasPermission } from "../../../common/SecureComponent"; import { CONSOLE_UI_RESOURCE, IAM_PAGES_PERMISSIONS, diff --git a/portal-ui/src/screens/Console/Policies/ListPolicies.tsx b/portal-ui/src/screens/Console/Policies/ListPolicies.tsx index 85ad11b762..a543c46b39 100644 --- a/portal-ui/src/screens/Console/Policies/ListPolicies.tsx +++ b/portal-ui/src/screens/Console/Policies/ListPolicies.tsx @@ -43,9 +43,10 @@ import { IAM_PAGES, IAM_SCOPES, } from "../../../common/SecureComponent/permissions"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../common/SecureComponent/SecureComponent"; +} from "../../../common/SecureComponent"; import SearchBox from "../Common/SearchBox"; import withSuspense from "../Common/Components/withSuspense"; diff --git a/portal-ui/src/screens/Console/Policies/PolicyDetails.tsx b/portal-ui/src/screens/Console/Policies/PolicyDetails.tsx index d6051031dd..7ac9417d19 100644 --- a/portal-ui/src/screens/Console/Policies/PolicyDetails.tsx +++ b/portal-ui/src/screens/Console/Policies/PolicyDetails.tsx @@ -51,9 +51,10 @@ import { IAM_PAGES, IAM_SCOPES, } from "../../../common/SecureComponent/permissions"; -import SecureComponent, { +import { + SecureComponent, hasPermission, -} from "../../../common/SecureComponent/SecureComponent"; +} from "../../../common/SecureComponent"; import withSuspense from "../Common/Components/withSuspense"; import { AppState } from "../../../store"; diff --git a/portal-ui/src/screens/Console/Speedtest/Speedtest.tsx b/portal-ui/src/screens/Console/Speedtest/Speedtest.tsx index 6b8e724d84..ea503ecc6c 100644 --- a/portal-ui/src/screens/Console/Speedtest/Speedtest.tsx +++ b/portal-ui/src/screens/Console/Speedtest/Speedtest.tsx @@ -43,7 +43,7 @@ import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWr import ProgressBarWrapper from "../Common/ProgressBarWrapper/ProgressBarWrapper"; import InputUnitMenu from "../Common/FormComponents/InputUnitMenu/InputUnitMenu"; import PageLayout from "../Common/Layout/PageLayout"; -import SecureComponent from "../../../common/SecureComponent/SecureComponent"; +import { SecureComponent } from "../../../common/SecureComponent"; import DistributedOnly from "../Common/DistributedOnly/DistributedOnly"; import HelpBox from "../../../common/HelpBox"; import WarnIcon from "../../../icons/WarnIcon"; diff --git a/portal-ui/src/screens/Console/Support/Register.tsx b/portal-ui/src/screens/Console/Support/Register.tsx index 1dd6c5703c..10157101e7 100644 --- a/portal-ui/src/screens/Console/Support/Register.tsx +++ b/portal-ui/src/screens/Console/Support/Register.tsx @@ -49,7 +49,7 @@ import { import { ErrorResponseHandler } from "../../../common/types"; import LockOutlinedIcon from "@mui/icons-material/LockOutlined"; import SelectWrapper from "../Common/FormComponents/SelectWrapper/SelectWrapper"; -import { hasPermission } from "../../../common/SecureComponent/SecureComponent"; +import { hasPermission } from "../../../common/SecureComponent"; import { CONSOLE_UI_RESOURCE, IAM_PAGES, diff --git a/portal-ui/src/screens/Console/Tools/ToolsPanel/ToolsList.tsx b/portal-ui/src/screens/Console/Tools/ToolsPanel/ToolsList.tsx index 6eca0346c5..260c5e42f2 100644 --- a/portal-ui/src/screens/Console/Tools/ToolsPanel/ToolsList.tsx +++ b/portal-ui/src/screens/Console/Tools/ToolsPanel/ToolsList.tsx @@ -43,7 +43,7 @@ import { IAM_PAGES, IAM_PAGES_PERMISSIONS, } from "../../../../common/SecureComponent/permissions"; -import { hasPermission } from "../../../../common/SecureComponent/SecureComponent"; +import { hasPermission } from "../../../../common/SecureComponent"; import { AppState } from "../../../../store"; import { connect } from "react-redux"; diff --git a/portal-ui/src/screens/Console/Users/ListUsers.tsx b/portal-ui/src/screens/Console/Users/ListUsers.tsx index 850ed5e581..b50e9b667d 100644 --- a/portal-ui/src/screens/Console/Users/ListUsers.tsx +++ b/portal-ui/src/screens/Console/Users/ListUsers.tsx @@ -47,10 +47,12 @@ import { IAM_SCOPES, S3_ALL_RESOURCES, } from "../../../common/SecureComponent/permissions"; -import SecureComponent, { - hasPermission, -} from "../../../common/SecureComponent/SecureComponent"; + import RBIconButton from "../Buckets/BucketDetails/SummaryItems/RBIconButton"; +import { + hasPermission, + SecureComponent, +} from "../../../common/SecureComponent"; const AddUser = withSuspense(React.lazy(() => import("./AddUser"))); const SetPolicy = withSuspense( diff --git a/portal-ui/src/screens/Console/valid-routes.ts b/portal-ui/src/screens/Console/valid-routes.ts index 77169143a2..c107088c15 100644 --- a/portal-ui/src/screens/Console/valid-routes.ts +++ b/portal-ui/src/screens/Console/valid-routes.ts @@ -40,7 +40,7 @@ import { TraceMenuIcon, UsersMenuIcon, } from "../../icons/SidebarMenus"; -import { hasPermission } from "../../common/SecureComponent/SecureComponent"; +import { hasPermission } from "../../common/SecureComponent"; import WatchIcon from "../../icons/WatchIcon"; import RegisterMenuIcon from "../../icons/SidebarMenus/RegisterMenuIcon"; import {