1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-10 11:24:35 +00:00

fix: improve user experience for adding permissions

This commit is contained in:
2022-08-04 02:51:59 +05:00
parent 754704bca8
commit 7a162eda8f
4 changed files with 233 additions and 68 deletions

View File

@@ -1,4 +1,4 @@
import React from 'react'
import React, { useMemo } from 'react'
import {
Paper,
@@ -16,19 +16,92 @@ import { BootstrapDialog } from '../../components/modal'
import { BootstrapDialogTitle } from '../../components/dialogTitle'
import { PermissionResponse } from '../../utils/types'
export interface PermissionResponsePayload {
existingPermissions: PermissionResponse[]
newAddedPermissions: PermissionResponse[]
updatedPermissions: PermissionResponse[]
errorPaths: string[]
}
type Props = {
open: boolean
setOpen: React.Dispatch<React.SetStateAction<boolean>>
permissionResponses: PermissionResponse[]
errorResponses: any[]
payload: PermissionResponsePayload
}
const PermissionResponseModal = ({
open,
setOpen,
permissionResponses,
errorResponses
}: Props) => {
const PermissionResponseModal = ({ open, setOpen, payload }: Props) => {
const rows = useMemo(() => {
const paths: any = []
const existingPermissionsLength = payload.existingPermissions.length
const newAddedPermissionsLength = payload.newAddedPermissions.length
const updatedPermissionsLength = payload.updatedPermissions.length
if (
existingPermissionsLength >= newAddedPermissionsLength &&
existingPermissionsLength >= updatedPermissionsLength
) {
payload.existingPermissions.forEach((permission, index) => {
const obj = {
existing: permission.path,
newAdded:
index < newAddedPermissionsLength
? payload.newAddedPermissions[index].path
: '-',
updated:
index < updatedPermissionsLength
? payload.updatedPermissions[index].path
: '-'
}
paths.push(obj)
})
return paths
}
if (
newAddedPermissionsLength >= existingPermissionsLength &&
newAddedPermissionsLength >= updatedPermissionsLength
) {
payload.newAddedPermissions.forEach((permission, index) => {
const obj = {
newAdded: permission.path,
existing:
index < existingPermissionsLength
? payload.existingPermissions[index].path
: '-',
updated:
index < updatedPermissionsLength
? payload.updatedPermissions[index].path
: '-'
}
paths.push(obj)
})
return paths
}
if (
updatedPermissionsLength >= existingPermissionsLength &&
updatedPermissionsLength >= newAddedPermissionsLength
) {
payload.updatedPermissions.forEach((permission, index) => {
const obj = {
updated: permission.path,
existing:
index < existingPermissionsLength
? payload.existingPermissions[index].path
: '-',
newAdded:
index < newAddedPermissionsLength
? payload.newAddedPermissions[index].path
: '-'
}
paths.push(obj)
})
return paths
}
return paths
}, [payload])
return (
<div>
<BootstrapDialog onClose={() => setOpen(false)} open={open}>
@@ -39,52 +112,38 @@ const PermissionResponseModal = ({
Permission Response
</BootstrapDialogTitle>
<DialogContent dividers>
{permissionResponses.length > 0 && (
<>
<Typography gutterBottom>Added Permissions</Typography>
{permissionResponses.length > 0 && (
<TableContainer component={Paper}>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Path</TableCell>
<TableCell>Type</TableCell>
<TableCell>Setting</TableCell>
</TableRow>
</TableHead>
<TableBody>
{permissionResponses.map((permission, index) => {
return (
<TableRow key={index}>
<TableCell>{permission.path}</TableCell>
<TableCell>{permission.type}</TableCell>
<TableCell>{permission.setting}</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</TableContainer>
)}
</>
)}
<TableContainer component={Paper}>
<Table size="small">
<TableHead sx={{ background: 'rgb(0,0,0, 0.3)' }}>
<TableRow>
<TableCell>New</TableCell>
<TableCell>Updated</TableCell>
<TableCell>Unchanged</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((obj: any, index: number) => {
return (
<TableRow key={index}>
<TableCell>{obj.newAdded}</TableCell>
<TableCell>{obj.updated}</TableCell>
<TableCell>{obj.existing}</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</TableContainer>
{errorResponses.length > 0 && (
{payload.errorPaths.length > 0 && (
<>
<Typography style={{ color: 'red', marginTop: '10px' }}>
Errors
Errors occurred for following paths:
</Typography>
<ul>
{errorResponses.map((err, index) => (
{payload.errorPaths.map((path, index) => (
<li key={index}>
<Typography>
Error occurred for Path: {err.permission.path}
</Typography>
<Typography>
{typeof err.error.response.data === 'object'
? JSON.stringify(err.error.response.data)
: err.error.response.data}
</Typography>
<Typography>{path}</Typography>
</li>
))}
</ul>

View File

@@ -47,7 +47,7 @@ const Settings = () => {
>
<StyledTab label="Profile" value="profile" />
{appContext.mode === ModeType.Server && (
<StyledTab label="Permission" value="permission" />
<StyledTab label="Permissions" value="permission" />
)}
</TabList>
</Box>

View File

@@ -27,7 +27,9 @@ import { styled } from '@mui/material/styles'
import Modal from '../../components/modal'
import PermissionFilterModal from './permissionFilterModal'
import AddPermissionModal from './addPermissionModal'
import PermissionResponseModal from './addPermissionResponseModal'
import PermissionResponseModal, {
PermissionResponsePayload
} from './addPermissionResponseModal'
import UpdatePermissionModal from './updatePermissionModal'
import DeleteConfirmationModal from '../../components/deleteConfirmationModal'
import BootstrapSnackbar, { AlertSeverityType } from '../../components/snackbar'
@@ -37,6 +39,11 @@ import {
PermissionResponse,
RegisterPermissionPayload
} from '../../utils/types'
import {
findExistingPermission,
findUpdatingPermission
} from '../../utils/helper'
import { AppContext } from '../../context/appContext'
const BootstrapTableCell = styled(TableCell)({
@@ -62,10 +69,13 @@ const Permission = () => {
const [addPermissionModalOpen, setAddPermissionModalOpen] = useState(false)
const [openPermissionResponseModal, setOpenPermissionResponseModal] =
useState(false)
const [addedPermissions, setAddedPermission] = useState<PermissionResponse[]>(
[]
)
const [errorResponses, setErrorResponses] = useState<any[]>([])
const [permissionResponsePayload, setPermissionResponsePayload] =
useState<PermissionResponsePayload>({
existingPermissions: [],
newAddedPermissions: [],
updatedPermissions: [],
errorPaths: []
})
const [updatePermissionModalOpen, setUpdatePermissionModalOpen] =
useState(false)
@@ -189,31 +199,69 @@ const Permission = () => {
setFilterApplied(false)
}
const addPermission = (permissions: RegisterPermissionPayload[]) => {
const addPermission = async (
permissionsToAdd: RegisterPermissionPayload[]
) => {
setAddPermissionModalOpen(false)
setAddedPermission([])
setErrorResponses([])
setIsLoading(true)
const permissionResponses: PermissionResponse[] = []
const errors: any = []
const newAddedPermissions: PermissionResponse[] = []
const updatedPermissions: PermissionResponse[] = []
const errorPaths: string[] = []
permissions.forEach(async (permission) => {
const existingPermissions: PermissionResponse[] = []
const updatingPermissions: PermissionResponse[] = []
const newPermissions: RegisterPermissionPayload[] = []
permissionsToAdd.forEach((permission) => {
const existingPermission = findExistingPermission(permissions, permission)
if (existingPermission) {
existingPermissions.push(existingPermission)
return
}
const updatingPermission = findUpdatingPermission(permissions, permission)
if (updatingPermission) {
updatingPermissions.push(updatingPermission)
return
}
newPermissions.push(permission)
})
for (const permission of newPermissions) {
await axios
.post('/SASjsApi/permission', permission)
.then((res) => {
permissionResponses.push(res.data)
newAddedPermissions.push(res.data)
})
.catch((error) => {
errors.push({ error, permission })
errorPaths.push(permission.path)
})
})
}
for (const permission of updatingPermissions) {
await axios
.patch(`/SASjsApi/permission/${permission.permissionId}`, {
setting: permission.setting === 'Grant' ? 'Deny' : 'Grant'
})
.then((res) => {
updatedPermissions.push(res.data)
})
.catch((error) => {
errorPaths.push(permission.path)
})
}
fetchPermissions()
setIsLoading(false)
setPermissionResponsePayload({
existingPermissions,
updatedPermissions,
newAddedPermissions,
errorPaths
})
setOpenPermissionResponseModal(true)
setAddedPermission(permissionResponses)
setErrorResponses(errors)
}
const handleUpdatePermissionClick = (permission: PermissionResponse) => {
@@ -353,8 +401,7 @@ const Permission = () => {
<PermissionResponseModal
open={openPermissionResponseModal}
setOpen={setOpenPermissionResponseModal}
permissionResponses={addedPermissions}
errorResponses={errorResponses}
payload={permissionResponsePayload}
/>
<UpdatePermissionModal
open={updatePermissionModalOpen}

59
web/src/utils/helper.ts Normal file
View File

@@ -0,0 +1,59 @@
import { PermissionResponse, RegisterPermissionPayload } from './types'
export const findExistingPermission = (
existingPermissions: PermissionResponse[],
newPermission: RegisterPermissionPayload
) => {
for (const permission of existingPermissions) {
if (
permission.user?.id === newPermission.principalId &&
hasSameCombination(permission, newPermission)
)
return permission
if (
permission.group?.groupId === newPermission.principalId &&
hasSameCombination(permission, newPermission)
)
return permission
}
return null
}
export const findUpdatingPermission = (
existingPermissions: PermissionResponse[],
newPermission: RegisterPermissionPayload
) => {
for (const permission of existingPermissions) {
if (
permission.user?.id === newPermission.principalId &&
hasDifferentSetting(permission, newPermission)
)
return permission
if (
permission.group?.groupId === newPermission.principalId &&
hasDifferentSetting(permission, newPermission)
)
return permission
}
return null
}
const hasSameCombination = (
existingPermission: PermissionResponse,
newPermission: RegisterPermissionPayload
) =>
existingPermission.path === newPermission.path &&
existingPermission.type === newPermission.type &&
existingPermission.setting === newPermission.setting
const hasDifferentSetting = (
existingPermission: PermissionResponse,
newPermission: RegisterPermissionPayload
) =>
existingPermission.path === newPermission.path &&
existingPermission.type === newPermission.type &&
existingPermission.setting !== newPermission.setting