unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
233 lines • 11.1 kB
JavaScript
import Controller from '../../routes/controller.js';
import { CREATE_CONTEXT_FIELD, UPDATE_CONTEXT_FIELD, DELETE_CONTEXT_FIELD, NONE, } from '../../types/permissions.js';
import { contextFieldSchema, } from '../../openapi/spec/context-field-schema.js';
import { createRequestSchema } from '../../openapi/util/create-request-schema.js';
import { createResponseSchema, resourceCreatedResponseSchema, } from '../../openapi/util/create-response-schema.js';
import { serializeDates } from '../../types/serialize-dates.js';
import NotFoundError from '../../error/notfound-error.js';
import { emptyResponse, getStandardResponses, } from '../../openapi/util/standard-responses.js';
import { contextFieldStrategiesSchema, } from '../../openapi/spec/context-field-strategies-schema.js';
import { extractUserIdFromUser } from '../../util/index.js';
export class ContextController extends Controller {
constructor(config, { transactionalContextService, openApiService, }) {
super(config);
this.openApiService = openApiService;
this.logger = config.getLogger('/admin-api/context.ts');
this.transactionalContextService = transactionalContextService;
this.route({
method: 'get',
path: '',
handler: this.getContextFields,
permission: NONE,
middleware: [
openApiService.validPath({
tags: ['Context'],
summary: 'Gets configured context fields',
description: 'Returns all configured [Context fields](https://docs.getunleash.io/reference/unleash-context) that have been created.',
operationId: 'getContextFields',
responses: {
200: createResponseSchema('contextFieldsSchema'),
},
}),
],
});
this.route({
method: 'get',
path: '/:contextField',
handler: this.getContextField,
permission: NONE,
middleware: [
openApiService.validPath({
tags: ['Context'],
summary: 'Gets context field',
description: 'Returns specific [context field](https://docs.getunleash.io/reference/unleash-context) identified by the name in the path',
operationId: 'getContextField',
responses: {
200: createResponseSchema('contextFieldSchema'),
},
}),
],
});
this.route({
method: 'get',
path: '/:contextField/strategies',
handler: this.getStrategiesByContextField,
permission: NONE,
middleware: [
openApiService.validPath({
tags: ['Strategies'],
operationId: 'getStrategiesByContextField',
summary: 'Get strategies that use a context field',
description: "Retrieves a list of all strategies that use the specified context field. If the context field doesn't exist, returns an empty list of strategies",
responses: {
200: createResponseSchema('contextFieldStrategiesSchema'),
...getStandardResponses(401),
},
}),
],
});
this.route({
method: 'post',
path: '',
handler: this.createContextField,
permission: CREATE_CONTEXT_FIELD,
middleware: [
openApiService.validPath({
tags: ['Context'],
operationId: 'createContextField',
summary: 'Create a context field',
description: 'Endpoint that allows creation of [custom context fields](https://docs.getunleash.io/reference/unleash-context#custom-context-fields)',
requestBody: createRequestSchema('createContextFieldSchema'),
responses: {
201: resourceCreatedResponseSchema('contextFieldSchema'),
},
}),
],
});
this.route({
method: 'put',
path: '/:contextField',
handler: this.updateContextField,
permission: UPDATE_CONTEXT_FIELD,
middleware: [
openApiService.validPath({
tags: ['Context'],
summary: 'Update an existing context field',
description: `Endpoint that allows updating a custom context field. Used to toggle stickiness and add/remove legal values for this context field`,
operationId: 'updateContextField',
requestBody: createRequestSchema('updateContextFieldSchema'),
responses: {
200: emptyResponse,
},
}),
],
});
this.route({
method: 'post',
path: '/:contextField/legal-values',
handler: this.updateLegalValue,
permission: UPDATE_CONTEXT_FIELD,
middleware: [
openApiService.validPath({
tags: ['Context'],
summary: 'Add or update legal value for the context field',
description: `Endpoint that allows adding or updating a single custom context field legal value. If the legal value already exists, it will be updated with the new description`,
operationId: 'updateContextFieldLegalValue',
requestBody: createRequestSchema('legalValueSchema'),
responses: {
200: emptyResponse,
},
}),
],
});
this.route({
method: 'delete',
path: '/:contextField/legal-values/:legalValue',
handler: this.deleteLegalValue,
acceptAnyContentType: true,
permission: UPDATE_CONTEXT_FIELD,
middleware: [
openApiService.validPath({
tags: ['Context'],
summary: 'Delete legal value for the context field',
description: `Removes the specified custom context field legal value. Does not validate that the legal value is not in use and does not remove usage from constraints that use it.`,
operationId: 'deleteContextFieldLegalValue',
responses: {
200: emptyResponse,
},
}),
],
});
this.route({
method: 'delete',
path: '/:contextField',
handler: this.deleteContextField,
acceptAnyContentType: true,
permission: DELETE_CONTEXT_FIELD,
middleware: [
openApiService.validPath({
tags: ['Context'],
summary: 'Delete an existing context field',
description: 'Endpoint that allows deletion of a custom context field. Does not validate that context field is not in use, but since context field configuration is stored in a json blob for the strategy, existing strategies are safe.',
operationId: 'deleteContextField',
responses: {
200: emptyResponse,
},
}),
],
});
this.route({
method: 'post',
path: '/validate',
handler: this.validate,
permission: UPDATE_CONTEXT_FIELD,
middleware: [
openApiService.validPath({
tags: ['Context'],
summary: 'Validate a context field',
description: 'Check whether the provided data can be used to create a context field. If the data is not valid, returns a 400 status code with the reason why it is not valid.',
operationId: 'validate',
requestBody: createRequestSchema('nameSchema'),
responses: {
200: emptyResponse,
},
}),
],
});
}
async getContextFields(req, res) {
res.status(200)
.json(serializeDates(await this.transactionalContextService.getAll()))
.end();
}
async getContextField(req, res) {
try {
const name = req.params.contextField;
const contextField = await this.transactionalContextService.getContextField(name);
this.openApiService.respondWithValidation(200, res, contextFieldSchema.$id, serializeDates(contextField));
}
catch (err) {
throw new NotFoundError('Could not find context field');
}
}
async createContextField(req, res) {
const value = req.body;
const result = await this.transactionalContextService.transactional((service) => service.createContextField(value, req.audit));
this.openApiService.respondWithValidation(201, res, contextFieldSchema.$id, serializeDates(result), { location: `context/${result.name}` });
}
async updateContextField(req, res) {
const name = req.params.contextField;
const contextField = req.body;
await this.transactionalContextService.transactional((service) => service.updateContextField({ ...contextField, name }, req.audit));
res.status(200).end();
}
async updateLegalValue(req, res) {
const name = req.params.contextField;
const legalValue = req.body;
await this.transactionalContextService.transactional((service) => service.updateLegalValue({ name, legalValue }, req.audit));
res.status(200).end();
}
async deleteLegalValue(req, res) {
const name = req.params.contextField;
const legalValue = req.params.legalValue;
await this.transactionalContextService.transactional((service) => service.deleteLegalValue({ name, legalValue }, req.audit));
res.status(200).end();
}
async deleteContextField(req, res) {
const name = req.params.contextField;
await this.transactionalContextService.transactional((service) => service.deleteContextField(name, req.audit));
res.status(200).end();
}
async validate(req, res) {
const { name } = req.body;
await this.transactionalContextService.validateName(name);
res.status(200).end();
}
async getStrategiesByContextField(req, res) {
const { contextField } = req.params;
const { user } = req;
const contextFields = await this.transactionalContextService.getStrategiesByContextField(contextField, extractUserIdFromUser(user));
this.openApiService.respondWithValidation(200, res, contextFieldStrategiesSchema.$id, serializeDates(contextFields));
}
}
//# sourceMappingURL=context.js.map