mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +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