mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Merge pull request #71 from finn-no/promisify_feature_api
Cleaned up and changed promises used in the feature API
This commit is contained in:
		
						commit
						756219eb69
					
				
							
								
								
									
										13
									
								
								lib/error/NameExistsError.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/error/NameExistsError.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					var util = require('util');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function NameExistsError(message) {
 | 
				
			||||||
 | 
					    Error.call(this);
 | 
				
			||||||
 | 
					    Error.captureStackTrace(this, this.constructor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.name = this.constructor.name;
 | 
				
			||||||
 | 
					    this.message = message;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					util.inherits(NameExistsError, Error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = NameExistsError;
 | 
				
			||||||
							
								
								
									
										13
									
								
								lib/error/NotFoundError.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/error/NotFoundError.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					var util = require('util');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function NotFoundError(message) {
 | 
				
			||||||
 | 
					    Error.call(this);
 | 
				
			||||||
 | 
					    Error.captureStackTrace(this, this.constructor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.name = this.constructor.name;
 | 
				
			||||||
 | 
					    this.message = message;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					util.inherits(NotFoundError, Error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = NotFoundError;
 | 
				
			||||||
							
								
								
									
										13
									
								
								lib/error/ValidationError.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/error/ValidationError.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					var util = require('util');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function ValidationError(message) {
 | 
				
			||||||
 | 
					    Error.call(this);
 | 
				
			||||||
 | 
					    Error.captureStackTrace(this, this.constructor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.name = this.constructor.name;
 | 
				
			||||||
 | 
					    this.message = message;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					util.inherits(ValidationError, Error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = ValidationError;
 | 
				
			||||||
							
								
								
									
										14
									
								
								lib/error/validateRequest.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								lib/error/validateRequest.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					var Promise = require("bluebird");
 | 
				
			||||||
 | 
					var ValidationError = require('./ValidationError');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function validateRequest(req) {
 | 
				
			||||||
 | 
					    return new Promise(function(resolve, reject) {
 | 
				
			||||||
 | 
					        if (req.validationErrors()) {
 | 
				
			||||||
 | 
					            reject(new ValidationError("Invalid syntax"));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            resolve(req);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports =  validateRequest;
 | 
				
			||||||
@ -1,6 +1,12 @@
 | 
				
			|||||||
 | 
					var Promise             = require("bluebird");
 | 
				
			||||||
 | 
					var logger              = require('./logger');
 | 
				
			||||||
var eventStore          = require('./eventStore');
 | 
					var eventStore          = require('./eventStore');
 | 
				
			||||||
var eventType           = require('./eventType');
 | 
					var eventType           = require('./eventType');
 | 
				
			||||||
var featureDb           = require('./featureDb');
 | 
					var featureDb           = require('./featureDb');
 | 
				
			||||||
 | 
					var NameExistsError     = require('./error/NameExistsError');
 | 
				
			||||||
 | 
					var NotFoundError       = require('./error/NotFoundError');
 | 
				
			||||||
 | 
					var ValidationError     = require('./error/ValidationError');
 | 
				
			||||||
 | 
					var validateRequest    = require('./error/validateRequest');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = function (app) {
 | 
					module.exports = function (app) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -22,62 +28,66 @@ module.exports = function (app) {
 | 
				
			|||||||
        req.checkBody('name', 'Name is required').notEmpty();
 | 
					        req.checkBody('name', 'Name is required').notEmpty();
 | 
				
			||||||
        req.checkBody('name', 'Name must match format ^[a-zA-Z\\.\\-]+$').matches(/^[a-zA-Z\\.\\-]+$/i);
 | 
					        req.checkBody('name', 'Name must match format ^[a-zA-Z\\.\\-]+$').matches(/^[a-zA-Z\\.\\-]+$/i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var errors = req.validationErrors();
 | 
					        validateRequest(req)
 | 
				
			||||||
 | 
					            .then(validateUniqueName)
 | 
				
			||||||
        if (errors) {
 | 
					            .then(function() {
 | 
				
			||||||
            res.status(400).json(errors);
 | 
					                return eventStore.create({
 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var newFeature = req.body;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var handleFeatureExist = function() {
 | 
					 | 
				
			||||||
            var errors = [
 | 
					 | 
				
			||||||
                {msg: "A feature named '" + newFeature.name + "' already exists."}
 | 
					 | 
				
			||||||
            ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            res.status(403).json(errors).end();
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var handleCreateFeature = function () {
 | 
					 | 
				
			||||||
            eventStore.create({
 | 
					 | 
				
			||||||
                    type: eventType.featureCreated,
 | 
					                    type: eventType.featureCreated,
 | 
				
			||||||
                    createdBy: req.connection.remoteAddress,
 | 
					                    createdBy: req.connection.remoteAddress,
 | 
				
			||||||
                data: newFeature
 | 
					                    data: req.body
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
                .then(function ()  { res.status(201).end(); })
 | 
					            .then(function () {
 | 
				
			||||||
                .catch(function () { res.status(500).end(); });
 | 
					                res.status(201).end();
 | 
				
			||||||
        };
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(NameExistsError, function() {
 | 
				
			||||||
        featureDb.getFeature(newFeature.name)
 | 
					                res.status(403).json([{msg: "A feature named '" + req.body.name + "' already exists."}]).end();
 | 
				
			||||||
            .then(handleFeatureExist)
 | 
					            })
 | 
				
			||||||
            .catch(handleCreateFeature);
 | 
					            .catch(ValidationError, function() {
 | 
				
			||||||
 | 
					                res.status(400).json(req.validationErrors());
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(function(err) {
 | 
				
			||||||
 | 
					                logger.error("Could not create feature toggle", err);
 | 
				
			||||||
 | 
					                res.status(500).end();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app.put('/features/:featureName', function (req, res) {
 | 
					    app.put('/features/:featureName', function (req, res) {
 | 
				
			||||||
        var featureName    = req.params.featureName;
 | 
					        var featureName    = req.params.featureName;
 | 
				
			||||||
        var createdBy      = req.connection.remoteAddress;
 | 
					        var userName       = req.connection.remoteAddress;
 | 
				
			||||||
        var updatedFeature = req.body;
 | 
					        var updatedFeature = req.body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        updatedFeature.name = featureName;
 | 
					        updatedFeature.name = featureName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var event = {
 | 
					 | 
				
			||||||
            type: eventType.featureUpdated,
 | 
					 | 
				
			||||||
            createdBy: createdBy,
 | 
					 | 
				
			||||||
            data: updatedFeature
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        featureDb.getFeature(featureName)
 | 
					        featureDb.getFeature(featureName)
 | 
				
			||||||
            .then(function () {
 | 
					            .then(function () {
 | 
				
			||||||
                eventStore
 | 
					                return eventStore.create({
 | 
				
			||||||
                    .create(event)
 | 
					                    type: eventType.featureUpdated,
 | 
				
			||||||
                    .then(function () { res.status(200).end(); })
 | 
					                    createdBy: userName,
 | 
				
			||||||
                    .catch(function () { res.status(500).end(); });
 | 
					                    data: updatedFeature
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .catch(function () {
 | 
					            .then(function () {
 | 
				
			||||||
 | 
					                res.status(200).end();
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(NotFoundError, function () {
 | 
				
			||||||
                res.status(404).end();
 | 
					                res.status(404).end();
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(function (err) {
 | 
				
			||||||
 | 
					                logger.error("Could not update feature toggle="+featureName, err);
 | 
				
			||||||
 | 
					                res.status(500).end();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function validateUniqueName(req) {
 | 
				
			||||||
 | 
					        return new Promise(function(resolve, reject) {
 | 
				
			||||||
 | 
					            featureDb.getFeature(req.body.name)
 | 
				
			||||||
 | 
					                .then(function() {
 | 
				
			||||||
 | 
					                    reject(new NameExistsError("Feature name already exist"));
 | 
				
			||||||
 | 
					                }, function() {
 | 
				
			||||||
 | 
					                    resolve(req);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ var eventStore      = require('./eventStore');
 | 
				
			|||||||
var eventType       = require('./eventType');
 | 
					var eventType       = require('./eventType');
 | 
				
			||||||
var logger          = require('./logger');
 | 
					var logger          = require('./logger');
 | 
				
			||||||
var knex            = require('./dbPool');
 | 
					var knex            = require('./dbPool');
 | 
				
			||||||
 | 
					var NotFoundError   = require('./error/NotFoundError');
 | 
				
			||||||
var FEATURE_COLUMNS = ['name', 'description', 'enabled', 'strategy_name', 'parameters'];
 | 
					var FEATURE_COLUMNS = ['name', 'description', 'enabled', 'strategy_name', 'parameters'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
eventStore.on(eventType.featureCreated, function (event) {
 | 
					eventStore.on(eventType.featureCreated, function (event) {
 | 
				
			||||||
@ -39,7 +40,7 @@ function getFeature(name) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function rowToFeature(row) {
 | 
					function rowToFeature(row) {
 | 
				
			||||||
    if (!row) {
 | 
					    if (!row) {
 | 
				
			||||||
        throw new Error('invalid row');
 | 
					        throw new NotFoundError('No feature toggle found');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,11 @@
 | 
				
			|||||||
 | 
					var Promise             = require("bluebird");
 | 
				
			||||||
var eventStore          = require('./eventStore');
 | 
					var eventStore          = require('./eventStore');
 | 
				
			||||||
var eventType           = require('./eventType');
 | 
					var eventType           = require('./eventType');
 | 
				
			||||||
var strategyDb          = require('./strategyDb');
 | 
					var strategyDb          = require('./strategyDb');
 | 
				
			||||||
 | 
					var logger              = require('./logger');
 | 
				
			||||||
 | 
					var NameExistsError     = require('./error/NameExistsError');
 | 
				
			||||||
 | 
					var ValidationError     = require('./error/ValidationError');
 | 
				
			||||||
 | 
					var validateRequest    = require('./error/validateRequest');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = function (app) {
 | 
					module.exports = function (app) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -32,34 +37,42 @@ module.exports = function (app) {
 | 
				
			|||||||
        req.checkBody('name', 'Name is required').notEmpty();
 | 
					        req.checkBody('name', 'Name is required').notEmpty();
 | 
				
			||||||
        req.checkBody('name', 'Name must match format ^[a-zA-Z\\.\\-]+$').matches(/^[a-zA-Z\\.\\-]+$/i);
 | 
					        req.checkBody('name', 'Name must match format ^[a-zA-Z\\.\\-]+$').matches(/^[a-zA-Z\\.\\-]+$/i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var errors = req.validationErrors();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (errors) {
 | 
					 | 
				
			||||||
            res.status(400).json(errors);
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var newStrategy = req.body;
 | 
					        var newStrategy = req.body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var handleStrategyExists = function() {
 | 
					        validateRequest(req)
 | 
				
			||||||
            var errors = [{msg: "A strategy named " + newStrategy.name + " already exists."}];
 | 
					            .then(validateStrategyName)
 | 
				
			||||||
            res.status(403).json(errors);
 | 
					            .then(function() {
 | 
				
			||||||
        };
 | 
					                return eventStore.create({
 | 
				
			||||||
 | 
					 | 
				
			||||||
        var handleCreateStrategy = function() {
 | 
					 | 
				
			||||||
            eventStore.create({
 | 
					 | 
				
			||||||
                    type: eventType.strategyCreated,
 | 
					                    type: eventType.strategyCreated,
 | 
				
			||||||
                    createdBy: req.connection.remoteAddress,
 | 
					                    createdBy: req.connection.remoteAddress,
 | 
				
			||||||
                    data: newStrategy
 | 
					                    data: newStrategy
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
                .then(function ()  { res.status(201).end(); })
 | 
					 | 
				
			||||||
                .catch(function () { res.status(500).end(); });
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        strategyDb.getStrategy(newStrategy.name)
 | 
					 | 
				
			||||||
            .then(handleStrategyExists)
 | 
					 | 
				
			||||||
            .catch(handleCreateStrategy);
 | 
					 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .then(function () {
 | 
				
			||||||
 | 
					                res.status(201).end();
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(NameExistsError, function() {
 | 
				
			||||||
 | 
					                res.status(403).json([{msg: "A strategy named '" + req.body.name + "' already exists."}]).end();
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(ValidationError, function() {
 | 
				
			||||||
 | 
					                res.status(400).json(req.validationErrors());
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(function(err) {
 | 
				
			||||||
 | 
					                logger.error("Could not create strategy", err);
 | 
				
			||||||
 | 
					                res.status(500).end();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function validateStrategyName(req) {
 | 
				
			||||||
 | 
					        return new Promise(function(resolve, reject) {
 | 
				
			||||||
 | 
					            strategyDb.getStrategy(req.body.name)
 | 
				
			||||||
 | 
					                .then(function() {
 | 
				
			||||||
 | 
					                    reject(new NameExistsError("Feature name already exist"));
 | 
				
			||||||
 | 
					                }, function() {
 | 
				
			||||||
 | 
					                    resolve(req);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
var Promise = require("bluebird");
 | 
					var Promise = require("bluebird");
 | 
				
			||||||
 | 
					var NotFoundError = require('../lib/error/NotFoundError');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var features = [
 | 
					var features = [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -49,7 +50,7 @@ module.exports = {
 | 
				
			|||||||
        if(feature) {
 | 
					        if(feature) {
 | 
				
			||||||
            return Promise.resolve(feature);
 | 
					            return Promise.resolve(feature);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return Promise.reject("feature not found");
 | 
					            return Promise.reject(new NotFoundError("feature not found"));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user