From bc0704581b2441c0216f21c4ad2086f2caab0432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Wed, 17 Apr 2024 08:27:56 +0100 Subject: [PATCH] chore: UI SCIM guard for groups (#6866) https://linear.app/unleash/issue/2-2113/ui-should-not-allow-manual-management-of-scim-managed-groups-in Adds a UI SCIM guard when trying to manage groups. The condition for the guard is: - Enterprise - SCIM flag enabled - SCIM setting enabled - SCIM group Similar to https://github.com/Unleash/unleash/pull/6859 --- .../admin/groups/EditGroup/EditGroup.tsx | 31 ++++++++++++------ .../component/admin/groups/Group/Group.tsx | 30 +++++++++++++++-- .../groups/GroupsList/GroupCard/GroupCard.tsx | 8 +++++ .../GroupCardActions/GroupCardActions.tsx | 32 ++++++++++++------- .../component/admin/groups/group-constants.ts | 2 ++ .../UsersActionsCell/UsersActionsCell.tsx | 20 ++++++------ .../admin/users/UsersList/UsersList.tsx | 6 ++-- 7 files changed, 91 insertions(+), 38 deletions(-) create mode 100644 frontend/src/component/admin/groups/group-constants.ts diff --git a/frontend/src/component/admin/groups/EditGroup/EditGroup.tsx b/frontend/src/component/admin/groups/EditGroup/EditGroup.tsx index 88f0e23eaf..46cfd42dc1 100644 --- a/frontend/src/component/admin/groups/EditGroup/EditGroup.tsx +++ b/frontend/src/component/admin/groups/EditGroup/EditGroup.tsx @@ -6,7 +6,7 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useToast from 'hooks/useToast'; import { useGroupApi } from 'hooks/api/actions/useGroupApi/useGroupApi'; import { formatUnknownError } from 'utils/formatUnknownError'; -import { Button } from '@mui/material'; +import { Button, Tooltip } from '@mui/material'; import { EDIT } from 'constants/misc'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useGroup } from 'hooks/api/getters/useGroup/useGroup'; @@ -14,6 +14,8 @@ import { UG_SAVE_BTN_ID } from 'utils/testIds'; import { GO_BACK } from 'constants/navigate'; import { useGroups } from 'hooks/api/getters/useGroups/useGroups'; import type { IGroup } from 'interfaces/group'; +import { scimGroupTooltip } from '../group-constants'; +import { useScimSettings } from 'hooks/api/getters/useScimSettings/useScimSettings'; export const EditGroupContainer = () => { const groupId = Number(useRequiredPathParam('groupId')); @@ -46,6 +48,11 @@ export const EditGroup = ({ const { uiConfig } = useUiConfig(); const navigate = useNavigate(); + const { + settings: { enabled: scimEnabled }, + } = useScimSettings(); + const isScimGroup = scimEnabled && Boolean(group?.scimId); + const { name, setName, @@ -143,15 +150,19 @@ export const EditGroup = ({ handleCancel={handleCancel} mode={EDIT} > - + +
+ +
+
); diff --git a/frontend/src/component/admin/groups/Group/Group.tsx b/frontend/src/component/admin/groups/Group/Group.tsx index 850679ef10..69d42107b2 100644 --- a/frontend/src/component/admin/groups/Group/Group.tsx +++ b/frontend/src/component/admin/groups/Group/Group.tsx @@ -41,6 +41,8 @@ import { UG_EDIT_USERS_BTN_ID, UG_REMOVE_USER_BTN_ID, } from 'utils/testIds'; +import { useScimSettings } from 'hooks/api/getters/useScimSettings/useScimSettings'; +import { scimGroupTooltip } from '../group-constants'; export const groupUsersPlaceholder: IGroupUser[] = Array(15).fill({ name: 'Name of the user', @@ -68,6 +70,11 @@ export const Group: VFC = () => { const [removeUserOpen, setRemoveUserOpen] = useState(false); const [selectedUser, setSelectedUser] = useState(); + const { + settings: { enabled: scimEnabled }, + } = useScimSettings(); + const isScimGroup = scimEnabled && Boolean(group?.scimId); + const columns = useMemo( () => [ { @@ -127,7 +134,11 @@ export const Group: VFC = () => { Cell: ({ row: { original: rowUser } }: any) => ( @@ -138,6 +149,7 @@ export const Group: VFC = () => { setSelectedUser(rowUser); setRemoveUserOpen(true); }} + disabled={isScimGroup} > @@ -245,8 +257,11 @@ export const Group: VFC = () => { data-loading permission={ADMIN} tooltipProps={{ - title: 'Edit group', + title: isScimGroup + ? scimGroupTooltip + : 'Edit group', }} + disabled={isScimGroup} > @@ -256,8 +271,11 @@ export const Group: VFC = () => { onClick={() => setRemoveOpen(true)} permission={ADMIN} tooltipProps={{ - title: 'Delete group', + title: isScimGroup + ? scimGroupTooltip + : 'Delete group', }} + disabled={isScimGroup} > @@ -304,6 +322,12 @@ export const Group: VFC = () => { maxWidth='700px' Icon={Add} permission={ADMIN} + disabled={isScimGroup} + tooltipProps={{ + title: isScimGroup + ? scimGroupTooltip + : '', + }} > Edit users diff --git a/frontend/src/component/admin/groups/GroupsList/GroupCard/GroupCard.tsx b/frontend/src/component/admin/groups/GroupsList/GroupCard/GroupCard.tsx index 88a9f0bd95..4705eec80c 100644 --- a/frontend/src/component/admin/groups/GroupsList/GroupCard/GroupCard.tsx +++ b/frontend/src/component/admin/groups/GroupsList/GroupCard/GroupCard.tsx @@ -7,6 +7,7 @@ import { Badge } from 'component/common/Badge/Badge'; import { GroupCardActions } from './GroupCardActions/GroupCardActions'; import TopicOutlinedIcon from '@mui/icons-material/TopicOutlined'; import { RoleBadge } from 'component/common/RoleBadge/RoleBadge'; +import { useScimSettings } from 'hooks/api/getters/useScimSettings/useScimSettings'; const StyledLink = styled(Link)(({ theme }) => ({ textDecoration: 'none', @@ -96,6 +97,12 @@ export const GroupCard = ({ onRemoveGroup, }: IGroupCardProps) => { const navigate = useNavigate(); + + const { + settings: { enabled: scimEnabled }, + } = useScimSettings(); + const isScimGroup = scimEnabled && Boolean(group.scimId); + return ( <> @@ -107,6 +114,7 @@ export const GroupCard = ({ groupId={group.id} onEditUsers={() => onEditUsers(group)} onRemove={() => onRemoveGroup(group)} + isScimGroup={isScimGroup} /> diff --git a/frontend/src/component/admin/groups/GroupsList/GroupCard/GroupCardActions/GroupCardActions.tsx b/frontend/src/component/admin/groups/GroupsList/GroupCard/GroupCardActions/GroupCardActions.tsx index ade5846149..efc0f4e955 100644 --- a/frontend/src/component/admin/groups/GroupsList/GroupCard/GroupCardActions/GroupCardActions.tsx +++ b/frontend/src/component/admin/groups/GroupsList/GroupCard/GroupCardActions/GroupCardActions.tsx @@ -15,6 +15,7 @@ import Edit from '@mui/icons-material/Edit'; import GroupRounded from '@mui/icons-material/GroupRounded'; import MoreVert from '@mui/icons-material/MoreVert'; import { Link } from 'react-router-dom'; +import { scimGroupTooltip } from 'component/admin/groups/group-constants'; const StyledActions = styled('div')(({ theme }) => ({ display: 'flex', @@ -31,12 +32,14 @@ interface IGroupCardActions { groupId: number; onEditUsers: () => void; onRemove: () => void; + isScimGroup?: boolean; } export const GroupCardActions: FC = ({ groupId, onEditUsers, onRemove, + isScimGroup, }) => { const [anchorEl, setAnchorEl] = useState(null); @@ -58,17 +61,24 @@ export const GroupCardActions: FC = ({ e.stopPropagation(); }} > - - - - + +
+ + + +
void; onResetPassword: (event: React.SyntheticEvent) => void; onDelete: (event: React.SyntheticEvent) => void; - scimEnabled?: boolean; + isScimUser?: boolean; } export const UsersActionsCell: VFC = ({ @@ -29,7 +29,7 @@ export const UsersActionsCell: VFC = ({ onChangePassword, onResetPassword, onDelete, - scimEnabled, + isScimUser, }) => { const scimTooltip = 'This user is managed by your SCIM provider and cannot be changed manually'; @@ -41,9 +41,9 @@ export const UsersActionsCell: VFC = ({ onClick={onEdit} permission={ADMIN} tooltipProps={{ - title: scimEnabled ? scimTooltip : 'Edit user', + title: isScimUser ? scimTooltip : 'Edit user', }} - disabled={scimEnabled} + disabled={isScimUser} > @@ -69,9 +69,9 @@ export const UsersActionsCell: VFC = ({ onClick={onChangePassword} permission={ADMIN} tooltipProps={{ - title: scimEnabled ? scimTooltip : 'Change password', + title: isScimUser ? scimTooltip : 'Change password', }} - disabled={scimEnabled} + disabled={isScimUser} > @@ -80,9 +80,9 @@ export const UsersActionsCell: VFC = ({ onClick={onResetPassword} permission={ADMIN} tooltipProps={{ - title: scimEnabled ? scimTooltip : 'Reset password', + title: isScimUser ? scimTooltip : 'Reset password', }} - disabled={scimEnabled} + disabled={isScimUser} > @@ -91,9 +91,9 @@ export const UsersActionsCell: VFC = ({ onClick={onDelete} permission={ADMIN} tooltipProps={{ - title: scimEnabled ? scimTooltip : 'Remove user', + title: isScimUser ? scimTooltip : 'Remove user', }} - disabled={scimEnabled} + disabled={isScimUser} > diff --git a/frontend/src/component/admin/users/UsersList/UsersList.tsx b/frontend/src/component/admin/users/UsersList/UsersList.tsx index 5fc10628fc..c03aa2a322 100644 --- a/frontend/src/component/admin/users/UsersList/UsersList.tsx +++ b/frontend/src/component/admin/users/UsersList/UsersList.tsx @@ -58,10 +58,8 @@ const UsersList = () => { }); const userAccessUIEnabled = useUiFlag('userAccessUIEnabled'); const { - settings: { enabled: scimSettingEnabled }, + settings: { enabled: scimEnabled }, } = useScimSettings(); - const scimFlagEnabled = useUiFlag('scimApi'); - const scimEnabled = isEnterprise() && scimSettingEnabled && scimFlagEnabled; const [delDialog, setDelDialog] = useState(false); const [showConfirm, setShowConfirm] = useState(false); const [emailSent, setEmailSent] = useState(false); @@ -218,7 +216,7 @@ const UsersList = () => { onChangePassword={openPwDialog(user)} onResetPassword={openResetPwDialog(user)} onDelete={openDelDialog(user)} - scimEnabled={scimEnabled && Boolean(user.scimId)} + isScimUser={scimEnabled && Boolean(user.scimId)} /> ), width: userAccessUIEnabled ? 240 : 200,