mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-16 00:06:40 +01:00
c17a1980a2
This simplifies stores to just be storage interaction, they no longer react to events. Controllers now call services and awaits the result from the call. When the service calls are returned the database is updated. This simplifies testing dramatically, cause you know that your state is updated when returned from a call, rather than hoping the store has picked up the event (which really was a command) and reacted to it. Events are still emitted from eventStore, so other parts of the app can react to events as they're being sent out. As part of the move to services, we now also emit an application-created event when we see a new client application. Fixes: #685 Fixes: #595
181 lines
5.3 KiB
JavaScript
181 lines
5.3 KiB
JavaScript
const Controller = require('../controller');
|
|
|
|
const { handleErrors } = require('./util');
|
|
const extractUser = require('../../extract-user');
|
|
const {
|
|
UPDATE_FEATURE,
|
|
DELETE_FEATURE,
|
|
CREATE_FEATURE,
|
|
} = require('../../permissions');
|
|
|
|
const version = 1;
|
|
|
|
class FeatureController extends Controller {
|
|
constructor(config, { featureToggleService }) {
|
|
super(config);
|
|
this.featureService = featureToggleService;
|
|
this.logger = config.getLogger('/admin-api/feature.js');
|
|
|
|
this.get('/', this.getAllToggles);
|
|
this.post('/', this.createToggle, CREATE_FEATURE);
|
|
this.get('/:featureName', this.getToggle);
|
|
this.put('/:featureName', this.updateToggle, UPDATE_FEATURE);
|
|
this.delete('/:featureName', this.deleteToggle, DELETE_FEATURE);
|
|
this.post('/validate', this.validate);
|
|
this.post('/:featureName/toggle', this.toggle, UPDATE_FEATURE);
|
|
this.post('/:featureName/toggle/on', this.toggleOn, UPDATE_FEATURE);
|
|
this.post('/:featureName/toggle/off', this.toggleOff, UPDATE_FEATURE);
|
|
this.post('/:featureName/stale/on', this.staleOn, UPDATE_FEATURE);
|
|
this.post('/:featureName/stale/off', this.staleOff, UPDATE_FEATURE);
|
|
this.get('/:featureName/tags', this.listTags, UPDATE_FEATURE);
|
|
this.post('/:featureName/tags', this.addTag, UPDATE_FEATURE);
|
|
this.delete(
|
|
'/:featureName/tags/:type/:value',
|
|
this.removeTag,
|
|
UPDATE_FEATURE,
|
|
);
|
|
}
|
|
|
|
async getAllToggles(req, res) {
|
|
const features = await this.featureService.getFeatures();
|
|
res.json({ version, features });
|
|
}
|
|
|
|
async getToggle(req, res) {
|
|
try {
|
|
const name = req.params.featureName;
|
|
const feature = await this.featureService.getFeature(name);
|
|
res.json(feature).end();
|
|
} catch (err) {
|
|
res.status(404).json({ error: 'Could not find feature' });
|
|
}
|
|
}
|
|
|
|
async listTags(req, res) {
|
|
const tags = await this.featureService.listTags(req.params.featureName);
|
|
res.json({ version, tags });
|
|
}
|
|
|
|
async addTag(req, res) {
|
|
const { featureName } = req.params;
|
|
const userName = extractUser(req);
|
|
try {
|
|
const tag = await this.featureService.addTag(
|
|
featureName,
|
|
req.body,
|
|
userName,
|
|
);
|
|
res.status(201).json(tag);
|
|
} catch (err) {
|
|
handleErrors(res, this.logger, err);
|
|
}
|
|
}
|
|
|
|
async removeTag(req, res) {
|
|
const { featureName, type, value } = req.params;
|
|
const userName = extractUser(req);
|
|
await this.featureService.removeTag(
|
|
featureName,
|
|
{ type, value },
|
|
userName,
|
|
);
|
|
res.status(200).end();
|
|
}
|
|
|
|
async validate(req, res) {
|
|
const { name } = req.body;
|
|
|
|
try {
|
|
await this.featureService.validateName({ name });
|
|
res.status(200).end();
|
|
} catch (error) {
|
|
handleErrors(res, this.logger, error);
|
|
}
|
|
}
|
|
|
|
async createToggle(req, res) {
|
|
const userName = extractUser(req);
|
|
|
|
try {
|
|
await this.featureService.createFeatureToggle(req.body, userName);
|
|
res.status(201).end();
|
|
} catch (error) {
|
|
handleErrors(res, this.logger, error);
|
|
}
|
|
}
|
|
|
|
async updateToggle(req, res) {
|
|
const { featureName } = req.params;
|
|
const userName = extractUser(req);
|
|
const updatedFeature = req.body;
|
|
|
|
updatedFeature.name = featureName;
|
|
|
|
try {
|
|
await this.featureService.updateToggle(updatedFeature, userName);
|
|
res.status(200).end();
|
|
} catch (error) {
|
|
handleErrors(res, this.logger, error);
|
|
}
|
|
}
|
|
|
|
// Kept to keep backward compatibility
|
|
async toggle(req, res) {
|
|
const userName = extractUser(req);
|
|
try {
|
|
const name = req.params.featureName;
|
|
const feature = await this.featureService.toggle(name, userName);
|
|
res.status(200).json(feature);
|
|
} catch (error) {
|
|
handleErrors(res, this.logger, error);
|
|
}
|
|
}
|
|
|
|
async toggleOn(req, res) {
|
|
await this._updateField('enabled', true, req, res);
|
|
}
|
|
|
|
async toggleOff(req, res) {
|
|
await this._updateField('enabled', false, req, res);
|
|
}
|
|
|
|
async staleOn(req, res) {
|
|
await this._updateField('stale', true, req, res);
|
|
}
|
|
|
|
async staleOff(req, res) {
|
|
await this._updateField('stale', false, req, res);
|
|
}
|
|
|
|
async _updateField(field, value, req, res) {
|
|
const { featureName } = req.params;
|
|
const userName = extractUser(req);
|
|
|
|
try {
|
|
const feature = await this.featureService.updateField(
|
|
featureName,
|
|
field,
|
|
value,
|
|
userName,
|
|
);
|
|
res.json(feature).end();
|
|
} catch (error) {
|
|
handleErrors(res, this.logger, error);
|
|
}
|
|
}
|
|
|
|
async deleteToggle(req, res) {
|
|
const { featureName } = req.params;
|
|
const userName = extractUser(req);
|
|
|
|
try {
|
|
await this.featureService.archiveToggle(featureName, userName);
|
|
res.status(200).end();
|
|
} catch (error) {
|
|
handleErrors(res, this.logger, error);
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = FeatureController;
|