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:
parent
b319cec5f0
commit
296cc9a9f2
@ -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>
|
||||||
}
|
}
|
||||||
|
@ -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:');
|
||||||
|
@ -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';
|
||||||
|
@ -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({
|
||||||
|
@ -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';
|
||||||
|
@ -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
|
||||||
|
);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user