Adding SecureComponent to list groups and group details page (#1238)

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>

Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
Lenin Alevski
2021-11-18 19:51:40 -08:00
committed by GitHub
parent f0d5398748
commit 7f5de2d70e
3 changed files with 188 additions and 94 deletions

View File

@@ -112,6 +112,11 @@ export const IAM_SCOPES = {
S3_GET_BUCKET_LOCATION: "s3:GetBucketLocation",
S3_DELETE_BUCKET_POLICY: "s3:DeleteBucketPolicy",
S3_ABORT_MULTIPART_UPLOAD: "s3:AbortMultipartUpload",
ADMIN_ADD_USER_TO_GROUP: "admin:AddUserToGroup",
ADMIN_REMOVE_USER_FROM_GROUP: "admin:RemoveUserFromGroup",
ADMIN_GET_GROUP: "admin:GetGroup",
ADMIN_ENABLE_GROUP: "admin:EnableGroup",
ADMIN_DISABLE_GROUP: "admin:DisableGroup",
S3_ALL_ACTIONS: "s3:*",
ADMIN_ALL_ACTIONS: "admin:*",
};

View File

@@ -43,6 +43,13 @@ import history from "../../../history";
import AButton from "../Common/AButton/AButton";
import PageLayout from "../Common/Layout/PageLayout";
import SearchBox from "../Common/SearchBox";
import {
CONSOLE_UI_RESOURCE,
IAM_SCOPES,
} from "../../../common/SecureComponent/permissions";
import SecureComponent, {
hasPermission,
} from "../../../common/SecureComponent/SecureComponent";
interface IGroupsProps {
classes: any;
@@ -85,27 +92,43 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
isLoading(true);
}, []);
const displayGroups = hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_LIST_GROUPS,
]);
const deleteGroup = hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_REMOVE_USER_FROM_GROUP,
]);
const getGroup = hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_GET_GROUP,
]);
useEffect(() => {
if (loading) {
const fetchRecords = () => {
api
.invoke("GET", `/api/v1/groups`)
.then((res: GroupsList) => {
let resGroups: string[] = [];
if (res.groups !== null) {
resGroups = res.groups.sort(stringSort);
}
setRecords(resGroups);
isLoading(false);
})
.catch((err: ErrorResponseHandler) => {
setErrorSnackMessage(err);
isLoading(false);
});
};
fetchRecords();
if (displayGroups) {
const fetchRecords = () => {
api
.invoke("GET", `/api/v1/groups`)
.then((res: GroupsList) => {
let resGroups: string[] = [];
if (res.groups !== null) {
resGroups = res.groups.sort(stringSort);
}
setRecords(resGroups);
isLoading(false);
})
.catch((err: ErrorResponseHandler) => {
setErrorSnackMessage(err);
isLoading(false);
});
};
fetchRecords();
} else {
isLoading(false);
}
}
}, [loading, setErrorSnackMessage]);
}, [loading, setErrorSnackMessage, displayGroups]);
const closeAddModalAndRefresh = () => {
setGroupOpen(false);
@@ -134,8 +157,16 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
};
const tableActions = [
{ type: "view", onClick: viewAction },
{ type: "delete", onClick: deleteAction },
{
type: "view",
onClick: viewAction,
disableButtonFunction: () => !getGroup,
},
{
type: "delete",
onClick: deleteAction,
disableButtonFunction: () => !deleteGroup,
},
];
return (
@@ -173,19 +204,27 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
onChange={setFilter}
classes={classes}
/>
<Button
variant="contained"
color="primary"
endIcon={<AddIcon />}
onClick={() => {
setSelectedGroup(null);
setGroupOpen(true);
}}
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[
IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP,
IAM_SCOPES.ADMIN_LIST_USERS,
]}
matchAll
>
Create Group
</Button>
<Button
variant="contained"
color="primary"
endIcon={<AddIcon />}
onClick={() => {
setSelectedGroup(null);
setGroupOpen(true);
}}
>
Create Group
</Button>
</SecureComponent>
</Grid>
{loading && <LinearProgress />}
{!loading && (
<Fragment>
@@ -245,18 +284,27 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
users with membership in that group inherit that policy.
Groups support more simplified management of user
permissions on the MinIO Tenant.
<br />
<br />
To get started,{" "}
<AButton
onClick={() => {
setSelectedGroup(null);
setGroupOpen(true);
}}
<SecureComponent
resource="console-ui"
scopes={[
IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP,
IAM_SCOPES.ADMIN_LIST_USERS,
]}
matchAll
>
Create a Group
</AButton>
.
<br />
<br />
To get started,{" "}
<AButton
onClick={() => {
setSelectedGroup(null);
setGroupOpen(true);
}}
>
Create a Group
</AButton>
.
</SecureComponent>
</Fragment>
}
/>

View File

@@ -33,6 +33,13 @@ import BackLink from "../../../common/BackLink";
import PanelTitle from "../Common/PanelTitle/PanelTitle";
import BoxIconButton from "../Common/BoxIconButton/BoxIconButton";
import SearchBox from "../Common/SearchBox";
import {
CONSOLE_UI_RESOURCE,
IAM_SCOPES,
} from "../../../common/SecureComponent/permissions";
import SecureComponent, {
hasPermission,
} from "../../../common/SecureComponent/SecureComponent";
const styles = (theme: Theme) =>
createStyles({
@@ -154,16 +161,22 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
const isGroupEnabled = groupEnabled === "enabled";
const memberActionText = members.length > 0 ? "Edit Members" : "Add Members";
const getGroupDetails = hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_GET_GROUP,
]);
function fetchGroupInfo() {
api
.invoke("GET", `/api/v1/group?name=${encodeURI(groupName)}`)
.then((res: any) => {
setGroupDetails(res);
})
.catch((err) => {
setModalErrorSnackMessage(err);
setGroupDetails({});
});
if (getGroupDetails) {
api
.invoke("GET", `/api/v1/group?name=${encodeURI(groupName)}`)
.then((res: any) => {
setGroupDetails(res);
})
.catch((err) => {
setModalErrorSnackMessage(err);
setGroupDetails({});
});
}
}
function toggleGroupStatus(nextStatus: boolean) {
@@ -192,28 +205,40 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
}}
classes={classes}
/>
<Button
variant="contained"
color="primary"
endIcon={<UsersIcon />}
size="medium"
onClick={() => {
setUsersOpen(true);
}}
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP]}
errorProps={{ disabled: true }}
>
{memberActionText}
</Button>
<Button
variant="contained"
color="primary"
endIcon={<UsersIcon />}
size="medium"
onClick={() => {
setUsersOpen(true);
}}
>
{memberActionText}
</Button>
</SecureComponent>
</div>
<div className={classes.tableBlock}>
<TableWrapper
columns={[{ label: "Access Key", elementKey: "" }]}
selectedItems={[]}
isLoading={false}
records={filteredMembers}
entityName="Users"
idField=""
/>
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[IAM_SCOPES.ADMIN_LIST_USERS]}
errorProps={{ disabled: true }}
>
<TableWrapper
columns={[{ label: "Access Key", elementKey: "" }]}
selectedItems={[]}
isLoading={false}
records={filteredMembers}
entityName="Users"
idField=""
/>
</SecureComponent>
</div>
</React.Fragment>
);
@@ -274,31 +299,47 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
<span className={classes.statusValue}>
{isGroupEnabled ? "Enabled" : "Disabled"}
</span>
<FormSwitchWrapper
indicatorLabels={["Enabled", "Disabled"]}
checked={isGroupEnabled}
value={"group_enabled"}
id="group-status"
name="group-status"
onChange={() => {
toggleGroupStatus(!isGroupEnabled);
}}
switchOnly
/>
<Tooltip title="Delete Group">
<div className={classes.spacerLeft}>
<BoxIconButton
color="primary"
aria-label="Delete Group"
onClick={() => {
setDeleteOpen(true);
}}
size="large"
>
<TrashIcon />
</BoxIconButton>
</div>
</Tooltip>
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[
IAM_SCOPES.ADMIN_ENABLE_GROUP,
IAM_SCOPES.ADMIN_DISABLE_GROUP,
]}
errorProps={{ disabled: true }}
matchAll
>
<FormSwitchWrapper
indicatorLabels={["Enabled", "Disabled"]}
checked={isGroupEnabled}
value={"group_enabled"}
id="group-status"
name="group-status"
onChange={() => {
toggleGroupStatus(!isGroupEnabled);
}}
switchOnly
/>
</SecureComponent>
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[IAM_SCOPES.ADMIN_REMOVE_USER_FROM_GROUP]}
>
<Tooltip title="Delete Group">
<div className={classes.spacerLeft}>
<BoxIconButton
color="primary"
aria-label="Delete Group"
onClick={() => {
setDeleteOpen(true);
}}
size="large"
>
<TrashIcon />
</BoxIconButton>
</div>
</Tooltip>
</SecureComponent>
</Fragment>
}
/>