diff --git a/lib/routes/admin-api/index.js b/lib/routes/admin-api/index.js index 88a6e76b5b..dc32c2021c 100644 --- a/lib/routes/admin-api/index.js +++ b/lib/routes/admin-api/index.js @@ -4,7 +4,7 @@ const Controller = require('../controller'); const FeatureController = require('./feature.js'); const ArchiveController = require('./archive.js'); const EventController = require('./event.js'); -const strategies = require('./strategy'); +const StrategyController = require('./strategy'); const MetricsController = require('./metrics'); const UserController = require('./user'); const apiDef = require('./api-def.json'); @@ -18,7 +18,7 @@ class AdminApi extends Controller { this.app.get('/', this.index); this.app.use('/features', new FeatureController(stores).router); this.app.use('/archive', new ArchiveController(stores).router); - this.app.use('/strategies', strategies.router(config)); + this.app.use('/strategies', new StrategyController(stores).router); this.app.use('/events', new EventController(stores).router); this.app.use('/metrics', new MetricsController(stores).router); this.app.use('/user', new UserController().router); diff --git a/lib/routes/admin-api/strategy.js b/lib/routes/admin-api/strategy.js index 05b3c0255b..1fb0384bbd 100644 --- a/lib/routes/admin-api/strategy.js +++ b/lib/routes/admin-api/strategy.js @@ -1,6 +1,6 @@ 'use strict'; -const { Router } = require('express'); +const Controller = require('../controller'); const joi = require('joi'); const eventType = require('../../event-type'); @@ -10,139 +10,130 @@ const extractUser = require('../../extract-user'); const strategySchema = require('./strategy-schema'); const version = 1; -const handleError = (req, res, error) => { - logger.warn('Error creating or updating strategy', error); - switch (error.name) { - case 'NotFoundError': - return res.status(404).end(); - case 'NameExistsError': - return res - .status(403) - .json([ - { - msg: `A strategy named '${ - req.body.name - }' already exists.`, - }, - ]) - .end(); - case 'ValidationError': - return res - .status(400) - .json(error) - .end(); - default: - logger.error('Could perfom operation', error); - return res.status(500).end(); +class StrategyController extends Controller { + constructor({ strategyStore, eventStore }) { + super(); + this.strategyStore = strategyStore; + this.eventStore = eventStore; + + this.get('/', this.getAllStratgies); + this.get('/:name', this.getStrategy); + this.delete('/:name', this.removeStrategy); + this.post('/', this.createStrategy); + this.put('/:strategyName', this.updateStrategy); } -}; -function validateEditable(strategyName) { - return strategy => { - if (strategy.editable === false) { - throw new Error( - `Cannot edit strategy ${strategyName}, editable is false` - ); + async getAllStratgies(req, res) { + const strategies = await this.strategyStore.getStrategies(); + res.json({ version, strategies }); + } + + async getStrategy(req, res) { + try { + const name = req.params.name; + const strategy = await this.strategyStore.getStrategy(name); + res.json(strategy).end(); + } catch (err) { + res.status(404).json({ error: 'Could not find strategy' }); } - return strategy; - }; -} + } -function validateInput(data) { - return new Promise((resolve, reject) => { - joi.validate(data, strategySchema, (err, cleaned) => { - if (err) { - return reject(err); - } - return resolve(cleaned); - }); - }); -} - -exports.router = function(config) { - const { strategyStore, eventStore } = config.stores; - const router = Router(); - - router.get('/', (req, res) => { - strategyStore.getStrategies().then(strategies => { - res.json({ version, strategies }); - }); - }); - - router.get('/:name', (req, res) => { - strategyStore - .getStrategy(req.params.name) - .then(strategy => res.json(strategy).end()) - .catch(() => - res.status(404).json({ error: 'Could not find strategy' }) - ); - }); - - router.delete('/:name', (req, res) => { + async removeStrategy(req, res) { const strategyName = req.params.name; - strategyStore - .getStrategy(strategyName) - .then(validateEditable(strategyName)) - .then(() => - eventStore.store({ - type: eventType.STRATEGY_DELETED, - createdBy: extractUser(req), - data: { - name: strategyName, - }, - }) - ) - .then(() => res.status(200).end()) - .catch(error => handleError(req, res, error)); - }); + try { + const strategy = await this.strategyStore.getStrategy(strategyName); + await this._validateEditable(strategy); + await this.eventStore.store({ + type: eventType.STRATEGY_DELETED, + createdBy: extractUser(req), + data: { + name: strategyName, + }, + }); + res.status(200).end(); + } catch (error) { + this._handleErrorResponse(req, res, error); + } + } - function validateStrategyName(data) { + async createStrategy(req, res) { + try { + const newStrategy = await joi.validate(req.body, strategySchema); + await this._validateStrategyName(newStrategy); + await this.eventStore.store({ + type: eventType.STRATEGY_CREATED, + createdBy: extractUser(req), + data: newStrategy, + }); + res.status(201).end(); + } catch (error) { + this._handleErrorResponse(req, res, error); + } + } + + async updateStrategy(req, res) { + const input = req.body; + + try { + const updatedStrategy = await joi.validate(input, strategySchema); + const strategy = await this.strategyStore.getStrategy(input.name); + await this._validateEditable(strategy); + + await this.eventStore.store({ + type: eventType.STRATEGY_UPDATED, + createdBy: extractUser(req), + data: updatedStrategy, + }); + res.status(200).end(); + } catch (error) { + this._handleErrorResponse(req, res, error); + } + } + + // This check belongs in the store. + async _validateStrategyName(data) { return new Promise((resolve, reject) => { - strategyStore + this.strategyStore .getStrategy(data.name) .then(() => - reject(new NameExistsError('Strategy already exist!')) + reject( + new NameExistsError( + `Strategy with name ${data.name} already exist!` + ) + ) ) .catch(() => resolve(data)); }); } - router.post('/', (req, res) => { - const data = req.body; - validateInput(data) - .then(validateStrategyName) - .then(newStrategy => - eventStore.store({ - type: eventType.STRATEGY_CREATED, - createdBy: extractUser(req), - data: newStrategy, - }) - ) - .then(() => res.status(201).end()) - .catch(error => handleError(req, res, error)); - }); + // This check belongs in the store. + _validateEditable(strategy) { + if (strategy.editable === false) { + throw new Error(`Cannot edit strategy ${strategy.name}`); + } + } - router.put('/:strategyName', (req, res) => { - const strategyName = req.params.strategyName; - const updatedStrategy = req.body; + _handleErrorResponse(req, res, error) { + logger.warn('Error creating or updating strategy', error); + switch (error.name) { + case 'NotFoundError': + return res.status(404).end(); + case 'NameExistsError': + return res + .status(403) + .json([{ msg: error.message }]) + .end(); + case 'ValidationError': + return res + .status(400) + .json(error) + .end(); + default: + logger.error('Could perfom operation', error); + return res.status(500).end(); + } + } +} - updatedStrategy.name = strategyName; - - strategyStore - .getStrategy(strategyName) - .then(validateEditable(strategyName)) - .then(() => validateInput(updatedStrategy)) - .then(() => - eventStore.store({ - type: eventType.STRATEGY_UPDATED, - createdBy: extractUser(req), - data: updatedStrategy, - }) - ) - .then(() => res.status(200).end()) - .catch(error => handleError(req, res, error)); - }); - - return router; -}; +module.exports = StrategyController;