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

feat: update dependency permission (#4910)

This commit is contained in:
Mateusz Kwasniewski 2023-10-04 09:27:14 +02:00 committed by GitHub
parent b319cec5f0
commit 296cc9a9f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 16 deletions

View File

@ -1,6 +1,4 @@
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { Button } from '@mui/material';
import { Add } from '@mui/icons-material';
import { AddDependencyDialogue } from 'component/feature/Dependencies/AddDependencyDialogue'; import { AddDependencyDialogue } from 'component/feature/Dependencies/AddDependencyDialogue';
import { IFeatureToggle } from 'interfaces/featureToggle'; import { IFeatureToggle } from 'interfaces/featureToggle';
import { FC, useState } from 'react'; import { FC, useState } from 'react';
@ -9,6 +7,9 @@ import { DependencyActions } from './DependencyActions';
import { useDependentFeaturesApi } from 'hooks/api/actions/useDependentFeaturesApi/useDependentFeaturesApi'; import { useDependentFeaturesApi } from 'hooks/api/actions/useDependentFeaturesApi/useDependentFeaturesApi';
import { useFeature } from 'hooks/api/getters/useFeature/useFeature'; import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
import { ChildrenTooltip } from './ChildrenTooltip'; import { ChildrenTooltip } from './ChildrenTooltip';
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
import { UPDATE_FEATURE_DEPENDENCY } from 'component/providers/AccessProvider/permissions';
import { useCheckProjectPermissions } from 'hooks/useHasAccess';
export const DependencyRow: FC<{ feature: IFeatureToggle }> = ({ feature }) => { export const DependencyRow: FC<{ feature: IFeatureToggle }> = ({ feature }) => {
const { removeDependencies } = useDependentFeaturesApi(feature.project); const { removeDependencies } = useDependentFeaturesApi(feature.project);
@ -21,6 +22,7 @@ export const DependencyRow: FC<{ feature: IFeatureToggle }> = ({ feature }) => {
const hasParentDependency = const hasParentDependency =
Boolean(feature.project) && Boolean(feature.dependencies.length > 0); Boolean(feature.project) && Boolean(feature.dependencies.length > 0);
const hasChildren = Boolean(feature.project) && feature.children.length > 0; const hasChildren = Boolean(feature.project) && feature.children.length > 0;
const checkAccess = useCheckProjectPermissions(feature.project);
return ( return (
<> <>
@ -30,14 +32,16 @@ export const DependencyRow: FC<{ feature: IFeatureToggle }> = ({ feature }) => {
<FlexRow> <FlexRow>
<StyledDetail> <StyledDetail>
<StyledLabel>Dependency:</StyledLabel> <StyledLabel>Dependency:</StyledLabel>
<Button <PermissionButton
startIcon={<Add />} permission={UPDATE_FEATURE_DEPENDENCY}
projectId={feature.project}
variant='text'
onClick={() => { onClick={() => {
setShowDependencyDialogue(true); setShowDependencyDialogue(true);
}} }}
> >
Add parent feature Add parent feature
</Button> </PermissionButton>
</StyledDetail> </StyledDetail>
</FlexRow> </FlexRow>
} }
@ -54,13 +58,20 @@ export const DependencyRow: FC<{ feature: IFeatureToggle }> = ({ feature }) => {
{feature.dependencies[0]?.feature} {feature.dependencies[0]?.feature}
</StyledLink> </StyledLink>
</StyledDetail> </StyledDetail>
<DependencyActions <ConditionallyRender
feature={feature.name} condition={checkAccess(UPDATE_FEATURE_DEPENDENCY)}
onEdit={() => setShowDependencyDialogue(true)} show={
onDelete={async () => { <DependencyActions
await removeDependencies(feature.name); feature={feature.name}
await refetchFeature(); onEdit={() =>
}} setShowDependencyDialogue(true)
}
onDelete={async () => {
await removeDependencies(feature.name);
await refetchFeature();
}}
/>
}
/> />
</FlexRow> </FlexRow>
} }

View File

@ -38,6 +38,11 @@ test('show dependency dialogue', async () => {
} }
header={''} header={''}
/>, />,
{
permissions: [
{ permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' },
],
},
); );
const addParentButton = await screen.findByText('Add parent feature'); const addParentButton = await screen.findByText('Add parent feature');
@ -100,6 +105,11 @@ test('delete dependency', async () => {
} }
header={''} header={''}
/>, />,
{
permissions: [
{ permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' },
],
},
); );
await screen.findByText('Dependency:'); await screen.findByText('Dependency:');
@ -127,6 +137,11 @@ test('edit dependency', async () => {
} }
header={''} header={''}
/>, />,
{
permissions: [
{ permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' },
],
},
); );
await screen.findByText('Dependency:'); await screen.findByText('Dependency:');

View File

@ -1,6 +1,7 @@
export const ADMIN = 'ADMIN'; export const ADMIN = 'ADMIN';
export const CREATE_FEATURE = 'CREATE_FEATURE'; export const CREATE_FEATURE = 'CREATE_FEATURE';
export const UPDATE_FEATURE = 'UPDATE_FEATURE'; export const UPDATE_FEATURE = 'UPDATE_FEATURE';
export const UPDATE_FEATURE_DEPENDENCY = 'UPDATE_FEATURE_DEPENDENCY';
export const DELETE_FEATURE = 'DELETE_FEATURE'; export const DELETE_FEATURE = 'DELETE_FEATURE';
export const CREATE_STRATEGY = 'CREATE_STRATEGY'; export const CREATE_STRATEGY = 'CREATE_STRATEGY';
export const UPDATE_STRATEGY = 'UPDATE_STRATEGY'; export const UPDATE_STRATEGY = 'UPDATE_STRATEGY';

View File

@ -6,7 +6,7 @@ import {
IUnleashConfig, IUnleashConfig,
IUnleashServices, IUnleashServices,
NONE, NONE,
UPDATE_FEATURE, UPDATE_FEATURE_DEPENDENCY,
} from '../../types'; } from '../../types';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
import { import {
@ -88,7 +88,7 @@ export default class DependentFeaturesController extends Controller {
method: 'post', method: 'post',
path: PATH_DEPENDENCIES, path: PATH_DEPENDENCIES,
handler: this.addFeatureDependency, handler: this.addFeatureDependency,
permission: UPDATE_FEATURE, permission: UPDATE_FEATURE_DEPENDENCY,
middleware: [ middleware: [
openApiService.validPath({ openApiService.validPath({
tags: ['Features'], tags: ['Features'],
@ -111,7 +111,7 @@ export default class DependentFeaturesController extends Controller {
method: 'delete', method: 'delete',
path: PATH_DEPENDENCY, path: PATH_DEPENDENCY,
handler: this.deleteFeatureDependency, handler: this.deleteFeatureDependency,
permission: UPDATE_FEATURE, permission: UPDATE_FEATURE_DEPENDENCY,
acceptAnyContentType: true, acceptAnyContentType: true,
middleware: [ middleware: [
openApiService.validPath({ openApiService.validPath({
@ -131,7 +131,7 @@ export default class DependentFeaturesController extends Controller {
method: 'delete', method: 'delete',
path: PATH_DEPENDENCIES, path: PATH_DEPENDENCIES,
handler: this.deleteFeatureDependencies, handler: this.deleteFeatureDependencies,
permission: UPDATE_FEATURE, permission: UPDATE_FEATURE_DEPENDENCY,
acceptAnyContentType: true, acceptAnyContentType: true,
middleware: [ middleware: [
openApiService.validPath({ openApiService.validPath({

View File

@ -43,6 +43,7 @@ export const DELETE_TAG_TYPE = 'DELETE_TAG_TYPE';
// Project // Project
export const CREATE_FEATURE = 'CREATE_FEATURE'; export const CREATE_FEATURE = 'CREATE_FEATURE';
export const UPDATE_FEATURE = 'UPDATE_FEATURE'; export const UPDATE_FEATURE = 'UPDATE_FEATURE';
export const UPDATE_FEATURE_DEPENDENCY = 'UPDATE_FEATURE_DEPENDENCY';
export const DELETE_FEATURE = 'DELETE_FEATURE'; export const DELETE_FEATURE = 'DELETE_FEATURE';
export const UPDATE_PROJECT = 'UPDATE_PROJECT'; export const UPDATE_PROJECT = 'UPDATE_PROJECT';
export const DELETE_PROJECT = 'DELETE_PROJECT'; export const DELETE_PROJECT = 'DELETE_PROJECT';

View File

@ -0,0 +1,19 @@
exports.up = function (db, cb) {
db.runSql(
`
INSERT INTO permissions (permission, display_name, type) VALUES ('UPDATE_FEATURE_DEPENDENCY', 'Update feature dependency', 'project');
SELECT assign_unleash_permission_to_role('UPDATE_FEATURE_DEPENDENCY', 'Member');
SELECT assign_unleash_permission_to_role('UPDATE_FEATURE_DEPENDENCY', 'Owner');
`,
cb
);
};
exports.down = function (db, cb) {
db.runSql(
`
DELETE FROM permissions WHERE permission = 'UPDATE_FEATURE_DEPENDENCY';
`,
cb
);
};