Added tooltips, button permission UI, for Groups, GroupDetails screens (#2353)
This commit is contained in:
@@ -449,11 +449,15 @@ export const permissionTooltipHelper = (scopes: string[], name: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const listUsersPermissions = [IAM_SCOPES.ADMIN_LIST_USERS];
|
export const listUsersPermissions = [IAM_SCOPES.ADMIN_LIST_USERS];
|
||||||
export const viewUserPermissions = [IAM_SCOPES.ADMIN_GET_USER];
|
|
||||||
export const addUserToGroupPermissions = [IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP];
|
export const addUserToGroupPermissions = [IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP];
|
||||||
|
|
||||||
export const deleteUserPermissions = [IAM_SCOPES.ADMIN_DELETE_USER];
|
export const deleteUserPermissions = [IAM_SCOPES.ADMIN_DELETE_USER];
|
||||||
|
|
||||||
export const enableUserPermissions = [IAM_SCOPES.ADMIN_ENABLE_USER];
|
export const enableUserPermissions = [IAM_SCOPES.ADMIN_ENABLE_USER];
|
||||||
|
|
||||||
export const disableUserPermissions = [IAM_SCOPES.ADMIN_DISABLE_USER];
|
export const disableUserPermissions = [IAM_SCOPES.ADMIN_DISABLE_USER];
|
||||||
|
|
||||||
export const assignIAMPolicyPermissions = [
|
export const assignIAMPolicyPermissions = [
|
||||||
IAM_SCOPES.ADMIN_ATTACH_USER_OR_GROUP_POLICY,
|
IAM_SCOPES.ADMIN_ATTACH_USER_OR_GROUP_POLICY,
|
||||||
IAM_SCOPES.ADMIN_LIST_USER_POLICIES,
|
IAM_SCOPES.ADMIN_LIST_USER_POLICIES,
|
||||||
@@ -479,3 +483,35 @@ export const editServiceAccountPermissions = [
|
|||||||
IAM_SCOPES.ADMIN_UPDATE_SERVICEACCOUNT,
|
IAM_SCOPES.ADMIN_UPDATE_SERVICEACCOUNT,
|
||||||
IAM_SCOPES.ADMIN_REMOVE_SERVICEACCOUNT,
|
IAM_SCOPES.ADMIN_REMOVE_SERVICEACCOUNT,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const applyPolicyPermissions = [
|
||||||
|
IAM_SCOPES.ADMIN_ATTACH_USER_OR_GROUP_POLICY,
|
||||||
|
IAM_SCOPES.ADMIN_LIST_USER_POLICIES,
|
||||||
|
];
|
||||||
|
|
||||||
|
export const deleteGroupPermissions = [IAM_SCOPES.ADMIN_REMOVE_USER_FROM_GROUP];
|
||||||
|
|
||||||
|
export const displayGroupsPermissions = [IAM_SCOPES.ADMIN_LIST_GROUPS];
|
||||||
|
|
||||||
|
export const createGroupPermissions = [
|
||||||
|
IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP,
|
||||||
|
IAM_SCOPES.ADMIN_LIST_USERS,
|
||||||
|
];
|
||||||
|
|
||||||
|
export const viewUserPermissions = [
|
||||||
|
IAM_SCOPES.ADMIN_GET_USER,
|
||||||
|
IAM_SCOPES.ADMIN_LIST_USERS,
|
||||||
|
];
|
||||||
|
export const editGroupMembersPermissions = [
|
||||||
|
IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP,
|
||||||
|
IAM_SCOPES.ADMIN_LIST_USERS,
|
||||||
|
];
|
||||||
|
export const setGroupPoliciesPermissions = [
|
||||||
|
IAM_SCOPES.ADMIN_ATTACH_USER_OR_GROUP_POLICY,
|
||||||
|
IAM_SCOPES.ADMIN_LIST_USER_POLICIES,
|
||||||
|
];
|
||||||
|
export const viewPolicyPermissions = [IAM_SCOPES.ADMIN_GET_POLICY];
|
||||||
|
export const enableDisableGroupPermissions = [
|
||||||
|
IAM_SCOPES.ADMIN_ENABLE_GROUP,
|
||||||
|
IAM_SCOPES.ADMIN_DISABLE_GROUP,
|
||||||
|
];
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import {
|
|||||||
TableRowPredefStyles,
|
TableRowPredefStyles,
|
||||||
} from "../FormComponents/common/styleLibrary";
|
} from "../FormComponents/common/styleLibrary";
|
||||||
import Loader from "../Loader/Loader";
|
import Loader from "../Loader/Loader";
|
||||||
|
import TooltipWrapper from "../TooltipWrapper/TooltipWrapper";
|
||||||
|
|
||||||
//Interfaces for table Items
|
//Interfaces for table Items
|
||||||
|
|
||||||
@@ -111,6 +112,7 @@ interface TableWrapperProps {
|
|||||||
index: number;
|
index: number;
|
||||||
}) => "deleted" | "" | React.CSSProperties;
|
}) => "deleted" | "" | React.CSSProperties;
|
||||||
parentClassName?: string;
|
parentClassName?: string;
|
||||||
|
tooltip?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const borderColor = "#9c9c9c80";
|
const borderColor = "#9c9c9c80";
|
||||||
@@ -465,6 +467,7 @@ const TableWrapper = ({
|
|||||||
onSelectAll,
|
onSelectAll,
|
||||||
rowStyle,
|
rowStyle,
|
||||||
parentClassName = "",
|
parentClassName = "",
|
||||||
|
tooltip,
|
||||||
}: TableWrapperProps) => {
|
}: TableWrapperProps) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -558,235 +561,249 @@ const TableWrapper = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid item xs={12} className={parentClassName}>
|
<Grid item xs={12} className={parentClassName}>
|
||||||
<Paper
|
<TooltipWrapper tooltip={tooltip ? tooltip : ""}>
|
||||||
className={`${classes.paper} ${noBackground ? classes.noBackground : ""}
|
<Paper
|
||||||
|
className={`${classes.paper} ${
|
||||||
|
noBackground ? classes.noBackground : ""
|
||||||
|
}
|
||||||
${disabled ? classes.disabled : ""}
|
${disabled ? classes.disabled : ""}
|
||||||
${
|
${
|
||||||
customPaperHeight !== ""
|
customPaperHeight !== ""
|
||||||
? customPaperHeight
|
? customPaperHeight
|
||||||
: classes.defaultPaperHeight
|
: classes.defaultPaperHeight
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
<Grid container className={classes.loadingBox}>
|
<Grid container className={classes.loadingBox}>
|
||||||
<Grid item xs={12} style={{ textAlign: "center" }}>
|
<Grid item xs={12} style={{ textAlign: "center" }}>
|
||||||
{loadingMessage}
|
{loadingMessage}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<LinearProgress />
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
)}
|
||||||
<LinearProgress />
|
{columnsSelector && !isLoading && records.length > 0 && (
|
||||||
</Grid>
|
<div className={classes.overlayColumnSelection}>
|
||||||
</Grid>
|
{columnsSelection(columns)}
|
||||||
)}
|
</div>
|
||||||
{columnsSelector && !isLoading && records.length > 0 && (
|
)}
|
||||||
<div className={classes.overlayColumnSelection}>
|
{records && !isLoading && records.length > 0 ? (
|
||||||
{columnsSelection(columns)}
|
// @ts-ignore
|
||||||
</div>
|
<InfiniteLoader
|
||||||
)}
|
isRowLoaded={({ index }) => !!records[index]}
|
||||||
{records && !isLoading && records.length > 0 ? (
|
loadMoreRows={
|
||||||
// @ts-ignore
|
infiniteScrollConfig
|
||||||
<InfiniteLoader
|
? infiniteScrollConfig.loadMoreRecords
|
||||||
isRowLoaded={({ index }) => !!records[index]}
|
: () => new Promise(() => true)
|
||||||
loadMoreRows={
|
}
|
||||||
infiniteScrollConfig
|
rowCount={
|
||||||
? infiniteScrollConfig.loadMoreRecords
|
infiniteScrollConfig
|
||||||
: () => new Promise(() => true)
|
? infiniteScrollConfig.recordsCount
|
||||||
}
|
: records.length
|
||||||
rowCount={
|
}
|
||||||
infiniteScrollConfig
|
>
|
||||||
? infiniteScrollConfig.recordsCount
|
{({ onRowsRendered, registerChild }) => (
|
||||||
: records.length
|
// @ts-ignore
|
||||||
}
|
<AutoSizer>
|
||||||
>
|
{({ width, height }: any) => {
|
||||||
{({ onRowsRendered, registerChild }) => (
|
const optionsWidth = calculateOptionsSize(
|
||||||
// @ts-ignore
|
width,
|
||||||
<AutoSizer>
|
itemActions
|
||||||
{({ width, height }: any) => {
|
? itemActions.filter((el) => el.type !== "view").length
|
||||||
const optionsWidth = calculateOptionsSize(
|
: 0
|
||||||
width,
|
);
|
||||||
itemActions
|
const hasSelect: boolean = !!(onSelect && selectedItems);
|
||||||
? itemActions.filter((el) => el.type !== "view").length
|
const hasOptions: boolean = !!(
|
||||||
: 0
|
(itemActions && itemActions.length > 1) ||
|
||||||
);
|
(itemActions &&
|
||||||
const hasSelect: boolean = !!(onSelect && selectedItems);
|
itemActions.length === 1 &&
|
||||||
const hasOptions: boolean = !!(
|
itemActions[0].type !== "view")
|
||||||
(itemActions && itemActions.length > 1) ||
|
);
|
||||||
(itemActions &&
|
return (
|
||||||
itemActions.length === 1 &&
|
// @ts-ignore
|
||||||
itemActions[0].type !== "view")
|
<Table
|
||||||
);
|
ref={registerChild}
|
||||||
return (
|
disableHeader={false}
|
||||||
// @ts-ignore
|
headerClassName={"headerItem"}
|
||||||
<Table
|
headerHeight={40}
|
||||||
ref={registerChild}
|
height={height}
|
||||||
disableHeader={false}
|
noRowsRenderer={() => (
|
||||||
headerClassName={"headerItem"}
|
<Fragment>
|
||||||
headerHeight={40}
|
{customEmptyMessage !== ""
|
||||||
height={height}
|
? customEmptyMessage
|
||||||
noRowsRenderer={() => (
|
: `There are no ${entityName} yet.`}
|
||||||
<Fragment>
|
</Fragment>
|
||||||
{customEmptyMessage !== ""
|
)}
|
||||||
? customEmptyMessage
|
overscanRowCount={10}
|
||||||
: `There are no ${entityName} yet.`}
|
rowHeight={40}
|
||||||
</Fragment>
|
width={width}
|
||||||
)}
|
rowCount={records.length}
|
||||||
overscanRowCount={10}
|
rowGetter={({ index }) => records[index]}
|
||||||
rowHeight={40}
|
onRowClick={({ rowData }) => {
|
||||||
width={width}
|
clickAction(rowData);
|
||||||
rowCount={records.length}
|
}}
|
||||||
rowGetter={({ index }) => records[index]}
|
rowClassName={`rowLine ${findView ? "canClick" : ""} ${
|
||||||
onRowClick={({ rowData }) => {
|
!findView && textSelectable ? "canSelectText" : ""
|
||||||
clickAction(rowData);
|
}`}
|
||||||
}}
|
onRowsRendered={onRowsRendered}
|
||||||
rowClassName={`rowLine ${findView ? "canClick" : ""} ${
|
sort={sortConfig ? sortConfig.triggerSort : undefined}
|
||||||
!findView && textSelectable ? "canSelectText" : ""
|
sortBy={sortConfig ? sortConfig.currentSort : undefined}
|
||||||
}`}
|
sortDirection={
|
||||||
onRowsRendered={onRowsRendered}
|
sortConfig ? sortConfig.currentDirection : undefined
|
||||||
sort={sortConfig ? sortConfig.triggerSort : undefined}
|
}
|
||||||
sortBy={sortConfig ? sortConfig.currentSort : undefined}
|
scrollToIndex={
|
||||||
sortDirection={
|
autoScrollToBottom ? records.length - 1 : -1
|
||||||
sortConfig ? sortConfig.currentDirection : undefined
|
}
|
||||||
}
|
rowStyle={(r) => {
|
||||||
scrollToIndex={
|
if (rowStyle) {
|
||||||
autoScrollToBottom ? records.length - 1 : -1
|
const returnElement = rowStyle(r);
|
||||||
}
|
|
||||||
rowStyle={(r) => {
|
|
||||||
if (rowStyle) {
|
|
||||||
const returnElement = rowStyle(r);
|
|
||||||
|
|
||||||
if (typeof returnElement === "string") {
|
if (typeof returnElement === "string") {
|
||||||
return get(TableRowPredefStyles, returnElement, {});
|
return get(
|
||||||
|
TableRowPredefStyles,
|
||||||
|
returnElement,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnElement;
|
return {};
|
||||||
}
|
}}
|
||||||
|
>
|
||||||
|
{hasSelect && (
|
||||||
|
// @ts-ignore
|
||||||
|
<Column
|
||||||
|
headerRenderer={() => (
|
||||||
|
<Fragment>
|
||||||
|
{onSelectAll ? (
|
||||||
|
<div className={classes.checkAllWrapper}>
|
||||||
|
<CheckboxWrapper
|
||||||
|
label={""}
|
||||||
|
onChange={onSelectAll}
|
||||||
|
value="all"
|
||||||
|
id={"selectAll"}
|
||||||
|
name={"selectAll"}
|
||||||
|
checked={
|
||||||
|
selectedItems?.length === records.length
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Fragment>Select</Fragment>
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
dataKey={`select-${idField}`}
|
||||||
|
width={selectWidth}
|
||||||
|
disableSort
|
||||||
|
cellRenderer={({ rowData }) => {
|
||||||
|
const isSelected = selectedItems
|
||||||
|
? selectedItems.includes(
|
||||||
|
isString(rowData)
|
||||||
|
? rowData
|
||||||
|
: rowData[idField]
|
||||||
|
)
|
||||||
|
: false;
|
||||||
|
|
||||||
return {};
|
return (
|
||||||
}}
|
<Checkbox
|
||||||
>
|
value={
|
||||||
{hasSelect && (
|
isString(rowData)
|
||||||
// @ts-ignore
|
? rowData
|
||||||
<Column
|
: rowData[idField]
|
||||||
headerRenderer={() => (
|
}
|
||||||
<Fragment>
|
color="primary"
|
||||||
{onSelectAll ? (
|
inputProps={{
|
||||||
<div className={classes.checkAllWrapper}>
|
"aria-label": "secondary checkbox",
|
||||||
<CheckboxWrapper
|
}}
|
||||||
label={""}
|
className="TableCheckbox"
|
||||||
onChange={onSelectAll}
|
checked={isSelected}
|
||||||
value="all"
|
onChange={onSelect}
|
||||||
id={"selectAll"}
|
onClick={(e) => {
|
||||||
name={"selectAll"}
|
e.stopPropagation();
|
||||||
checked={
|
}}
|
||||||
selectedItems?.length === records.length
|
checkedIcon={
|
||||||
}
|
<span
|
||||||
/>
|
className={
|
||||||
</div>
|
radioSelection
|
||||||
) : (
|
? classes.radioSelectedIcon
|
||||||
<Fragment>Select</Fragment>
|
: classes.checkedIcon
|
||||||
)}
|
}
|
||||||
</Fragment>
|
/>
|
||||||
)}
|
}
|
||||||
dataKey={`select-${idField}`}
|
icon={
|
||||||
width={selectWidth}
|
<span
|
||||||
disableSort
|
className={
|
||||||
cellRenderer={({ rowData }) => {
|
radioSelection
|
||||||
const isSelected = selectedItems
|
? classes.radioUnselectedIcon
|
||||||
? selectedItems.includes(
|
: classes.unCheckedIcon
|
||||||
isString(rowData) ? rowData : rowData[idField]
|
}
|
||||||
)
|
/>
|
||||||
: false;
|
}
|
||||||
|
/>
|
||||||
return (
|
);
|
||||||
<Checkbox
|
}}
|
||||||
value={
|
/>
|
||||||
isString(rowData) ? rowData : rowData[idField]
|
)}
|
||||||
}
|
{generateColumnsMap(
|
||||||
color="primary"
|
columns,
|
||||||
inputProps={{
|
width,
|
||||||
"aria-label": "secondary checkbox",
|
optionsWidth,
|
||||||
}}
|
hasSelect,
|
||||||
className="TableCheckbox"
|
hasOptions,
|
||||||
checked={isSelected}
|
selectedItems || [],
|
||||||
onChange={onSelect}
|
idField,
|
||||||
onClick={(e) => {
|
columnsSelector,
|
||||||
e.stopPropagation();
|
columnsShown,
|
||||||
}}
|
sortConfig ? sortConfig.currentSort : "",
|
||||||
checkedIcon={
|
sortConfig ? sortConfig.currentDirection : undefined
|
||||||
<span
|
)}
|
||||||
className={
|
{hasOptions && (
|
||||||
radioSelection
|
// @ts-ignore
|
||||||
? classes.radioSelectedIcon
|
<Column
|
||||||
: classes.checkedIcon
|
dataKey={idField}
|
||||||
}
|
width={optionsWidth}
|
||||||
/>
|
headerClassName="optionsAlignment"
|
||||||
}
|
className="optionsAlignment"
|
||||||
icon={
|
cellRenderer={({ rowData }) => {
|
||||||
<span
|
const isSelected = selectedItems
|
||||||
className={
|
? selectedItems.includes(
|
||||||
radioSelection
|
isString(rowData)
|
||||||
? classes.radioUnselectedIcon
|
? rowData
|
||||||
: classes.unCheckedIcon
|
: rowData[idField]
|
||||||
}
|
)
|
||||||
/>
|
: false;
|
||||||
}
|
return elementActions(
|
||||||
/>
|
itemActions || [],
|
||||||
);
|
rowData,
|
||||||
}}
|
isSelected,
|
||||||
/>
|
idField
|
||||||
)}
|
);
|
||||||
{generateColumnsMap(
|
}}
|
||||||
columns,
|
/>
|
||||||
width,
|
)}
|
||||||
optionsWidth,
|
</Table>
|
||||||
hasSelect,
|
);
|
||||||
hasOptions,
|
}}
|
||||||
selectedItems || [],
|
</AutoSizer>
|
||||||
idField,
|
)}
|
||||||
columnsSelector,
|
</InfiniteLoader>
|
||||||
columnsShown,
|
) : (
|
||||||
sortConfig ? sortConfig.currentSort : "",
|
<Fragment>
|
||||||
sortConfig ? sortConfig.currentDirection : undefined
|
{!isLoading && (
|
||||||
)}
|
<div id={"empty-results"}>
|
||||||
{hasOptions && (
|
{customEmptyMessage !== ""
|
||||||
// @ts-ignore
|
? customEmptyMessage
|
||||||
<Column
|
: `There are no ${entityName} yet.`}
|
||||||
dataKey={idField}
|
</div>
|
||||||
width={optionsWidth}
|
)}
|
||||||
headerClassName="optionsAlignment"
|
</Fragment>
|
||||||
className="optionsAlignment"
|
)}
|
||||||
cellRenderer={({ rowData }) => {
|
</Paper>
|
||||||
const isSelected = selectedItems
|
</TooltipWrapper>
|
||||||
? selectedItems.includes(
|
|
||||||
isString(rowData) ? rowData : rowData[idField]
|
|
||||||
)
|
|
||||||
: false;
|
|
||||||
return elementActions(
|
|
||||||
itemActions || [],
|
|
||||||
rowData,
|
|
||||||
isSelected,
|
|
||||||
idField
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Table>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</AutoSizer>
|
|
||||||
)}
|
|
||||||
</InfiniteLoader>
|
|
||||||
) : (
|
|
||||||
<Fragment>
|
|
||||||
{!isLoading && (
|
|
||||||
<div id={"empty-results"}>
|
|
||||||
{customEmptyMessage !== ""
|
|
||||||
? customEmptyMessage
|
|
||||||
: `There are no ${entityName} yet.`}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Fragment>
|
|
||||||
)}
|
|
||||||
</Paper>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,7 +49,12 @@ import SearchBox from "../Common/SearchBox";
|
|||||||
import {
|
import {
|
||||||
CONSOLE_UI_RESOURCE,
|
CONSOLE_UI_RESOURCE,
|
||||||
IAM_PAGES,
|
IAM_PAGES,
|
||||||
IAM_SCOPES,
|
permissionTooltipHelper,
|
||||||
|
applyPolicyPermissions,
|
||||||
|
displayGroupsPermissions,
|
||||||
|
deleteGroupPermissions,
|
||||||
|
getGroupPermissions,
|
||||||
|
createGroupPermissions,
|
||||||
} from "../../../common/SecureComponent/permissions";
|
} from "../../../common/SecureComponent/permissions";
|
||||||
import {
|
import {
|
||||||
hasPermission,
|
hasPermission,
|
||||||
@@ -107,17 +112,23 @@ const Groups = ({ classes }: IGroupsProps) => {
|
|||||||
isLoading(true);
|
isLoading(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const displayGroups = hasPermission(CONSOLE_UI_RESOURCE, [
|
const displayGroups = hasPermission(
|
||||||
IAM_SCOPES.ADMIN_LIST_GROUPS,
|
CONSOLE_UI_RESOURCE,
|
||||||
]);
|
displayGroupsPermissions
|
||||||
|
);
|
||||||
|
|
||||||
const deleteGroup = hasPermission(CONSOLE_UI_RESOURCE, [
|
const deleteGroup = hasPermission(
|
||||||
IAM_SCOPES.ADMIN_REMOVE_USER_FROM_GROUP,
|
CONSOLE_UI_RESOURCE,
|
||||||
]);
|
deleteGroupPermissions
|
||||||
|
);
|
||||||
|
|
||||||
const getGroup = hasPermission(CONSOLE_UI_RESOURCE, [
|
const getGroup = hasPermission(CONSOLE_UI_RESOURCE, getGroupPermissions);
|
||||||
IAM_SCOPES.ADMIN_GET_GROUP,
|
|
||||||
]);
|
const applyPolicy = hasPermission(
|
||||||
|
CONSOLE_UI_RESOURCE,
|
||||||
|
applyPolicyPermissions,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const selectionChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const selectionChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const { target: { value = "", checked = false } = {} } = e;
|
const { target: { value = "", checked = false } = {} } = e;
|
||||||
@@ -217,7 +228,7 @@ const Groups = ({ classes }: IGroupsProps) => {
|
|||||||
<Grid item xs={12} className={classes.actionsTray}>
|
<Grid item xs={12} className={classes.actionsTray}>
|
||||||
<SecureComponent
|
<SecureComponent
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
scopes={[IAM_SCOPES.ADMIN_LIST_GROUPS]}
|
scopes={displayGroupsPermissions}
|
||||||
errorProps={{ disabled: true }}
|
errorProps={{ disabled: true }}
|
||||||
>
|
>
|
||||||
<SearchBox
|
<SearchBox
|
||||||
@@ -234,11 +245,22 @@ const Groups = ({ classes }: IGroupsProps) => {
|
|||||||
>
|
>
|
||||||
<SecureComponent
|
<SecureComponent
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
scopes={[IAM_SCOPES.ADMIN_ATTACH_USER_OR_GROUP_POLICY]}
|
scopes={applyPolicyPermissions}
|
||||||
matchAll
|
matchAll
|
||||||
errorProps={{ disabled: true }}
|
errorProps={{ disabled: true }}
|
||||||
>
|
>
|
||||||
<TooltipWrapper tooltip={"Select Policy"}>
|
<TooltipWrapper
|
||||||
|
tooltip={
|
||||||
|
checkedGroups.length < 1
|
||||||
|
? "Please select Groups on which you want to apply Policies"
|
||||||
|
: applyPolicy
|
||||||
|
? "Select Policy"
|
||||||
|
: permissionTooltipHelper(
|
||||||
|
applyPolicyPermissions,
|
||||||
|
"apply policies to Groups"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
id={"assign-policy"}
|
id={"assign-policy"}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -246,18 +268,29 @@ const Groups = ({ classes }: IGroupsProps) => {
|
|||||||
}}
|
}}
|
||||||
label={"Assign Policy"}
|
label={"Assign Policy"}
|
||||||
icon={<IAMPoliciesIcon />}
|
icon={<IAMPoliciesIcon />}
|
||||||
disabled={checkedGroups.length < 1}
|
disabled={checkedGroups.length < 1 || !applyPolicy}
|
||||||
variant={"regular"}
|
variant={"regular"}
|
||||||
/>
|
/>
|
||||||
</TooltipWrapper>
|
</TooltipWrapper>
|
||||||
</SecureComponent>
|
</SecureComponent>
|
||||||
<SecureComponent
|
<SecureComponent
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
scopes={[IAM_SCOPES.ADMIN_REMOVE_USER_FROM_GROUP]}
|
scopes={deleteGroupPermissions}
|
||||||
matchAll
|
matchAll
|
||||||
errorProps={{ disabled: true }}
|
errorProps={{ disabled: true }}
|
||||||
>
|
>
|
||||||
<TooltipWrapper tooltip={"Delete Selected"}>
|
<TooltipWrapper
|
||||||
|
tooltip={
|
||||||
|
checkedGroups.length === 0
|
||||||
|
? "Select Groups to delete"
|
||||||
|
: getGroup
|
||||||
|
? "Delete Selected"
|
||||||
|
: permissionTooltipHelper(
|
||||||
|
getGroupPermissions,
|
||||||
|
"delete Groups"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
id="delete-selected-groups"
|
id="delete-selected-groups"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -266,16 +299,13 @@ const Groups = ({ classes }: IGroupsProps) => {
|
|||||||
label={"Delete Selected"}
|
label={"Delete Selected"}
|
||||||
icon={<DeleteIcon />}
|
icon={<DeleteIcon />}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
disabled={checkedGroups.length === 0}
|
disabled={checkedGroups.length === 0 || !getGroup}
|
||||||
/>
|
/>
|
||||||
</TooltipWrapper>
|
</TooltipWrapper>
|
||||||
</SecureComponent>
|
</SecureComponent>
|
||||||
<SecureComponent
|
<SecureComponent
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
scopes={[
|
scopes={createGroupPermissions}
|
||||||
IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP,
|
|
||||||
IAM_SCOPES.ADMIN_LIST_USERS,
|
|
||||||
]}
|
|
||||||
matchAll
|
matchAll
|
||||||
errorProps={{ disabled: true }}
|
errorProps={{ disabled: true }}
|
||||||
>
|
>
|
||||||
@@ -298,24 +328,37 @@ const Groups = ({ classes }: IGroupsProps) => {
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
{records.length > 0 && (
|
{records.length > 0 && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Grid item xs={12} className={classes.tableBlock}>
|
<TooltipWrapper
|
||||||
<SecureComponent
|
tooltip={
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
getGroup
|
||||||
scopes={[IAM_SCOPES.ADMIN_LIST_GROUPS]}
|
? ""
|
||||||
errorProps={{ disabled: true }}
|
: permissionTooltipHelper(
|
||||||
>
|
getGroupPermissions,
|
||||||
<TableWrapper
|
"view Group details"
|
||||||
itemActions={tableActions}
|
)
|
||||||
columns={[{ label: "Name", elementKey: "" }]}
|
}
|
||||||
isLoading={loading}
|
>
|
||||||
selectedItems={checkedGroups}
|
<Grid item xs={12} className={classes.tableBlock}>
|
||||||
onSelect={deleteGroup ? selectionChanged : undefined}
|
<SecureComponent
|
||||||
records={filteredRecords}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
entityName="Groups"
|
scopes={displayGroupsPermissions}
|
||||||
idField=""
|
errorProps={{ disabled: true }}
|
||||||
/>
|
>
|
||||||
</SecureComponent>
|
<TableWrapper
|
||||||
</Grid>
|
itemActions={tableActions}
|
||||||
|
columns={[{ label: "Name", elementKey: "" }]}
|
||||||
|
isLoading={loading}
|
||||||
|
selectedItems={checkedGroups}
|
||||||
|
onSelect={
|
||||||
|
deleteGroup || getGroup ? selectionChanged : undefined
|
||||||
|
}
|
||||||
|
records={filteredRecords}
|
||||||
|
entityName="Groups"
|
||||||
|
idField=""
|
||||||
|
/>
|
||||||
|
</SecureComponent>
|
||||||
|
</Grid>
|
||||||
|
</TooltipWrapper>
|
||||||
<Grid item xs={12} marginTop={"25px"}>
|
<Grid item xs={12} marginTop={"25px"}>
|
||||||
<HelpBox
|
<HelpBox
|
||||||
title={"Groups"}
|
title={"Groups"}
|
||||||
@@ -362,10 +405,7 @@ const Groups = ({ classes }: IGroupsProps) => {
|
|||||||
permissions on the MinIO Tenant.
|
permissions on the MinIO Tenant.
|
||||||
<SecureComponent
|
<SecureComponent
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
scopes={[
|
scopes={createGroupPermissions}
|
||||||
IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP,
|
|
||||||
IAM_SCOPES.ADMIN_LIST_USERS,
|
|
||||||
]}
|
|
||||||
matchAll
|
matchAll
|
||||||
>
|
>
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -32,9 +32,18 @@ import PageLayout from "../Common/Layout/PageLayout";
|
|||||||
import PanelTitle from "../Common/PanelTitle/PanelTitle";
|
import PanelTitle from "../Common/PanelTitle/PanelTitle";
|
||||||
import SearchBox from "../Common/SearchBox";
|
import SearchBox from "../Common/SearchBox";
|
||||||
import {
|
import {
|
||||||
|
addUserToGroupPermissions,
|
||||||
CONSOLE_UI_RESOURCE,
|
CONSOLE_UI_RESOURCE,
|
||||||
|
createGroupPermissions,
|
||||||
|
editGroupMembersPermissions,
|
||||||
|
enableDisableGroupPermissions,
|
||||||
|
getGroupPermissions,
|
||||||
IAM_PAGES,
|
IAM_PAGES,
|
||||||
IAM_SCOPES,
|
listUsersPermissions,
|
||||||
|
permissionTooltipHelper,
|
||||||
|
setGroupPoliciesPermissions,
|
||||||
|
viewPolicyPermissions,
|
||||||
|
viewUserPermissions,
|
||||||
} from "../../../common/SecureComponent/permissions";
|
} from "../../../common/SecureComponent/permissions";
|
||||||
import {
|
import {
|
||||||
hasPermission,
|
hasPermission,
|
||||||
@@ -130,6 +139,12 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
elementItem.includes(memberFilter)
|
elementItem.includes(memberFilter)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const viewUser = hasPermission(
|
||||||
|
CONSOLE_UI_RESOURCE,
|
||||||
|
viewUserPermissions,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupName) {
|
if (groupName) {
|
||||||
fetchGroupInfo();
|
fetchGroupInfo();
|
||||||
@@ -141,9 +156,28 @@ 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, [
|
const getGroupDetails = hasPermission(
|
||||||
IAM_SCOPES.ADMIN_GET_GROUP,
|
CONSOLE_UI_RESOURCE,
|
||||||
]);
|
getGroupPermissions
|
||||||
|
);
|
||||||
|
|
||||||
|
const canEditGroupMembers = hasPermission(
|
||||||
|
CONSOLE_UI_RESOURCE,
|
||||||
|
editGroupMembersPermissions,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
const canSetPolicies = hasPermission(
|
||||||
|
CONSOLE_UI_RESOURCE,
|
||||||
|
setGroupPoliciesPermissions,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
const canViewPolicy = hasPermission(
|
||||||
|
CONSOLE_UI_RESOURCE,
|
||||||
|
viewPolicyPermissions,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
function fetchGroupInfo() {
|
function fetchGroupInfo() {
|
||||||
if (getGroupDetails) {
|
if (getGroupDetails) {
|
||||||
@@ -188,10 +222,19 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
/>
|
/>
|
||||||
<SecureComponent
|
<SecureComponent
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
scopes={[IAM_SCOPES.ADMIN_ADD_USER_TO_GROUP]}
|
scopes={addUserToGroupPermissions}
|
||||||
errorProps={{ disabled: true }}
|
errorProps={{ disabled: true }}
|
||||||
>
|
>
|
||||||
<TooltipWrapper tooltip={memberActionText}>
|
<TooltipWrapper
|
||||||
|
tooltip={
|
||||||
|
canEditGroupMembers
|
||||||
|
? memberActionText
|
||||||
|
: permissionTooltipHelper(
|
||||||
|
createGroupPermissions,
|
||||||
|
"edit Group membership"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
id={"add-user-group"}
|
id={"add-user-group"}
|
||||||
label={memberActionText}
|
label={memberActionText}
|
||||||
@@ -200,6 +243,7 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setUsersOpen(true);
|
setUsersOpen(true);
|
||||||
}}
|
}}
|
||||||
|
disabled={!canEditGroupMembers}
|
||||||
/>
|
/>
|
||||||
</TooltipWrapper>
|
</TooltipWrapper>
|
||||||
</SecureComponent>
|
</SecureComponent>
|
||||||
@@ -208,7 +252,7 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
<div className={classes.tableBlock}>
|
<div className={classes.tableBlock}>
|
||||||
<SecureComponent
|
<SecureComponent
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
scopes={[IAM_SCOPES.ADMIN_LIST_USERS]}
|
scopes={listUsersPermissions}
|
||||||
errorProps={{ disabled: true }}
|
errorProps={{ disabled: true }}
|
||||||
>
|
>
|
||||||
<TableWrapper
|
<TableWrapper
|
||||||
@@ -218,6 +262,7 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
onClick: (userName) => {
|
onClick: (userName) => {
|
||||||
navigate(`${IAM_PAGES.USERS}/${encodeURLString(userName)}`);
|
navigate(`${IAM_PAGES.USERS}/${encodeURLString(userName)}`);
|
||||||
},
|
},
|
||||||
|
disableButtonFunction: () => !viewUser,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
columns={[{ label: "Access Key", elementKey: "" }]}
|
columns={[{ label: "Access Key", elementKey: "" }]}
|
||||||
@@ -226,6 +271,14 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
records={filteredMembers}
|
records={filteredMembers}
|
||||||
entityName="Users"
|
entityName="Users"
|
||||||
idField=""
|
idField=""
|
||||||
|
tooltip={
|
||||||
|
viewUser
|
||||||
|
? ""
|
||||||
|
: permissionTooltipHelper(
|
||||||
|
viewUserPermissions,
|
||||||
|
"view User details"
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</SecureComponent>
|
</SecureComponent>
|
||||||
</div>
|
</div>
|
||||||
@@ -236,7 +289,16 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className={classes.actionsTray}>
|
<div className={classes.actionsTray}>
|
||||||
<PanelTitle>Policies</PanelTitle>
|
<PanelTitle>Policies</PanelTitle>
|
||||||
<TooltipWrapper tooltip={"Set Policies"}>
|
<TooltipWrapper
|
||||||
|
tooltip={
|
||||||
|
canSetPolicies
|
||||||
|
? "Set Policies"
|
||||||
|
: permissionTooltipHelper(
|
||||||
|
setGroupPoliciesPermissions,
|
||||||
|
"assign Policies"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
id={"set-policies"}
|
id={"set-policies"}
|
||||||
label={`Set Policies`}
|
label={`Set Policies`}
|
||||||
@@ -245,6 +307,7 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPolicyOpen(true);
|
setPolicyOpen(true);
|
||||||
}}
|
}}
|
||||||
|
disabled={!canSetPolicies}
|
||||||
/>
|
/>
|
||||||
</TooltipWrapper>
|
</TooltipWrapper>
|
||||||
</div>
|
</div>
|
||||||
@@ -256,6 +319,7 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
onClick: (policy) => {
|
onClick: (policy) => {
|
||||||
navigate(`${IAM_PAGES.POLICIES}/${encodeURLString(policy)}`);
|
navigate(`${IAM_PAGES.POLICIES}/${encodeURLString(policy)}`);
|
||||||
},
|
},
|
||||||
|
disableButtonFunction: () => !canViewPolicy,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
columns={[{ label: "Policy", elementKey: "" }]}
|
columns={[{ label: "Policy", elementKey: "" }]}
|
||||||
@@ -263,6 +327,14 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
records={groupPolicies}
|
records={groupPolicies}
|
||||||
entityName="Policies"
|
entityName="Policies"
|
||||||
idField=""
|
idField=""
|
||||||
|
tooltip={
|
||||||
|
canViewPolicy
|
||||||
|
? ""
|
||||||
|
: permissionTooltipHelper(
|
||||||
|
viewPolicyPermissions,
|
||||||
|
"view Policy details"
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
@@ -287,46 +359,52 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
|
|||||||
<span id="group-status" className={classes.statusValue}>
|
<span id="group-status" className={classes.statusValue}>
|
||||||
{isGroupEnabled ? "Enabled" : "Disabled"}
|
{isGroupEnabled ? "Enabled" : "Disabled"}
|
||||||
</span>
|
</span>
|
||||||
<SecureComponent
|
<TooltipWrapper
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
tooltip={
|
||||||
scopes={[
|
hasPermission(
|
||||||
IAM_SCOPES.ADMIN_ENABLE_GROUP,
|
CONSOLE_UI_RESOURCE,
|
||||||
IAM_SCOPES.ADMIN_DISABLE_GROUP,
|
enableDisableGroupPermissions,
|
||||||
]}
|
true
|
||||||
errorProps={{ disabled: true }}
|
)
|
||||||
matchAll
|
? ""
|
||||||
|
: permissionTooltipHelper(
|
||||||
|
enableDisableGroupPermissions,
|
||||||
|
"enable or disable Groups"
|
||||||
|
)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FormSwitchWrapper
|
<SecureComponent
|
||||||
indicatorLabels={["Enabled", "Disabled"]}
|
resource={CONSOLE_UI_RESOURCE}
|
||||||
checked={isGroupEnabled}
|
scopes={enableDisableGroupPermissions}
|
||||||
value={"group_enabled"}
|
errorProps={{ disabled: true }}
|
||||||
id="group-status"
|
matchAll
|
||||||
name="group-status"
|
>
|
||||||
onChange={() => {
|
<FormSwitchWrapper
|
||||||
toggleGroupStatus(!isGroupEnabled);
|
indicatorLabels={["Enabled", "Disabled"]}
|
||||||
}}
|
checked={isGroupEnabled}
|
||||||
switchOnly
|
value={"group_enabled"}
|
||||||
/>
|
id="group-status"
|
||||||
</SecureComponent>
|
name="group-status"
|
||||||
|
onChange={() => {
|
||||||
|
toggleGroupStatus(!isGroupEnabled);
|
||||||
|
}}
|
||||||
|
switchOnly
|
||||||
|
/>
|
||||||
|
</SecureComponent>
|
||||||
|
</TooltipWrapper>
|
||||||
|
|
||||||
<SecureComponent
|
<div className={classes.spacerLeft}>
|
||||||
resource={CONSOLE_UI_RESOURCE}
|
<TooltipWrapper tooltip={"Delete Group"}>
|
||||||
scopes={[IAM_SCOPES.ADMIN_REMOVE_USER_FROM_GROUP]}
|
<Button
|
||||||
errorProps={{ disabled: true }}
|
id={"delete-user-group"}
|
||||||
>
|
variant="secondary"
|
||||||
<div className={classes.spacerLeft}>
|
icon={<TrashIcon />}
|
||||||
<TooltipWrapper tooltip={"Delete Group"}>
|
onClick={() => {
|
||||||
<Button
|
setDeleteOpen(true);
|
||||||
id={"delete-user-group"}
|
}}
|
||||||
variant="secondary"
|
/>
|
||||||
icon={<TrashIcon />}
|
</TooltipWrapper>
|
||||||
onClick={() => {
|
</div>
|
||||||
setDeleteOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</TooltipWrapper>
|
|
||||||
</div>
|
|
||||||
</SecureComponent>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user