mirror of
https://github.com/sasjs/server.git
synced 2025-12-12 03:54:34 +00:00
feat: created modal for adding permission
This commit is contained in:
@@ -7,19 +7,19 @@ import CloseIcon from '@mui/icons-material/Close'
|
|||||||
export interface DialogTitleProps {
|
export interface DialogTitleProps {
|
||||||
id: string
|
id: string
|
||||||
children?: React.ReactNode
|
children?: React.ReactNode
|
||||||
onClose: Dispatch<SetStateAction<boolean>>
|
handleOpen: Dispatch<SetStateAction<boolean>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BootstrapDialogTitle = (props: DialogTitleProps) => {
|
export const BootstrapDialogTitle = (props: DialogTitleProps) => {
|
||||||
const { children, onClose, ...other } = props
|
const { children, handleOpen, ...other } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DialogTitle sx={{ m: 0, p: 2 }} {...other}>
|
<DialogTitle sx={{ m: 0, p: 2 }} {...other}>
|
||||||
{children}
|
{children}
|
||||||
{onClose ? (
|
{handleOpen ? (
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label="close"
|
aria-label="close"
|
||||||
onClick={() => onClose(false)}
|
onClick={() => handleOpen(false)}
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
right: 8,
|
right: 8,
|
||||||
|
|||||||
217
web/src/containers/Settings/addPermissionModal.tsx
Normal file
217
web/src/containers/Settings/addPermissionModal.tsx
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
import React, {
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
Dispatch,
|
||||||
|
SetStateAction
|
||||||
|
} from 'react'
|
||||||
|
import axios from 'axios'
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Grid,
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogActions,
|
||||||
|
TextField,
|
||||||
|
CircularProgress
|
||||||
|
} from '@mui/material'
|
||||||
|
import { styled } from '@mui/material/styles'
|
||||||
|
import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete'
|
||||||
|
|
||||||
|
import { BootstrapDialogTitle } from '../../components/dialogTitle'
|
||||||
|
|
||||||
|
import {
|
||||||
|
PermissionResponse,
|
||||||
|
UserResponse,
|
||||||
|
GroupResponse,
|
||||||
|
RegisterPermissionPayload
|
||||||
|
} from '../../utils/types'
|
||||||
|
|
||||||
|
const BootstrapDialog = styled(Dialog)(({ theme }) => ({
|
||||||
|
'& .MuiDialogContent-root': {
|
||||||
|
padding: theme.spacing(2)
|
||||||
|
},
|
||||||
|
'& .MuiDialogActions-root': {
|
||||||
|
padding: theme.spacing(1)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
type AddPermissionModalProps = {
|
||||||
|
open: boolean
|
||||||
|
handleOpen: Dispatch<SetStateAction<boolean>>
|
||||||
|
permissions: PermissionResponse[]
|
||||||
|
addPermission: (addPermissionPayload: RegisterPermissionPayload) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = createFilterOptions<string>()
|
||||||
|
|
||||||
|
const AddPermissionModal = ({
|
||||||
|
open,
|
||||||
|
handleOpen,
|
||||||
|
permissions,
|
||||||
|
addPermission
|
||||||
|
}: AddPermissionModalProps) => {
|
||||||
|
const [uri, setUri] = useState<string>()
|
||||||
|
const [principalType, setPrincipalType] = useState('user')
|
||||||
|
const [userPrincipal, setUserPrincipal] = useState<UserResponse>()
|
||||||
|
const [groupPrincipal, setGroupPrincipal] = useState<GroupResponse>()
|
||||||
|
const [permissionSetting, setPermissionSetting] = useState('Grant')
|
||||||
|
const [loadingPrincipals, setLoadingPrincipals] = useState(false)
|
||||||
|
const [userPrincipals, setUserPrincipals] = useState<UserResponse[]>([])
|
||||||
|
const [groupPrincipals, setGroupPrincipals] = useState<GroupResponse[]>([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLoadingPrincipals(true)
|
||||||
|
axios
|
||||||
|
.get(`/SASjsApi/${principalType}`)
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.data) {
|
||||||
|
if (principalType === 'user') setUserPrincipals(res.data)
|
||||||
|
else setGroupPrincipals(res.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setLoadingPrincipals(false)
|
||||||
|
})
|
||||||
|
}, [principalType])
|
||||||
|
|
||||||
|
const handleAddPermission = () => {
|
||||||
|
const addPermissionPayload: any = {
|
||||||
|
uri,
|
||||||
|
setting: permissionSetting,
|
||||||
|
principalType
|
||||||
|
}
|
||||||
|
if (principalType === 'user' && userPrincipal) {
|
||||||
|
addPermissionPayload.principalId = userPrincipal.id
|
||||||
|
} else if (principalType === 'group' && groupPrincipal) {
|
||||||
|
addPermissionPayload.principalId = groupPrincipal.groupId
|
||||||
|
}
|
||||||
|
addPermission(addPermissionPayload)
|
||||||
|
}
|
||||||
|
|
||||||
|
const URIs = useMemo(() => {
|
||||||
|
return permissions.map((permission) => permission.uri)
|
||||||
|
}, [permissions])
|
||||||
|
|
||||||
|
const addButtonDisabled =
|
||||||
|
!uri || (principalType === 'user' ? !userPrincipal : !groupPrincipal)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BootstrapDialog onClose={() => handleOpen(false)} open={open}>
|
||||||
|
<BootstrapDialogTitle
|
||||||
|
id="add-permission-dialog-title"
|
||||||
|
handleOpen={handleOpen}
|
||||||
|
>
|
||||||
|
Add Permission
|
||||||
|
</BootstrapDialogTitle>
|
||||||
|
<DialogContent dividers>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Autocomplete
|
||||||
|
disableClearable
|
||||||
|
value={uri}
|
||||||
|
onChange={(event, newValue) => setUri(newValue)}
|
||||||
|
filterOptions={(options, params) => {
|
||||||
|
const filtered = filter(options, params)
|
||||||
|
|
||||||
|
const { inputValue } = params
|
||||||
|
|
||||||
|
const isExisting = options.some(
|
||||||
|
(option) => inputValue === option
|
||||||
|
)
|
||||||
|
if (inputValue !== '' && !isExisting) {
|
||||||
|
filtered.push(inputValue)
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}}
|
||||||
|
selectOnFocus
|
||||||
|
clearOnBlur
|
||||||
|
handleHomeEndKeys
|
||||||
|
options={URIs}
|
||||||
|
renderOption={(props, option) => <li {...props}>{option}</li>}
|
||||||
|
freeSolo
|
||||||
|
renderInput={(params) => <TextField {...params} label="URI" />}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Autocomplete
|
||||||
|
options={['user', 'group']}
|
||||||
|
disableClearable
|
||||||
|
value={principalType}
|
||||||
|
onChange={(event: any, newValue: string) =>
|
||||||
|
setPrincipalType(newValue)
|
||||||
|
}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField {...params} label="Principal Type" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
{principalType === 'user' ? (
|
||||||
|
<Autocomplete
|
||||||
|
options={userPrincipals}
|
||||||
|
getOptionLabel={(option) => option.displayName}
|
||||||
|
disableClearable
|
||||||
|
value={userPrincipal}
|
||||||
|
onChange={(event: any, newValue: UserResponse) =>
|
||||||
|
setUserPrincipal(newValue)
|
||||||
|
}
|
||||||
|
renderInput={(params) =>
|
||||||
|
loadingPrincipals ? (
|
||||||
|
<CircularProgress />
|
||||||
|
) : (
|
||||||
|
<TextField {...params} label="Principal" />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Autocomplete
|
||||||
|
options={groupPrincipals}
|
||||||
|
getOptionLabel={(option) => option.name}
|
||||||
|
disableClearable
|
||||||
|
value={groupPrincipal}
|
||||||
|
onChange={(event: any, newValue: GroupResponse) =>
|
||||||
|
setGroupPrincipal(newValue)
|
||||||
|
}
|
||||||
|
renderInput={(params) =>
|
||||||
|
loadingPrincipals ? (
|
||||||
|
<CircularProgress />
|
||||||
|
) : (
|
||||||
|
<TextField {...params} label="Principal" />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Autocomplete
|
||||||
|
options={['Grant', 'Deny']}
|
||||||
|
disableClearable
|
||||||
|
value={permissionSetting}
|
||||||
|
onChange={(event: any, newValue: string) =>
|
||||||
|
setPermissionSetting(newValue)
|
||||||
|
}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField {...params} label="Settings" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={handleAddPermission}
|
||||||
|
disabled={addButtonDisabled}
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</BootstrapDialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddPermissionModal
|
||||||
@@ -23,26 +23,9 @@ import DeleteForeverIcon from '@mui/icons-material/DeleteForever'
|
|||||||
import { styled } from '@mui/material/styles'
|
import { styled } from '@mui/material/styles'
|
||||||
|
|
||||||
import PermissionFilterModal from './permissionFilterModal'
|
import PermissionFilterModal from './permissionFilterModal'
|
||||||
|
import AddPermissionModal from './addPermissionModal'
|
||||||
|
|
||||||
interface UserResponse {
|
import { PermissionResponse } from '../../utils/types'
|
||||||
id: number
|
|
||||||
username: string
|
|
||||||
displayName: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GroupResponse {
|
|
||||||
groupId: number
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PermissionResponse {
|
|
||||||
permissionId: number
|
|
||||||
uri: string
|
|
||||||
setting: string
|
|
||||||
user?: UserResponse
|
|
||||||
group?: GroupResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
const BootstrapTableCell = styled(TableCell)({
|
const BootstrapTableCell = styled(TableCell)({
|
||||||
textAlign: 'left'
|
textAlign: 'left'
|
||||||
@@ -50,6 +33,7 @@ const BootstrapTableCell = styled(TableCell)({
|
|||||||
|
|
||||||
const Permission = () => {
|
const Permission = () => {
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const [addPermissionModalOpen, setAddPermissionModalOpen] = useState(false)
|
||||||
const [filterModalOpen, setFilterModalOpen] = useState(false)
|
const [filterModalOpen, setFilterModalOpen] = useState(false)
|
||||||
const [uriFilter, setUriFilter] = useState<string[]>([])
|
const [uriFilter, setUriFilter] = useState<string[]>([])
|
||||||
const [principalFilter, setPrincipalFilter] = useState<string[]>([])
|
const [principalFilter, setPrincipalFilter] = useState<string[]>([])
|
||||||
@@ -128,6 +112,8 @@ const Permission = () => {
|
|||||||
setFilterApplied(false)
|
setFilterApplied(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addPermission = () => {}
|
||||||
|
|
||||||
return isLoading ? (
|
return isLoading ? (
|
||||||
<CircularProgress
|
<CircularProgress
|
||||||
style={{ position: 'absolute', left: '50%', top: '50%' }}
|
style={{ position: 'absolute', left: '50%', top: '50%' }}
|
||||||
@@ -142,8 +128,12 @@ const Permission = () => {
|
|||||||
<FilterListIcon onClick={() => setFilterModalOpen(true)} />
|
<FilterListIcon onClick={() => setFilterModalOpen(true)} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title="Add Permission" placement="bottom-end">
|
<Tooltip
|
||||||
<IconButton sx={{ flexGrow: 1, justifyContent: 'flex-end' }}>
|
sx={{ marginLeft: 'auto' }}
|
||||||
|
title="Add Permission"
|
||||||
|
placement="bottom-end"
|
||||||
|
>
|
||||||
|
<IconButton onClick={() => setAddPermissionModalOpen(true)}>
|
||||||
<AddIcon />
|
<AddIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -157,7 +147,7 @@ const Permission = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
<PermissionFilterModal
|
<PermissionFilterModal
|
||||||
open={filterModalOpen}
|
open={filterModalOpen}
|
||||||
handleClose={setFilterModalOpen}
|
handleOpen={setFilterModalOpen}
|
||||||
permissions={permissions}
|
permissions={permissions}
|
||||||
uriFilter={uriFilter}
|
uriFilter={uriFilter}
|
||||||
setUriFilter={setUriFilter}
|
setUriFilter={setUriFilter}
|
||||||
@@ -168,6 +158,12 @@ const Permission = () => {
|
|||||||
applyFilter={applyFilter}
|
applyFilter={applyFilter}
|
||||||
resetFilter={resetFilter}
|
resetFilter={resetFilter}
|
||||||
/>
|
/>
|
||||||
|
<AddPermissionModal
|
||||||
|
open={addPermissionModalOpen}
|
||||||
|
handleOpen={setAddPermissionModalOpen}
|
||||||
|
permissions={permissions}
|
||||||
|
addPermission={addPermission}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -192,7 +188,7 @@ const PermissionTable = ({ permissions }: PermissionTableProps) => {
|
|||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{permissions.map((permission) => (
|
{permissions.map((permission) => (
|
||||||
<TableRow>
|
<TableRow key={permission.permissionId}>
|
||||||
<BootstrapTableCell>{permission.uri}</BootstrapTableCell>
|
<BootstrapTableCell>{permission.uri}</BootstrapTableCell>
|
||||||
<BootstrapTableCell>
|
<BootstrapTableCell>
|
||||||
{displayPrincipal(permission)}
|
{displayPrincipal(permission)}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
import { styled } from '@mui/material/styles'
|
import { styled } from '@mui/material/styles'
|
||||||
import Autocomplete from '@mui/material/Autocomplete'
|
import Autocomplete from '@mui/material/Autocomplete'
|
||||||
|
|
||||||
import { PermissionResponse } from './permission'
|
import { PermissionResponse } from '../../utils/types'
|
||||||
import { BootstrapDialogTitle } from '../../components/dialogTitle'
|
import { BootstrapDialogTitle } from '../../components/dialogTitle'
|
||||||
const BootstrapDialog = styled(Dialog)(({ theme }) => ({
|
const BootstrapDialog = styled(Dialog)(({ theme }) => ({
|
||||||
'& .MuiDialogContent-root': {
|
'& .MuiDialogContent-root': {
|
||||||
@@ -23,7 +23,7 @@ const BootstrapDialog = styled(Dialog)(({ theme }) => ({
|
|||||||
|
|
||||||
type FilterModalProps = {
|
type FilterModalProps = {
|
||||||
open: boolean
|
open: boolean
|
||||||
handleClose: Dispatch<SetStateAction<boolean>>
|
handleOpen: Dispatch<SetStateAction<boolean>>
|
||||||
permissions: PermissionResponse[]
|
permissions: PermissionResponse[]
|
||||||
uriFilter: string[]
|
uriFilter: string[]
|
||||||
setUriFilter: Dispatch<SetStateAction<string[]>>
|
setUriFilter: Dispatch<SetStateAction<string[]>>
|
||||||
@@ -37,7 +37,7 @@ type FilterModalProps = {
|
|||||||
|
|
||||||
const PermissionFilterModal = ({
|
const PermissionFilterModal = ({
|
||||||
open,
|
open,
|
||||||
handleClose,
|
handleOpen,
|
||||||
permissions,
|
permissions,
|
||||||
uriFilter,
|
uriFilter,
|
||||||
setUriFilter,
|
setUriFilter,
|
||||||
@@ -58,10 +58,10 @@ const PermissionFilterModal = ({
|
|||||||
.filter((principal) => principal !== '')
|
.filter((principal) => principal !== '')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BootstrapDialog onClose={handleClose} open={open}>
|
<BootstrapDialog onClose={() => handleOpen(false)} open={open}>
|
||||||
<BootstrapDialogTitle
|
<BootstrapDialogTitle
|
||||||
id="permission-filter-dialog-title"
|
id="permission-filter-dialog-title"
|
||||||
onClose={handleClose}
|
handleOpen={handleOpen}
|
||||||
>
|
>
|
||||||
Permission Filter
|
Permission Filter
|
||||||
</BootstrapDialogTitle>
|
</BootstrapDialogTitle>
|
||||||
|
|||||||
Reference in New Issue
Block a user