mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-23 13:46:45 +02:00
fix: bulk tags will work now with project permissions (#4177)
This commit is contained in:
parent
2d44656a9b
commit
3c52550474
@ -59,7 +59,7 @@ export const ManageTags: VFC<IManageTagsProps> = ({ projectId, data }) => {
|
|||||||
const features = data.map(({ name }) => name);
|
const features = data.map(({ name }) => name);
|
||||||
const payload = { features, tags: { addedTags, removedTags } };
|
const payload = { features, tags: { addedTags, removedTags } };
|
||||||
try {
|
try {
|
||||||
await bulkUpdateTags(payload);
|
await bulkUpdateTags(payload, projectId);
|
||||||
refetch();
|
refetch();
|
||||||
const added = addedTags.length
|
const added = addedTags.length
|
||||||
? `Added tags: ${addedTags
|
? `Added tags: ${addedTags
|
||||||
|
@ -20,8 +20,11 @@ const useTagApi = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const bulkUpdateTags = async (payload: TagsBulkAddSchema) => {
|
const bulkUpdateTags = async (
|
||||||
const path = `api/admin/tags/features`;
|
payload: TagsBulkAddSchema,
|
||||||
|
projectId: string
|
||||||
|
) => {
|
||||||
|
const path = `api/admin/projects/${projectId}/tags`;
|
||||||
const req = createRequest(path, {
|
const req = createRequest(path, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
|
@ -36,10 +36,16 @@ import {
|
|||||||
getStandardResponses,
|
getStandardResponses,
|
||||||
ParametersSchema,
|
ParametersSchema,
|
||||||
SetStrategySortOrderSchema,
|
SetStrategySortOrderSchema,
|
||||||
|
TagsBulkAddSchema,
|
||||||
|
TagSchema,
|
||||||
UpdateFeatureSchema,
|
UpdateFeatureSchema,
|
||||||
UpdateFeatureStrategySchema,
|
UpdateFeatureStrategySchema,
|
||||||
} from '../../../openapi';
|
} from '../../../openapi';
|
||||||
import { OpenApiService, FeatureToggleService } from '../../../services';
|
import {
|
||||||
|
OpenApiService,
|
||||||
|
FeatureToggleService,
|
||||||
|
FeatureTagService,
|
||||||
|
} from '../../../services';
|
||||||
import { querySchema } from '../../../schema/feature-schema';
|
import { querySchema } from '../../../schema/feature-schema';
|
||||||
import { BatchStaleSchema } from '../../../openapi/spec/batch-stale-schema';
|
import { BatchStaleSchema } from '../../../openapi/spec/batch-stale-schema';
|
||||||
import {
|
import {
|
||||||
@ -85,6 +91,7 @@ export interface IFeatureProjectUserParams extends ProjectParam {
|
|||||||
|
|
||||||
const PATH = '/:projectId/features';
|
const PATH = '/:projectId/features';
|
||||||
const PATH_STALE = '/:projectId/stale';
|
const PATH_STALE = '/:projectId/stale';
|
||||||
|
const PATH_TAGS = `/:projectId/tags`;
|
||||||
const PATH_FEATURE = `${PATH}/:featureName`;
|
const PATH_FEATURE = `${PATH}/:featureName`;
|
||||||
const PATH_FEATURE_CLONE = `${PATH_FEATURE}/clone`;
|
const PATH_FEATURE_CLONE = `${PATH_FEATURE}/clone`;
|
||||||
const PATH_ENV = `${PATH_FEATURE}/environments/:environment`;
|
const PATH_ENV = `${PATH_FEATURE}/environments/:environment`;
|
||||||
@ -98,11 +105,14 @@ type ProjectFeaturesServices = Pick<
|
|||||||
| 'projectHealthService'
|
| 'projectHealthService'
|
||||||
| 'openApiService'
|
| 'openApiService'
|
||||||
| 'transactionalFeatureToggleService'
|
| 'transactionalFeatureToggleService'
|
||||||
|
| 'featureTagService'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export default class ProjectFeaturesController extends Controller {
|
export default class ProjectFeaturesController extends Controller {
|
||||||
private featureService: FeatureToggleService;
|
private featureService: FeatureToggleService;
|
||||||
|
|
||||||
|
private featureTagService: FeatureTagService;
|
||||||
|
|
||||||
private transactionalFeatureToggleService: (
|
private transactionalFeatureToggleService: (
|
||||||
db: UnleashTransaction,
|
db: UnleashTransaction,
|
||||||
) => FeatureToggleService;
|
) => FeatureToggleService;
|
||||||
@ -121,6 +131,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
featureToggleServiceV2,
|
featureToggleServiceV2,
|
||||||
openApiService,
|
openApiService,
|
||||||
transactionalFeatureToggleService,
|
transactionalFeatureToggleService,
|
||||||
|
featureTagService,
|
||||||
}: ProjectFeaturesServices,
|
}: ProjectFeaturesServices,
|
||||||
startTransaction: TransactionCreator<UnleashTransaction>,
|
startTransaction: TransactionCreator<UnleashTransaction>,
|
||||||
) {
|
) {
|
||||||
@ -130,6 +141,7 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
transactionalFeatureToggleService;
|
transactionalFeatureToggleService;
|
||||||
this.startTransaction = startTransaction;
|
this.startTransaction = startTransaction;
|
||||||
this.openApiService = openApiService;
|
this.openApiService = openApiService;
|
||||||
|
this.featureTagService = featureTagService;
|
||||||
this.flagResolver = config.flagResolver;
|
this.flagResolver = config.flagResolver;
|
||||||
this.logger = config.getLogger('/admin-api/project/features.ts');
|
this.logger = config.getLogger('/admin-api/project/features.ts');
|
||||||
|
|
||||||
@ -480,6 +492,21 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route({
|
||||||
|
method: 'put',
|
||||||
|
path: PATH_TAGS,
|
||||||
|
handler: this.updateFeaturesTags,
|
||||||
|
permission: UPDATE_FEATURE,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['Tags'],
|
||||||
|
operationId: 'addTagToFeatures',
|
||||||
|
requestBody: createRequestSchema('tagsBulkAddSchema'),
|
||||||
|
responses: { 200: emptyResponse },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFeatures(
|
async getFeatures(
|
||||||
@ -976,6 +1003,21 @@ export default class ProjectFeaturesController extends Controller {
|
|||||||
res.status(200).json(updatedStrategy);
|
res.status(200).json(updatedStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateFeaturesTags(
|
||||||
|
req: IAuthRequest<void, void, TagsBulkAddSchema>,
|
||||||
|
res: Response<TagSchema>,
|
||||||
|
): Promise<void> {
|
||||||
|
const { features, tags } = req.body;
|
||||||
|
const userName = extractUsername(req);
|
||||||
|
await this.featureTagService.updateTags(
|
||||||
|
features,
|
||||||
|
tags.addedTags,
|
||||||
|
tags.removedTags,
|
||||||
|
userName,
|
||||||
|
);
|
||||||
|
res.status(200).end();
|
||||||
|
}
|
||||||
|
|
||||||
async getStrategyParameters(
|
async getStrategyParameters(
|
||||||
req: Request<StrategyIdParams, any, any, any>,
|
req: Request<StrategyIdParams, any, any, any>,
|
||||||
res: Response<ParametersSchema>,
|
res: Response<ParametersSchema>,
|
||||||
|
@ -23,7 +23,6 @@ import {
|
|||||||
} from '../../openapi/spec/tag-with-version-schema';
|
} from '../../openapi/spec/tag-with-version-schema';
|
||||||
import { emptyResponse } from '../../openapi/util/standard-responses';
|
import { emptyResponse } from '../../openapi/util/standard-responses';
|
||||||
import FeatureTagService from 'lib/services/feature-tag-service';
|
import FeatureTagService from 'lib/services/feature-tag-service';
|
||||||
import { TagsBulkAddSchema } from '../../openapi/spec/tags-bulk-add-schema';
|
|
||||||
import { IFlagResolver } from '../../types';
|
import { IFlagResolver } from '../../types';
|
||||||
|
|
||||||
const version = 1;
|
const version = 1;
|
||||||
@ -74,7 +73,7 @@ class TagController extends Controller {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
path: '',
|
path: '',
|
||||||
handler: this.createTag,
|
handler: this.createTag,
|
||||||
permission: UPDATE_FEATURE,
|
permission: NONE,
|
||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['Tags'],
|
tags: ['Tags'],
|
||||||
@ -88,20 +87,7 @@ class TagController extends Controller {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
this.route({
|
|
||||||
method: 'put',
|
|
||||||
path: '/features',
|
|
||||||
handler: this.updateFeaturesTags,
|
|
||||||
permission: UPDATE_FEATURE,
|
|
||||||
middleware: [
|
|
||||||
openApiService.validPath({
|
|
||||||
tags: ['Tags'],
|
|
||||||
operationId: 'addTagToFeatures',
|
|
||||||
requestBody: createRequestSchema('tagsBulkAddSchema'),
|
|
||||||
responses: { 200: emptyResponse },
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
this.route({
|
this.route({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
path: '/:type',
|
path: '/:type',
|
||||||
@ -208,20 +194,5 @@ class TagController extends Controller {
|
|||||||
await this.tagService.deleteTag({ type, value }, userName);
|
await this.tagService.deleteTag({ type, value }, userName);
|
||||||
res.status(200).end();
|
res.status(200).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateFeaturesTags(
|
|
||||||
req: IAuthRequest<void, void, TagsBulkAddSchema>,
|
|
||||||
res: Response<TagSchema>,
|
|
||||||
): Promise<void> {
|
|
||||||
const { features, tags } = req.body;
|
|
||||||
const userName = extractUsername(req);
|
|
||||||
await this.featureTagService.updateTags(
|
|
||||||
features,
|
|
||||||
tags.addedTags,
|
|
||||||
tags.removedTags,
|
|
||||||
userName,
|
|
||||||
);
|
|
||||||
res.status(200).end();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
export default TagController;
|
export default TagController;
|
||||||
|
@ -143,7 +143,7 @@ test('Can tag features', async () => {
|
|||||||
strategies: [{ name: 'default' }],
|
strategies: [{ name: 'default' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
await app.request.put('/api/admin/tags/features').send({
|
await app.request.put('/api/admin/projects/default/tags').send({
|
||||||
features: [featureName, featureName2],
|
features: [featureName, featureName2],
|
||||||
tags: {
|
tags: {
|
||||||
addedTags: [addedTag],
|
addedTags: [addedTag],
|
||||||
@ -185,7 +185,7 @@ test('Can bulk remove tags', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.put('/api/admin/tags/features')
|
.put('/api/admin/projects/default/tags')
|
||||||
.send({
|
.send({
|
||||||
features: [featureName, featureName2],
|
features: [featureName, featureName2],
|
||||||
tags: {
|
tags: {
|
||||||
@ -196,7 +196,7 @@ test('Can bulk remove tags', async () => {
|
|||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
await app.request
|
await app.request
|
||||||
.put('/api/admin/tags/features')
|
.put('/api/admin/projects/default/tags')
|
||||||
.send({
|
.send({
|
||||||
features: [featureName, featureName2],
|
features: [featureName, featureName2],
|
||||||
tags: {
|
tags: {
|
||||||
|
Loading…
Reference in New Issue
Block a user