github.com/minio/console@v1.4.1/web-app/src/screens/Console/Buckets/ListBuckets/UploadFilesButton.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2022 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 import React, { Fragment, useState } from "react"; 18 import { CSSObject } from "styled-components"; 19 import { Button, DropdownSelector, UploadFolderIcon, UploadIcon } from "mds"; 20 import { 21 IAM_SCOPES, 22 permissionTooltipHelper, 23 } from "../../../../common/SecureComponent/permissions"; 24 import { hasPermission } from "../../../../common/SecureComponent"; 25 import TooltipWrapper from "../../Common/TooltipWrapper/TooltipWrapper"; 26 import { useSelector } from "react-redux"; 27 import { AppState } from "../../../../store"; 28 import { getSessionGrantsWildCard } from "./UploadPermissionUtils"; 29 30 interface IUploadFilesButton { 31 uploadPath: string; 32 bucketName: string; 33 forceDisable?: boolean; 34 uploadFileFunction: (closeFunction: () => void) => void; 35 uploadFolderFunction: (closeFunction: () => void) => void; 36 overrideStyles?: CSSObject; 37 } 38 39 const UploadFilesButton = ({ 40 uploadPath, 41 bucketName, 42 forceDisable = false, 43 uploadFileFunction, 44 uploadFolderFunction, 45 overrideStyles = {}, 46 }: IUploadFilesButton) => { 47 const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); 48 const [uploadOptionsOpen, uploadOptionsSetOpen] = useState<boolean>(false); 49 50 const anonymousMode = useSelector( 51 (state: AppState) => state.system.anonymousMode, 52 ); 53 54 const sessionGrants = useSelector((state: AppState) => 55 state.console.session ? state.console.session.permissions || {} : {}, 56 ); 57 58 const putObjectPermScopes = [ 59 IAM_SCOPES.S3_PUT_OBJECT, 60 IAM_SCOPES.S3_PUT_ACTIONS, 61 ]; 62 63 const sessionGrantWildCards = getSessionGrantsWildCard( 64 sessionGrants, 65 uploadPath, 66 putObjectPermScopes, 67 ); 68 69 const openUploadMenu = Boolean(anchorEl); 70 const handleClick = (event: React.MouseEvent<HTMLElement>) => { 71 uploadOptionsSetOpen(!uploadOptionsOpen); 72 setAnchorEl(event.currentTarget); 73 }; 74 const handleCloseUpload = () => { 75 setAnchorEl(null); 76 }; 77 78 const uploadObjectAllowed = 79 hasPermission( 80 [uploadPath, ...sessionGrantWildCards], 81 putObjectPermScopes, 82 ) || anonymousMode; 83 84 const uploadFolderAllowed = hasPermission( 85 [bucketName, ...sessionGrantWildCards], 86 putObjectPermScopes, 87 false, 88 true, 89 ); 90 91 const uploadFolderAction = (action: string) => { 92 if (action === "folder") { 93 uploadFolderFunction(handleCloseUpload); 94 return; 95 } 96 97 uploadFileFunction(handleCloseUpload); 98 }; 99 100 const uploadEnabled: boolean = uploadObjectAllowed || uploadFolderAllowed; 101 102 return ( 103 <Fragment> 104 <TooltipWrapper 105 tooltip={ 106 uploadEnabled 107 ? "Upload Files" 108 : permissionTooltipHelper( 109 [IAM_SCOPES.S3_PUT_OBJECT, IAM_SCOPES.S3_PUT_ACTIONS], 110 "upload files to this bucket", 111 ) 112 } 113 > 114 <Button 115 id={"upload-main"} 116 aria-controls={`upload-main-menu`} 117 aria-haspopup="true" 118 aria-expanded={openUploadMenu ? "true" : undefined} 119 onClick={handleClick} 120 label={"Upload"} 121 icon={<UploadIcon />} 122 variant={"callAction"} 123 disabled={forceDisable || !uploadEnabled} 124 sx={overrideStyles} 125 /> 126 </TooltipWrapper> 127 <DropdownSelector 128 id={"upload-main-menu"} 129 options={[ 130 { 131 label: "Upload File", 132 icon: <UploadIcon />, 133 value: "file", 134 disabled: !uploadObjectAllowed || forceDisable, 135 }, 136 { 137 label: "Upload Folder", 138 icon: <UploadFolderIcon />, 139 value: "folder", 140 disabled: !uploadFolderAllowed || forceDisable, 141 }, 142 ]} 143 selectedOption={""} 144 onSelect={(nValue) => uploadFolderAction(nValue)} 145 hideTriggerAction={() => { 146 uploadOptionsSetOpen(false); 147 }} 148 open={uploadOptionsOpen} 149 anchorEl={anchorEl} 150 anchorOrigin={"end"} 151 useAnchorWidth 152 /> 153 </Fragment> 154 ); 155 }; 156 157 export default UploadFilesButton;