diff --git a/web/src/containers/Settings/addPermissionModal.tsx b/web/src/containers/Settings/addPermissionModal.tsx index 1e3553e..e2f44d2 100644 --- a/web/src/containers/Settings/addPermissionModal.tsx +++ b/web/src/containers/Settings/addPermissionModal.tsx @@ -32,7 +32,7 @@ const BootstrapDialog = styled(Dialog)(({ theme }) => ({ type AddPermissionModalProps = { open: boolean handleOpen: Dispatch> - addPermission: (addPermissionPayload: RegisterPermissionPayload) => void + addPermission: (permissions: RegisterPermissionPayload[]) => void } const AddPermissionModal = ({ @@ -42,9 +42,9 @@ const AddPermissionModal = ({ }: AddPermissionModalProps) => { const [paths, setPaths] = useState([]) const [loadingPaths, setLoadingPaths] = useState(false) - const [path, setPath] = useState() + const [selectedPaths, setSelectedPaths] = useState([]) const [permissionType, setPermissionType] = useState('Route') - const [principalType, setPrincipalType] = useState('group') + const [principalType, setPrincipalType] = useState('Group') const [userPrincipal, setUserPrincipal] = useState() const [groupPrincipal, setGroupPrincipal] = useState() const [permissionSetting, setPermissionSetting] = useState('Grant') @@ -72,10 +72,10 @@ const AddPermissionModal = ({ useEffect(() => { setLoadingPrincipals(true) axios - .get(`/SASjsApi/${principalType}`) + .get(`/SASjsApi/${principalType.toLowerCase()}`) .then((res: any) => { if (res.data) { - if (principalType === 'user') { + if (principalType.toLowerCase() === 'user') { const users: UserResponse[] = res.data const nonAdminUsers = users.filter((user) => !user.isAdmin) setUserPrincipals(nonAdminUsers) @@ -93,22 +93,29 @@ const AddPermissionModal = ({ }, [principalType]) const handleAddPermission = () => { - const addPermissionPayload: any = { - path, - type: permissionType, - setting: permissionSetting, - principalType - } - if (principalType === 'user' && userPrincipal) { - addPermissionPayload.principalId = userPrincipal.id - } else if (principalType === 'group' && groupPrincipal) { - addPermissionPayload.principalId = groupPrincipal.groupId - } - addPermission(addPermissionPayload) + const permissions: RegisterPermissionPayload[] = [] + + selectedPaths.forEach((path) => { + const addPermissionPayload: any = { + path, + type: permissionType, + setting: permissionSetting, + principalType: principalType.toLowerCase(), + principalId: + principalType.toLowerCase() === 'user' + ? userPrincipal?.id + : groupPrincipal?.groupId + } + + permissions.push(addPermissionPayload) + }) + + addPermission(permissions) } const addButtonDisabled = - !path || (principalType === 'user' ? !userPrincipal : !groupPrincipal) + !selectedPaths.length || + (principalType.toLowerCase() === 'user' ? !userPrincipal : !groupPrincipal) return ( handleOpen(false)} open={open}> @@ -122,17 +129,14 @@ const AddPermissionModal = ({ setPath(newValue)} - renderInput={(params) => - loadingPaths ? ( - - ) : ( - - ) - } + filterSelectedOptions + value={selectedPaths} + onChange={(event: any, newValue: string[]) => { + setSelectedPaths(newValue) + }} + renderInput={(params) => } /> @@ -154,8 +158,7 @@ const AddPermissionModal = ({ option.toUpperCase()} + options={['Group', 'User']} disableClearable value={principalType} onChange={(event: any, newValue: string) => @@ -167,7 +170,7 @@ const AddPermissionModal = ({ /> - {principalType === 'user' ? ( + {principalType.toLowerCase() === 'user' ? ( option.displayName} diff --git a/web/src/containers/Settings/addPermissionResponseModal.tsx b/web/src/containers/Settings/addPermissionResponseModal.tsx new file mode 100644 index 0000000..181778c --- /dev/null +++ b/web/src/containers/Settings/addPermissionResponseModal.tsx @@ -0,0 +1,99 @@ +import React from 'react' + +import { + Paper, + Typography, + DialogContent, + TableContainer, + Table, + TableHead, + TableBody, + TableRow, + TableCell +} from '@mui/material' + +import { BootstrapDialog } from '../../components/modal' +import { BootstrapDialogTitle } from '../../components/dialogTitle' +import { PermissionResponse } from '../../utils/types' + +type Props = { + open: boolean + setOpen: React.Dispatch> + permissionResponses: PermissionResponse[] + errorResponses: any[] +} + +const PermissionResponseModal = ({ + open, + setOpen, + permissionResponses, + errorResponses +}: Props) => { + return ( +
+ setOpen(false)} open={open}> + + Permission Response + + + {permissionResponses.length > 0 && ( + <> + Added Permissions + {permissionResponses.length > 0 && ( + + + + + Path + Type + Setting + + + + {permissionResponses.map((permission, index) => { + return ( + + {permission.path} + {permission.type} + {permission.setting} + + ) + })} + +
+
+ )} + + )} + + {errorResponses.length > 0 && ( + <> + + Errors + +
    + {errorResponses.map((err, index) => ( +
  • + + Error occurred for Path: {err.permission.path} + + + {typeof err.error.response.data === 'object' + ? JSON.stringify(err.error.response.data) + : err.error.response.data} + +
  • + ))} +
+ + )} +
+
+
+ ) +} + +export default PermissionResponseModal diff --git a/web/src/containers/Settings/permission.tsx b/web/src/containers/Settings/permission.tsx index 3238d69..32223f1 100644 --- a/web/src/containers/Settings/permission.tsx +++ b/web/src/containers/Settings/permission.tsx @@ -27,6 +27,7 @@ import { styled } from '@mui/material/styles' import Modal from '../../components/modal' import PermissionFilterModal from './permissionFilterModal' import AddPermissionModal from './addPermissionModal' +import PermissionResponseModal from './addPermissionResponseModal' import UpdatePermissionModal from './updatePermissionModal' import DeleteConfirmationModal from '../../components/deleteConfirmationModal' import BootstrapSnackbar, { AlertSeverityType } from '../../components/snackbar' @@ -59,6 +60,13 @@ const Permission = () => { AlertSeverityType.Success ) const [addPermissionModalOpen, setAddPermissionModalOpen] = useState(false) + const [openPermissionResponseModal, setOpenPermissionResponseModal] = + useState(false) + const [addedPermissions, setAddedPermission] = useState( + [] + ) + const [errorResponses, setErrorResponses] = useState([]) + const [updatePermissionModalOpen, setUpdatePermissionModalOpen] = useState(false) const [deleteConfirmationModalOpen, setDeleteConfirmationModalOpen] = @@ -181,29 +189,31 @@ const Permission = () => { setFilterApplied(false) } - const addPermission = (addPermissionPayload: RegisterPermissionPayload) => { + const addPermission = (permissions: RegisterPermissionPayload[]) => { setAddPermissionModalOpen(false) + setAddedPermission([]) + setErrorResponses([]) setIsLoading(true) - axios - .post('/SASjsApi/permission', addPermissionPayload) - .then((res: any) => { - fetchPermissions() - setSnackbarMessage('Permission added!') - setSnackbarSeverity(AlertSeverityType.Success) - setOpenSnackbar(true) - }) - .catch((err) => { - setModalTitle('Abort') - setModalPayload( - typeof err.response.data === 'object' - ? JSON.stringify(err.response.data) - : err.response.data - ) - setOpenModal(true) - }) - .finally(() => { - setIsLoading(false) - }) + + const permissionResponses: PermissionResponse[] = [] + const errors: any = [] + + permissions.forEach(async (permission) => { + await axios + .post('/SASjsApi/permission', permission) + .then((res) => { + permissionResponses.push(res.data) + }) + .catch((error) => { + errors.push({ error, permission }) + }) + }) + + fetchPermissions() + setIsLoading(false) + setOpenPermissionResponseModal(true) + setAddedPermission(permissionResponses) + setErrorResponses(errors) } const handleUpdatePermissionClick = (permission: PermissionResponse) => { @@ -340,6 +350,12 @@ const Permission = () => { handleOpen={setAddPermissionModalOpen} addPermission={addPermission} /> + { setPathFilter(newValue) }} - renderInput={(params) => } + renderInput={(params) => } />