1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

feat: add CREATE_TAG_TYPE permission (#5386)

https://linear.app/unleash/issue/2-1164/update-tag-type-covers-both-creation-and-update

Adds a new `CREATE_TAG_TYPE` permission instead of using
`UPDATE_TAG_TYPE` for both actions.
This commit is contained in:
Nuno Góis 2023-11-22 10:20:19 +00:00 committed by GitHub
parent fac2578922
commit 5dc3e830a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 63 additions and 13 deletions

View File

@ -224,7 +224,7 @@ export const ManageBulkTagsDialog: VFC<IManageBulkTagsDialogProps> = ({
open={open}
secondaryButtonText='Cancel'
primaryButtonText='Save tags'
title='Update tags to feature toggle'
title='Update feature toggle tags'
onClick={() => onSubmit(payload)}
disabledPrimaryButton={
payload.addedTags.length === 0 &&

View File

@ -248,7 +248,7 @@ export const ManageTagsDialog = ({ open, setOpen }: IManageTagsProps) => {
open={open}
secondaryButtonText='Cancel'
primaryButtonText='Save tags'
title='Update tags to feature toggle'
title='Update feature toggle tags'
onClick={onSubmit}
disabledPrimaryButton={loading || differenceCount === 0}
onClose={onCancel}

View File

@ -13,8 +13,9 @@ export const DELETE_CONTEXT_FIELD = 'DELETE_CONTEXT_FIELD';
export const CREATE_PROJECT = 'CREATE_PROJECT';
export const UPDATE_PROJECT = 'UPDATE_PROJECT';
export const DELETE_PROJECT = 'DELETE_PROJECT';
export const DELETE_TAG_TYPE = 'DELETE_TAG_TYPE';
export const CREATE_TAG_TYPE = 'CREATE_TAG_TYPE';
export const UPDATE_TAG_TYPE = 'UPDATE_TAG_TYPE';
export const DELETE_TAG_TYPE = 'DELETE_TAG_TYPE';
export const CREATE_ADDON = 'CREATE_ADDON';
export const UPDATE_ADDON = 'UPDATE_ADDON';
export const DELETE_ADDON = 'DELETE_ADDON';

View File

@ -3,7 +3,7 @@ import useTagTypeForm from '../TagTypeForm/useTagTypeForm';
import TagTypeForm from '../TagTypeForm/TagTypeForm';
import { CreateButton } from 'component/common/CreateButton/CreateButton';
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import { UPDATE_TAG_TYPE } from 'component/providers/AccessProvider/permissions';
import { CREATE_TAG_TYPE } from 'component/providers/AccessProvider/permissions';
import useTagTypesApi from 'hooks/api/actions/useTagTypesApi/useTagTypesApi';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import useToast from 'hooks/useToast';
@ -78,7 +78,7 @@ const CreateTagType = () => {
clearErrors={clearErrors}
validateNameUniqueness={validateNameUniqueness}
>
<CreateButton name='type' permission={UPDATE_TAG_TYPE} />
<CreateButton name='type' permission={CREATE_TAG_TYPE} />
</TagTypeForm>
</FormTemplate>
);

View File

@ -1,7 +1,7 @@
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
import { UPDATE_TAG_TYPE } from 'component/providers/AccessProvider/permissions';
import { CREATE_TAG_TYPE } from 'component/providers/AccessProvider/permissions';
import useMediaQuery from '@mui/material/useMediaQuery';
import { useNavigate } from 'react-router-dom';
@ -18,14 +18,14 @@ export const AddTagTypeButton = () => {
<PermissionIconButton
onClick={() => navigate('/tag-types/create')}
size='large'
permission={UPDATE_TAG_TYPE}
permission={CREATE_TAG_TYPE}
>
<Add />
</PermissionIconButton>
}
elseShow={
<PermissionButton
permission={UPDATE_TAG_TYPE}
permission={CREATE_TAG_TYPE}
onClick={() => navigate('/tag-types/create')}
>
New tag type

View File

@ -373,11 +373,11 @@ test('validate import data', async () => {
affectedItems: [
'Create feature toggles',
'Update feature toggles',
'Update tag types',
'Create context fields',
'Create activation strategies',
'Delete activation strategies',
'Update variants',
'Create tag types',
],
},
],

View File

@ -11,6 +11,7 @@ import {
UPDATE_FEATURE,
UPDATE_FEATURE_ENVIRONMENT_VARIANTS,
UPDATE_TAG_TYPE,
CREATE_TAG_TYPE,
} from '../../types';
import { PermissionError } from '../../error';
@ -94,7 +95,7 @@ export class ImportPermissionsService {
]);
const permissions = [UPDATE_FEATURE];
if (newTagTypes.length > 0) {
permissions.push(UPDATE_TAG_TYPE);
permissions.push(CREATE_TAG_TYPE);
}
if (Array.isArray(newContextFields) && newContextFields.length > 0) {
permissions.push(CREATE_CONTEXT_FIELD);

View File

@ -329,6 +329,34 @@ test('Does not double check permission if not changing project when updating tog
);
});
test('CREATE_TAG_TYPE does not need projectId', async () => {
const accessService = {
hasPermission: jest.fn().mockReturnValue(true),
};
const func = rbacMiddleware(
config,
{ featureToggleStore, segmentStore },
accessService,
);
const cb = jest.fn();
const req: any = {
user: new User({ username: 'user', id: 1 }),
params: {},
body: { name: 'new-tag-type', description: 'New tag type for testing' },
};
func(req, undefined, cb);
await req.checkRbac(perms.CREATE_TAG_TYPE);
expect(accessService.hasPermission).toHaveBeenCalledTimes(1);
expect(accessService.hasPermission).toHaveBeenCalledWith(
req.user,
[perms.CREATE_TAG_TYPE],
undefined,
undefined,
);
});
test('UPDATE_TAG_TYPE does not need projectId', async () => {
const accessService = {
hasPermission: jest.fn().mockReturnValue(true),

View File

@ -2,6 +2,7 @@ import { Request, Response } from 'express';
import Controller from '../controller';
import {
CREATE_TAG_TYPE,
DELETE_TAG_TYPE,
NONE,
UPDATE_TAG_TYPE,
@ -72,7 +73,7 @@ class TagTypeController extends Controller {
method: 'post',
path: '',
handler: this.createTagType,
permission: UPDATE_TAG_TYPE,
permission: CREATE_TAG_TYPE,
middleware: [
openApiService.validPath({
tags: ['Tags'],
@ -91,7 +92,7 @@ class TagTypeController extends Controller {
method: 'post',
path: '/validate',
handler: this.validateTagType,
permission: UPDATE_TAG_TYPE,
permission: NONE,
middleware: [
openApiService.validPath({
tags: ['Tags'],

View File

@ -37,6 +37,7 @@ export const CREATE_STRATEGY = 'CREATE_STRATEGY';
export const UPDATE_STRATEGY = 'UPDATE_STRATEGY';
export const DELETE_STRATEGY = 'DELETE_STRATEGY';
export const CREATE_TAG_TYPE = 'CREATE_TAG_TYPE';
export const UPDATE_TAG_TYPE = 'UPDATE_TAG_TYPE';
export const DELETE_TAG_TYPE = 'DELETE_TAG_TYPE';
@ -112,6 +113,6 @@ export const ROOT_PERMISSION_CATEGORIES = [
},
{
label: 'Tag type',
permissions: [UPDATE_TAG_TYPE, DELETE_TAG_TYPE],
permissions: [CREATE_TAG_TYPE, UPDATE_TAG_TYPE, DELETE_TAG_TYPE],
},
];

View File

@ -0,0 +1,18 @@
exports.up = function (db, cb) {
db.runSql(
`
INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_TAG_TYPE', 'Create tag types', 'root');
SELECT assign_unleash_permission_to_role('CREATE_TAG_TYPE', 'Editor');
`,
cb
);
};
exports.down = function (db, cb) {
db.runSql(
`
DELETE FROM permissions WHERE permission = 'CREATE_TAG_TYPE';
`,
cb
);
};