1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-04 00:18:01 +01:00

task: Use fine-grained project permissions in frontend (#5974)

Connected to [#5932](https://github.com/Unleash/unleash/pull/5932) -
This starts using the new permissions in addition to the old
UPDATE_PROJECT permission. That way, if you're happy with
UPDATE_PROJECT, you don't need to change.

However, you can now add more fine grained permissions for both READ and
WRITE operations.
This commit is contained in:
Christopher Kolstad 2024-01-22 15:34:10 +01:00 committed by GitHub
parent b7483e8989
commit 8256c2eaf2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 73 additions and 19 deletions

View File

@ -8,7 +8,7 @@ import {
} from 'hooks/useHasAccess';
interface IPermissionSwitchProps extends SwitchProps {
permission: string;
permission: string | string[];
tooltip?: string;
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
disabled?: boolean;

View File

@ -4,7 +4,10 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { Alert } from '@mui/material';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import AccessContext from 'contexts/AccessContext';
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
import {
PROJECT_CHANGE_REQUEST_READ,
UPDATE_PROJECT,
} from 'component/providers/AccessProvider/permissions';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { usePageTitle } from 'hooks/usePageTitle';
import { useProjectNameOrId } from 'hooks/api/getters/useProject/useProject';
@ -36,7 +39,7 @@ export const ChangeRequestConfiguration = () => {
);
}
if (!hasAccess(UPDATE_PROJECT, projectId)) {
if (!hasAccess([UPDATE_PROJECT, PROJECT_CHANGE_REQUEST_READ], projectId)) {
return (
<PageContent
header={<PageHeader title='Change request configuration' />}

View File

@ -30,6 +30,7 @@ import { KeyboardArrowDownOutlined } from '@mui/icons-material';
import { useTheme } from '@mui/material/styles';
import AccessContext from 'contexts/AccessContext';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { PROJECT_CHANGE_REQUEST_WRITE } from '../../../../providers/AccessProvider/permissions';
const StyledBox = styled(Box)(({ theme }) => ({
padding: theme.spacing(1),
@ -159,7 +160,10 @@ export const ChangeRequestTable: VFC = () => {
}}
disabled={
!hasAccess(
UPDATE_PROJECT,
[
UPDATE_PROJECT,
PROJECT_CHANGE_REQUEST_WRITE,
],
projectId,
)
}
@ -188,7 +192,10 @@ export const ChangeRequestTable: VFC = () => {
<PermissionSwitch
checked={value}
projectId={projectId}
permission={UPDATE_PROJECT}
permission={[
UPDATE_PROJECT,
PROJECT_CHANGE_REQUEST_WRITE,
]}
inputProps={{ 'aria-label': original.environment }}
onClick={onRowChange(
original.environment,

View File

@ -4,7 +4,10 @@ import AccessContext from 'contexts/AccessContext';
import { usePageTitle } from 'hooks/usePageTitle';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
import {
PROJECT_DEFAULT_STRATEGY_READ,
UPDATE_PROJECT,
} from 'component/providers/AccessProvider/permissions';
import { Alert, styled } from '@mui/material';
import ProjectEnvironment from './ProjectEnvironment/ProjectEnvironment';
import { Route, Routes, useNavigate } from 'react-router-dom';
@ -25,7 +28,9 @@ export const ProjectDefaultStrategySettings = () => {
const navigate = useNavigate();
usePageTitle(`Project default strategy configuration ${projectName}`);
if (!hasAccess(UPDATE_PROJECT, projectId)) {
if (
!hasAccess([UPDATE_PROJECT, PROJECT_DEFAULT_STRATEGY_READ], projectId)
) {
return (
<PageContent
header={<PageHeader title='Default Strategy configuration' />}

View File

@ -1,4 +1,7 @@
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
import {
PROJECT_SETTINGS_WRITE,
UPDATE_PROJECT,
} from 'component/providers/AccessProvider/permissions';
import useProject from 'hooks/api/getters/useProject/useProject';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
@ -26,7 +29,10 @@ const EditProject = () => {
return null;
}
const accessDeniedAlert = !hasAccess(UPDATE_PROJECT, id) && (
const accessDeniedAlert = !hasAccess(
[UPDATE_PROJECT, PROJECT_SETTINGS_WRITE],
id,
) && (
<Alert severity='error' sx={{ mb: 4 }}>
You do not have the required permissions to edit this project.
</Alert>

View File

@ -1,7 +1,10 @@
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import ProjectForm from '../../../ProjectForm/ProjectForm';
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
import {
PROJECT_SETTINGS_WRITE,
UPDATE_PROJECT,
} from 'component/providers/AccessProvider/permissions';
import useProjectForm, {
DEFAULT_PROJECT_STICKINESS,
} from '../../../hooks/useProjectForm';
@ -138,7 +141,10 @@ export const UpdateProject = ({ project }: IUpdateProject) => {
>
<PermissionButton
type='submit'
permission={UPDATE_PROJECT}
permission={[
UPDATE_PROJECT,
PROJECT_SETTINGS_WRITE,
]}
projectId={projectId}
data-testid={EDIT_PROJECT_BTN}
>

View File

@ -3,7 +3,10 @@ import { PageContent } from 'component/common/PageContent/PageContent';
import { Alert } from '@mui/material';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import AccessContext from 'contexts/AccessContext';
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
import {
PROJECT_SETTINGS_READ,
UPDATE_PROJECT,
} from 'component/providers/AccessProvider/permissions';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { usePageTitle } from 'hooks/usePageTitle';
import EditProject from './EditProject/EditProject';
@ -29,7 +32,7 @@ export const Settings = () => {
);
}
if (!hasAccess(UPDATE_PROJECT, projectId)) {
if (!hasAccess([UPDATE_PROJECT, PROJECT_SETTINGS_READ], projectId)) {
return (
<PageContent header={<PageHeader title='Access' />}>
<Alert severity='error'>

View File

@ -4,7 +4,10 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { Alert } from '@mui/material';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import AccessContext from 'contexts/AccessContext';
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
import {
PROJECT_USER_ACCESS_READ,
UPDATE_PROJECT,
} from 'component/providers/AccessProvider/permissions';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { usePageTitle } from 'hooks/usePageTitle';
import { ProjectAccessTable } from 'component/project/ProjectAccess/ProjectAccessTable/ProjectAccessTable';
@ -29,7 +32,7 @@ export const ProjectAccess = () => {
);
}
if (!hasAccess(UPDATE_PROJECT, projectId)) {
if (!hasAccess([UPDATE_PROJECT, PROJECT_USER_ACCESS_READ], projectId)) {
return (
<PageContent header={<PageHeader title='Access' />}>
<Alert severity='error'>

View File

@ -9,7 +9,10 @@ import useProjectAccess, {
IProjectAccess,
} from 'hooks/api/getters/useProjectAccess/useProjectAccess';
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions';
import {
PROJECT_USER_ACCESS_WRITE,
UPDATE_PROJECT,
} from 'component/providers/AccessProvider/permissions';
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
@ -212,7 +215,10 @@ export const ProjectAccessTable: VFC = () => {
<PermissionIconButton
data-testid={PA_EDIT_BUTTON_ID}
component={Link}
permission={UPDATE_PROJECT}
permission={[
UPDATE_PROJECT,
PROJECT_USER_ACCESS_WRITE,
]}
projectId={projectId}
to={`edit/${
row.type === ENTITY_TYPE.GROUP
@ -231,7 +237,10 @@ export const ProjectAccessTable: VFC = () => {
</PermissionIconButton>
<PermissionIconButton
data-testid={PA_REMOVE_BUTTON_ID}
permission={UPDATE_PROJECT}
permission={[
UPDATE_PROJECT,
PROJECT_USER_ACCESS_WRITE,
]}
projectId={projectId}
onClick={() => {
setSelectedRow(row);
@ -411,7 +420,10 @@ export const ProjectAccessTable: VFC = () => {
onClick={() => navigate('create')}
maxWidth='700px'
Icon={Add}
permission={UPDATE_PROJECT}
permission={[
UPDATE_PROJECT,
PROJECT_USER_ACCESS_WRITE,
]}
projectId={projectId}
data-testid={PA_ASSIGN_BUTTON_ID}
>

View File

@ -39,3 +39,12 @@ export const READ_PROJECT_API_TOKEN = 'READ_PROJECT_API_TOKEN';
export const CREATE_PROJECT_API_TOKEN = 'CREATE_PROJECT_API_TOKEN';
export const DELETE_PROJECT_API_TOKEN = 'DELETE_PROJECT_API_TOKEN';
export const UPDATE_PROJECT_SEGMENT = 'UPDATE_PROJECT_SEGMENT';
export const PROJECT_USER_ACCESS_READ = 'PROJECT_USER_ACCESS_READ';
export const PROJECT_DEFAULT_STRATEGY_READ = 'PROJECT_DEFAULT_STRATEGY_READ';
export const PROJECT_CHANGE_REQUEST_READ = 'PROJECT_CHANGE_REQUEST_READ';
export const PROJECT_SETTINGS_READ = 'PROJECT_SETTINGS_READ';
export const PROJECT_USER_ACCESS_WRITE = 'PROJECT_USER_ACCESS_WRITE';
export const PROJECT_DEFAULT_STRATEGY_WRITE = 'PROJECT_DEFAULT_STRATEGY_WRITE';
export const PROJECT_CHANGE_REQUEST_WRITE = 'PROJECT_CHANGE_REQUEST_WRITE';
export const PROJECT_SETTINGS_WRITE = 'PROJECT_SETTINGS_WRITE';