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:
@@ -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:*",
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user