From 97ecfdc95563c72dbdecaebcb504e5194250a763 Mon Sep 17 00:00:00 2001 From: Sabir Hassan Date: Fri, 24 Jun 2022 14:48:57 +0500 Subject: [PATCH] feat: add, remove and update permissions from web component --- api/public/swagger.yaml | 24 ++- web/src/components/modal.tsx | 43 ++++++ .../Settings/addPermissionModal.tsx | 4 +- .../Settings/deletePermissionModal.tsx | 44 ++++++ web/src/containers/Settings/permission.tsx | 138 +++++++++++++++--- .../Settings/permissionFilterModal.tsx | 6 +- .../Settings/updatePermissionModal.tsx | 4 +- 7 files changed, 233 insertions(+), 30 deletions(-) create mode 100644 web/src/components/modal.tsx create mode 100644 web/src/containers/Settings/deletePermissionModal.tsx diff --git a/api/public/swagger.yaml b/api/public/swagger.yaml index 5182869..9c78804 100644 --- a/api/public/swagger.yaml +++ b/api/public/swagger.yaml @@ -535,6 +535,24 @@ components: - setting type: object additionalProperties: false + SessionResponse: + properties: + id: + type: number + format: double + username: + type: string + displayName: + type: string + isAdmin: + type: boolean + required: + - id + - username + - displayName + - isAdmin + type: object + additionalProperties: false ExecuteReturnJsonPayload: properties: _program: @@ -638,7 +656,7 @@ paths: application/json: schema: properties: - user: {properties: {displayName: {type: string}, username: {type: string}, id: {type: number, format: double}}, required: [displayName, username, id], type: object} + user: {properties: {isAdmin: {type: boolean}, displayName: {type: string}, username: {type: string}, id: {type: number, format: double}}, required: [isAdmin, displayName, username, id], type: object} loggedIn: {type: boolean} required: - user @@ -1589,10 +1607,10 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/UserResponse' + $ref: '#/components/schemas/SessionResponse' examples: 'Example 1': - value: {id: 123, username: johnusername, displayName: John} + value: {id: 123, username: johnusername, displayName: John, isAdmin: false} summary: 'Get session info (username).' tags: - Session diff --git a/web/src/components/modal.tsx b/web/src/components/modal.tsx new file mode 100644 index 0000000..223bd9a --- /dev/null +++ b/web/src/components/modal.tsx @@ -0,0 +1,43 @@ +import React from 'react' + +import { Typography, Dialog, DialogContent } from '@mui/material' +import { styled } from '@mui/material/styles' + +import { BootstrapDialogTitle } from './dialogTitle' + +const BootstrapDialog = styled(Dialog)(({ theme }) => ({ + '& .MuiDialogContent-root': { + padding: theme.spacing(2) + }, + '& .MuiDialogActions-root': { + padding: theme.spacing(1) + } +})) + +export interface ModalProps { + open: boolean + setOpen: React.Dispatch> + title: string + payload: string +} + +const Modal = (props: ModalProps) => { + const { open, setOpen, title, payload } = props + + return ( +
+ setOpen(false)} open={open}> + + {title} + + + + {payload} + + + +
+ ) +} + +export default Modal diff --git a/web/src/containers/Settings/addPermissionModal.tsx b/web/src/containers/Settings/addPermissionModal.tsx index 0d413b8..ac113b8 100644 --- a/web/src/containers/Settings/addPermissionModal.tsx +++ b/web/src/containers/Settings/addPermissionModal.tsx @@ -93,7 +93,9 @@ const AddPermissionModal = ({ } const URIs = useMemo(() => { - return permissions.map((permission) => permission.uri) + return permissions + .map((permission) => permission.uri) + .filter((uri, index, array) => array.indexOf(uri) === index) }, [permissions]) const addButtonDisabled = diff --git a/web/src/containers/Settings/deletePermissionModal.tsx b/web/src/containers/Settings/deletePermissionModal.tsx new file mode 100644 index 0000000..59527bd --- /dev/null +++ b/web/src/containers/Settings/deletePermissionModal.tsx @@ -0,0 +1,44 @@ +import React from 'react' + +import { + Button, + Dialog, + DialogContent, + DialogActions, + Typography +} from '@mui/material' +import { styled } from '@mui/material/styles' + +const BootstrapDialog = styled(Dialog)(({ theme }) => ({ + '& .MuiDialogContent-root': { + padding: theme.spacing(2) + }, + '& .MuiDialogActions-root': { + padding: theme.spacing(1) + } +})) + +type DeleteModalProps = { + open: boolean + setOpen: React.Dispatch> + deletePermission: () => void +} + +const DeleteModal = ({ open, setOpen, deletePermission }: DeleteModalProps) => { + return ( + setOpen(false)} open={open}> + + + Are you sure to delete this permission? + + + + + + + ) +} + +export default DeleteModal diff --git a/web/src/containers/Settings/permission.tsx b/web/src/containers/Settings/permission.tsx index 10f6fd5..36712d4 100644 --- a/web/src/containers/Settings/permission.tsx +++ b/web/src/containers/Settings/permission.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useContext } from 'react' +import React, { useState, useEffect, useContext, useCallback } from 'react' import axios from 'axios' import { Box, @@ -22,11 +22,16 @@ import DeleteForeverIcon from '@mui/icons-material/DeleteForever' import { styled } from '@mui/material/styles' +import Modal from '../../components/modal' import PermissionFilterModal from './permissionFilterModal' import AddPermissionModal from './addPermissionModal' import UpdatePermissionModal from './updatePermissionModal' +import DeleteModal from './deletePermissionModal' -import { PermissionResponse } from '../../utils/types' +import { + PermissionResponse, + RegisterPermissionPayload +} from '../../utils/types' import { AppContext } from '../../context/appContext' const BootstrapTableCell = styled(TableCell)({ @@ -36,10 +41,14 @@ const BootstrapTableCell = styled(TableCell)({ const Permission = () => { const appContext = useContext(AppContext) const [isLoading, setIsLoading] = useState(false) + const [openModal, setOpenModal] = useState(false) + const [modalTitle, setModalTitle] = useState('') + const [modalPayload, setModalPayload] = useState('') const [addPermissionModalOpen, setAddPermissionModalOpen] = useState(false) const [updatePermissionModalOpen, setUpdatePermissionModalOpen] = useState(false) - const [selectedPermissionForUpdate, setSelectedPermissionForUpdate] = + const [deleteModalOpen, setDeleteModalOpen] = useState(false) + const [selectedPermission, setSelectedPermission] = useState() const [filterModalOpen, setFilterModalOpen] = useState(false) const [uriFilter, setUriFilter] = useState([]) @@ -51,8 +60,7 @@ const Permission = () => { >([]) const [filterApplied, setFilterApplied] = useState(false) - useEffect(() => { - setIsLoading(true) + const fetchPermissions = useCallback(() => { axios .get(`/SASjsApi/permission`) .then((res: any) => { @@ -61,13 +69,16 @@ const Permission = () => { } }) .catch((err) => { - console.log(err) - }) - .finally(() => { - setIsLoading(false) + setModalTitle('Abort') + setModalPayload(typeof err === 'object' ? err.toSting() : err) + setOpenModal(true) }) }, []) + useEffect(() => { + fetchPermissions() + }, [fetchPermissions]) + /** * first find the permissions w.r.t each filter type * take intersection of resultant arrays @@ -119,14 +130,82 @@ const Permission = () => { setFilterApplied(false) } - const addPermission = () => {} + const addPermission = (addPermissionPayload: RegisterPermissionPayload) => { + setAddPermissionModalOpen(false) + setIsLoading(true) + axios + .post('/SASjsApi/permission', addPermissionPayload) + .then((res: any) => { + fetchPermissions() + setModalTitle('Success') + setModalPayload('Permission added Successfully.') + setOpenModal(true) + }) + .catch((err) => { + setModalTitle('Abort') + setModalPayload(typeof err === 'object' ? err.toSting() : err) + setOpenModal(true) + }) + .finally(() => { + setIsLoading(false) + }) + } const handleUpdatePermissionClick = (permission: PermissionResponse) => { - setSelectedPermissionForUpdate(permission) + setSelectedPermission(permission) setUpdatePermissionModalOpen(true) } - const updatePermission = () => {} + const updatePermission = (setting: string) => { + setUpdatePermissionModalOpen(false) + setIsLoading(true) + axios + .patch(`/SASjsApi/permission/${selectedPermission?.permissionId}`, { + setting + }) + .then((res: any) => { + fetchPermissions() + setModalTitle('Success') + setModalPayload('Permission updated Successfully.') + setOpenModal(true) + }) + .catch((err) => { + setModalTitle('Abort') + setModalPayload(typeof err === 'object' ? err.toSting() : err) + setOpenModal(true) + }) + .finally(() => { + setIsLoading(false) + setSelectedPermission(undefined) + }) + } + + const handleDeletePermissionClick = (permission: PermissionResponse) => { + setSelectedPermission(permission) + setDeleteModalOpen(true) + } + + const deletePermission = () => { + setDeleteModalOpen(false) + setIsLoading(true) + axios + .delete(`/SASjsApi/permission/${selectedPermission?.permissionId}`) + .then((res: any) => { + fetchPermissions() + setModalTitle('Success') + setModalPayload('Permission deleted Successfully.') + setOpenModal(true) + }) + .catch((err) => { + setModalTitle('Abort') + setModalPayload(typeof err === 'object' ? err.toSting() : err) + setOpenModal(true) + }) + .finally(() => { + setIsLoading(false) + setSelectedPermission(undefined) + }) + } return isLoading ? ( { + { permissions={permissions} addPermission={addPermission} /> - {selectedPermissionForUpdate && ( - - )} + + ) } @@ -198,11 +287,13 @@ export default Permission type PermissionTableProps = { permissions: PermissionResponse[] handleUpdatePermissionClick: (permission: PermissionResponse) => void + handleDeletePermissionClick: (permission: PermissionResponse) => void } const PermissionTable = ({ permissions, - handleUpdatePermissionClick + handleUpdatePermissionClick, + handleDeletePermissionClick }: PermissionTableProps) => { const appContext = useContext(AppContext) @@ -237,7 +328,10 @@ const PermissionTable = ({ - + handleDeletePermissionClick(permission)} + > diff --git a/web/src/containers/Settings/permissionFilterModal.tsx b/web/src/containers/Settings/permissionFilterModal.tsx index 962c3da..a487276 100644 --- a/web/src/containers/Settings/permissionFilterModal.tsx +++ b/web/src/containers/Settings/permissionFilterModal.tsx @@ -48,7 +48,9 @@ const PermissionFilterModal = ({ applyFilter, resetFilter }: FilterModalProps) => { - const URIs = permissions.map((permission) => permission.uri) + const URIs = permissions + .map((permission) => permission.uri) + .filter((uri, index, array) => array.indexOf(uri) === index) // fetch all the principals from permissions array let principals = permissions.map((permission) => { @@ -62,7 +64,7 @@ const PermissionFilterModal = ({ // removes the duplicates principals = principals.filter( - (value, index, self) => self.indexOf(value) === index + (principal, index, array) => array.indexOf(principal) === index ) return ( diff --git a/web/src/containers/Settings/updatePermissionModal.tsx b/web/src/containers/Settings/updatePermissionModal.tsx index e134f4f..796017d 100644 --- a/web/src/containers/Settings/updatePermissionModal.tsx +++ b/web/src/containers/Settings/updatePermissionModal.tsx @@ -26,7 +26,7 @@ const BootstrapDialog = styled(Dialog)(({ theme }) => ({ type UpdatePermissionModalProps = { open: boolean handleOpen: Dispatch> - permission: PermissionResponse + permission: PermissionResponse | undefined updatePermission: (setting: string) => void } @@ -68,7 +68,7 @@ const UpdatePermissionModal = ({