Skip to content

Commit c4c6d48

Browse files
authored
Tooltips for Bucket Lifecycle, Delete bucket, Manage bucket (#2334)
1 parent 43c5f90 commit c4c6d48

File tree

4 files changed

+103
-11
lines changed

4 files changed

+103
-11
lines changed

portal-ui/src/common/SecureComponent/permissions.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const IAM_ROLES = {
1818
BUCKET_OWNER: "BUCKET_OWNER", // upload/delete objects from the bucket
1919
BUCKET_VIEWER: "BUCKET_VIEWER", // only view objects on the bucket
2020
BUCKET_ADMIN: "BUCKET_ADMIN", // administrate the bucket
21+
BUCKET_LIFECYCLE: "BUCKET_LIFECYCLE", // can manage bucket lifecycle
2122
};
2223

2324
export const IAM_SCOPES = {
@@ -281,6 +282,12 @@ export const IAM_PERMISSIONS = {
281282
IAM_SCOPES.ADMIN_LIST_USERS,
282283
IAM_SCOPES.ADMIN_HEAL,
283284
],
285+
[IAM_ROLES.BUCKET_LIFECYCLE]: [
286+
IAM_SCOPES.S3_GET_LIFECYCLE_CONFIGURATION,
287+
IAM_SCOPES.S3_PUT_LIFECYCLE_CONFIGURATION,
288+
IAM_SCOPES.ADMIN_LIST_TIERS,
289+
IAM_SCOPES.ADMIN_SET_TIER,
290+
],
284291
};
285292

286293
// application pages/routes and required scopes/roles
@@ -434,6 +441,10 @@ export const permissionTooltipHelper = (scopes: string[], name: string) => {
434441
name +
435442
". Please ask your MinIO administrator to grant you " +
436443
scopes +
437-
" permission in order to enable Versioning."
444+
" permission" +
445+
(scopes.length > 1 ? "s" : "") +
446+
" in order to enable " +
447+
name +
448+
"."
438449
);
439450
};

portal-ui/src/screens/Console/Buckets/BucketDetails/BucketDetails.tsx

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ import ScreenTitle from "../../Common/ScreenTitle/ScreenTitle";
4545
import { Box } from "@mui/material";
4646

4747
import RefreshIcon from "../../../../icons/RefreshIcon";
48-
import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions";
48+
import {
49+
IAM_SCOPES,
50+
IAM_PERMISSIONS,
51+
IAM_ROLES,
52+
permissionTooltipHelper,
53+
} from "../../../../common/SecureComponent/permissions";
4954
import PageLayout from "../../Common/Layout/PageLayout";
5055
import VerticalTabs from "../../Common/VerticalTabs/VerticalTabs";
5156
import BackLink from "../../../../common/BackLink";
@@ -136,6 +141,14 @@ const BucketDetails = ({ classes }: IBucketDetailsProps) => {
136141
selTab = selTab ? selTab : "summary";
137142

138143
const [activeTab, setActiveTab] = useState(selTab);
144+
const canDelete = hasPermission(bucketName, [
145+
IAM_SCOPES.S3_DELETE_BUCKET,
146+
IAM_SCOPES.S3_FORCE_DELETE_BUCKET,
147+
]);
148+
const canBrowse = hasPermission(
149+
bucketName,
150+
IAM_PERMISSIONS[IAM_ROLES.BUCKET_VIEWER]
151+
);
139152

140153
useEffect(() => {
141154
setActiveTab(selTab);
@@ -209,7 +222,16 @@ const BucketDetails = ({ classes }: IBucketDetailsProps) => {
209222
<PageHeader
210223
label={<BackLink to={"/buckets"} label={"Buckets"} />}
211224
actions={
212-
<TooltipWrapper tooltip={"Browse Bucket"}>
225+
<TooltipWrapper
226+
tooltip={
227+
canBrowse
228+
? "Browse Bucket"
229+
: permissionTooltipHelper(
230+
IAM_PERMISSIONS[IAM_ROLES.BUCKET_VIEWER],
231+
"browsing this bucket"
232+
)
233+
}
234+
>
213235
<Button
214236
id={"switch-browse-view"}
215237
aria-label="Browse Bucket"
@@ -220,6 +242,7 @@ const BucketDetails = ({ classes }: IBucketDetailsProps) => {
220242
style={{
221243
padding: "0 10px",
222244
}}
245+
disabled={!canBrowse}
223246
/>
224247
</TooltipWrapper>
225248
}
@@ -260,7 +283,19 @@ const BucketDetails = ({ classes }: IBucketDetailsProps) => {
260283
resource={bucketName}
261284
errorProps={{ disabled: true }}
262285
>
263-
<TooltipWrapper tooltip={"Delete Bucket"}>
286+
<TooltipWrapper
287+
tooltip={
288+
canDelete
289+
? ""
290+
: permissionTooltipHelper(
291+
[
292+
IAM_SCOPES.S3_DELETE_BUCKET,
293+
IAM_SCOPES.S3_FORCE_DELETE_BUCKET,
294+
],
295+
"deleting this bucket"
296+
)
297+
}
298+
>
264299
<Button
265300
id={"delete-bucket-button"}
266301
onClick={() => {
@@ -269,6 +304,7 @@ const BucketDetails = ({ classes }: IBucketDetailsProps) => {
269304
label={"Delete Bucket"}
270305
icon={<TrashIcon />}
271306
variant={"secondary"}
307+
disabled={!canDelete}
272308
/>
273309
</TooltipWrapper>
274310
</SecureComponent>

portal-ui/src/screens/Console/Buckets/ListBuckets/BucketListItem.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ import { Link, useNavigate } from "react-router-dom";
3838
import {
3939
IAM_PERMISSIONS,
4040
IAM_ROLES,
41+
permissionTooltipHelper,
4142
} from "../../../../common/SecureComponent/permissions";
4243
import { SecureComponent } from "../../../../common/SecureComponent";
4344
import clsx from "clsx";
4445
import TooltipWrapper from "../../Common/TooltipWrapper/TooltipWrapper";
46+
import { hasPermission } from "../../../../common/SecureComponent";
4547

4648
const styles = (theme: Theme) =>
4749
createStyles({
@@ -187,6 +189,11 @@ const BucketListItem = ({
187189
const quota = get(bucket, "details.quota.quota", "0");
188190
const quotaForString = calculateBytes(quota, true, false);
189191

192+
const manageAllowed = hasPermission(
193+
bucket.name,
194+
IAM_PERMISSIONS[IAM_ROLES.BUCKET_ADMIN]
195+
);
196+
190197
const accessToStr = (bucket: Bucket): string => {
191198
if (bucket.rw_access?.read && !bucket.rw_access?.write) {
192199
return "R";
@@ -249,14 +256,24 @@ const BucketListItem = ({
249256
scopes={IAM_PERMISSIONS[IAM_ROLES.BUCKET_ADMIN]}
250257
resource={bucket.name}
251258
>
252-
<TooltipWrapper tooltip={"Manage"}>
259+
<TooltipWrapper
260+
tooltip={
261+
manageAllowed
262+
? "Manage Bucket"
263+
: permissionTooltipHelper(
264+
IAM_PERMISSIONS[IAM_ROLES.BUCKET_ADMIN],
265+
"managing this bucket"
266+
)
267+
}
268+
>
253269
<Button
254270
onClick={() => navigate(`/buckets/${bucket.name}/admin`)}
255271
label={"Manage"}
256272
icon={<SettingsIcon />}
257273
color={"primary"}
258274
variant={"regular"}
259275
id={`manage-${bucket.name}`}
276+
disabled={!manageAllowed}
260277
/>
261278
</TooltipWrapper>
262279
</SecureComponent>

portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ import { SecureComponent } from "../../../../common/SecureComponent";
4747
import {
4848
CONSOLE_UI_RESOURCE,
4949
IAM_PAGES,
50+
IAM_PERMISSIONS,
51+
IAM_ROLES,
5052
IAM_SCOPES,
53+
permissionTooltipHelper,
5154
} from "../../../../common/SecureComponent/permissions";
5255
import PageLayout from "../../Common/Layout/PageLayout";
5356
import SearchBox from "../../Common/SearchBox";
@@ -105,6 +108,7 @@ const ListBuckets = ({ classes }: IListBucketsProps) => {
105108
const [replicationModalOpen, setReplicationModalOpen] =
106109
useState<boolean>(false);
107110
const [lifecycleModalOpen, setLifecycleModalOpen] = useState<boolean>(false);
111+
const [canPutLifecycle, setCanPutLifecycle] = useState<boolean>(false);
108112
const [bulkSelect, setBulkSelect] = useState<boolean>(false);
109113

110114
const features = useSelector(selFeatures);
@@ -172,6 +176,16 @@ const ListBuckets = ({ classes }: IListBucketsProps) => {
172176
}
173177
};
174178

179+
useEffect(() => {
180+
var failLifecycle = false;
181+
selectedBuckets.forEach((bucket: string) => {
182+
hasPermission(bucket, IAM_PERMISSIONS[IAM_ROLES.BUCKET_LIFECYCLE], true)
183+
? setCanPutLifecycle(true)
184+
: (failLifecycle = true);
185+
});
186+
failLifecycle ? setCanPutLifecycle(false) : setCanPutLifecycle(true);
187+
}, [selectedBuckets]);
188+
175189
const renderItemLine = (index: number) => {
176190
const bucket = filteredRecords[index] || null;
177191
if (bucket) {
@@ -282,15 +296,28 @@ const ListBuckets = ({ classes }: IListBucketsProps) => {
282296
</TooltipWrapper>
283297
)}
284298

285-
<TooltipWrapper tooltip={"Set Lifecycle"}>
299+
<TooltipWrapper
300+
tooltip={
301+
selectedBuckets.length === 0
302+
? bulkSelect
303+
? "Please select at least one bucket on which to configure Lifecycle"
304+
: "Use the Select Multiple Buckets button to choose buckets on which to configure Lifecycle"
305+
: canPutLifecycle
306+
? "Set Lifecycle"
307+
: permissionTooltipHelper(
308+
IAM_PERMISSIONS[IAM_ROLES.BUCKET_LIFECYCLE],
309+
"configuring lifecycle for the selected buckets"
310+
)
311+
}
312+
>
286313
<Button
287314
id={"set-lifecycle"}
288315
onClick={() => {
289316
setLifecycleModalOpen(true);
290317
}}
291318
icon={<LifecycleConfigIcon />}
292319
variant={"regular"}
293-
disabled={selectedBuckets.length === 0}
320+
disabled={selectedBuckets.length === 0 || !canPutLifecycle}
294321
/>
295322
</TooltipWrapper>
296323

@@ -323,10 +350,11 @@ const ListBuckets = ({ classes }: IListBucketsProps) => {
323350
<TooltipWrapper
324351
tooltip={
325352
canCreateBucket
326-
? "Create Bucket"
327-
: "You require additional permissions in order to create a new Bucket. Please ask your MinIO administrator to grant you " +
328-
IAM_SCOPES.S3_CREATE_BUCKET +
329-
" permission in order to create a Bucket."
353+
? ""
354+
: permissionTooltipHelper(
355+
[IAM_SCOPES.S3_CREATE_BUCKET],
356+
"creating a bucket"
357+
)
330358
}
331359
>
332360
<Button

0 commit comments

Comments
 (0)