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:
parent
e60c7c5cfc
commit
bc82aa6e77
20
lib/routes/strategy-schema.js
Normal file
20
lib/routes/strategy-schema.js
Normal 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;
|
@ -1,29 +1,28 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const joi = require('joi');
|
||||||
const eventType = require('../event-type');
|
const eventType = require('../event-type');
|
||||||
const logger = require('../logger');
|
const logger = require('../logger');
|
||||||
const NameExistsError = require('../error/name-exists-error');
|
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 extractUser = require('../extract-user');
|
||||||
|
const strategySchema = require('./strategy-schema');
|
||||||
const version = 1;
|
const version = 1;
|
||||||
|
|
||||||
const handleError = (req, res, error) => {
|
const handleError = (req, res, error) => {
|
||||||
switch (error.constructor) {
|
switch (error.name) {
|
||||||
case NotFoundError:
|
case 'NotFoundError':
|
||||||
return res
|
return res
|
||||||
.status(404)
|
.status(404)
|
||||||
.end();
|
.end();
|
||||||
case NameExistsError:
|
case 'NameExistsError':
|
||||||
return res
|
return res
|
||||||
.status(403)
|
.status(403)
|
||||||
.json([{ msg: `A strategy named '${req.body.name}' already exists.` }])
|
.json([{ msg: `A strategy named '${req.body.name}' already exists.` }])
|
||||||
.end();
|
.end();
|
||||||
case ValidationError:
|
case 'ValidationError':
|
||||||
return res
|
return res
|
||||||
.status(400)
|
.status(400)
|
||||||
.json(req.validationErrors())
|
.json(error)
|
||||||
.end();
|
.end();
|
||||||
default:
|
default:
|
||||||
logger.error('Could perfom operation', error);
|
logger.error('Could perfom operation', error);
|
||||||
@ -64,14 +63,10 @@ module.exports = function (app, config) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post('/strategies', (req, res) => {
|
app.post('/strategies', (req, res) => {
|
||||||
req.checkBody('name', 'Name is required').notEmpty();
|
const data = req.body;
|
||||||
req.checkBody('name', 'Name must match format ^[0-9a-zA-Z\\.\\-]+$').matches(/^[0-9a-zA-Z\\.\\-]+$/i);
|
validateInput(data)
|
||||||
|
|
||||||
const newStrategy = req.body;
|
|
||||||
|
|
||||||
validateRequest(req)
|
|
||||||
.then(validateStrategyName)
|
.then(validateStrategyName)
|
||||||
.then(() => eventStore.store({
|
.then((newStrategy) => eventStore.store({
|
||||||
type: eventType.STRATEGY_CREATED,
|
type: eventType.STRATEGY_CREATED,
|
||||||
createdBy: extractUser(req),
|
createdBy: extractUser(req),
|
||||||
data: newStrategy,
|
data: newStrategy,
|
||||||
@ -80,11 +75,22 @@ module.exports = function (app, config) {
|
|||||||
.catch(error => handleError(req, res, error));
|
.catch(error => handleError(req, res, error));
|
||||||
});
|
});
|
||||||
|
|
||||||
function validateStrategyName (req) {
|
function validateStrategyName (data) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
strategyStore.getStrategy(req.body.name)
|
strategyStore.getStrategy(data.name)
|
||||||
.then(() => reject(new NameExistsError('Feature name already exist')))
|
.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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const { getInstance } = require('db-migrate');
|
const { getInstance } = require('db-migrate');
|
||||||
const parseDbUrl = require('parse-database-url');
|
const parseDbUrl = require('parse-database-url');
|
||||||
|
require('db-migrate-shared').log.silence(true);
|
||||||
|
|
||||||
function migrateDb ({ databaseUrl, databaseSchema = 'public' }) {
|
function migrateDb ({ databaseUrl, databaseSchema = 'public' }) {
|
||||||
const custom = parseDbUrl(databaseUrl);
|
const custom = parseDbUrl(databaseUrl);
|
||||||
|
@ -42,7 +42,7 @@ test.serial('creates a new strategy', async (t) => {
|
|||||||
const { request, destroy } = await setupApp('strategy_api_serial');
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
return request
|
return request
|
||||||
.post('/api/strategies')
|
.post('/api/strategies')
|
||||||
.send({ name: 'myCustomStrategy', description: 'Best strategy ever.' })
|
.send({ name: 'myCustomStrategy', description: 'Best strategy ever.', parameters: [] })
|
||||||
.set('Content-Type', 'application/json')
|
.set('Content-Type', 'application/json')
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.then(destroy);
|
.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');
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
return request
|
return request
|
||||||
.post('/api/strategies')
|
.post('/api/strategies')
|
||||||
.send({ name: 'default' })
|
.send({ name: 'default', parameters: [] })
|
||||||
.set('Content-Type', 'application/json')
|
.set('Content-Type', 'application/json')
|
||||||
.expect(403)
|
.expect(403)
|
||||||
.then(destroy);
|
.then(destroy);
|
||||||
|
Loading…
Reference in New Issue
Block a user