From d8b387434bf3958d86e7723b53ebfbb42f035841 Mon Sep 17 00:00:00 2001 From: Lenin Alevski Date: Fri, 28 Jan 2022 16:16:38 -0600 Subject: [PATCH] Enable/Disable upload file and folder button for bucket (#1486) --- .../SecureComponent/SecureComponent.tsx | 23 +++++- .../Objects/ListObjects/ListObjects.tsx | 80 ++++++++++--------- .../Buckets/ListBuckets/UploadFilesButton.tsx | 79 ++++++++++++------ 3 files changed, 117 insertions(+), 65 deletions(-) diff --git a/portal-ui/src/common/SecureComponent/SecureComponent.tsx b/portal-ui/src/common/SecureComponent/SecureComponent.tsx index f2544c446..575475aa6 100644 --- a/portal-ui/src/common/SecureComponent/SecureComponent.tsx +++ b/portal-ui/src/common/SecureComponent/SecureComponent.tsx @@ -21,7 +21,8 @@ import { hasAccessToResource } from "./permissions"; export const hasPermission = ( resource: string | undefined, scopes: string[], - matchAll?: boolean + matchAll?: boolean, + containsResource?: boolean ) => { if (!resource) { return false; @@ -33,8 +34,17 @@ export const hasPermission = ( sessionGrants[`arn:aws:s3:::${resource}/*`] || []; const globalGrants = sessionGrants["arn:aws:s3:::*"] || []; + let containsResourceGrants: string[] = []; + if (containsResource) { + const matchResource = `arn:aws:s3:::${resource}`; + for (const [key, value] of Object.entries(sessionGrants)) { + if (key.includes(matchResource)) { + containsResourceGrants = containsResourceGrants.concat(value); + } + } + } return hasAccessToResource( - [...resourceGrants, ...globalGrants], + [...resourceGrants, ...globalGrants, ...containsResourceGrants], scopes, matchAll ); @@ -47,6 +57,7 @@ interface ISecureComponentProps { children: any; scopes: string[]; resource: string; + containsResource?: boolean; } const SecureComponent = ({ @@ -56,8 +67,14 @@ const SecureComponent = ({ matchAll = false, scopes = [], resource, + containsResource = false, }: ISecureComponentProps) => { - const permissionGranted = hasPermission(resource, scopes, matchAll); + const permissionGranted = hasPermission( + resource, + scopes, + matchAll, + containsResource + ); if (!permissionGranted && !errorProps) return ; if (!permissionGranted && errorProps) { return Array.isArray(children) ? ( 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 c39defe8f..f7a9f3a75 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 @@ -142,7 +142,7 @@ const styles = (theme: Theme) => right: 1, width: 5, height: 5, - minWidth: 5 + minWidth: 5, }, }, screenTitle: { @@ -764,7 +764,12 @@ const ListObjects = ({ xhr.status === 400 || xhr.status === 500 ) { - setSnackBarMessage(errorMessage); + if (xhr.response) { + const err = JSON.parse(xhr.response); + setSnackBarMessage(err.detailedMessage); + } else { + setSnackBarMessage(errorMessage); + } } if (xhr.status === 413) { setSnackBarMessage("Error - File size too large"); @@ -1061,7 +1066,10 @@ const ListObjects = ({ }); } }; - + let uploadPath = [bucketName]; + if (currentPath.length > 0) { + uploadPath = uploadPath.concat(currentPath); + } return ( {shareFileModalOpen && selectedPreview && ( @@ -1131,42 +1139,36 @@ const ListObjects = ({ } actions={ - - - { - if (fileUpload && fileUpload.current) { - fileUpload.current.click(); - } - closeMenu(); - }} - uploadFolderFunction={(closeMenu) => { - if (folderUpload && folderUpload.current) { - folderUpload.current.click(); - } - closeMenu(); - }} - /> - - - - + + + { + if (fileUpload && fileUpload.current) { + fileUpload.current.click(); + } + closeMenu(); + }} + uploadFolderFunction={(closeMenu) => { + if (folderUpload && folderUpload.current) { + folderUpload.current.click(); + } + closeMenu(); + }} + /> } /> diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/UploadFilesButton.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/UploadFilesButton.tsx index 67016ce04..8266cc85a 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/UploadFilesButton.tsx +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/UploadFilesButton.tsx @@ -23,9 +23,15 @@ import ListItemText from "@mui/material/ListItemText"; import ListItemIcon from "@mui/material/ListItemIcon"; import { UploadFolderIcon, UploadIcon } from "../../../../icons"; import RBIconButton from "../BucketDetails/SummaryItems/RBIconButton"; +import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions"; +import SecureComponent, { + hasPermission, +} from "../../../../common/SecureComponent/SecureComponent"; interface IUploadFilesButton { - buttonDisabled?: boolean; + uploadPath: string; + bucketName: string; + forceDisable?: boolean; uploadFileFunction: (closeFunction: () => void) => void; uploadFolderFunction: (closeFunction: () => void) => void; classes: any; @@ -43,7 +49,9 @@ const styles = (theme: Theme) => }); const UploadFilesButton = ({ - buttonDisabled = false, + uploadPath, + bucketName, + forceDisable = false, uploadFileFunction, uploadFolderFunction, classes, @@ -57,6 +65,18 @@ const UploadFilesButton = ({ setAnchorEl(null); }; + const uploadObjectAllowed = hasPermission(uploadPath, [ + IAM_SCOPES.S3_PUT_OBJECT, + ]); + const uploadFolderAllowed = hasPermission( + bucketName, + [IAM_SCOPES.S3_PUT_OBJECT], + false, + true + ); + + const uploadEnabled: boolean = uploadObjectAllowed || uploadFolderAllowed; + return ( } color="primary" variant={"contained"} - disabled={buttonDisabled} + disabled={forceDisable || !uploadEnabled} /> - { - uploadFileFunction(handleCloseUpload); - }} - disabled={buttonDisabled} + - - - {" "} - Upload File - - { - uploadFolderFunction(handleCloseUpload); - }} - disabled={buttonDisabled} + { + uploadFileFunction(handleCloseUpload); + }} + disabled={forceDisable} + > + + + + Upload File + + + - - - {" "} - Upload Folder - + { + uploadFolderFunction(handleCloseUpload); + }} + disabled={forceDisable} + > + + + + Upload Folder + + );