mirror of
https://github.com/sasjs/server.git
synced 2025-12-10 11:24:35 +00:00
feat: add, remove and update permissions from web component
This commit is contained in:
@@ -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
|
||||
|
||||
43
web/src/components/modal.tsx
Normal file
43
web/src/components/modal.tsx
Normal file
@@ -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<React.SetStateAction<boolean>>
|
||||
title: string
|
||||
payload: string
|
||||
}
|
||||
|
||||
const Modal = (props: ModalProps) => {
|
||||
const { open, setOpen, title, payload } = props
|
||||
|
||||
return (
|
||||
<div>
|
||||
<BootstrapDialog onClose={() => setOpen(false)} open={open}>
|
||||
<BootstrapDialogTitle id="abort-modal" handleOpen={setOpen}>
|
||||
{title}
|
||||
</BootstrapDialogTitle>
|
||||
<DialogContent dividers>
|
||||
<Typography gutterBottom>
|
||||
<span style={{ fontFamily: 'monospace' }}>{payload}</span>
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
</BootstrapDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Modal
|
||||
@@ -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 =
|
||||
|
||||
44
web/src/containers/Settings/deletePermissionModal.tsx
Normal file
44
web/src/containers/Settings/deletePermissionModal.tsx
Normal file
@@ -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<React.SetStateAction<boolean>>
|
||||
deletePermission: () => void
|
||||
}
|
||||
|
||||
const DeleteModal = ({ open, setOpen, deletePermission }: DeleteModalProps) => {
|
||||
return (
|
||||
<BootstrapDialog onClose={() => setOpen(false)} open={open}>
|
||||
<DialogContent dividers>
|
||||
<Typography gutterBottom>
|
||||
Are you sure to delete this permission?
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button color="error" onClick={() => deletePermission()}>
|
||||
Delete
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</BootstrapDialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default DeleteModal
|
||||
@@ -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<PermissionResponse>()
|
||||
const [filterModalOpen, setFilterModalOpen] = useState(false)
|
||||
const [uriFilter, setUriFilter] = useState<string[]>([])
|
||||
@@ -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 ? (
|
||||
<CircularProgress
|
||||
@@ -159,9 +238,16 @@ const Permission = () => {
|
||||
<PermissionTable
|
||||
permissions={filterApplied ? filteredPermissions : permissions}
|
||||
handleUpdatePermissionClick={handleUpdatePermissionClick}
|
||||
handleDeletePermissionClick={handleDeletePermissionClick}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Modal
|
||||
open={openModal}
|
||||
setOpen={setOpenModal}
|
||||
title={modalTitle}
|
||||
payload={modalPayload}
|
||||
/>
|
||||
<PermissionFilterModal
|
||||
open={filterModalOpen}
|
||||
handleOpen={setFilterModalOpen}
|
||||
@@ -181,14 +267,17 @@ const Permission = () => {
|
||||
permissions={permissions}
|
||||
addPermission={addPermission}
|
||||
/>
|
||||
{selectedPermissionForUpdate && (
|
||||
<UpdatePermissionModal
|
||||
open={updatePermissionModalOpen}
|
||||
handleOpen={setUpdatePermissionModalOpen}
|
||||
permission={selectedPermissionForUpdate}
|
||||
updatePermission={updatePermission}
|
||||
/>
|
||||
)}
|
||||
<UpdatePermissionModal
|
||||
open={updatePermissionModalOpen}
|
||||
handleOpen={setUpdatePermissionModalOpen}
|
||||
permission={selectedPermission}
|
||||
updatePermission={updatePermission}
|
||||
/>
|
||||
<DeleteModal
|
||||
open={deleteModalOpen}
|
||||
setOpen={setDeleteModalOpen}
|
||||
deletePermission={deletePermission}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -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 = ({
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="Delete Permission">
|
||||
<IconButton color="error">
|
||||
<IconButton
|
||||
color="error"
|
||||
onClick={() => handleDeletePermissionClick(permission)}
|
||||
>
|
||||
<DeleteForeverIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -26,7 +26,7 @@ const BootstrapDialog = styled(Dialog)(({ theme }) => ({
|
||||
type UpdatePermissionModalProps = {
|
||||
open: boolean
|
||||
handleOpen: Dispatch<SetStateAction<boolean>>
|
||||
permission: PermissionResponse
|
||||
permission: PermissionResponse | undefined
|
||||
updatePermission: (setting: string) => void
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ const UpdatePermissionModal = ({
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => updatePermission(permissionSetting)}
|
||||
disabled={permission.setting === permissionSetting}
|
||||
disabled={permission?.setting === permissionSetting}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user