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_GET_BUCKET_LOCATION: "s3:GetBucketLocation",
|
||||||
S3_DELETE_BUCKET_POLICY: "s3:DeleteBucketPolicy",
|
S3_DELETE_BUCKET_POLICY: "s3:DeleteBucketPolicy",
|
||||||
S3_ABORT_MULTIPART_UPLOAD: "s3:AbortMultipartUpload",
|
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:*",
|
S3_ALL_ACTIONS: "s3:*",
|
||||||
ADMIN_ALL_ACTIONS: "admin:*",
|
ADMIN_ALL_ACTIONS: "admin:*",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,6 +43,13 @@ import history from "../../../history";
|
|||||||
import AButton from "../Common/AButton/AButton";
|
import AButton from "../Common/AButton/AButton";
|
||||||
import PageLayout from "../Common/Layout/PageLayout";
|
import PageLayout from "../Common/Layout/PageLayout";
|
||||||
import SearchBox from "../Common/SearchBox";
|
import SearchBox from "../Common/SearchBox";
|
||||||
|
import {
|
||||||
|
CONSOLE_UI_RESOURCE,
|
||||||
|
IAM_SCOPES,
|
||||||
|
} from "../../../common/SecureComponent/permissions";
|
||||||
|
import SecureComponent, {
|
||||||
|
hasPermission,
|
||||||
|
} from "../../../common/SecureComponent/SecureComponent";
|
||||||
|
|
||||||
interface IGroupsProps {
|
interface IGroupsProps {
|
||||||
classes: any;
|
classes: any;
|
||||||
@@ -85,27 +92,43 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
|||||||
isLoading(true);
|
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(() => {
|
useEffect(() => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
const fetchRecords = () => {
|
if (displayGroups) {
|
||||||
api
|
const fetchRecords = () => {
|
||||||
.invoke("GET", `/api/v1/groups`)
|
api
|
||||||
.then((res: GroupsList) => {
|
.invoke("GET", `/api/v1/groups`)
|
||||||
let resGroups: string[] = [];
|
.then((res: GroupsList) => {
|
||||||
if (res.groups !== null) {
|
let resGroups: string[] = [];
|
||||||
resGroups = res.groups.sort(stringSort);
|
if (res.groups !== null) {
|
||||||
}
|
resGroups = res.groups.sort(stringSort);
|
||||||
setRecords(resGroups);
|
}
|
||||||
isLoading(false);
|
setRecords(resGroups);
|
||||||
})
|
isLoading(false);
|
||||||
.catch((err: ErrorResponseHandler) => {
|
})
|
||||||
setErrorSnackMessage(err);
|
.catch((err: ErrorResponseHandler) => {
|
||||||
isLoading(false);
|
setErrorSnackMessage(err);
|
||||||
});
|
isLoading(false);
|
||||||
};
|
});
|
||||||
fetchRecords();
|
};
|
||||||
|
fetchRecords();
|
||||||
|
} else {
|
||||||
|
isLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [loading, setErrorSnackMessage]);
|
}, [loading, setErrorSnackMessage, displayGroups]);
|
||||||
|
|
||||||
const closeAddModalAndRefresh = () => {
|
const closeAddModalAndRefresh = () => {
|
||||||
setGroupOpen(false);
|
setGroupOpen(false);
|
||||||
@@ -134,8 +157,16 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const tableActions = [
|
const tableActions = [
|
||||||
{ type: "view", onClick: viewAction },
|
{
|
||||||
{ type: "delete", onClick: deleteAction },
|
type: "view",
|
||||||
|
onClick: viewAction,
|
||||||
|
disableButtonFunction: () => !getGroup,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "delete",
|
||||||
|
onClick: deleteAction,
|
||||||
|
disableButtonFunction: () => !deleteGroup,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -173,19 +204,27 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
|||||||
onChange={setFilter}
|
onChange={setFilter}
|
||||||
classes={classes}
|
classes={classes}
|
||||||
/>
|
/>
|
||||||
<Button
|
<SecureComponent
|
||||||
variant="contained"
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
color="primary"
|
scopes={[
|
||||||
endIcon={<AddIcon />}
|
IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP,
|
||||||
onClick={() => {
|
IAM_SCOPES.ADMIN_LIST_USERS,
|
||||||
setSelectedGroup(null);
|
]}
|
||||||
setGroupOpen(true);
|
matchAll
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Create Group
|
<Button
|
||||||
</Button>
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
endIcon={<AddIcon />}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedGroup(null);
|
||||||
|
setGroupOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Create Group
|
||||||
|
</Button>
|
||||||
|
</SecureComponent>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{loading && <LinearProgress />}
|
{loading && <LinearProgress />}
|
||||||
{!loading && (
|
{!loading && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@@ -245,18 +284,27 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => {
|
|||||||
users with membership in that group inherit that policy.
|
users with membership in that group inherit that policy.
|
||||||
Groups support more simplified management of user
|
Groups support more simplified management of user
|
||||||
permissions on the MinIO Tenant.
|
permissions on the MinIO Tenant.
|
||||||
<br />
|
<SecureComponent
|
||||||
<br />
|
resource="console-ui"
|
||||||
To get started,{" "}
|
scopes={[
|
||||||
<AButton
|
IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP,
|
||||||
onClick={() => {
|
IAM_SCOPES.ADMIN_LIST_USERS,
|
||||||
setSelectedGroup(null);
|
]}
|
||||||
setGroupOpen(true);
|
matchAll
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Create a Group
|
<br />
|
||||||
</AButton>
|
<br />
|
||||||
.
|
To get started,{" "}
|
||||||
|
<AButton
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedGroup(null);
|
||||||
|
setGroupOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Create a Group
|
||||||
|
</AButton>
|
||||||
|
.
|
||||||
|
</SecureComponent>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -33,6 +33,13 @@ import BackLink from "../../../common/BackLink";
|
|||||||
import PanelTitle from "../Common/PanelTitle/PanelTitle";
|
import PanelTitle from "../Common/PanelTitle/PanelTitle";
|
||||||
import BoxIconButton from "../Common/BoxIconButton/BoxIconButton";
|
import BoxIconButton from "../Common/BoxIconButton/BoxIconButton";
|
||||||
import SearchBox from "../Common/SearchBox";
|
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) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
@@ -154,16 +161,22 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
const isGroupEnabled = groupEnabled === "enabled";
|
const isGroupEnabled = groupEnabled === "enabled";
|
||||||
const memberActionText = members.length > 0 ? "Edit Members" : "Add Members";
|
const memberActionText = members.length > 0 ? "Edit Members" : "Add Members";
|
||||||
|
|
||||||
|
const getGroupDetails = hasPermission(CONSOLE_UI_RESOURCE, [
|
||||||
|
IAM_SCOPES.ADMIN_GET_GROUP,
|
||||||
|
]);
|
||||||
|
|
||||||
function fetchGroupInfo() {
|
function fetchGroupInfo() {
|
||||||
api
|
if (getGroupDetails) {
|
||||||
.invoke("GET", `/api/v1/group?name=${encodeURI(groupName)}`)
|
api
|
||||||
.then((res: any) => {
|
.invoke("GET", `/api/v1/group?name=${encodeURI(groupName)}`)
|
||||||
setGroupDetails(res);
|
.then((res: any) => {
|
||||||
})
|
setGroupDetails(res);
|
||||||
.catch((err) => {
|
})
|
||||||
setModalErrorSnackMessage(err);
|
.catch((err) => {
|
||||||
setGroupDetails({});
|
setModalErrorSnackMessage(err);
|
||||||
});
|
setGroupDetails({});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleGroupStatus(nextStatus: boolean) {
|
function toggleGroupStatus(nextStatus: boolean) {
|
||||||
@@ -192,28 +205,40 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
}}
|
}}
|
||||||
classes={classes}
|
classes={classes}
|
||||||
/>
|
/>
|
||||||
<Button
|
<SecureComponent
|
||||||
variant="contained"
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
color="primary"
|
scopes={[IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP]}
|
||||||
endIcon={<UsersIcon />}
|
errorProps={{ disabled: true }}
|
||||||
size="medium"
|
|
||||||
onClick={() => {
|
|
||||||
setUsersOpen(true);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{memberActionText}
|
<Button
|
||||||
</Button>
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
endIcon={<UsersIcon />}
|
||||||
|
size="medium"
|
||||||
|
onClick={() => {
|
||||||
|
setUsersOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{memberActionText}
|
||||||
|
</Button>
|
||||||
|
</SecureComponent>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={classes.tableBlock}>
|
<div className={classes.tableBlock}>
|
||||||
<TableWrapper
|
<SecureComponent
|
||||||
columns={[{ label: "Access Key", elementKey: "" }]}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
selectedItems={[]}
|
scopes={[IAM_SCOPES.ADMIN_LIST_USERS]}
|
||||||
isLoading={false}
|
errorProps={{ disabled: true }}
|
||||||
records={filteredMembers}
|
>
|
||||||
entityName="Users"
|
<TableWrapper
|
||||||
idField=""
|
columns={[{ label: "Access Key", elementKey: "" }]}
|
||||||
/>
|
selectedItems={[]}
|
||||||
|
isLoading={false}
|
||||||
|
records={filteredMembers}
|
||||||
|
entityName="Users"
|
||||||
|
idField=""
|
||||||
|
/>
|
||||||
|
</SecureComponent>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
@@ -274,31 +299,47 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
<span className={classes.statusValue}>
|
<span className={classes.statusValue}>
|
||||||
{isGroupEnabled ? "Enabled" : "Disabled"}
|
{isGroupEnabled ? "Enabled" : "Disabled"}
|
||||||
</span>
|
</span>
|
||||||
<FormSwitchWrapper
|
<SecureComponent
|
||||||
indicatorLabels={["Enabled", "Disabled"]}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
checked={isGroupEnabled}
|
scopes={[
|
||||||
value={"group_enabled"}
|
IAM_SCOPES.ADMIN_ENABLE_GROUP,
|
||||||
id="group-status"
|
IAM_SCOPES.ADMIN_DISABLE_GROUP,
|
||||||
name="group-status"
|
]}
|
||||||
onChange={() => {
|
errorProps={{ disabled: true }}
|
||||||
toggleGroupStatus(!isGroupEnabled);
|
matchAll
|
||||||
}}
|
>
|
||||||
switchOnly
|
<FormSwitchWrapper
|
||||||
/>
|
indicatorLabels={["Enabled", "Disabled"]}
|
||||||
<Tooltip title="Delete Group">
|
checked={isGroupEnabled}
|
||||||
<div className={classes.spacerLeft}>
|
value={"group_enabled"}
|
||||||
<BoxIconButton
|
id="group-status"
|
||||||
color="primary"
|
name="group-status"
|
||||||
aria-label="Delete Group"
|
onChange={() => {
|
||||||
onClick={() => {
|
toggleGroupStatus(!isGroupEnabled);
|
||||||
setDeleteOpen(true);
|
}}
|
||||||
}}
|
switchOnly
|
||||||
size="large"
|
/>
|
||||||
>
|
</SecureComponent>
|
||||||
<TrashIcon />
|
|
||||||
</BoxIconButton>
|
<SecureComponent
|
||||||
</div>
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
</Tooltip>
|
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>
|
</Fragment>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user