1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-28 00:06:53 +01:00

Add schema validation for strategies

This commit is contained in:
ivaosthu 2016-12-12 21:44:21 +01:00
parent e60c7c5cfc
commit bc82aa6e77
4 changed files with 47 additions and 20 deletions

View File

@ -0,0 +1,20 @@
'use strict';
const joi = require('joi');
const strategySchema = joi.object().keys({
name: joi.string()
.regex(/^[a-zA-Z0-9\\.\\-]{3,30}$/)
.required(),
description: joi.string(),
parameters: joi.array()
.required()
.items(joi.object().keys({
name: joi.string().required(),
type: joi.string().required(),
description: joi.string(),
required: joi.boolean(),
})),
});
module.exports = strategySchema;

View File

@ -1,29 +1,28 @@
'use strict';
const joi = require('joi');
const eventType = require('../event-type');
const logger = require('../logger');
const NameExistsError = require('../error/name-exists-error');
const ValidationError = require('../error/validation-error.js');
const NotFoundError = require('../error/notfound-error');
const validateRequest = require('../error/validate-request');
const extractUser = require('../extract-user');
const strategySchema = require('./strategy-schema');
const version = 1;
const handleError = (req, res, error) => {
switch (error.constructor) {
case NotFoundError:
switch (error.name) {
case 'NotFoundError':
return res
.status(404)
.end();
case NameExistsError:
case 'NameExistsError':
return res
.status(403)
.json([{ msg: `A strategy named '${req.body.name}' already exists.` }])
.end();
case ValidationError:
case 'ValidationError':
return res
.status(400)
.json(req.validationErrors())
.json(error)
.end();
default:
logger.error('Could perfom operation', error);
@ -64,14 +63,10 @@ module.exports = function (app, config) {
});
app.post('/strategies', (req, res) => {
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('name', 'Name must match format ^[0-9a-zA-Z\\.\\-]+$').matches(/^[0-9a-zA-Z\\.\\-]+$/i);
const newStrategy = req.body;
validateRequest(req)
const data = req.body;
validateInput(data)
.then(validateStrategyName)
.then(() => eventStore.store({
.then((newStrategy) => eventStore.store({
type: eventType.STRATEGY_CREATED,
createdBy: extractUser(req),
data: newStrategy,
@ -80,11 +75,22 @@ module.exports = function (app, config) {
.catch(error => handleError(req, res, error));
});
function validateStrategyName (req) {
function validateStrategyName (data) {
return new Promise((resolve, reject) => {
strategyStore.getStrategy(req.body.name)
strategyStore.getStrategy(data.name)
.then(() => reject(new NameExistsError('Feature name already exist')))
.catch(() => resolve(req));
.catch(() => resolve(data));
});
}
function validateInput (data) {
return new Promise((resolve, reject) => {
joi.validate(data, strategySchema, (err, cleaned) => {
if (err) {
return reject(err);
}
return resolve(cleaned);
});
});
}
};

View File

@ -2,6 +2,7 @@
const { getInstance } = require('db-migrate');
const parseDbUrl = require('parse-database-url');
require('db-migrate-shared').log.silence(true);
function migrateDb ({ databaseUrl, databaseSchema = 'public' }) {
const custom = parseDbUrl(databaseUrl);

View File

@ -42,7 +42,7 @@ test.serial('creates a new strategy', async (t) => {
const { request, destroy } = await setupApp('strategy_api_serial');
return request
.post('/api/strategies')
.send({ name: 'myCustomStrategy', description: 'Best strategy ever.' })
.send({ name: 'myCustomStrategy', description: 'Best strategy ever.', parameters: [] })
.set('Content-Type', 'application/json')
.expect(201)
.then(destroy);
@ -62,7 +62,7 @@ test.serial('refuses to create a strategy with an existing name', async (t) => {
const { request, destroy } = await setupApp('strategy_api_serial');
return request
.post('/api/strategies')
.send({ name: 'default' })
.send({ name: 'default', parameters: [] })
.set('Content-Type', 'application/json')
.expect(403)
.then(destroy);