Replace the when promise library with bluebird.

Closes #968
This commit is contained in:
Jason Williams 2014-08-17 06:17:23 +00:00
parent f7e92d20e2
commit 07ad400ee0
80 changed files with 924 additions and 981 deletions

54
core/bootstrap.js vendored
View File

@ -6,7 +6,7 @@
var fs = require('fs'),
url = require('url'),
when = require('when'),
Promise = require('bluebird'),
validator = require('validator'),
errors = require('./server/errors'),
config = require('./server/config'),
@ -20,10 +20,9 @@ function readConfigFile(envVal) {
}
function writeConfigFile() {
var written = when.defer();
/* Check for config file and copy from config.example.js
if one doesn't exist. After that, start the server. */
return new Promise(function (resolve, reject) {
fs.exists(configExample, function checkTemplate(templateExists) {
var read,
write,
@ -34,7 +33,7 @@ function writeConfigFile() {
error.context = appRoot;
error.help = 'Please check your deployment for config.js or config.example.js.';
return written.reject(error);
return reject(error);
}
// Copy config.example.js => config.js
@ -42,21 +41,21 @@ function writeConfigFile() {
read.on('error', function (err) {
errors.logError(new Error('Could not open config.example.js for read.'), appRoot, 'Please check your deployment for config.js or config.example.js.');
return written.reject(err);
reject(err);
});
write = fs.createWriteStream(configFile);
write.on('error', function (err) {
errors.logError(new Error('Could not open config.js for write.'), appRoot, 'Please check your deployment for config.js or config.example.js.');
return written.reject(err);
reject(err);
});
write.on('finish', written.resolve);
write.on('finish', resolve);
read.pipe(write);
});
return written.promise;
});
}
function validateConfigEnvironment() {
@ -70,7 +69,7 @@ function validateConfigEnvironment() {
config = readConfigFile(envVal);
}
catch (e) {
return when.reject(e);
return Promise.reject(e);
}
// Check if we don't even have a config
@ -78,14 +77,14 @@ function validateConfigEnvironment() {
errors.logError(new Error('Cannot find the configuration for the current NODE_ENV'), 'NODE_ENV=' + envVal,
'Ensure your config.js has a section for the current NODE_ENV value and is formatted properly.');
return when.reject(new Error('Unable to load config for NODE_ENV=' + envVal));
return Promise.reject(new Error('Unable to load config for NODE_ENV=' + envVal));
}
// Check that our url is valid
if (!validator.isURL(config.url, { protocols: ['http', 'https'], require_protocol: true })) {
errors.logError(new Error('Your site url in config.js is invalid.'), config.url, 'Please make sure this is a valid url before restarting');
return when.reject(new Error('invalid site url'));
return Promise.reject(new Error('invalid site url'));
}
parsedUrl = url.parse(config.url || 'invalid', false, true);
@ -93,14 +92,14 @@ function validateConfigEnvironment() {
if (/\/ghost(\/|$)/.test(parsedUrl.pathname)) {
errors.logError(new Error('Your site url in config.js cannot contain a subdirectory called ghost.'), config.url, 'Please rename the subdirectory before restarting');
return when.reject(new Error('ghost subdirectory not allowed'));
return Promise.reject(new Error('ghost subdirectory not allowed'));
}
// Check that we have database values
if (!config.database || !config.database.client) {
errors.logError(new Error('Your database configuration in config.js is invalid.'), JSON.stringify(config.database), 'Please make sure this is a valid Bookshelf database configuration');
return when.reject(new Error('invalid database configuration'));
return Promise.reject(new Error('invalid database configuration'));
}
hasHostAndPort = config.server && !!config.server.host && !!config.server.port;
@ -110,33 +109,32 @@ function validateConfigEnvironment() {
if (!config.server || !(hasHostAndPort || hasSocket)) {
errors.logError(new Error('Your server values (socket, or host and port) in config.js are invalid.'), JSON.stringify(config.server), 'Please provide them before restarting.');
return when.reject(new Error('invalid server configuration'));
return Promise.reject(new Error('invalid server configuration'));
}
return when.resolve(config);
return Promise.resolve(config);
}
function loadConfig(configFilePath) {
var loaded = when.defer(),
pendingConfig;
// Allow config file path to be taken from, in order of importance:
// environment process, passed in value, default location
configFile = process.env.GHOST_CONFIG || configFilePath || config.paths.config;
/* Check for config file and copy from config.example.js
if one doesn't exist. After that, start the server. */
fs.exists(configFile, function checkConfig(configExists) {
if (!configExists) {
return new Promise(function (resolve, reject) {
fs.exists(configFile, function (exists) {
var pendingConfig;
if (!exists) {
pendingConfig = writeConfigFile();
}
when(pendingConfig).then(validateConfigEnvironment).then(function (rawConfig) {
return config.init(rawConfig).then(loaded.resolve);
}).catch(loaded.reject);
Promise.resolve(pendingConfig)
.then(validateConfigEnvironment)
.then(function (rawConfig) {
resolve(config.init(rawConfig));
}).catch(reject);
});
});
return loaded.promise;
}
module.exports = loadConfig;

View File

@ -2,33 +2,17 @@
// Orchestrates the loading of Ghost
// When run from command line.
var when = require('when'),
bootstrap = require('./bootstrap'),
var bootstrap = require('./bootstrap'),
server = require('./server');
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
function makeGhost(options) {
var deferred = when.defer();
options = options || {};
bootstrap(options.config).then(function () {
try {
return server(options.app)
.then(deferred.resolve)
.catch(function (err) {
// We don't return the rejected promise to stop
// the propagation of the rejection and just
// allow the user to manage what to do.
deferred.reject(err);
return bootstrap(options.config).then(function () {
return server(options.app);
});
} catch (e) {
deferred.reject(e);
}
}).catch(deferred.reject);
return deferred.promise;
}
module.exports = makeGhost;

View File

@ -1,4 +1,4 @@
var when = require('when'),
var Promise = require('bluebird'),
fs = require('fs'),
semver = require('semver'),
packageInfo = require('../../package.json'),
@ -88,8 +88,10 @@ GhostServer.prototype.logUpgradeWarning = function () {
// Starts the ghost server listening on the configured port
GhostServer.prototype.start = function () {
var self = this;
// ## Start Ghost App
var deferred = when.defer();
return new Promise(function (resolve) {
if (config.getSocket()) {
// Make sure the socket is gone before trying to create another
try {
@ -98,44 +100,47 @@ GhostServer.prototype.start = function () {
// We can ignore this.
}
this.httpServer = this.app.listen(
self.httpServer = self.app.listen(
config.getSocket()
);
fs.chmod(config.getSocket(), '0660');
} else {
this.httpServer = this.app.listen(
self.httpServer = self.app.listen(
config.server.port,
config.server.host
);
}
this.httpServer.on('connection', this.connection.bind(this));
this.httpServer.on('listening', function () {
this.logStartMessages();
clearTimeout(this.upgradeWarning);
deferred.resolve(this);
}.bind(this));
return deferred.promise;
self.httpServer.on('connection', self.connection.bind(self));
self.httpServer.on('listening', function () {
self.logStartMessages();
clearTimeout(self.upgradeWarning);
resolve(self);
});
});
};
// Returns a promise that will be fulfilled when the server stops.
// If the server has not been started, the promise will be fulfilled
// immediately
GhostServer.prototype.stop = function () {
var deferred = when.defer();
var self = this;
if (this.httpServer === null) {
deferred.resolve(this);
return new Promise(function (resolve) {
if (self.httpServer === null) {
resolve(self);
} else {
this.httpServer.close(function () {
this.httpServer = null;
this.logShutdownMessages();
deferred.resolve(this);
}.bind(this));
this.closeConnections();
self.httpServer.close(function () {
self.httpServer = null;
self.logShutdownMessages();
resolve(self);
});
self.closeConnections();
}
return deferred.promise;
});
};
// Restarts the ghost application
@ -146,8 +151,8 @@ GhostServer.prototype.restart = function () {
// To be called after `stop`
GhostServer.prototype.hammertime = function () {
console.log('Can\'t touch this'.green);
return this;
return Promise.resolve(this);
};
module.exports = GhostServer;

View File

@ -5,7 +5,7 @@ var _ = require('lodash'),
globalUtils = require('../utils'),
utils = require('./utils'),
users = require('./users'),
when = require('when'),
Promise = require('bluebird'),
errors = require('../errors'),
config = require('../config'),
authentication;
@ -31,7 +31,7 @@ authentication = {
var setup = result.setup[0].status;
if (!setup) {
return when.reject(new errors.NoPermissionError('Setup must be completed before making this request.'));
return Promise.reject(new errors.NoPermissionError('Setup must be completed before making this request.'));
}
return utils.checkObject(object, 'passwordreset');
@ -39,13 +39,10 @@ authentication = {
if (checkedPasswordReset.passwordreset[0].email) {
email = checkedPasswordReset.passwordreset[0].email;
} else {
return when.reject(new errors.BadRequestError('No email provided.'));
return Promise.reject(new errors.BadRequestError('No email provided.'));
}
return users.read({ context: {internal: true}, email: email, status: 'active' }).then(function (foundUser) {
if (!foundUser) {
when.reject(new errors.NotFound('Invalid email address'));
}
return users.read({ context: {internal: true}, email: email, status: 'active' }).then(function () {
return settings.read({context: {internal: true}, key: 'dbHash'});
}).then(function (response) {
var dbHash = response.settings[0].value;
@ -69,9 +66,9 @@ authentication = {
};
return mail.send(payload, {context: {internal: true}});
}).then(function () {
return when.resolve({passwordreset: [{message: 'Check your email for further instructions.'}]});
}).otherwise(function (error) {
return when.reject(error);
return Promise.resolve({passwordreset: [{message: 'Check your email for further instructions.'}]});
}).catch(function (error) {
return Promise.reject(error);
});
});
},
@ -91,7 +88,7 @@ authentication = {
var setup = result.setup[0].status;
if (!setup) {
return when.reject(new errors.NoPermissionError('Setup must be completed before making this request.'));
return Promise.reject(new errors.NoPermissionError('Setup must be completed before making this request.'));
}
return utils.checkObject(object, 'passwordreset');
@ -104,9 +101,9 @@ authentication = {
var dbHash = response.settings[0].value;
return dataProvider.User.resetPassword(resetToken, newPassword, ne2Password, dbHash);
}).then(function () {
return when.resolve({passwordreset: [{message: 'Password changed successfully.'}]});
}).otherwise(function (error) {
return when.reject(new errors.UnauthorizedError(error.message));
return Promise.resolve({passwordreset: [{message: 'Password changed successfully.'}]});
}).catch(function (error) {
return Promise.reject(new errors.UnauthorizedError(error.message));
});
});
},
@ -127,7 +124,7 @@ authentication = {
var setup = result.setup[0].status;
if (!setup) {
return when.reject(new errors.NoPermissionError('Setup must be completed before making this request.'));
return Promise.reject(new errors.NoPermissionError('Setup must be completed before making this request.'));
}
return utils.checkObject(object, 'invitation');
@ -144,9 +141,9 @@ authentication = {
}).then(function (user) {
return dataProvider.User.edit({name: name, email: email}, {id: user.id});
}).then(function () {
return when.resolve({invitation: [{message: 'Invitation accepted.'}]});
}).otherwise(function (error) {
return when.reject(new errors.UnauthorizedError(error.message));
return Promise.resolve({invitation: [{message: 'Invitation accepted.'}]});
}).catch(function (error) {
return Promise.reject(new errors.UnauthorizedError(error.message));
});
});
},
@ -156,9 +153,9 @@ authentication = {
qb.whereIn('status', ['active', 'warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked']);
}).fetch().then(function (users) {
if (users) {
return when.resolve({ setup: [{status: true}]});
return Promise.resolve({ setup: [{status: true}]});
} else {
return when.resolve({ setup: [{status: false}]});
return Promise.resolve({ setup: [{status: false}]});
}
});
},
@ -171,7 +168,7 @@ authentication = {
var setup = result.setup[0].status;
if (setup) {
return when.reject(new errors.NoPermissionError('Setup has already been completed.'));
return Promise.reject(new errors.NoPermissionError('Setup has already been completed.'));
}
return utils.checkObject(object, 'setup');
@ -226,7 +223,7 @@ authentication = {
}]
};
return mail.send(payload, {context: {internal: true}}).otherwise(function (error) {
return mail.send(payload, {context: {internal: true}}).catch(function (error) {
errors.logError(
error.message,
"Unable to send welcome email, your blog will continue to function.",
@ -235,7 +232,7 @@ authentication = {
});
}).then(function () {
return when.resolve({ users: [setupUser]});
return Promise.resolve({ users: [setupUser]});
});
}
};

View File

@ -4,8 +4,7 @@ var dataExport = require('../data/export'),
dataImport = require('../data/import'),
dataProvider = require('../models'),
fs = require('fs-extra'),
when = require('when'),
nodefn = require('when/node'),
Promise = require('bluebird'),
_ = require('lodash'),
path = require('path'),
errors = require('../../server/errors'),
@ -42,12 +41,12 @@ db = {
// Export data, otherwise send error 500
return canThis(options.context).exportContent.db().then(function () {
return dataExport().then(function (exportedData) {
return when.resolve({ db: [exportedData] });
}).otherwise(function (error) {
return when.reject(new errors.InternalServerError(error.message || error));
return { db: [exportedData] };
}).catch(function (error) {
return Promise.reject(new errors.InternalServerError(error.message || error));
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to export data. (no rights)'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to export data. (no rights)'));
});
},
/**
@ -67,16 +66,16 @@ db = {
return canThis(options.context).importContent.db().then(function () {
if (!options.importfile || !options.importfile.type || !options.importfile.path) {
return when.reject(new errors.NoPermissionError('Please select a file to import.'));
return Promise.reject(new errors.NoPermissionError('Please select a file to import.'));
}
type = options.importfile.type;
ext = path.extname(options.importfile.name).toLowerCase();
filepath = options.importfile.path;
return when(isValidFile(ext)).then(function (result) {
return Promise.resolve(isValidFile(ext)).then(function (result) {
if (!result) {
return when.reject(new errors.UnsupportedMediaTypeError('Please select a .json file to import.'));
return Promise.reject(new errors.UnsupportedMediaTypeError('Please select a .json file to import.'));
}
}).then(function () {
return api.settings.read(
@ -84,12 +83,12 @@ db = {
).then(function (response) {
var setting = response.settings[0];
return when(setting.value);
return setting.value;
});
}).then(function (version) {
databaseVersion = version;
// Read the file contents
return nodefn.call(fs.readFile, filepath);
return Promise.promisify(fs.readFile)(filepath);
}).then(function (fileContents) {
var importData;
@ -103,11 +102,11 @@ db = {
}
} catch (e) {
errors.logError(e, 'API DB import content', 'check that the import file is valid JSON.');
return when.reject(new errors.BadRequest('Failed to parse the import JSON file'));
return Promise.reject(new errors.BadRequest('Failed to parse the import JSON file'));
}
if (!importData.meta || !importData.meta.version) {
return when.reject(
return Promise.reject(
new errors.ValidationError('Import data does not specify version', 'meta.version')
);
}
@ -115,16 +114,14 @@ db = {
// Import for the current version
return dataImport(databaseVersion, importData);
}).then(function importSuccess() {
return api.settings.updateSettingsCache();
}).then(function () {
return when.resolve({ db: [] });
}).finally(function () {
}).then(api.settings.updateSettingsCache)
.return({ db: [] })
.finally(function () {
// Unlink the file after import
return nodefn.call(fs.unlink, filepath);
return Promise.promisify(fs.unlink)(filepath);
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to import data. (no rights)'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to import data. (no rights)'));
});
},
/**
@ -139,14 +136,13 @@ db = {
options = options || {};
return canThis(options.context).deleteAllContent.db().then(function () {
return when(dataProvider.deleteAllContent())
.then(function () {
return when.resolve({ db: [] });
}, function (error) {
return when.reject(new errors.InternalServerError(error.message || error));
return Promise.resolve(dataProvider.deleteAllContent())
.return({ db: [] })
.catch(function (error) {
return Promise.reject(new errors.InternalServerError(error.message || error));
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to export data. (no rights)'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to export data. (no rights)'));
});
}
};

View File

@ -5,7 +5,7 @@
// from a theme, an app, or from an external app, you'll use the Ghost JSON API to do so.
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
config = require('../config'),
// Include Endpoints
db = require('./db'),
@ -90,7 +90,7 @@ cacheInvalidationHeader = function (req, result) {
}
}
return when(cacheInvalidate);
return Promise.resolve(cacheInvalidate);
};
/**
@ -122,7 +122,7 @@ locationHeader = function (req, result) {
}
}
return when(location);
return Promise.resolve(location);
};
/**
@ -219,7 +219,7 @@ addHeaders = function (apiMethod, req, res, result) {
ops.push(contentDisposition);
}
return when.all(ops);
return Promise.all(ops);
};
/**

View File

@ -1,7 +1,7 @@
// # Mail API
// API for sending Mail
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
config = require('../config'),
canThis = require('../permissions').canThis,
errors = require('../errors'),
@ -42,12 +42,12 @@ mail = {
};
return object;
})
.otherwise(function (error) {
return when.reject(new errors.EmailError(error.message));
.catch(function (error) {
return Promise.reject(new errors.EmailError(error.message));
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to send mail.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to send mail.'));
});
},
@ -73,7 +73,7 @@ mail = {
return mail.send(payload, options);
});
}, function () {
return when.reject(new errors.NotFoundError('Could not find the current user'));
return Promise.reject(new errors.NotFoundError('Could not find the current user'));
});
},
@ -95,7 +95,7 @@ mail = {
_.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
//read the proper email body template
return when.promise(function (resolve, reject) {
return new Promise(function (resolve, reject) {
fs.readFile(templatesDir + '/' + options.template + '.html', {encoding: 'utf8'}, function (err, fileContent) {
if (err) {
reject(err);

View File

@ -1,6 +1,6 @@
// # Notifications API
// RESTful API for creating notifications
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
canThis = require('../permissions').canThis,
errors = require('../errors'),
@ -26,9 +26,9 @@ notifications = {
*/
browse: function browse(options) {
return canThis(options.context).browse.notification().then(function () {
return when({ 'notifications': notificationsStore });
return { 'notifications': notificationsStore };
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to browse notifications.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to browse notifications.'));
});
},
@ -69,10 +69,10 @@ notifications = {
addedNotifications.push(notification);
});
return when({ notifications: addedNotifications});
return { notifications: addedNotifications };
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to add notifications.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to add notifications.'));
});
},
@ -90,21 +90,21 @@ notifications = {
});
if (notification && !notification.dismissible) {
return when.reject(
return Promise.reject(
new errors.NoPermissionError('You do not have permission to dismiss this notification.')
);
}
if (!notification) {
return when.reject(new errors.NotFoundError('Notification does not exist.'));
return Promise.reject(new errors.NotFoundError('Notification does not exist.'));
}
notificationsStore = _.reject(notificationsStore, function (element) {
return element.id === parseInt(options.id, 10);
});
return when({notifications: [notification]});
return { notifications: [notification] };
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to destroy notifications.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to destroy notifications.'));
});
},
@ -119,9 +119,10 @@ notifications = {
return canThis(options.context).destroy.notification().then(function () {
notificationsStore = [];
notificationCounter = 0;
return when(notificationsStore);
return notificationsStore;
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to destroy notifications.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to destroy notifications.'));
});
}
};

View File

@ -1,6 +1,6 @@
// # Posts API
// RESTful API for the Post resource
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
dataProvider = require('../models'),
canThis = require('../permissions').canThis,
@ -88,8 +88,7 @@ posts = {
return { posts: [ result.toJSON() ]};
}
return when.reject(new errors.NotFoundError('Post not found.'));
return Promise.reject(new errors.NotFoundError('Post not found.'));
});
},
@ -122,10 +121,10 @@ posts = {
return { posts: [ post ]};
}
return when.reject(new errors.NotFoundError('Post not found.'));
return Promise.reject(new errors.NotFoundError('Post not found.'));
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to edit this post.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to edit posts.'));
});
},
@ -158,7 +157,7 @@ posts = {
return { posts: [ post ]};
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to add posts.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to add posts.'));
});
},
@ -188,7 +187,7 @@ posts = {
});
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to remove posts.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to remove posts.'));
});
}

View File

@ -1,6 +1,6 @@
// # Roles API
// RESTful API for the Role resource
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
canThis = require('../permissions').canThis,
dataProvider = require('../models'),
@ -45,12 +45,12 @@ roles = {
return null;
}
return role;
}, function () {
}).catch(function () {
return null;
}));
});
return when.all(permissionMap).then(function (resolved) {
return Promise.all(permissionMap).then(function (resolved) {
return { roles: _.filter(resolved, function (role) {
return role !== null;
}) };

View File

@ -2,7 +2,7 @@
// RESTful API for the Setting resource
var _ = require('lodash'),
dataProvider = require('../models'),
when = require('when'),
Promise = require('bluebird'),
config = require('../config'),
canThis = require('../permissions').canThis,
errors = require('../errors'),
@ -44,7 +44,7 @@ updateSettingsCache = function (settings) {
settingsCache[key] = setting;
});
return when(settingsCache);
return Promise.resolve(settingsCache);
}
return dataProvider.Settings.findAll()
@ -206,14 +206,14 @@ populateDefaultSetting = function (key) {
}).then(function () {
// Get the result from the cache with permission checks
});
}).otherwise(function (err) {
}).catch(function (err) {
// Pass along NotFoundError
if (typeof err === errors.NotFoundError) {
return when.reject(err);
return Promise.reject(err);
}
// TODO: Different kind of error?
return when.reject(new errors.NotFoundError('Problem finding setting: ' + key));
return Promise.reject(new errors.NotFoundError('Problem finding setting: ' + key));
});
};
@ -227,13 +227,13 @@ populateDefaultSetting = function (key) {
canEditAllSettings = function (settingsInfo, options) {
var checkSettingPermissions = function (setting) {
if (setting.type === 'core' && !(options.context && options.context.internal)) {
return when.reject(
return Promise.reject(
new errors.NoPermissionError('Attempted to access core setting from external request')
);
}
return canThis(options.context).edit.setting(setting.key).catch(function () {
return when.reject(new errors.NoPermissionError('You do not have permission to edit settings.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to edit settings.'));
});
},
@ -251,7 +251,7 @@ canEditAllSettings = function (settingsInfo, options) {
return checkSettingPermissions(setting);
});
return when.all(checks);
return Promise.all(checks);
};
/**
@ -281,7 +281,7 @@ settings = {
// If there is no context, return only blog settings
if (!options.context) {
return when(_.filter(result.settings, function (setting) { return setting.type === 'blog'; }));
return Promise.resolve(_.filter(result.settings, function (setting) { return setting.type === 'blog'; }));
}
// Otherwise return whatever this context is allowed to browse
@ -312,19 +312,19 @@ settings = {
result[options.key] = setting;
if (setting.type === 'core' && !(options.context && options.context.internal)) {
return when.reject(
return Promise.reject(
new errors.NoPermissionError('Attempted to access core setting from external request')
);
}
if (setting.type === 'blog') {
return when(settingsResult(result));
return Promise.resolve(settingsResult(result));
}
return canThis(options.context).read.setting(options.key).then(function () {
return settingsResult(result);
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to read settings.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to read settings.'));
});
};

View File

@ -3,7 +3,7 @@
var canThis = require('../permissions').canThis,
dataProvider = require('../models'),
errors = require('../errors'),
when = require('when'),
Promise = require('bluebird'),
slugs,
allowedTypes;
@ -35,22 +35,22 @@ slugs = {
return canThis(options.context).generate.slug().then(function () {
if (allowedTypes[options.type] === undefined) {
return when.reject(new errors.BadRequestError('Unknown slug type \'' + options.type + '\'.'));
return Promise.reject(new errors.BadRequestError('Unknown slug type \'' + options.type + '\'.'));
}
return dataProvider.Base.Model.generateSlug(allowedTypes[options.type], options.name, {status: 'all'}).then(function (slug) {
if (!slug) {
return when.reject(new errors.InternalServerError('Could not generate slug.'));
return Promise.reject(new errors.InternalServerError('Could not generate slug.'));
}
return { slugs: [{ slug: slug }] };
});
}).catch(function (err) {
if (err) {
return when.reject(err);
return Promise.reject(err);
}
return when.reject(new errors.NoPermissionError('You do not have permission to generate a slug.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to generate a slug.'));
});
}

View File

@ -1,6 +1,6 @@
// # Tag API
// RESTful API for the Tag resource
var when = require('when'),
var Promise = require('bluebird'),
canThis = require('../permissions').canThis,
dataProvider = require('../models'),
errors = require('../errors'),
@ -24,7 +24,7 @@ tags = {
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to browse tags.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to browse tags.'));
});
}
};

View File

@ -1,12 +1,11 @@
// # Themes API
// RESTful API for Themes
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
canThis = require('../permissions').canThis,
config = require('../config'),
errors = require('../errors'),
settings = require('./settings'),
when = require('when'),
themes;
/**
@ -25,7 +24,7 @@ themes = {
options = options || {};
return canThis(options.context).browse.theme().then(function () {
return when.all([
return Promise.all([
settings.read({key: 'activeTheme', context: {internal: true}}),
config.paths.availableThemes
]).then(function (result) {
@ -57,7 +56,7 @@ themes = {
return { themes: themes };
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to browse themes.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to browse themes.'));
});
},
@ -73,7 +72,7 @@ themes = {
// Check whether the request is properly formatted.
if (!_.isArray(object.themes)) {
return when.reject({type: 'BadRequest', message: 'Invalid request.'});
return Promise.reject({type: 'BadRequest', message: 'Invalid request.'});
}
themeName = object.themes[0].uuid;
@ -88,7 +87,7 @@ themes = {
});
if (!theme) {
return when.reject(new errors.BadRequestError('Theme does not exist.'));
return Promise.reject(new errors.BadRequestError('Theme does not exist.'));
}
// Activate the theme
@ -100,7 +99,7 @@ themes = {
});
});
}, function () {
return when.reject(new errors.NoPermissionError('You do not have permission to edit themes.'));
return Promise.reject(new errors.NoPermissionError('You do not have permission to edit themes.'));
});
}
};

View File

@ -1,14 +1,11 @@
var when = require('when'),
var Promise = require('bluebird'),
path = require('path'),
nodefn = require('when/node'),
fs = require('fs-extra'),
storage = require('../storage'),
errors = require('../errors'),
upload;
function isImage(type, ext) {
if ((type === 'image/jpeg' || type === 'image/png' || type === 'image/gif' || type === 'image/svg+xml')
&& (ext === '.jpg' || ext === '.jpeg' || ext === '.png' || ext === '.gif' || ext === '.svg' || ext === '.svgz')) {
@ -17,7 +14,6 @@ function isImage(type, ext) {
return false;
}
/**
* ## Upload API Methods
*
@ -32,31 +28,31 @@ upload = {
* @param {{context}} options
* @returns {Promise} Success
*/
'add': function (options) {
add: function (options) {
var store = storage.get_storage(),
type,
ext,
filepath;
if (!options.uploadimage || !options.uploadimage.type || !options.uploadimage.path) {
return when.reject(new errors.NoPermissionError('Please select an image.'));
return Promise.reject(new errors.NoPermissionError('Please select an image.'));
}
type = options.uploadimage.type;
ext = path.extname(options.uploadimage.name).toLowerCase();
filepath = options.uploadimage.path;
return when(isImage(type, ext)).then(function (result) {
return Promise.resolve(isImage(type, ext)).then(function (result) {
if (!result) {
return when.reject(new errors.UnsupportedMediaTypeError('Please select a valid image.'));
return Promise.reject(new errors.UnsupportedMediaTypeError('Please select a valid image.'));
}
}).then(function () {
return store.save(options.uploadimage);
}).then(function (url) {
return when.resolve(url);
return url;
}).finally(function () {
// Remove uploaded file from tmp location
return nodefn.call(fs.unlink, filepath);
return Promise.promisify(fs.unlink)(filepath);
});
}
};

View File

@ -1,6 +1,6 @@
// # Users API
// RESTful API for the User resource
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
dataProvider = require('../models'),
settings = require('./settings'),
@ -26,7 +26,7 @@ function prepareInclude(include) {
sendInviteEmail = function sendInviteEmail(user) {
var emailData;
return when.join(
return Promise.join(
users.read({'id': user.created_by}),
settings.read({'key': 'title'}),
settings.read({context: {internal: true}, key: 'dbHash'})
@ -114,7 +114,7 @@ users = {
return { users: [result.toJSON()] };
}
return when.reject(new errors.NotFoundError('User not found.'));
return Promise.reject(new errors.NotFoundError('User not found.'));
});
},
@ -143,7 +143,7 @@ users = {
return { users: [result.toJSON()]};
}
return when.reject(new errors.NotFoundError('User not found.'));
return Promise.reject(new errors.NotFoundError('User not found.'));
});
};
@ -160,7 +160,7 @@ users = {
if (roleId !== contextRoleId &&
parseInt(options.id, 10) === parseInt(options.context.user, 10)) {
return when.reject(new errors.NoPermissionError('You cannot change your own role.'));
return Promise.reject(new errors.NoPermissionError('You cannot change your own role.'));
} else if (roleId !== contextRoleId) {
return dataProvider.User.findOne({role: 'Owner'}).then(function (result) {
if (parseInt(result.id, 10) !== parseInt(options.id, 10)) {
@ -168,7 +168,7 @@ users = {
return editOperation();
});
} else {
return when.reject(new errors.NoPermissionError('There has to be one owner.'));
return Promise.reject(new errors.NoPermissionError('There has to be one owner.'));
}
});
}
@ -208,7 +208,7 @@ users = {
newUser.password = globalUtils.uid(50);
newUser.status = 'invited';
} else {
return when.reject(new errors.BadRequestError('No email provided.'));
return Promise.reject(new errors.BadRequestError('No email provided.'));
}
return dataProvider.User.getByEmail(
@ -221,7 +221,7 @@ users = {
if (foundUser.get('status') === 'invited' || foundUser.get('status') === 'invited-pending') {
return foundUser;
} else {
return when.reject(new errors.BadRequestError('User is already registered.'));
return Promise.reject(new errors.BadRequestError('User is already registered.'));
}
}
}).then(function (invitedUser) {
@ -237,7 +237,7 @@ users = {
});
}
}).then(function () {
return when.resolve({users: [user]});
return Promise.resolve({users: [user]});
}).catch(function (error) {
if (error && error.type === 'EmailError') {
error.message = 'Error sending email: ' + error.message + ' Please check your email settings and resend the invitation.';
@ -250,7 +250,7 @@ users = {
});
});
}
return when.reject(error);
return Promise.reject(error);
});
};
@ -262,7 +262,7 @@ users = {
// Make sure user is allowed to add a user with this role
return dataProvider.Role.findOne({id: roleId}).then(function (role) {
if (role.get('name') === 'Owner') {
return when.reject(new errors.NoPermissionError('Not allowed to create an owner user.'));
return Promise.reject(new errors.NoPermissionError('Not allowed to create an owner user.'));
}
return canThis(options.context).assign.role(role);
@ -300,7 +300,7 @@ users = {
}).then(function () {
return result;
}, function (error) {
return when.reject(new errors.InternalServerError(error));
return Promise.reject(new errors.InternalServerError(error));
});
}, function (error) {
return errors.handleAPIError(error);
@ -327,9 +327,9 @@ users = {
ne2Password = checkedPasswordReset.password[0].ne2Password;
return dataProvider.User.changePassword(oldPassword, newPassword, ne2Password, options).then(function () {
return when.resolve({password: [{message: 'Password changed successfully.'}]});
return Promise.resolve({password: [{message: 'Password changed successfully.'}]});
}).catch(function (error) {
return when.reject(new errors.ValidationError(error.message));
return Promise.reject(new errors.ValidationError(error.message));
});
});
},
@ -343,9 +343,9 @@ users = {
}).then(function () {
return utils.checkObject(object, 'owner').then(function (checkedOwnerTransfer) {
return dataProvider.User.transferOwnership(checkedOwnerTransfer.owner[0], options).then(function (updatedUsers) {
return when.resolve({ users: updatedUsers });
return Promise.resolve({ users: updatedUsers });
}).catch(function (error) {
return when.reject(new errors.ValidationError(error.message));
return Promise.reject(new errors.ValidationError(error.message));
});
});
}).catch(function (error) {

View File

@ -1,6 +1,6 @@
// # API Utils
// Shared helpers for working with the API
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
errors = require('../errors'),
utils;
@ -27,7 +27,7 @@ utils = {
delete object.posts[0].author;
}
}
return when(object);
return Promise.resolve(object);
}
};

View File

@ -2,7 +2,7 @@
var _ = require('lodash'),
fs = require('fs'),
path = require('path'),
when = require('when'),
Promise = require('bluebird'),
spawn = require('child_process').spawn,
win32 = process.platform === 'win32';
@ -11,32 +11,33 @@ function AppDependencies(appPath) {
}
AppDependencies.prototype.install = function installAppDependencies() {
var def = when.defer(),
spawnOpts;
var spawnOpts,
self = this;
fs.exists(path.join(this.appPath, 'package.json'), function (exists) {
return new Promise(function (resolve, reject) {
fs.exists(path.join(self.appPath, 'package.json'), function (exists) {
if (!exists) {
// Nothing to do, resolve right away?
def.resolve();
} else {
resolve();
}
else {
// Run npm install in the app directory
spawnOpts = {
cwd: this.appPath
cwd: self.appPath
};
this.spawnCommand('npm', ['install', '--production'], spawnOpts)
.on('error', def.reject)
self.spawnCommand('npm', ['install', '--production'], spawnOpts)
.on('error', reject)
.on('exit', function (err) {
if (err) {
def.reject(err);
reject(err);
}
def.resolve();
resolve();
});
}
}.bind(this));
return def.promise;
});
});
};
// Normalize a command across OS and spawn it; taken from yeoman/generator

View File

@ -1,13 +1,12 @@
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
errors = require('../errors'),
api = require('../api'),
loader = require('./loader'),
// Holds the available apps
availableApps = {};
function getInstalledApps() {
return api.settings.read({context: {internal: true}, key: 'installedApps'}).then(function (response) {
var installed = response.settings[0];
@ -17,7 +16,7 @@ function getInstalledApps() {
try {
installed = JSON.parse(installed.value);
} catch (e) {
return when.reject(e);
return Promise.reject(e);
}
return installed;
@ -49,7 +48,8 @@ module.exports = {
'Your apps will not be loaded.',
'Check your settings table for typos in the activeApps value. It should look like: ["app-1", "app2"] (double quotes required).'
);
return when.resolve();
return Promise.resolve();
}
// Grab all installed apps, install any not already installed that are in appsToLoad.
@ -59,7 +59,7 @@ module.exports = {
// After loading the app, add it to our hash of loaded apps
loadedApps[name] = loadedApp;
return when.resolve(loadedApp);
return Promise.resolve(loadedApp);
},
loadPromises = _.map(appsToLoad, function (app) {
// If already installed, just activate the app
@ -77,13 +77,13 @@ module.exports = {
});
});
return when.all(loadPromises).then(function () {
return Promise.all(loadPromises).then(function () {
// Save our installed apps to settings
return saveInstalledApps(_.keys(loadedApps));
}).then(function () {
// Extend the loadedApps onto the available apps
_.extend(availableApps, loadedApps);
}).otherwise(function (err) {
}).catch(function (err) {
errors.logError(
err.message || err,
'The app will not be loaded',

View File

@ -1,7 +1,7 @@
var path = require('path'),
_ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
AppProxy = require('./proxy'),
config = require('../config'),
AppSandbox = require('./sandbox'),
@ -64,9 +64,9 @@ loader = {
// Load app permissions
var perms = new AppPermissions(appPath);
return perms.read().otherwise(function (err) {
return perms.read().catch(function (err) {
// Provide a helpful error about which app
return when.reject(new Error("Error loading app named " + name + "; problem reading permissions: " + err.message));
return Promise.reject(new Error("Error loading app named " + name + "; problem reading permissions: " + err.message));
});
})
.then(function (appPerms) {
@ -76,15 +76,13 @@ loader = {
// Check for an install() method on the app.
if (!_.isFunction(app.install)) {
return when.reject(new Error("Error loading app named " + name + "; no install() method defined."));
return Promise.reject(new Error("Error loading app named " + name + "; no install() method defined."));
}
// Run the app.install() method
// Wrapping the install() with a when because it's possible
// to not return a promise from it.
return when(app.install(appProxy)).then(function () {
return when.resolve(app);
});
return Promise.resolve(app.install(appProxy)).return(app);
});
},
@ -99,14 +97,12 @@ loader = {
// Check for an activate() method on the app.
if (!_.isFunction(app.activate)) {
return when.reject(new Error("Error loading app named " + name + "; no activate() method defined."));
return Promise.reject(new Error("Error loading app named " + name + "; no activate() method defined."));
}
// Wrapping the activate() with a when because it's possible
// to not return a promise from it.
return when(app.activate(appProxy)).then(function () {
return when.resolve(app);
});
return Promise.resolve(app.activate(appProxy)).return(app);
});
}
};

View File

@ -1,6 +1,6 @@
var fs = require('fs'),
when = require('when'),
Promise = require('bluebird'),
path = require('path'),
parsePackageJson = require('../require-tree').parsePackageJson;
@ -10,44 +10,35 @@ function AppPermissions(appPath) {
}
AppPermissions.prototype.read = function () {
var self = this,
def = when.defer();
var self = this;
this.checkPackageContentsExists()
.then(function (exists) {
return this.checkPackageContentsExists().then(function (exists) {
if (!exists) {
// If no package.json, return default permissions
return def.resolve(AppPermissions.DefaultPermissions);
return Promise.resolve(AppPermissions.DefaultPermissions);
}
// Read and parse the package.json
self.getPackageContents()
.then(function (parsed) {
return self.getPackageContents().then(function (parsed) {
// If no permissions in the package.json then return the default permissions.
if (!(parsed.ghost && parsed.ghost.permissions)) {
return def.resolve(AppPermissions.DefaultPermissions);
return Promise.resolve(AppPermissions.DefaultPermissions);
}
// TODO: Validation on permissions object?
def.resolve(parsed.ghost.permissions);
})
.otherwise(def.reject);
})
.otherwise(def.reject);
return def.promise;
return Promise.resolve(parsed.ghost.permissions);
});
});
};
AppPermissions.prototype.checkPackageContentsExists = function () {
// Mostly just broken out for stubbing in unit tests
var def = when.defer();
return new Promise(function (resolve) {
fs.exists(this.packagePath, function (exists) {
def.resolve(exists);
resolve(exists);
});
});
return def.promise;
};
// Get the contents of the package.json in the appPath root
@ -60,7 +51,7 @@ AppPermissions.prototype.getPackageContents = function () {
return parsePackageJson(this.packagePath, messages)
.then(function (parsed) {
if (!parsed) {
return when.reject(new Error(messages.errors[0].message));
return Promise.reject(new Error(messages.errors[0].message));
}
return parsed;

View File

@ -4,7 +4,7 @@
// All other files that need to reference config.js should use this file.
var path = require('path'),
when = require('when'),
Promise = require('bluebird'),
url = require('url'),
_ = require('lodash'),
knex = require('knex'),
@ -101,7 +101,7 @@ function initConfig(rawConfig) {
// just the object appropriate for this NODE_ENV
updateConfig(rawConfig);
return when.all([requireTree(ghostConfig.paths.themePath), requireTree(ghostConfig.paths.appPath)]).then(function (paths) {
return Promise.all([requireTree(ghostConfig.paths.themePath), requireTree(ghostConfig.paths.appPath)]).then(function (paths) {
ghostConfig.paths.availableThemes = paths[0];
ghostConfig.paths.availableApps = paths[1];
return ghostConfig;

View File

@ -1,7 +1,7 @@
// Holds all theme configuration information
// that as mostly used by templates and handlebar helpers.
var when = require('when'),
var Promise = require('bluebird'),
// Variables
themeConfig = {};
@ -18,7 +18,7 @@ function theme() {
// tries to access the config() object before it is created.
function update(settings, configUrl) {
// TODO: Pass the context into this method instead of hard coding internal: true?
return when.all([
return Promise.all([
settings.read('title'),
settings.read('description'),
settings.read('logo'),
@ -30,7 +30,6 @@ function update(settings, configUrl) {
themeConfig.description = globals[1].settings[0].value;
themeConfig.logo = globals[2].settings[0] ? globals[2].settings[0].value : '';
themeConfig.cover = globals[3].settings[0] ? globals[3].settings[0].value : '';
return;
});
}

View File

@ -1,5 +1,4 @@
var _ = require('lodash'),
when = require('when'),
api = require('../api'),
errors = require('../errors'),
updateCheck = require('../update-check'),
@ -9,7 +8,7 @@ adminControllers = {
// Route: index
// Path: /ghost/
// Method: GET
'index': function (req, res) {
index: function (req, res) {
/*jslint unparam:true*/
function renderIndex() {
@ -20,7 +19,7 @@ adminControllers = {
return updateCheck.showUpdateNotification();
}).then(function (updateVersion) {
if (!updateVersion) {
return when.resolve();
return;
}
var notification = {

View File

@ -8,8 +8,7 @@ var moment = require('moment'),
RSS = require('rss'),
_ = require('lodash'),
url = require('url'),
when = require('when'),
Promise = require('bluebird'),
api = require('../api'),
config = require('../config'),
filters = require('../../server/filters'),
@ -84,9 +83,7 @@ function formatResponse(post) {
function handleError(next) {
return function (err) {
var e = new Error(err.message);
e.status = err.code;
return next(e);
return next(err);
};
}
@ -152,7 +149,7 @@ frontendControllers = {
res.render(view, formatPageResponse(posts, page));
});
});
}).otherwise(handleError(next));
}).catch(handleError(next));
},
'tag': function (req, res, next) {
// Parse the page number
@ -206,7 +203,7 @@ frontendControllers = {
res.render(view, result);
});
});
}).otherwise(handleError(next));
}).catch(handleError(next));
},
'author': function (req, res, next) {
@ -263,7 +260,7 @@ frontendControllers = {
res.render(view, result);
});
});
}).otherwise(handleError(next));
}).catch(handleError(next));
},
'single': function (req, res, next) {
@ -290,7 +287,7 @@ frontendControllers = {
// If there are still no matches then return.
if (staticPostPermalink.match(path) === false) {
// Reject promise chain with type 'NotFound'
return when.reject(new errors.NotFoundError());
return Promise.reject(new errors.NotFoundError());
}
permalink = staticPostPermalink;
@ -324,7 +321,7 @@ frontendControllers = {
return res.redirect(config.paths.subdir + '/ghost/editor/' + post.id + '/');
} else if (params.edit !== undefined) {
// reject with type: 'NotFound'
return when.reject(new errors.NotFoundError());
return Promise.reject(new errors.NotFoundError());
}
setReqCtx(req, post);
@ -380,7 +377,7 @@ frontendControllers = {
return render();
}).otherwise(function (err) {
}).catch(function (err) {
// If we've thrown an error message
// of type: 'NotFound' then we found
// no path match.
@ -422,13 +419,13 @@ frontendControllers = {
return res.redirect(baseUrl);
}
return when.settle([
return Promise.all([
api.settings.read('title'),
api.settings.read('description'),
api.settings.read('permalinks')
]).then(function (result) {
var options = {};
if (pageParam) { options.page = pageParam; }
if (isTag()) { options.tag = slugParam; }
if (isAuthor()) { options.author = slugParam; }
@ -436,16 +433,14 @@ frontendControllers = {
options.include = 'author,tags,fields';
return api.posts.browse(options).then(function (page) {
var title = result[0].value.settings[0].value,
description = result[1].value.settings[0].value,
permalinks = result[2].value.settings[0],
var title = result[0].settings[0].value,
description = result[1].settings[0].value,
permalinks = result[2].settings[0],
majorMinor = /^(\d+\.)?(\d+)/,
trimmedVersion = res.locals.version,
siteUrl = config.urlFor('home', {secure: req.secure}, true),
feedUrl = config.urlFor('rss', {secure: req.secure}, true),
maxPage = page.meta.pagination.pages,
feedItems = [],
feed;
trimmedVersion = trimmedVersion ? trimmedVersion.match(majorMinor)[0] : '?';
@ -482,8 +477,7 @@ frontendControllers = {
filters.doFilter('prePostsRender', page.posts).then(function (posts) {
posts.forEach(function (post) {
var deferred = when.defer(),
item = {
var item = {
title: post.title,
guid: post.uuid,
url: config.urlFor('post', {post: post, permalinks: permalinks}, true),
@ -499,25 +493,23 @@ frontendControllers = {
p1 = url.resolve(siteUrl, p1);
return "src='" + p1 + "' ";
});
//set a href to absolute url
content = content.replace(/href=["|'|\s]?([\w\/\?\$\.\+\-;%:@&=,_]+)["|'|\s]?/gi, function (match, p1) {
/*jslint unparam:true*/
p1 = url.resolve(siteUrl, p1);
return "href='" + p1 + "' ";
});
item.description = content;
feed.item(item);
feedItems.push(deferred.promise);
deferred.resolve();
});
});
when.all(feedItems).then(function () {
}).then(function () {
res.set('Content-Type', 'text/xml; charset=UTF-8');
res.send(feed.xml());
});
});
}).otherwise(handleError(next));
}).catch(handleError(next));
}
};

View File

@ -1,6 +1,5 @@
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
versioning = require('../versioning'),
config = require('../../config'),
utils = require('../utils'),
@ -28,7 +27,7 @@ exportFileName = function () {
};
exporter = function () {
return when.join(versioning.getDatabaseVersion(), utils.getTables()).then(function (results) {
return Promise.join(versioning.getDatabaseVersion(), utils.getTables()).then(function (results) {
var version = results[0],
tables = results[1],
selectOps = _.map(tables, function (name) {
@ -37,7 +36,7 @@ exporter = function () {
}
});
return when.all(selectOps).then(function (tableData) {
return Promise.all(selectOps).then(function (tableData) {
var exportData = {
meta: {
exported_on: new Date().getTime(),
@ -52,7 +51,7 @@ exporter = function () {
exportData.data[name] = tableData[i];
});
return when.resolve(exportData);
return exportData;
}).catch(function (err) {
errors.logAndThrowError(err, 'Error exporting data', '');
});

View File

@ -5,8 +5,8 @@
// rather than abstracted into a migration system. The upgrade function checks that its changes are safe before
// making them.
var when = require('when'),
sequence = require('when/sequence'),
var Promise = require('bluebird'),
sequence = require('../../utils/sequence'),
_ = require('lodash'),
errors = require('../../errors'),
utils = require('../../utils'),
@ -101,7 +101,7 @@ populate = function () {
});
});
return when.all(ops).then(function () {
return Promise.all(ops).then(function () {
return sequence(relations);
}).then(function () {
return permissions.populate(options);
@ -150,7 +150,7 @@ to003 = function () {
});
ops.push(upgradeOp);
return when.all(ops).then(function () {
return Promise.all(ops).then(function () {
return permissions.to003(options);
}).then(function () {
return convertAdminToOwner();

View File

@ -1,7 +1,7 @@
// # Permissions Fixtures
// Sets up the permissions, and the default permissions_roles relationships
var when = require('when'),
sequence = require('when/sequence'),
var Promise = require('bluebird'),
sequence = require('../../../utils/sequence'),
_ = require('lodash'),
errors = require('../../../errors'),
models = require('../../../models'),
@ -52,7 +52,7 @@ addAllRolesPermissions = function () {
ops.push(addRolesPermissionsForRole(roleName));
});
return when.all(ops);
return Promise.all(ops);
};
@ -100,7 +100,7 @@ to003 = function (options) {
});
// Now we can perfom the normal populate
return when.all(ops).then(function () {
return Promise.all(ops).then(function () {
return populate(options);
});
};

View File

@ -1,4 +1,4 @@
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
models = require('../../models'),
utils = require('./utils'),
@ -23,17 +23,15 @@ Importer000.prototype.importData = function (data) {
return this.canImport(data)
.then(function (importerFunc) {
return importerFunc(data);
}, function (reason) {
return when.reject(reason);
});
};
Importer000.prototype.canImport = function (data) {
if (data.meta && data.meta.version && this.importFrom[data.meta.version]) {
return when.resolve(this.importFrom[data.meta.version]);
return Promise.resolve(this.importFrom[data.meta.version]);
}
return when.reject('Unsupported version of data: ' + data.meta.version);
return Promise.reject('Unsupported version of data: ' + data.meta.version);
};
@ -49,10 +47,10 @@ Importer000.prototype.loadUsers = function () {
});
if (!users.owner) {
return when.reject('Unable to find an owner');
return Promise.reject('Unable to find an owner');
}
return when.resolve(users);
return users;
});
};
@ -72,12 +70,12 @@ Importer000.prototype.doUserImport = function (t, tableData, users, errors) {
// Import users, deduplicating with already present users
userOps = utils.importUsers(tableData.users, users, t);
return when.settle(userOps).then(function (descriptors) {
return Promise.settle(userOps).then(function (descriptors) {
descriptors.forEach(function (d) {
if (d.state === 'rejected') {
errors = errors.concat(d.reason);
if (d.isRejected()) {
errors = errors.concat(d.reason());
} else {
imported.push(d.value.toJSON());
imported.push(d.value().toJSON());
}
});
@ -85,12 +83,12 @@ Importer000.prototype.doUserImport = function (t, tableData, users, errors) {
if (errors.length > 0) {
t.rollback(errors);
} else {
return when.resolve(imported);
return imported;
}
});
}
return when.resolve({});
return Promise.resolve({});
};
Importer000.prototype.doImport = function (data) {
@ -149,13 +147,12 @@ Importer000.prototype.doImport = function (data) {
*/
// Write changes to DB, if successful commit, otherwise rollback
// when.all() does not work as expected, when.settle() does.
when.settle(ops).then(function (descriptors) {
Promise.settle(ops).then(function (descriptors) {
var errors = [];
descriptors.forEach(function (d) {
if (d.state === 'rejected') {
errors = errors.concat(d.reason);
if (d.isRejected()) {
errors = errors.concat(d.reason());
}
});
@ -168,9 +165,7 @@ Importer000.prototype.doImport = function (data) {
});
}).then(function () {
//TODO: could return statistics of imported items
return when.resolve();
}, function (error) {
return when.reject(error);
return Promise.resolve();
});
});
};

View File

@ -1,4 +1,4 @@
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
validation = require('../validation'),
errors = require('../../errors'),
@ -43,7 +43,7 @@ handleErrors = function handleErrors(errorList) {
var processedErrors = [];
if (!_.isArray(errorList)) {
return when.reject(errorList);
return Promise.reject(errorList);
}
_.each(errorList, function (error) {
@ -57,7 +57,7 @@ handleErrors = function handleErrors(errorList) {
}
});
return when.reject(processedErrors);
return Promise.reject(processedErrors);
};
validate = function validate(data) {
@ -69,20 +69,18 @@ validate = function validate(data) {
});
});
return when.settle(validateOps).then(function (descriptors) {
return Promise.settle(validateOps).then(function (descriptors) {
var errorList = [];
_.each(descriptors, function (d) {
if (d.state === 'rejected') {
errorList = errorList.concat(d.reason);
if (d.isRejected()) {
errorList = errorList.concat(d.reason());
}
});
if (!_.isEmpty(errorList)) {
return when.reject(errorList);
return Promise.reject(errorList);
}
return when.resolve();
});
};
@ -97,7 +95,7 @@ module.exports = function (version, data) {
}
if (!importer) {
return when.reject('No importer found');
return Promise.reject('No importer found');
}
return importer.importData(data);

View File

@ -1,4 +1,4 @@
var when = require('when'),
var Promise = require('bluebird'),
_ = require('lodash'),
models = require('../../models'),
errors = require('../../errors'),
@ -162,10 +162,11 @@ utils = {
return models.Tag.add(tag, _.extend(internal, {transacting: transaction}))
// add pass-through error handling so that bluebird doesn't think we've dropped it
.catch(function (error) {
return when.reject({raw: error, model: 'tag', data: tag});
return Promise.reject({raw: error, model: 'tag', data: tag});
});
}
return when.resolve(_tag);
return _tag;
}));
});
},
@ -180,7 +181,7 @@ utils = {
ops.push(models.Post.add(post, _.extend(internal, {transacting: transaction, importing: true}))
// add pass-through error handling so that bluebird doesn't think we've dropped it
.catch(function (error) {
return when.reject({raw: error, model: 'post', data: post});
return Promise.reject({raw: error, model: 'post', data: post});
}));
});
},
@ -207,7 +208,7 @@ utils = {
ops.push(models.User.add(user, _.extend(internal, {transacting: transaction}))
// add pass-through error handling so that bluebird doesn't think we've dropped it
.catch(function (error) {
return when.reject({raw: error, model: 'user', data: user});
return Promise.reject({raw: error, model: 'user', data: user});
}));
});
@ -233,7 +234,7 @@ utils = {
ops.push(models.Settings.edit(tableData, _.extend(internal, {transacting: transaction}))
// add pass-through error handling so that bluebird doesn't think we've dropped it
.catch(function (error) {
return when.reject({raw: error, model: 'setting', data: tableData});
return Promise.reject({raw: error, model: 'setting', data: tableData});
}));
},
@ -247,10 +248,11 @@ utils = {
return models.App.add(app, _.extend(internal, {transacting: transaction}))
// add pass-through error handling so that bluebird doesn't think we've dropped it
.catch(function (error) {
return when.reject({raw: error, model: 'app', data: app});
return Promise.reject({raw: error, model: 'app', data: app});
});
}
return when.resolve(_app);
return _app;
}));
});
}

View File

@ -1,11 +1,9 @@
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
sequence = require('../../utils/sequence'),
path = require('path'),
fs = require('fs'),
nodefn = require('when/node'),
errors = require('../../errors'),
sequence = require('when/sequence'),
commands = require('./commands'),
versioning = require('../versioning'),
models = require('../../models'),
@ -47,7 +45,7 @@ backupDatabase = function backupDatabase() {
return dataExport.fileName().then(function (fileName) {
fileName = path.resolve(config.paths.contentPath + '/data/' + fileName);
return nodefn.call(fs.writeFile, fileName, JSON.stringify(exportedData)).then(function () {
return Promise.promisify(fs.writeFile)(fileName, JSON.stringify(exportedData)).then(function () {
logInfo('Database backup written to: ' + fileName);
});
});
@ -80,7 +78,7 @@ init = function (tablesOnly) {
if (databaseVersion === defaultVersion) {
// 1. The database exists and is up-to-date
logInfo('Up to date at version ' + databaseVersion);
return when.resolve();
return;
}
if (databaseVersion > defaultVersion) {
@ -155,7 +153,7 @@ migrateUp = function (fromVersion, toVersion) {
}).then(function () {
migrateOps = migrateOps.concat(commands.getDeleteCommands(oldTables, schemaTables));
migrateOps = migrateOps.concat(commands.getAddCommands(oldTables, schemaTables));
return when.all(
return Promise.all(
_.map(oldTables, function (table) {
return utils.getIndexes(table).then(function (indexes) {
modifyUniCommands = modifyUniCommands.concat(commands.modifyUniqueCommands(table, indexes));
@ -163,7 +161,7 @@ migrateUp = function (fromVersion, toVersion) {
})
);
}).then(function () {
return when.all(
return Promise.all(
_.map(oldTables, function (table) {
return utils.getColumns(table).then(function (columns) {
migrateOps = migrateOps.concat(commands.addColumnCommands(table, columns));
@ -177,9 +175,9 @@ migrateUp = function (fromVersion, toVersion) {
// execute the commands in sequence
if (!_.isEmpty(migrateOps)) {
logInfo('Running migrations');
return sequence(migrateOps);
}
return;
}).then(function () {
return fixtures.update(fromVersion, toVersion);
}).then(function () {

View File

@ -1,5 +1,4 @@
var _ = require('lodash'),
when = require('when'),
config = require('../../../config/index'),
//private
@ -43,9 +42,7 @@ checkPostTable = function checkPostTable() {
return config.database.knex.raw('SHOW FIELDS FROM posts where Field ="html" OR Field = "markdown"').then(function (response) {
return _.flatten(_.map(response[0], function (entry) {
if (entry.Type.toLowerCase() !== 'mediumtext') {
return config.database.knex.raw('ALTER TABLE posts MODIFY ' + entry.Field + ' MEDIUMTEXT').then(function () {
return when.resolve();
});
return config.database.knex.raw('ALTER TABLE posts MODIFY ' + entry.Field + ' MEDIUMTEXT');
}
}));
});

View File

@ -1,5 +1,5 @@
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
config = require('../../config'),
schema = require('../schema').tables,
clients = require('./clients'),
@ -87,7 +87,7 @@ function getTables() {
return clients[client].getTables();
}
return when.reject('No support for database client ' + client);
return Promise.reject('No support for database client ' + client);
}
function getIndexes(table) {
@ -98,7 +98,7 @@ function getIndexes(table) {
return clients[client].getIndexes(table);
}
return when.reject('No support for database client ' + client);
return Promise.reject('No support for database client ' + client);
}
function getColumns(table) {
@ -109,7 +109,7 @@ function getColumns(table) {
return clients[client].getColumns(table);
}
return when.reject('No support for database client ' + client);
return Promise.reject('No support for database client ' + client);
}
function checkTables() {

View File

@ -1,7 +1,7 @@
var schema = require('../schema').tables,
_ = require('lodash'),
validator = require('validator'),
when = require('when'),
Promise = require('bluebird'),
errors = require('../../errors'),
config = require('../../config'),
requireTree = require('../../require-tree').readAll,
@ -73,10 +73,10 @@ validateSchema = function (tableName, model) {
});
if (validationErrors.length !== 0) {
return when.reject(validationErrors);
return Promise.reject(validationErrors);
}
return when.resolve();
return Promise.resolve();
};
// Validation for settings
@ -92,10 +92,10 @@ validateSettings = function (defaultSettings, model) {
}
if (validationErrors.length !== 0) {
return when.reject(validationErrors);
return Promise.reject(validationErrors);
}
return when.resolve();
return Promise.resolve();
};
// A Promise that will resolve to an object with a property for each installed theme.
@ -107,15 +107,13 @@ validateActiveTheme = function (themeName) {
// If Ghost is running and its availableThemes collection exists
// give it priority.
if (config.paths.availableThemes && Object.keys(config.paths.availableThemes).length > 0) {
availableThemes = when(config.paths.availableThemes);
availableThemes = Promise.resolve(config.paths.availableThemes);
}
return availableThemes.then(function (themes) {
if (!themes.hasOwnProperty(themeName)) {
return when.reject(new errors.ValidationError(themeName + ' cannot be activated because it is not currently installed.', 'activeTheme'));
return Promise.reject(new errors.ValidationError(themeName + ' cannot be activated because it is not currently installed.', 'activeTheme'));
}
return when.resolve();
});
};

View File

@ -3,7 +3,7 @@ var _ = require('lodash'),
colors = require('colors'),
config = require('../config'),
path = require('path'),
when = require('when'),
Promise = require('bluebird'),
hbs = require('express-hbs'),
NotFoundError = require('./notfounderror'),
BadRequestError = require('./badrequesterror'),
@ -47,7 +47,7 @@ errors = {
// ## Reject Error
// Used to pass through promise errors when we want to handle them at a later time
rejectError: function (err) {
return when.reject(err);
return Promise.reject(err);
},
logInfo: function (component, info) {

View File

@ -1,10 +1,8 @@
var when = require('when'),
var Promise = require('bluebird'),
pipeline = require('./utils/pipeline'),
_ = require('lodash'),
defaults;
when.pipeline = require('when/pipeline');
// ## Default values
/**
* A hash of default values to use instead of 'magic' numbers/strings.
@ -64,7 +62,7 @@ Filters.prototype.doFilter = function (name, args, context) {
// Bug out early if no callbacks by that name
if (!callbacks) {
return when.resolve(args);
return Promise.resolve(args);
}
// For each priorityLevel
@ -75,7 +73,7 @@ Filters.prototype.doFilter = function (name, args, context) {
// Bug out if no handlers on this priority
if (!_.isArray(callbacks[priority])) {
return when.resolve(currentArgs);
return Promise.resolve(currentArgs);
}
callables = _.map(callbacks[priority], function (callback) {
@ -84,11 +82,11 @@ Filters.prototype.doFilter = function (name, args, context) {
};
});
// Call each handler for this priority level, allowing for promises or values
return when.pipeline(callables, currentArgs);
return pipeline(callables, currentArgs);
});
});
return when.pipeline(priorityCallbacks, args);
return pipeline(priorityCallbacks, args);
};
module.exports = new Filters();

View File

@ -2,8 +2,7 @@ var downsize = require('downsize'),
hbs = require('express-hbs'),
moment = require('moment'),
_ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
api = require('../api'),
config = require('../config'),
errors = require('../errors'),
@ -147,15 +146,15 @@ coreHelpers.url = function (options) {
}
if (schema.isTag(this)) {
return when(config.urlFor('tag', {tag: this}, absolute));
return Promise.resolve(config.urlFor('tag', {tag: this}, absolute));
}
if (schema.isUser(this)) {
return when(config.urlFor('author', {author: this}, absolute));
return Promise.resolve(config.urlFor('author', {author: this}, absolute));
}
return when(config.urlFor(this, absolute));
return Promise.resolve(config.urlFor(this, absolute));
};
// ### Asset helper
@ -786,9 +785,9 @@ function registerAsyncHelper(hbs, name, fn) {
hbs.registerAsyncHelper(name, function (options, cb) {
// Wrap the function passed in with a when.resolve so it can
// return either a promise or a value
when.resolve(fn.call(this, options)).then(function (result) {
Promise.resolve(fn.call(this, options)).then(function (result) {
cb(result);
}).otherwise(function (err) {
}).catch(function (err) {
errors.logAndThrowError(err, 'registerAsyncThemeHelper: ' + name);
});
});

View File

@ -6,7 +6,7 @@ var crypto = require('crypto'),
fs = require('fs'),
uuid = require('node-uuid'),
_ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
api = require('./api'),
config = require('./config'),
@ -24,13 +24,6 @@ var crypto = require('crypto'),
// Variables
dbHash;
// If we're in development mode, require "when/console/monitor"
// for help in seeing swallowed promise errors, and log any
// stderr messages from bluebird promises.
if (process.env.NODE_ENV === 'development') {
require('when/monitor/console');
}
function doFirstRun() {
var firstRunMessage = [
'Welcome to Ghost.',
@ -80,30 +73,29 @@ function builtFilesExist() {
helpers.scriptFiles.production : helpers.scriptFiles.development;
function checkExist(fileName) {
var deferred = when.defer(),
errorMessage = "Javascript files have not been built.",
var errorMessage = "Javascript files have not been built.",
errorHelp = "\nPlease read the getting started instructions at:" +
"\nhttps://github.com/TryGhost/Ghost#getting-started-guide-for-developers";
return new Promise(function (resolve, reject) {
fs.exists(fileName, function (exists) {
if (exists) {
deferred.resolve(true);
resolve(true);
} else {
var err = new Error(errorMessage);
err.help = errorHelp;
deferred.reject(err);
reject(err);
}
});
return deferred.promise;
});
}
fileNames.forEach(function (fileName) {
deferreds.push(checkExist(location + fileName));
});
return when.all(deferreds);
return Promise.all(deferreds);
}
// This is run after every initialization is done, right before starting server.
@ -174,7 +166,7 @@ function init(server) {
// into this method due to circular dependencies.
return config.theme.update(api.settings, config.url);
}).then(function () {
return when.join(
return Promise.join(
// Check for or initialise a dbHash.
initDbHashAndFirstRun(),
// Initialize mail
@ -219,7 +211,6 @@ function init(server) {
errors.logWarn(warn.message, warn.context, warn.help);
});
return new GhostServer(server);
});
}

View File

@ -1,7 +1,6 @@
var cp = require('child_process'),
_ = require('lodash'),
when = require('when'),
nodefn = require('when/node'),
Promise = require('bluebird'),
nodemailer = require('nodemailer'),
config = require('./config');
@ -17,7 +16,7 @@ GhostMailer.prototype.init = function () {
self.state = {};
if (config.mail && config.mail.transport) {
this.createTransport();
return when.resolve();
return Promise.resolve();
}
// Attempt to detect and fallback to `sendmail`
@ -26,11 +25,9 @@ GhostMailer.prototype.init = function () {
path: binpath
});
self.state.usingSendmail = true;
}, function () {
}).catch(function () {
self.state.emailDisabled = true;
self.transport = null;
}).ensure(function () {
return when.resolve();
});
};
@ -40,13 +37,15 @@ GhostMailer.prototype.isWindows = function () {
GhostMailer.prototype.detectSendmail = function () {
if (this.isWindows()) {
return when.reject();
return Promise.reject();
}
return when.promise(function (resolve, reject) {
return new Promise(function (resolve, reject) {
cp.exec('which sendmail', function (err, stdout) {
if (err && !/bin\/sendmail/.test(stdout)) {
return reject();
}
resolve(stdout.toString().replace(/(\n|\r|\r\n)$/, ''));
});
});
@ -63,7 +62,7 @@ GhostMailer.prototype.fromAddress = function () {
if (!from) {
// Extract the domain name from url set in config.js
domain = config.url.match(new RegExp("^https?://([^/:?#]+)(?:[/:?#]|$)", "i"));
domain = config.url.match(new RegExp('^https?://([^/:?#]+)(?:[/:?#]|$)', 'i'));
domain = domain && domain[1];
// Default to ghost@[blog.url]
@ -84,12 +83,12 @@ GhostMailer.prototype.send = function (message) {
to = message.to || false;
if (!this.transport) {
return when.reject(new Error('Email Error: No e-mail transport configured.'));
return Promise.reject(new Error('Email Error: No e-mail transport configured.'));
}
if (!(message && message.subject && message.html && message.to)) {
return when.reject(new Error('Email Error: Incomplete message data.'));
return Promise.reject(new Error('Email Error: Incomplete message data.'));
}
sendMail = nodefn.lift(self.transport.sendMail.bind(self.transport));
sendMail = Promise.promisify(self.transport.sendMail.bind(self.transport));
message = _.extend(message, {
from: self.fromAddress(),

View File

@ -130,7 +130,7 @@ function updateActiveTheme(req, res, next) {
}
}
next();
}).otherwise(function (err) {
}).catch(function (err) {
// Trying to start up without the active theme present, setup a simple hbs instance
// and render an error page straight away.
expressServer.engine('hbs', hbs.express3());
@ -147,7 +147,7 @@ function redirectToSetup(req, res, next) {
return res.redirect(config.paths.subdir + '/ghost/setup/');
}
next();
}).otherwise(function (err) {
}).catch(function (err) {
return next(new Error(err));
});
}

View File

@ -6,7 +6,7 @@
// accesses the models directly. All other parts of Ghost, including the blog frontend, admin UI, and apps are only
// allowed to access data via the API.
var bookshelf = require('bookshelf'),
when = require('when'),
Promise = require('bluebird'),
moment = require('moment'),
_ = require('lodash'),
uuid = require('node-uuid'),
@ -55,7 +55,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
this.on('creating', this.creating, this);
this.on('saving', function (model, attributes, options) {
return when(self.saving(model, attributes, options)).then(function () {
return Promise.resolve(self.saving(model, attributes, options)).then(function () {
return self.validate(model, attributes, options);
});
});
@ -327,7 +327,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
var trimSpace;
if (!found) {
return when.resolve(slugToFind);
return slugToFind;
}
slugTryCount += 1;

View File

@ -1,5 +1,5 @@
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
requireTree = require('../require-tree'),
models;
@ -48,12 +48,12 @@ models = {
var self = this;
return self.Post.findAll().then(function (posts) {
return when.all(_.map(posts.toJSON(), function (post) {
return Promise.all(_.map(posts.toJSON(), function (post) {
return self.Post.destroy({id: post.id});
}));
}).then(function () {
return self.Tag.findAll().then(function (tags) {
return when.all(_.map(tags.toJSON(), function (tag) {
return Promise.all(_.map(tags.toJSON(), function (tag) {
return self.Tag.destroy({id: tag.id});
}));
});

View File

@ -1,7 +1,7 @@
// # Post Model
var _ = require('lodash'),
uuid = require('node-uuid'),
when = require('when'),
Promise = require('bluebird'),
errors = require('../errors'),
Showdown = require('showdown'),
ghostgfm = require('../../shared/lib/showdown/extensions/ghostgfm'),
@ -123,7 +123,7 @@ Post = ghostBookshelf.Model.extend({
tagOps.push(post.tags().detach(null, _.omit(options, 'query')));
if (_.isEmpty(self.myTags)) {
return when.all(tagOps);
return Promise.all(tagOps);
}
return ghostBookshelf.collection('Tags').forge().query('whereIn', 'name', _.pluck(self.myTags, 'name')).fetch(options).then(function (existingTags) {
@ -157,7 +157,7 @@ Post = ghostBookshelf.Model.extend({
tagOps.push(post.tags().attach(tag.id, _.omit(options, 'query')));
});
return when.all(tagOps);
return Promise.all(tagOps);
});
});
},
@ -341,7 +341,7 @@ Post = ghostBookshelf.Model.extend({
return false;
}
return when.join(fetchTagQuery(), fetchAuthorQuery())
return Promise.join(fetchTagQuery(), fetchAuthorQuery())
// Set the limit & offset for the query, fetching
// with the opts (to specify any eager relations, etc.)
@ -536,16 +536,16 @@ Post = ghostBookshelf.Model.extend({
options = this.filterOptions(options, 'destroyByAuthor');
if (authorId) {
return postCollection.query('where', 'author_id', '=', authorId).fetch(options).then(function (results) {
return when.map(results.models, function (post) {
return Promise.map(results.models, function (post) {
return post.related('tags').detach(null, options).then(function () {
return post.destroy(options);
});
});
}, function (error) {
return when.reject(new errors.InternalServerError(error.message || error));
return Promise.reject(new errors.InternalServerError(error.message || error));
});
}
return when.reject(new errors.NotFoundError('No user found'));
return Promise.reject(new errors.NotFoundError('No user found'));
},
@ -574,10 +574,10 @@ Post = ghostBookshelf.Model.extend({
}
if (hasUserPermission && hasAppPermission) {
return when.resolve();
return Promise.resolve();
}
return when.reject();
return Promise.reject();
}
});

View File

@ -1,7 +1,7 @@
var _ = require('lodash'),
errors = require('../errors'),
ghostBookshelf = require('./base'),
when = require('when'),
Promise = require('bluebird'),
Role,
Roles;
@ -73,9 +73,10 @@ Role = ghostBookshelf.Model.extend({
}
if (hasUserPermission && hasAppPermission) {
return when.resolve();
return Promise.resolve();
}
return when.reject();
return Promise.reject();
}
});

View File

@ -3,7 +3,7 @@ var Settings,
uuid = require('node-uuid'),
_ = require('lodash'),
errors = require('../errors'),
when = require('when'),
Promise = require('bluebird'),
validation = require('../data/validation'),
internal = {context: {internal: true}},
@ -64,7 +64,7 @@ Settings = ghostBookshelf.Model.extend({
var themeName = setting.value || '';
if (setting.key !== 'activeTheme') {
return when.resolve();
return;
}
return validation.validateActiveTheme(themeName);
@ -87,7 +87,7 @@ Settings = ghostBookshelf.Model.extend({
if (!_.isObject(options)) {
options = { key: options };
}
return when(ghostBookshelf.Model.findOne.call(this, options));
return Promise.resolve(ghostBookshelf.Model.findOne.call(this, options));
},
edit: function (data, options) {
@ -98,11 +98,11 @@ Settings = ghostBookshelf.Model.extend({
data = [data];
}
return when.map(data, function (item) {
return Promise.map(data, function (item) {
// Accept an array of models as input
if (item.toJSON) { item = item.toJSON(); }
if (!(_.isString(item.key) && item.key.length > 0)) {
return when.reject(new errors.ValidationError('Value in [settings.key] cannot be blank.'));
return Promise.reject(new errors.ValidationError('Value in [settings.key] cannot be blank.'));
}
item = self.filterData(item);
@ -113,7 +113,7 @@ Settings = ghostBookshelf.Model.extend({
return setting.save({value: item.value}, options);
}
return when.reject(new errors.NotFoundError('Unable to find setting to update: ' + item.key));
return Promise.reject(new errors.NotFoundError('Unable to find setting to update: ' + item.key));
}, errors.logAndThrowError);
});
@ -121,7 +121,7 @@ Settings = ghostBookshelf.Model.extend({
populateDefault: function (key) {
if (!getDefaultSettings()[key]) {
return when.reject(new errors.NotFoundError('Unable to find default setting: ' + key));
return Promise.reject(new errors.NotFoundError('Unable to find default setting: ' + key));
}
return this.findOne({ key: key }).then(function (foundSetting) {
@ -153,7 +153,7 @@ Settings = ghostBookshelf.Model.extend({
}
});
return when.all(insertOperations);
return Promise.all(insertOperations);
});
}

View File

@ -1,7 +1,6 @@
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
errors = require('../errors'),
nodefn = require('when/node'),
bcrypt = require('bcryptjs'),
ghostBookshelf = require('./base'),
http = require('http'),
@ -9,6 +8,10 @@ var _ = require('lodash'),
validator = require('validator'),
validation = require('../data/validation'),
bcryptGenSalt = Promise.promisify(bcrypt.genSalt),
bcryptHash = Promise.promisify(bcrypt.hash),
bcryptCompare = Promise.promisify(bcrypt.compare),
tokenSecurity = {},
activeStates = ['active', 'warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked'],
invitedStates = ['invited', 'invited-pending'],
@ -21,16 +24,16 @@ function validatePasswordLength(password) {
throw new Error('Your password must be at least 8 characters long.');
}
} catch (error) {
return when.reject(error);
return Promise.reject(error);
}
return when.resolve();
return Promise.resolve();
}
function generatePasswordHash(password) {
// Generate a new salt
return nodefn.call(bcrypt.genSalt).then(function (salt) {
return bcryptGenSalt().then(function (salt) {
// Hash the provided password with bcrypt
return nodefn.call(bcrypt.hash, password, salt);
return bcryptHash(password, salt);
});
}
@ -239,7 +242,7 @@ User = ghostBookshelf.Model.extend({
return false;
}
return when(fetchRoleQuery())
return Promise.resolve(fetchRoleQuery())
.then(function () {
if (roleInstance) {
@ -394,7 +397,7 @@ User = ghostBookshelf.Model.extend({
roleId = parseInt(data.roles[0].id || data.roles[0], 10);
if (data.roles.length > 1) {
return when.reject(
return Promise.reject(
new errors.ValidationError('Only one role per user is supported at the moment.')
);
}
@ -407,7 +410,7 @@ User = ghostBookshelf.Model.extend({
return ghostBookshelf.model('Role').findOne({id: roleId});
}).then(function (roleToAssign) {
if (roleToAssign && roleToAssign.get('name') === 'Owner') {
return when.reject(
return Promise.reject(
new errors.ValidationError('This method does not support assigning the owner role')
);
} else {
@ -447,7 +450,7 @@ User = ghostBookshelf.Model.extend({
// check for too many roles
if (roles.length > 1) {
return when.reject(new errors.ValidationError('Only one role per user is supported at the moment.'));
return Promise.reject(new errors.ValidationError('Only one role per user is supported at the moment.'));
}
// remove roles from the object
delete data.roles;
@ -552,7 +555,7 @@ User = ghostBookshelf.Model.extend({
if (action === 'destroy') {
// Owner cannot be deleted EVER
if (userModel.hasRole('Owner')) {
return when.reject();
return Promise.reject();
}
// Users with the role 'Editor' have complex permissions when the action === 'destroy'
@ -566,10 +569,10 @@ User = ghostBookshelf.Model.extend({
}
if (hasUserPermission && hasAppPermission) {
return when.resolve();
return Promise.resolve();
}
return when.reject();
return Promise.reject();
},
setWarning: function (user, options) {
@ -588,7 +591,7 @@ User = ghostBookshelf.Model.extend({
user.set('status', 'warn-' + level);
}
}
return when(user.save(options)).then(function () {
return Promise.resolve(user.save(options)).then(function () {
return 5 - level;
});
},
@ -599,19 +602,19 @@ User = ghostBookshelf.Model.extend({
s;
return this.getByEmail(object.email).then(function (user) {
if (!user) {
return when.reject(new errors.NotFoundError('There is no user with that email address.'));
return Promise.reject(new errors.NotFoundError('There is no user with that email address.'));
}
if (user.get('status') === 'invited' || user.get('status') === 'invited-pending' ||
user.get('status') === 'inactive'
) {
return when.reject(new Error('The user with that email address is inactive.'));
return Promise.reject(new Error('The user with that email address is inactive.'));
}
if (user.get('status') !== 'locked') {
return nodefn.call(bcrypt.compare, object.password, user.get('password')).then(function (matched) {
return bcryptCompare(object.password, user.get('password')).then(function (matched) {
if (!matched) {
return when(self.setWarning(user, {validate: false})).then(function (remaining) {
return Promise.resolve(self.setWarning(user, {validate: false})).then(function (remaining) {
s = (remaining > 1) ? 's' : '';
return when.reject(new errors.UnauthorizedError('Your password is incorrect.<br>' +
return Promise.reject(new errors.UnauthorizedError('Your password is incorrect.<br>' +
remaining + ' attempt' + s + ' remaining!'));
// Use comma structure, not .catch, because we don't want to catch incorrect passwords
@ -624,11 +627,11 @@ User = ghostBookshelf.Model.extend({
'Error thrown from user update during login',
'Visit and save your profile after logging in to check for problems.'
);
return when.reject(new errors.UnauthorizedError('Your password is incorrect.'));
return Promise.reject(new errors.UnauthorizedError('Your password is incorrect.'));
});
}
return when(user.set({status : 'active', last_login : new Date()}).save({validate: false}))
return Promise.resolve(user.set({status : 'active', last_login : new Date()}).save({validate: false}))
.catch(function (error) {
// If we get a validation or other error during this save, catch it and log it, but don't
// cause a login error because of it. The user validation is not important here.
@ -641,16 +644,16 @@ User = ghostBookshelf.Model.extend({
});
}, errors.logAndThrowError);
}
return when.reject(new errors.NoPermissionError('Your account is locked due to too many ' +
return Promise.reject(new errors.NoPermissionError('Your account is locked due to too many ' +
'login attempts. Please reset your password to log in again by clicking ' +
'the "Forgotten password?" link!'));
}, function (error) {
if (error.message === 'NotFound' || error.message === 'EmptyResponse') {
return when.reject(new errors.NotFoundError('There is no user with that email address.'));
return Promise.reject(new errors.NotFoundError('There is no user with that email address.'));
}
return when.reject(error);
return Promise.reject(error);
});
},
@ -664,21 +667,21 @@ User = ghostBookshelf.Model.extend({
user = null;
if (newPassword !== ne2Password) {
return when.reject(new Error('Your new passwords do not match'));
return Promise.reject(new Error('Your new passwords do not match'));
}
return validatePasswordLength(newPassword).then(function () {
return self.forge({id: userid}).fetch({require: true});
}).then(function (_user) {
user = _user;
return nodefn.call(bcrypt.compare, oldPassword, user.get('password'));
return bcryptCompare(oldPassword, user.get('password'));
}).then(function (matched) {
if (!matched) {
return when.reject(new Error('Your password is incorrect'));
return Promise.reject(new Error('Your password is incorrect'));
}
return nodefn.call(bcrypt.genSalt);
return bcryptGenSalt();
}).then(function (salt) {
return nodefn.call(bcrypt.hash, newPassword, salt);
return bcryptHash(newPassword, salt);
}).then(function (hash) {
user.save({password: hash});
return user;
@ -688,7 +691,7 @@ User = ghostBookshelf.Model.extend({
generateResetToken: function (email, expires, dbHash) {
return this.getByEmail(email).then(function (foundUser) {
if (!foundUser) {
return when.reject(new errors.NotFoundError('There is no user with that email address.'));
return Promise.reject(new errors.NotFoundError('There is no user with that email address.'));
}
var hash = crypto.createHash('sha256'),
@ -720,25 +723,25 @@ User = ghostBookshelf.Model.extend({
// Check if invalid structure
if (!parts || parts.length !== 3) {
return when.reject(new Error('Invalid token structure'));
return Promise.reject(new Error('Invalid token structure'));
}
expires = parseInt(parts[0], 10);
email = parts[1];
if (isNaN(expires)) {
return when.reject(new Error('Invalid token expiration'));
return Promise.reject(new Error('Invalid token expiration'));
}
// Check if token is expired to prevent replay attacks
if (expires < Date.now()) {
return when.reject(new Error('Expired token'));
return Promise.reject(new Error('Expired token'));
}
// to prevent brute force attempts to reset the password the combination of email+expires is only allowed for
// 10 attempts
if (tokenSecurity[email + '+' + expires] && tokenSecurity[email + '+' + expires].count >= 10) {
return when.reject(new Error('Token locked'));
return Promise.reject(new Error('Token locked'));
}
return this.generateResetToken(email, expires, dbHash).then(function (generatedToken) {
@ -756,14 +759,14 @@ User = ghostBookshelf.Model.extend({
}
if (diff === 0) {
return when.resolve(email);
return email;
}
// increase the count for email+expires for each failed attempt
tokenSecurity[email + '+' + expires] = {
count: tokenSecurity[email + '+' + expires] ? tokenSecurity[email + '+' + expires].count + 1 : 1
};
return when.reject(new Error('Invalid token'));
return Promise.reject(new Error('Invalid token'));
});
},
@ -771,7 +774,7 @@ User = ghostBookshelf.Model.extend({
var self = this;
if (newPassword !== ne2Password) {
return when.reject(new Error('Your new passwords do not match'));
return Promise.reject(new Error('Your new passwords do not match'));
}
return validatePasswordLength(newPassword).then(function () {
@ -779,7 +782,7 @@ User = ghostBookshelf.Model.extend({
return self.validateToken(token, dbHash);
}).then(function (email) {
// Fetch the user by email, and hash the password at the same time.
return when.join(
return Promise.join(
self.forge({email: email.toLocaleLowerCase()}).fetch({require: true}),
generatePasswordHash(newPassword)
);
@ -809,7 +812,7 @@ User = ghostBookshelf.Model.extend({
// check if user has the owner role
var currentRoles = ctxUser.toJSON().roles;
if (!_.contains(currentRoles, ownerRole.id)) {
return when.reject(new errors.NoPermissionError('Only owners are able to transfer the owner role.'));
return Promise.reject(new errors.NoPermissionError('Only owners are able to transfer the owner role.'));
}
contextUser = ctxUser;
return User.findOne({id: object.id});
@ -817,7 +820,7 @@ User = ghostBookshelf.Model.extend({
var currentRoles = user.toJSON().roles;
if (!_.contains(currentRoles, adminRole.id)) {
return when.reject(new errors.ValidationError('Only administrators can be assigned the owner role.'));
return Promise.reject(new errors.ValidationError('Only administrators can be assigned the owner role.'));
}
assignUser = user;
@ -838,20 +841,20 @@ User = ghostBookshelf.Model.extend({
gravatarLookup: function (userData) {
var gravatarUrl = '//www.gravatar.com/avatar/' +
crypto.createHash('md5').update(userData.email.toLowerCase().trim()).digest('hex') +
'?d=404&s=250',
checkPromise = when.defer();
'?d=404&s=250';
return new Promise(function (resolve) {
http.get('http:' + gravatarUrl, function (res) {
if (res.statusCode !== 404) {
userData.image = gravatarUrl;
}
checkPromise.resolve(userData);
resolve(userData);
}).on('error', function () {
//Error making request just continue.
checkPromise.resolve(userData);
resolve(userData);
});
});
return checkPromise.promise;
},
// Get the user by email address, enforces case insensitivity rejects if the user is not found
// When multi-user support is added, email addresses must be deduplicated with case insensitivity, so that
@ -869,7 +872,7 @@ User = ghostBookshelf.Model.extend({
return user.get('email').toLowerCase() === email.toLowerCase();
});
if (userWithEmail) {
return when.resolve(userWithEmail);
return userWithEmail;
}
});
}

View File

@ -2,7 +2,7 @@
// canThis(someUser).edit.post(somePost|somePostId)
var _ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
Models = require('../models'),
effectivePerms = require('./effective'),
init,
@ -65,7 +65,7 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type,
// If it's an internal request, resolve immediately
if (context.internal) {
return when.resolve();
return Promise.resolve();
}
if (_.isNumber(modelOrId) || _.isString(modelOrId)) {
@ -127,9 +127,10 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type,
}
if (hasUserPermission && hasAppPermission) {
return when.resolve();
return;
}
return when.reject();
return Promise.reject();
});
};
@ -155,7 +156,7 @@ CanThisResult.prototype.beginCheck = function (context) {
userPermissionLoad = effectivePerms.user(context.user);
} else {
// Resolve null if no context.user to prevent db call
userPermissionLoad = when.resolve(null);
userPermissionLoad = Promise.resolve(null);
}
@ -164,11 +165,11 @@ CanThisResult.prototype.beginCheck = function (context) {
appPermissionLoad = effectivePerms.app(context.app);
} else {
// Resolve null if no context.app
appPermissionLoad = when.resolve(null);
appPermissionLoad = Promise.resolve(null);
}
// Wait for both user and app permissions to load
permissionsLoad = when.all([userPermissionLoad, appPermissionLoad]).then(function (result) {
permissionsLoad = Promise.all([userPermissionLoad, appPermissionLoad]).then(function (result) {
return {
user: result[0],
app: result[1]
@ -232,7 +233,7 @@ init = refresh = function () {
seenActions[action_type][object_type] = true;
});
return when(exported.actionsMap);
return exported.actionsMap;
});
};

View File

@ -1,8 +1,10 @@
var _ = require('lodash'),
fs = require('fs'),
keys = require('when/keys'),
path = require('path'),
when = require('when'),
Promise = require('bluebird'),
readdirAsync = Promise.promisify(fs.readdir),
lstatAsync = Promise.promisify(fs.lstat),
parsePackageJson = function (path, messages) {
// Default the messages if non were passed
messages = messages || {
@ -10,30 +12,29 @@ var _ = require('lodash'),
warns: []
};
var packageDeferred = when.defer(),
packagePromise = packageDeferred.promise,
jsonContainer;
var jsonContainer;
return new Promise(function (resolve) {
fs.readFile(path, function (error, data) {
if (error) {
messages.errors.push({
message: 'Could not read package.json file',
context: path
});
packageDeferred.resolve(false);
resolve(false);
return;
}
try {
jsonContainer = JSON.parse(data);
if (jsonContainer.hasOwnProperty('name') && jsonContainer.hasOwnProperty('version')) {
packageDeferred.resolve(jsonContainer);
resolve(jsonContainer);
} else {
messages.errors.push({
message: '"name" or "version" is missing from theme package.json file.',
context: path,
help: 'This will be required in future. Please see http://docs.ghost.org/themes/'
});
packageDeferred.resolve(false);
resolve(false);
}
} catch (e) {
messages.errors.push({
@ -41,11 +42,12 @@ var _ = require('lodash'),
context: path,
help: 'This will be required in future. Please see http://docs.ghost.org/themes/'
});
packageDeferred.resolve(false);
resolve(false);
}
});
return when(packagePromise);
});
},
readDir = function (dir, options, depth, messages) {
depth = depth || 0;
messages = messages || {
@ -58,44 +60,29 @@ var _ = require('lodash'),
}, options);
if (depth > 1) {
return null;
}
var subtree = {},
treeDeferred = when.defer(),
treePromise = treeDeferred.promise;
fs.readdir(dir, function (error, files) {
if (error) {
return treeDeferred.reject(error);
return Promise.resolve(null);
}
return readdirAsync(dir).then(function (files) {
files = files || [];
files.forEach(function (file) {
var fileDeferred = when.defer(),
filePromise = fileDeferred.promise,
fpath = path.join(dir, file);
subtree[file] = filePromise;
fs.lstat(fpath, function (error, result) {
/*jslint unparam:true*/
return Promise.reduce(files, function (results, file) {
var fpath = path.join(dir, file);
return lstatAsync(fpath).then(function (result) {
if (result.isDirectory()) {
fileDeferred.resolve(readDir(fpath, options, depth + 1, messages));
return readDir(fpath, options, depth + 1, messages);
} else if (depth === 1 && file === 'package.json') {
fileDeferred.resolve(parsePackageJson(fpath, messages));
return parsePackageJson(fpath, messages);
} else {
fileDeferred.resolve(fpath);
return fpath;
}
});
});
}).then(function (result) {
results[file] = result;
return keys.all(subtree).then(function (theFiles) {
return treeDeferred.resolve(theFiles);
return results;
});
});
return when(treePromise).then(function (prom) {
return prom;
}, {});
});
},
readAll = function (dir, options, depth) {
@ -105,7 +92,7 @@ var _ = require('lodash'),
warns: []
};
return when(readDir(dir, options, depth, messages)).then(function (paths) {
return readDir(dir, options, depth, messages).then(function (paths) {
// for all contents of the dir, I'm interested in the ones that are directories and within /theme/
if (typeof paths === 'object' && dir.indexOf('theme') !== -1) {
_.each(paths, function (path, index) {
@ -118,9 +105,11 @@ var _ = require('lodash'),
}
});
}
paths._messages = messages;
return paths;
}).otherwise(function () {
}).catch(function () {
return {'_messages': messages};
});
};

View File

@ -1,6 +1,6 @@
var moment = require('moment'),
path = require('path'),
when = require('when'),
Promise = require('bluebird'),
baseStore;
// TODO: would probably be better to put these on the prototype and have proper constructors etc
@ -34,18 +34,18 @@ baseStore = {
self.generateUnique(store, dir, name, ext, i, done);
});
} else {
done.resolve(filename);
done(filename);
}
});
},
'getUniqueFileName': function (store, image, targetDir) {
var done = when.defer(),
ext = path.extname(image.name),
name = path.basename(image.name, ext).replace(/[\W]/gi, '-');
var ext = path.extname(image.name),
name = path.basename(image.name, ext).replace(/[\W]/gi, '-'),
self = this;
this.generateUnique(store, targetDir, name, ext, 0, done);
return done.promise;
return new Promise(function (resolve) {
self.generateUnique(store, targetDir, name, ext, 0, resolve);
});
}
};

View File

@ -4,9 +4,8 @@
var _ = require('lodash'),
express = require('express'),
fs = require('fs-extra'),
nodefn = require('when/node'),
path = require('path'),
when = require('when'),
Promise = require('bluebird'),
errors = require('../errors'),
config = require('../config'),
utils = require('../utils'),
@ -20,37 +19,31 @@ localFileStore = _.extend(baseStore, {
// - image is the express image object
// - returns a promise which ultimately returns the full url to the uploaded image
'save': function (image) {
var saved = when.defer(),
targetDir = this.getTargetDir(config.paths.imagesPath),
var targetDir = this.getTargetDir(config.paths.imagesPath),
targetFilename;
this.getUniqueFileName(this, image, targetDir).then(function (filename) {
return this.getUniqueFileName(this, image, targetDir).then(function (filename) {
targetFilename = filename;
return nodefn.call(fs.mkdirs, targetDir);
return Promise.promisify(fs.mkdirs)(targetDir);
}).then(function () {
return nodefn.call(fs.copy, image.path, targetFilename);
return Promise.promisify(fs.copy)(image.path, targetFilename);
}).then(function () {
// The src for the image must be in URI format, not a file system path, which in Windows uses \
// For local file system storage can use relative path so add a slash
var fullUrl = (config.paths.subdir + '/' + config.paths.imagesRelPath + '/' + path.relative(config.paths.imagesPath, targetFilename)).replace(new RegExp('\\' + path.sep, 'g'), '/');
return saved.resolve(fullUrl);
}).otherwise(function (e) {
return fullUrl;
}).catch(function (e) {
errors.logError(e);
return saved.reject(e);
return Promise.reject(e);
});
return saved.promise;
},
'exists': function (filename) {
// fs.exists does not play nicely with nodefn because the callback doesn't have an error argument
var done = when.defer();
return new Promise(function (resolve) {
fs.exists(filename, function (exists) {
done.resolve(exists);
resolve(exists);
});
});
return done.promise;
},
// middleware for serving the files

View File

@ -23,8 +23,7 @@ var crypto = require('crypto'),
https = require('https'),
moment = require('moment'),
semver = require('semver'),
when = require('when'),
nodefn = require('when/node'),
Promise = require('bluebird'),
_ = require('lodash'),
url = require('url'),
@ -51,8 +50,8 @@ function updateCheckData() {
ops = [],
mailConfig = config.mail;
ops.push(api.settings.read(_.extend(internal, {key: 'dbHash'})).otherwise(errors.rejectError));
ops.push(api.settings.read(_.extend(internal, {key: 'activeTheme'})).otherwise(errors.rejectError));
ops.push(api.settings.read(_.extend(internal, {key: 'dbHash'})).catch(errors.rejectError));
ops.push(api.settings.read(_.extend(internal, {key: 'activeTheme'})).catch(errors.rejectError));
ops.push(api.settings.read(_.extend(internal, {key: 'activeApps'}))
.then(function (response) {
var apps = response.settings[0];
@ -63,10 +62,10 @@ function updateCheckData() {
}
return _.reduce(apps, function (memo, item) { return memo === '' ? memo + item : memo + ', ' + item; }, '');
}).otherwise(errors.rejectError));
ops.push(api.posts.browse().otherwise(errors.rejectError));
ops.push(api.users.browse(internal).otherwise(errors.rejectError));
ops.push(nodefn.call(exec, 'npm -v').otherwise(errors.rejectError));
}).catch(errors.rejectError));
ops.push(api.posts.browse().catch(errors.rejectError));
ops.push(api.users.browse(internal).catch(errors.rejectError));
ops.push(Promise.promisify(exec)('npm -v').catch(errors.rejectError));
data.ghost_version = currentVersion;
data.node_version = process.versions.node;
@ -74,13 +73,13 @@ function updateCheckData() {
data.database_type = config.database.client;
data.email_transport = mailConfig && (mailConfig.options && mailConfig.options.service ? mailConfig.options.service : mailConfig.transport);
return when.settle(ops).then(function (descriptors) {
var hash = descriptors[0].value.settings[0],
theme = descriptors[1].value.settings[0],
apps = descriptors[2].value,
posts = descriptors[3].value,
users = descriptors[4].value,
npm = descriptors[5].value,
return Promise.settle(ops).then(function (descriptors) {
var hash = descriptors[0].value().settings[0],
theme = descriptors[1].value().settings[0],
apps = descriptors[2].value(),
posts = descriptors[3].value(),
users = descriptors[4].value(),
npm = descriptors[5].value(),
blogUrl = url.parse(config.url),
blogId = blogUrl.hostname + blogUrl.pathname.replace(/\//, '') + hash.value;
@ -93,13 +92,12 @@ function updateCheckData() {
data.npm_version = _.isArray(npm) && npm[0] ? npm[0].toString().replace(/\n/, '') : '';
return data;
}).otherwise(updateCheckError);
}).catch(updateCheckError);
}
function updateCheckRequest() {
return updateCheckData().then(function (reqData) {
var deferred = when.defer(),
resData = '',
var resData = '',
headers,
req;
@ -109,19 +107,20 @@ function updateCheckRequest() {
'Content-Length': reqData.length
};
return new Promise(function (resolve, reject) {
req = https.request({
hostname: checkEndpoint,
method: 'POST',
headers: headers
}, function (res) {
res.on('error', function (error) { deferred.reject(error); });
res.on('error', function (error) { reject(error); });
res.on('data', function (chunk) { resData += chunk; });
res.on('end', function () {
try {
resData = JSON.parse(resData);
deferred.resolve(resData);
resolve(resData);
} catch (e) {
deferred.reject('Unable to decode update response');
reject('Unable to decode update response');
}
});
});
@ -130,10 +129,9 @@ function updateCheckRequest() {
req.end();
req.on('error', function (error) {
deferred.reject(error);
reject(error);
});
});
return deferred.promise;
});
}
@ -149,53 +147,45 @@ function updateCheckResponse(response) {
api.settings.edit(
{settings: [{key: 'nextUpdateCheck', value: response.next_check}]},
internal
)
.otherwise(errors.rejectError),
).catch(errors.rejectError),
api.settings.edit(
{settings: [{key: 'displayUpdateNotification', value: response.version}]},
internal
)
.otherwise(errors.rejectError)
).catch(errors.rejectError)
);
return when.settle(ops).then(function (descriptors) {
return Promise.settle(ops).then(function (descriptors) {
descriptors.forEach(function (d) {
if (d.state === 'rejected') {
errors.rejectError(d.reason);
if (d.isRejected()) {
errors.rejectError(d.reason());
}
});
return when.resolve();
});
}
function updateCheck() {
var deferred = when.defer();
// The check will not happen if:
// 1. updateCheck is defined as false in config.js
// 2. we've already done a check this session
// 3. we're not in production or development mode
if (config.updateCheck === false || _.indexOf(allowedCheckEnvironments, process.env.NODE_ENV) === -1) {
// No update check
deferred.resolve();
return Promise.resolve();
} else {
api.settings.read(_.extend(internal, {key: 'nextUpdateCheck'})).then(function (result) {
return api.settings.read(_.extend(internal, {key: 'nextUpdateCheck'})).then(function (result) {
var nextUpdateCheck = result.settings[0];
if (nextUpdateCheck && nextUpdateCheck.value && nextUpdateCheck.value > moment().unix()) {
// It's not time to check yet
deferred.resolve();
return;
} else {
// We need to do a check
return updateCheckRequest()
.then(updateCheckResponse)
.otherwise(updateCheckError);
.catch(updateCheckError);
}
}).otherwise(updateCheckError)
.then(deferred.resolve);
}).catch(updateCheckError);
}
return deferred.promise;
}
function showUpdateNotification() {
@ -210,9 +200,10 @@ function showUpdateNotification() {
}
if (display && display.value && currentVersion && semver.gt(display.value, currentVersion)) {
return when(display.value);
return display.value;
}
return when(false);
return false;
});
}

View File

@ -0,0 +1,21 @@
var Promise = require('bluebird');
function pipeline(tasks /* initial arguments */) {
var args = Array.prototype.slice.call(arguments, 1),
runTask = function (task, args) {
runTask = function (task, arg) {
return task(arg);
};
return task.apply(null, args);
};
return Promise.all(tasks).reduce(function (arg, task) {
return Promise.resolve(runTask(task, arg)).then(function (result) {
return result;
});
}, args);
}
module.exports = pipeline;

View File

@ -0,0 +1,13 @@
var Promise = require('bluebird');
function sequence(tasks) {
return Promise.reduce(tasks, function (results, task) {
return task().then(function (result) {
results.push(result);
return results;
});
}, []);
}
module.exports = sequence;

View File

@ -62,7 +62,7 @@ describe('Admin Routing', function () {
}).then(function () {
done();
}).catch(done);
}).otherwise(function (e) {
}).catch(function (e) {
console.log('Ghost Error: ', e);
console.log(e.stack);
});
@ -332,7 +332,7 @@ describe('Admin Routing', function () {
// });
// }).catch(done);
// }).otherwise(function (e) {
// }).catch(function (e) {
// console.log('Ghost Error: ', e);
// console.log(e.stack);
// });

View File

@ -334,7 +334,8 @@ describe('User API', function () {
var jsonResponse = res.body,
changedValue = 'joe-bloggs.ghost.org';
jsonResponse.users[0].should.exist;
should.exist(jsonResponse.users[0]);
jsonResponse.users[0].website = changedValue;
request.put(testUtils.API.getApiQuery('users/me/'))

View File

@ -2,7 +2,7 @@
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
when = require('when'),
Promise = require('bluebird'),
rewire = require('rewire'),
// Stuff we are testing
@ -43,7 +43,7 @@ describe('Authentication API', function () {
send = mail.__get__('mail.send');
mail.__set__('mail.send', function () {
return when.resolve();
return Promise.resolve();
});
AuthAPI.setup({ setup: [setupData] }).then(function (result) {

View File

@ -5,7 +5,7 @@ var _ = require('lodash'),
rewire = require('rewire'),
should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
// Stuff we are testing
SettingsAPI = require('../../../server/api/settings'),
@ -30,11 +30,11 @@ describe('Themes API', function () {
beforeEach(function () {
// Override settings.read for activeTheme
sandbox.stub(SettingsAPI, 'read', function () {
return when({ settings: [{value: 'casper'}] });
return Promise.resolve({ settings: [{value: 'casper'}] });
});
sandbox.stub(SettingsAPI, 'edit', function () {
return when({ settings: [{value: 'rasper'}] });
return Promise.resolve({ settings: [{value: 'rasper'}] });
});
configStub = {

View File

@ -3,7 +3,7 @@
var fs = require('fs-extra'),
should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
storage = require('../../../server/storage'),
// Stuff we are testing
@ -23,9 +23,9 @@ describe('Upload API', function () {
beforeEach(function () {
store = sinon.stub();
store.save = sinon.stub().returns(when('URL'));
store.exists = sinon.stub().returns(when(true));
store.destroy = sinon.stub().returns(when());
store.save = sinon.stub().returns(Promise.resolve('URL'));
store.exists = sinon.stub().returns(Promise.resolve(true));
store.destroy = sinon.stub().returns(Promise.resolve());
sinon.stub(storage, 'get_storage').returns(store);
sinon.stub(fs, 'unlink').yields();
});

View File

@ -3,7 +3,7 @@
var testUtils = require('../../utils'),
should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
_ = require('lodash'),
// Stuff we are testing
@ -340,11 +340,11 @@ describe('Users API', function () {
newUser = _.clone(testUtils.DataGenerator.forKnex.createUser(testUtils.DataGenerator.Content.users[4]));
sandbox.stub(ModelUser.User, 'gravatarLookup', function (userData) {
return when.resolve(userData);
return Promise.resolve(userData);
});
sandbox.stub(mail, 'send', function () {
return when.resolve();
return Promise.resolve();
});
});
afterEach(function () {
@ -934,7 +934,7 @@ describe('Users API', function () {
]}, _.extend({}, context.editor, {id: userIdFor.author}, {include: 'roles'})
).then(function (response) {
done(new Error('Editor should not be able to upgrade the role of authors'));
}, function (error) {
}).catch(function (error) {
error.type.should.eql('NoPermissionError');
done();
}).catch(done);

View File

@ -3,7 +3,7 @@
var testUtils = require('../utils/index'),
should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
_ = require('lodash'),
// Stuff we are testing
@ -25,7 +25,7 @@ describe('Exporter', function () {
it('exports data', function (done) {
// Stub migrations to return 000 as the current database version
var versioningStub = sandbox.stub(versioning, 'getDatabaseVersion', function () {
return when.resolve('003');
return Promise.resolve('003');
});
exporter().then(function (exportData) {

View File

@ -3,7 +3,7 @@
var testUtils = require('../utils/index'),
should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
assert = require('assert'),
_ = require('lodash'),
rewire = require('rewire'),
@ -48,7 +48,7 @@ describe('Import', function () {
it('resolves 000', function (done) {
var importStub = sandbox.stub(Importer000, 'importData', function () {
return when.resolve();
return Promise.resolve();
}),
fakeData = { test: true };
@ -63,7 +63,7 @@ describe('Import', function () {
it('resolves 001', function (done) {
var importStub = sandbox.stub(Importer001, 'importData', function () {
return when.resolve();
return Promise.resolve();
}),
fakeData = { test: true };
@ -78,7 +78,7 @@ describe('Import', function () {
it('resolves 002', function (done) {
var importStub = sandbox.stub(Importer002, 'importData', function () {
return when.resolve();
return Promise.resolve();
}),
fakeData = { test: true };
@ -93,7 +93,7 @@ describe('Import', function () {
it('resolves 003', function (done) {
var importStub = sandbox.stub(Importer003, 'importData', function () {
return when.resolve();
return Promise.resolve();
}),
fakeData = { test: true };
@ -118,7 +118,7 @@ describe('Import', function () {
it('imports data from 000', function (done) {
var exportData,
versioningStub = sandbox.stub(versioning, 'getDatabaseVersion', function () {
return when.resolve('000');
return Promise.resolve('000');
});
testUtils.fixtures.loadExportFixture('export-000').then(function (exported) {
@ -127,7 +127,7 @@ describe('Import', function () {
return importer('000', exportData);
}).then(function () {
// Grab the data from tables
return when.all([
return Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
@ -186,7 +186,7 @@ describe('Import', function () {
return importer('001', exportData);
}).then(function () {
// Grab the data from tables
return when.all([
return Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
@ -261,7 +261,7 @@ describe('Import', function () {
error[0].message.should.eql('Value in [posts.title] exceeds maximum length of 150 characters.');
error[0].type.should.eql('ValidationError');
when.all([
Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
@ -310,7 +310,7 @@ describe('Import', function () {
error[0].message.should.eql('Value in [settings.key] cannot be blank.');
error[0].type.should.eql('ValidationError');
when.all([
Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
@ -367,7 +367,7 @@ describe('Import', function () {
return importer('002', exportData);
}).then(function () {
// Grab the data from tables
return when.all([
return Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
@ -443,7 +443,7 @@ describe('Import', function () {
error[0].message.should.eql('Value in [posts.title] exceeds maximum length of 150 characters.');
error[0].type.should.eql('ValidationError');
when.all([
Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
@ -489,7 +489,7 @@ describe('Import', function () {
error[0].message.should.eql('Value in [settings.key] cannot be blank.');
error[0].type.should.eql('ValidationError');
when.all([
Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
@ -537,7 +537,7 @@ describe('Import', function () {
return importer('003', exportData);
}).then(function () {
// Grab the data from tables
return when.all([
return Promise.all([
knex('users').select(),
knex('posts').select(),
knex('settings').select(),
@ -704,7 +704,7 @@ describe('Import (new test structure)', function () {
after(testUtils.teardown);
it('gets the right data', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('posts').select(),
knex('settings').select(),
knex('tags').select()
@ -755,7 +755,7 @@ describe('Import (new test structure)', function () {
});
it('imports users with correct roles and status', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('users').select(),
knex('roles_users').select()
);
@ -829,7 +829,7 @@ describe('Import (new test structure)', function () {
});
it('imports posts & tags with correct authors, owners etc', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('users').select(),
knex('posts').select(),
knex('tags').select()
@ -931,7 +931,7 @@ describe('Import (new test structure)', function () {
after(testUtils.teardown);
it('gets the right data', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('posts').select(),
knex('settings').select(),
knex('tags').select()
@ -982,7 +982,7 @@ describe('Import (new test structure)', function () {
});
it('imports users with correct roles and status', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('users').select(),
knex('roles_users').select()
);
@ -1056,7 +1056,7 @@ describe('Import (new test structure)', function () {
});
it('imports posts & tags with correct authors, owners etc', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('users').select(),
knex('posts').select(),
knex('tags').select()
@ -1159,7 +1159,7 @@ describe('Import (new test structure)', function () {
after(testUtils.teardown);
it('gets the right data', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('posts').select(),
knex('settings').select(),
knex('tags').select()
@ -1221,7 +1221,7 @@ describe('Import (new test structure)', function () {
});
it('imports users with correct roles and status', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('users').select(),
knex('roles_users').select()
);
@ -1290,7 +1290,7 @@ describe('Import (new test structure)', function () {
});
it('imports posts & tags with correct authors, owners etc', function (done) {
var fetchImported = when.join(
var fetchImported = Promise.join(
knex('users').select(),
knex('posts').select(),
knex('tags').select()

View File

@ -2,7 +2,8 @@
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
sequence = require('when/sequence'),
Promise = require('bluebird'),
sequence = require('../../../server/utils/sequence'),
_ = require('lodash'),
// Stuff we are testing

View File

@ -2,7 +2,8 @@
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
sequence = require('when/sequence'),
Promise = require('bluebird'),
sequence = require('../../../server/utils/sequence'),
_ = require('lodash'),
// Stuff we are testing
@ -541,6 +542,6 @@ describe('Post Model', function () {
// }).then(function (saved) {
// saved.get('title').should.eql("&lt;/title&gt;&lt;/head>&lt;body&gt;[removed]alert&#40;'blogtitle'&#41;;[removed]");
// done();
// }).otherwise(done);
// }).catch(done);
// });
});

View File

@ -2,7 +2,7 @@
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
when = require('when'),
Promise = require('bluebird'),
_ = require('lodash'),
// Stuff we are testing
@ -44,7 +44,7 @@ describe('Tag Model', function () {
newTag = testUtils.DataGenerator.forModel.tags[0],
createdPostID;
when.all([
Promise.all([
PostModel.add(newPost, context),
TagModel.add(newTag, context)
]).then(function (models) {
@ -71,7 +71,7 @@ describe('Tag Model', function () {
createdTagID,
createdPostID;
when.all([
Promise.all([
PostModel.add(newPost, context),
TagModel.add(newTag, context)
]).then(function (models) {
@ -106,7 +106,7 @@ describe('Tag Model', function () {
var tagModels = tagNames.map(function (tagName) { return TagModel.add({name: tagName}, context); });
createOperations = createOperations.concat(tagModels);
return when.all(createOperations).then(function (models) {
return Promise.all(createOperations).then(function (models) {
var postModel = models[0],
attachOperations;
@ -115,7 +115,7 @@ describe('Tag Model', function () {
attachOperations.push(postModel.tags().attach(models[i]));
}
return when.all(attachOperations).then(function () {
return Promise.all(attachOperations).then(function () {
return postModel;
});
}).then(function (postModel) {

View File

@ -2,7 +2,7 @@
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
when = require('when'),
Promise = require('bluebird'),
sinon = require('sinon'),
uuid = require('node-uuid'),
_ = require('lodash'),
@ -33,7 +33,7 @@ describe('User Model', function run() {
var userData = testUtils.DataGenerator.forModel.users[0];
sandbox.stub(UserModel, 'gravatarLookup', function (userData) {
return when.resolve(userData);
return Promise.resolve(userData);
});
UserModel.add(userData, context).then(function (createdUser) {
@ -50,7 +50,7 @@ describe('User Model', function run() {
var userData = testUtils.DataGenerator.forModel.users[2];
sandbox.stub(UserModel, 'gravatarLookup', function (userData) {
return when.resolve(userData);
return Promise.resolve(userData);
});
UserModel.add(userData, context).then(function (createdUser) {
@ -66,7 +66,7 @@ describe('User Model', function run() {
sandbox.stub(UserModel, 'gravatarLookup', function (userData) {
userData.image = 'http://www.gravatar.com/avatar/2fab21a4c4ed88e76add10650c73bae1?d=404';
return when.resolve(userData);
return Promise.resolve(userData);
});
UserModel.add(userData, context).then(function (createdUser) {
@ -83,7 +83,7 @@ describe('User Model', function run() {
var userData = testUtils.DataGenerator.forModel.users[0];
sandbox.stub(UserModel, 'gravatarLookup', function (userData) {
return when.resolve(userData);
return Promise.resolve(userData);
});
UserModel.add(userData, context).then(function (createdUser) {
@ -271,7 +271,7 @@ describe('User Model', function run() {
var userData = testUtils.DataGenerator.forModel.users[4];
sandbox.stub(UserModel, 'gravatarLookup', function (userData) {
return when.resolve(userData);
return Promise.resolve(userData);
});
RoleModel.findOne().then(function (role) {

View File

@ -5,7 +5,7 @@ var path = require('path'),
should = require('should'),
sinon = require('sinon'),
_ = require('lodash'),
when = require('when'),
Promise = require('bluebird'),
helpers = require('../../server/helpers'),
filters = require('../../server/filters'),
@ -432,7 +432,7 @@ describe('Apps', function () {
var perms = new AppPermissions("test");
// No package.json in this directory
sandbox.stub(perms, "checkPackageContentsExists").returns(when.resolve(false));
sandbox.stub(perms, "checkPackageContentsExists").returns(Promise.resolve(false));
perms.read().then(function (readPerms) {
should.exist(readPerms);
@ -447,9 +447,9 @@ describe('Apps', function () {
noGhostPackageJsonContents = JSON.stringify(noGhostPackageJson, null, 2);
// package.json IS in this directory
sandbox.stub(perms, "checkPackageContentsExists").returns(when.resolve(true));
sandbox.stub(perms, "checkPackageContentsExists").returns(Promise.resolve(true));
// no ghost property on package
sandbox.stub(perms, "getPackageContents").returns(when.resolve(noGhostPackageJsonContents));
sandbox.stub(perms, "getPackageContents").returns(Promise.resolve(noGhostPackageJsonContents));
perms.read().then(function (readPerms) {
should.exist(readPerms);
@ -463,9 +463,9 @@ describe('Apps', function () {
var perms = new AppPermissions("test");
// package.json IS in this directory
sandbox.stub(perms, "checkPackageContentsExists").returns(when.resolve(true));
sandbox.stub(perms, "checkPackageContentsExists").returns(Promise.resolve(true));
// malformed JSON on package
sandbox.stub(perms, "getPackageContents").returns(when.reject(new Error('package.json file is malformed')));
sandbox.stub(perms, "getPackageContents").returns(Promise.reject(new Error('package.json file is malformed')));
perms.read().then(function (readPerms) {
/*jshint unused:false*/
@ -480,9 +480,9 @@ describe('Apps', function () {
validGhostPackageJsonContents = validGhostPackageJson;
// package.json IS in this directory
sandbox.stub(perms, "checkPackageContentsExists").returns(when.resolve(true));
sandbox.stub(perms, "checkPackageContentsExists").returns(Promise.resolve(true));
// valid ghost property on package
sandbox.stub(perms, "getPackageContents").returns(when.resolve(validGhostPackageJsonContents));
sandbox.stub(perms, "getPackageContents").returns(Promise.resolve(validGhostPackageJsonContents));
perms.read().then(function (readPerms) {
should.exist(readPerms);

View File

@ -2,7 +2,7 @@
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
path = require('path'),
fs = require('fs'),
_ = require('lodash'),
@ -62,13 +62,10 @@ describe('Bootstrap', function () {
it('creates the config file if one does not exist', function (done) {
var deferred = when.defer(),
// trick bootstrap into thinking that the config file doesn't exist yet
existsStub = sandbox.stub(fs, 'exists', function (file, cb) { return cb(false); }),
var existsStub = sandbox.stub(fs, 'exists', function (file, cb) { return cb(false); }),
// create a method which will return a pre-resolved promise
resolvedPromise = sandbox.stub().returns(deferred.promise);
deferred.resolve();
resolvedPromise = sandbox.stub().returns(Promise.resolve());
// ensure that the file creation is a stub, the tests shouldn't really create a file
bootstrap.__set__('writeConfigFile', resolvedPromise);

View File

@ -2,7 +2,7 @@
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
path = require('path'),
_ = require('lodash'),
rewire = require('rewire'),
@ -32,7 +32,7 @@ describe('Config', function () {
settings = {'read': function read() {}};
settingsStub = sandbox.stub(settings, 'read', function () {
return when({ settings: [{value: 'casper'}] });
return Promise.resolve({ settings: [{value: 'casper'}] });
});
theme.update(settings, 'http://my-ghost-blog.com')
@ -270,7 +270,7 @@ describe('Config', function () {
it('should output correct url for post', function (done) {
var settings = {'read': function read() {}},
settingsStub = sandbox.stub(settings, 'read', function () {
return when({ settings: [{value: '/:slug/'}] });
return Promise.resolve({ settings: [{value: '/:slug/'}] });
}),
/*jshint unused:false*/
testData = testUtils.DataGenerator.Content.posts[2],
@ -308,7 +308,7 @@ describe('Config', function () {
it('should output correct url for post with date permalink', function (done) {
var settings = {'read': function read() {}},
settingsStub = sandbox.stub(settings, 'read', function () {
return when({ settings: [{value: '/:year/:month/:day/:slug/'}] });
return Promise.resolve({ settings: [{value: '/:year/:month/:day/:slug/'}] });
}),
/*jshint unused:false*/
testData = testUtils.DataGenerator.Content.posts[2],
@ -349,7 +349,7 @@ describe('Config', function () {
it('should output correct url for page with date permalink', function (done) {
var settings = {'read': function read() {}},
settingsStub = sandbox.stub(settings, 'read', function () {
return when({ settings: [{value: '/:year/:month/:day/:slug/'}] });
return Promise.resolve({ settings: [{value: '/:year/:month/:day/:slug/'}] });
}),
/*jshint unused:false*/
testData = testUtils.DataGenerator.Content.posts[5],

View File

@ -1,7 +1,7 @@
/*globals describe, after, before, beforeEach, afterEach, it*/
/*jshint expr:true*/
var should = require('should'),
when = require('when'),
Promise = require('bluebird'),
sinon = require('sinon'),
express = require('express'),
rewire = require('rewire'),
@ -181,9 +181,7 @@ describe('Error handling', function () {
});
it('logs promise errors and redirects', function (done) {
var def = when.defer(),
prom = def.promise,
req = null,
var req = null,
res = {
redirect: function () {
return;
@ -192,11 +190,11 @@ describe('Error handling', function () {
redirectStub = sinon.stub(res, 'redirect');
// give environment a value that will console log
prom.then(function () {
Promise.reject().then(function () {
throw new Error('Ran success handler');
}, errors.logErrorWithRedirect('test1', null, null, '/testurl', req, res));
prom.otherwise(function () {
Promise.reject().catch(function () {
logStub.calledWith('\nERROR:'.red, 'test1'.red).should.equal(true);
logStub.restore();
@ -205,7 +203,6 @@ describe('Error handling', function () {
done();
});
def.reject();
});
});

View File

@ -2,7 +2,7 @@
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
_ = require('lodash'),
// Stuff we are testing
@ -85,7 +85,7 @@ describe('Filters', function () {
it('executes filters that return a promise', function (done) {
var filterName = 'testprioritypromise',
testFilterHandler1 = sinon.spy(function (args) {
return when.promise(function (resolve) {
return new Promise(function (resolve) {
process.nextTick(function () {
args.filter1 = true;
@ -99,7 +99,7 @@ describe('Filters', function () {
return args;
}),
testFilterHandler3 = sinon.spy(function (args) {
return when.promise(function (resolve) {
return new Promise(function (resolve) {
process.nextTick(function () {
args.filter3 = true;

View File

@ -4,7 +4,7 @@ var assert = require('assert'),
moment = require('moment'),
should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
rewire = require('rewire'),
_ = require('lodash'),
@ -53,11 +53,11 @@ describe('Frontend Controller', function () {
};
sandbox.stub(api.posts, 'browse', function () {
return when({posts: {}, meta: {pagination: { pages: 3}}});
return Promise.resolve({posts: {}, meta: {pagination: { pages: 3}}});
});
apiSettingsStub = sandbox.stub(api.settings, 'read');
apiSettingsStub.withArgs('postsPerPage').returns(when({
apiSettingsStub.withArgs('postsPerPage').returns(Promise.resolve({
settings: [{
'key': 'postsPerPage',
'value': 5
@ -156,7 +156,7 @@ describe('Frontend Controller', function () {
beforeEach(function () {
sandbox.stub(api.posts, 'browse', function () {
return when({
return Promise.resolve({
posts: [],
meta: {
pagination: {
@ -169,14 +169,14 @@ describe('Frontend Controller', function () {
apiSettingsStub = sandbox.stub(api.settings, 'read');
apiSettingsStub.withArgs(sinon.match.has('key', 'activeTheme')).returns(when({
apiSettingsStub.withArgs(sinon.match.has('key', 'activeTheme')).returns(Promise.resolve({
settings: [{
'key': 'activeTheme',
'value': 'casper'
}]
}));
apiSettingsStub.withArgs('postsPerPage').returns(when({
apiSettingsStub.withArgs('postsPerPage').returns(Promise.resolve({
settings: [{
'key': 'postsPerPage',
'value': '10'
@ -306,7 +306,7 @@ describe('Frontend Controller', function () {
beforeEach(function () {
sandbox.stub(api.posts, 'browse', function () {
return when({
return Promise.resolve({
posts: mockPosts,
meta: {
pagination: {
@ -322,14 +322,14 @@ describe('Frontend Controller', function () {
apiSettingsStub = sandbox.stub(api.settings, 'read');
apiSettingsStub.withArgs(sinon.match.has('key', 'activeTheme')).returns(when({
apiSettingsStub.withArgs(sinon.match.has('key', 'activeTheme')).returns(Promise.resolve({
settings: [{
'key': 'activeTheme',
'value': 'casper'
}]
}));
apiSettingsStub.withArgs('postsPerPage').returns(when({
apiSettingsStub.withArgs('postsPerPage').returns(Promise.resolve({
settings: [{
'key': 'postsPerPage',
'value': '10'
@ -355,7 +355,7 @@ describe('Frontend Controller', function () {
describe('custom tag template', function () {
beforeEach(function () {
apiSettingsStub.withArgs('permalinks').returns(when({
apiSettingsStub.withArgs('permalinks').returns(Promise.resolve({
settings: [{
key: 'permalinks',
value: '/tag/:slug/'
@ -392,11 +392,11 @@ describe('Frontend Controller', function () {
};
sandbox.stub(api.posts, 'browse', function () {
return when({posts: {}, meta: {pagination: { pages: 3}}});
return Promise.resolve({posts: {}, meta: {pagination: { pages: 3}}});
});
apiSettingsStub = sandbox.stub(api.settings, 'read');
apiSettingsStub.withArgs('postsPerPage').returns(when({
apiSettingsStub.withArgs('postsPerPage').returns(Promise.resolve({
settings: [{
'key': 'postsPerPage',
'value': 5
@ -542,14 +542,14 @@ describe('Frontend Controller', function () {
beforeEach(function () {
sandbox.stub(api.posts, 'read', function (args) {
return when(_.find(mockPosts, function(mock) {
return Promise.resolve(_.find(mockPosts, function(mock) {
return mock.posts[0].slug === args.slug;
}));
});
apiSettingsStub = sandbox.stub(api.settings, 'read');
apiSettingsStub.withArgs(sinon.match.has('key', 'activeTheme')).returns(when({
apiSettingsStub.withArgs(sinon.match.has('key', 'activeTheme')).returns(Promise.resolve({
settings: [{
'key': 'activeTheme',
'value': 'casper'
@ -577,7 +577,7 @@ describe('Frontend Controller', function () {
describe('custom page templates', function () {
beforeEach(function () {
apiSettingsStub.withArgs('permalinks').returns(when({
apiSettingsStub.withArgs('permalinks').returns(Promise.resolve({
settings: [{
value: '/:slug/'
}]
@ -602,7 +602,7 @@ describe('Frontend Controller', function () {
describe('permalink set to slug', function () {
beforeEach(function () {
apiSettingsStub.withArgs('permalinks').returns(when({
apiSettingsStub.withArgs('permalinks').returns(Promise.resolve({
settings: [{
value: '/:slug/'
}]
@ -674,7 +674,7 @@ describe('Frontend Controller', function () {
describe('permalink set to date', function () {
beforeEach(function () {
apiSettingsStub.withArgs('permalinks').returns(when({
apiSettingsStub.withArgs('permalinks').returns(Promise.resolve({
settings: [{
value: '/:year/:month/:day/:slug/'
}]
@ -747,7 +747,7 @@ describe('Frontend Controller', function () {
describe('post', function () {
describe('permalink set to slug', function () {
beforeEach(function () {
apiSettingsStub.withArgs('permalinks').returns(when({
apiSettingsStub.withArgs('permalinks').returns(Promise.resolve({
settings: [{
value: '/:slug'
}]
@ -821,7 +821,7 @@ describe('Frontend Controller', function () {
describe('permalink set to date', function () {
beforeEach(function () {
apiSettingsStub.withArgs('permalinks').returns(when({
apiSettingsStub.withArgs('permalinks').returns(Promise.resolve({
settings: [{
value: '/:year/:month/:day/:slug'
}]
@ -912,7 +912,7 @@ describe('Frontend Controller', function () {
describe('permalink set to custom format', function () {
beforeEach(function () {
apiSettingsStub.withArgs('permalinks').returns(when({
apiSettingsStub.withArgs('permalinks').returns(Promise.resolve({
settings: [{
value: '/:year/:slug'
}]
@ -1035,25 +1035,25 @@ describe('Frontend Controller', function () {
};
sandbox.stub(api.posts, 'browse', function () {
return when({posts: {}, meta: {pagination: { pages: 3}}});
return Promise.resolve({posts: {}, meta: {pagination: { pages: 3}}});
});
apiUsersStub = sandbox.stub(api.users, 'read').returns(when({}));
apiUsersStub = sandbox.stub(api.users, 'read').returns(Promise.resolve({}));
apiSettingsStub = sandbox.stub(api.settings, 'read');
apiSettingsStub.withArgs('title').returns(when({
apiSettingsStub.withArgs('title').returns(Promise.resolve({
settings: [{
'key': 'title',
'value': 'Test'
}]
}));
apiSettingsStub.withArgs('description').returns(when({
apiSettingsStub.withArgs('description').returns(Promise.resolve({
settings: [{
'key': 'description',
'value': 'Some Text'
}]
}));
apiSettingsStub.withArgs('permalinks').returns(when({
apiSettingsStub.withArgs('permalinks').returns(Promise.resolve({
settings: [{
'key': 'permalinks',
'value': '/:slug/'

View File

@ -2,7 +2,7 @@
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
_ = require('lodash'),
rewire = require('rewire'),
@ -61,7 +61,7 @@ describe('Mail', function () {
});
sandbox.stub(mailer, 'detectSendmail', function () {
return when.resolve(fakeSendmail);
return Promise.resolve(fakeSendmail);
});
});
@ -119,7 +119,7 @@ describe('Mail', function () {
it('should disable transport if config is empty & sendmail not found', function (done) {
overrideConfig({mail: {}});
mailer.detectSendmail.restore();
sandbox.stub(mailer, 'detectSendmail', when.reject);
sandbox.stub(mailer, 'detectSendmail', Promise.reject);
mailer.init().then(function () {
should.not.exist(mailer.transport);
done();
@ -141,7 +141,7 @@ describe('Mail', function () {
it('should fail to send messages when no transport is set', function (done) {
mailer.detectSendmail.restore();
sandbox.stub(mailer, 'detectSendmail', when.reject);
sandbox.stub(mailer, 'detectSendmail', Promise.reject);
mailer.init().then(function () {
mailer.send().then(function () {
should.fail();
@ -154,15 +154,15 @@ describe('Mail', function () {
});
it('should fail to send messages when given insufficient data', function (done) {
when.settle([
Promise.settle([
mailer.send(),
mailer.send({}),
mailer.send({ subject: '123' }),
mailer.send({ subject: '', html: '123' })
]).then(function (descriptors) {
descriptors.forEach(function (d) {
d.state.should.equal('rejected');
d.reason.should.be.an.instanceOf(Error);
d.isRejected().should.be.true;
d.reason().should.be.an.instanceOf(Error);
});
done();
}).catch(done);

View File

@ -3,7 +3,7 @@
var testUtils = require('../utils'),
should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
_ = require('lodash'),
// Stuff we are testing
@ -31,7 +31,7 @@ describe('Permissions', function () {
});
sandbox.stub(Models.Permission, 'findAll', function () {
return when(Models.Permissions.forge(permissions));
return Promise.resolve(Models.Permissions.forge(permissions));
});
});
@ -112,7 +112,7 @@ describe('Permissions', function () {
// it('can use permissible function on Model to allow something', function (done) {
// var testUser,
// permissibleStub = sandbox.stub(Models.Post, 'permissible', function () {
// return when.resolve();
// return Promise.resolve();
// });
//
// testUtils.insertAuthorUser()
@ -141,7 +141,7 @@ describe('Permissions', function () {
// it('can use permissible function on Model to forbid something', function (done) {
// var testUser,
// permissibleStub = sandbox.stub(Models.Post, 'permissible', function () {
// return when.reject();
// return Promise.reject();
// });
//
// testUtils.insertAuthorUser()
@ -203,7 +203,7 @@ describe('Permissions', function () {
//
// return newPerm.save(null, context).then(function () {
// return foundUser.permissions().attach(newPerm).then(function () {
// return when.all([updatedPost, foundUser]);
// return Promise.all([updatedPost, foundUser]);
// });
// });
// });

View File

@ -2,7 +2,7 @@
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
when = require('when'),
Promise = require('bluebird'),
_ = require('lodash'),
rewire = require('rewire'),
moment = require('moment'),
@ -30,7 +30,7 @@ describe('Core Helpers', function () {
helpers = rewire('../../server/helpers');
sandbox = sinon.sandbox.create();
apiStub = sandbox.stub(api.settings, 'read', function () {
return when({
return Promise.resolve({
settings: [{value: 'casper'}]
});
});
@ -393,7 +393,7 @@ describe('Core Helpers', function () {
});
it('can render class string for context', function (done) {
when.all([
Promise.all([
helpers.body_class.call({relativeUrl: '/'}),
helpers.body_class.call({relativeUrl: '/a-post-title', post: {}}),
helpers.body_class.call({relativeUrl: '/page/4'}),
@ -762,7 +762,7 @@ describe('Core Helpers', function () {
beforeEach(function () {
apiStub.restore();
apiStub = sandbox.stub(api.settings, 'read', function () {
return when({ settings: [{ value: '/:slug/' }] });
return Promise.resolve({ settings: [{ value: '/:slug/' }] });
});
});

View File

@ -5,7 +5,7 @@ var nock = require('nock'),
should = require('should'),
sinon = require('sinon'),
testUtils = require('../utils'),
when = require('when'),
Promise = require('bluebird'),
xmlrpc = require('../../server/xmlrpc'),
// storing current environment
currentEnv = process.env.NODE_ENV;
@ -34,7 +34,7 @@ describe('XMLRPC', function () {
ping2 = nock('http://rpc.pingomatic.com').post('/').reply(200),
testPost = testUtils.DataGenerator.Content.posts[2],
settingsStub = sandbox.stub(settings, 'read', function () {
return when({ settings: [{value: '/:slug/'}] });
return Promise.resolve({ settings: [{value: '/:slug/'}] });
});
/*jshint unused:false */

View File

@ -3,33 +3,39 @@ var cp = require('child_process'),
fs = require('fs'),
url = require('url'),
net = require('net'),
when = require('when'),
Promise = require('bluebird'),
path = require('path'),
config = require('../../server/config');
function findFreePort(port) {
var deferred = when.defer();
return new Promise(function (resolve, reject) {
if (typeof port === 'string') {
port = parseInt(port);
}
if (typeof port !== 'number') {
port = 2368;
}
if (typeof port === 'string') port = parseInt(port);
if (typeof port !== 'number') port = 2368;
port = port + 1;
var server = net.createServer();
server.on('error', function(e) {
if (e.code === 'EADDRINUSE') {
when.chain(findFreePort(port), deferred);
resolve(findFreePort(port));
} else {
deferred.reject(e);
reject(e);
}
});
server.listen(port, function() {
var listenPort = server.address().port;
server.close(function() {
deferred.resolve(listenPort);
resolve(listenPort);
});
});
});
return deferred.promise;
}
// Get a copy of current config object from file, to be modified before
@ -43,17 +49,21 @@ function forkConfig() {
// Creates a new fork of Ghost process with a given config
// Useful for tests that want to verify certain config options
function forkGhost(newConfig, envName) {
var deferred = when.defer();
envName = envName || 'forked';
findFreePort(newConfig.server ? newConfig.server.port : undefined)
return findFreePort(newConfig.server ? newConfig.server.port : undefined)
.then(function(port) {
newConfig.server = newConfig.server || {};
newConfig.server.port = port;
newConfig.url = url.format(_.extend(url.parse(newConfig.url), {port: port, host: null}));
var newConfigFile = path.join(config.paths.appRoot, 'config.test' + port + '.js');
return new Promise(function (resolve, reject) {
fs.writeFile(newConfigFile, 'module.exports = {' + envName + ': ' + JSON.stringify(newConfig) + '}', function(err) {
if (err) throw err;
if (err) {
return reject(err);
}
// setup process environment for the forked Ghost to use the new config file
var env = _.clone(process.env);
@ -77,13 +87,13 @@ function forkGhost(newConfig, envName) {
socket.on('connect', function() {
socket.end();
if (pingStop()) {
deferred.resolve(child);
resolve(child);
}
});
socket.on('error', function(err) {
// continue checking
if (++pingTries >= 20 && pingStop()) {
deferred.reject(new Error("Timed out waiting for child process"));
reject(new Error("Timed out waiting for child process"));
}
});
}, 200);
@ -91,7 +101,7 @@ function forkGhost(newConfig, envName) {
child.on('exit', function(code, signal) {
child.exited = true;
if (pingStop()) {
deferred.reject(new Error("Child process exit code: " + code));
reject(new Error("Child process exit code: " + code));
}
// cleanup the temporary config file
fs.unlink(newConfigFile);
@ -118,10 +128,8 @@ function forkGhost(newConfig, envName) {
}
};
});
})
.otherwise(deferred.reject);
return deferred.promise;
});
});
}
module.exports.ghost = forkGhost;

View File

@ -1,6 +1,5 @@
var when = require('when'),
sequence = require('when/sequence'),
nodefn = require('when/node'),
var Promise = require('bluebird'),
sequence = require('../../server/utils/sequence'),
_ = require('lodash'),
fs = require('fs-extra'),
path = require('path'),
@ -32,7 +31,7 @@ var when = require('when'),
fixtures = {
insertPosts: function insertPosts() {
var knex = config.database.knex;
return when(knex('posts').insert(DataGenerator.forKnex.posts)).then(function () {
return Promise.resolve(knex('posts').insert(DataGenerator.forKnex.posts)).then(function () {
return knex('tags').insert(DataGenerator.forKnex.tags);
}).then(function () {
return knex('posts_tags').insert(DataGenerator.forKnex.posts_tags);
@ -49,7 +48,7 @@ fixtures = {
max = max || 50;
// insert users of different roles
return when(fixtures.createUsersWithRoles()).then(function (results) {
return Promise.resolve(fixtures.createUsersWithRoles()).then(function (results) {
// create the tags
return knex('tags').insert(DataGenerator.forKnex.tags);
}).then(function (results) {
@ -72,7 +71,7 @@ fixtures = {
};
}));
}).then(function () {
return when.all([
return Promise.all([
// PostgreSQL can return results in any order
knex('posts').orderBy('id', 'asc').select('id'),
knex('tags').select('id')
@ -84,7 +83,7 @@ fixtures = {
i;
if (max > posts.length) {
throw new Error('Trying to add more posts_tags than the number of posts.');
throw new Error('Trying to add more posts_tags than the number of posts. ' + max + ' ' + posts.length);
}
for (i = 0; i < max; i += 1) {
@ -133,7 +132,7 @@ fixtures = {
var knex = config.database.knex;
return when.all([
return Promise.all([
// PostgreSQL can return results in any order
knex('posts').orderBy('id', 'asc').select('id'),
knex('tags').select('id', 'name')
@ -268,16 +267,17 @@ fixtures = {
},
loadExportFixture: function loadExportFixture(filename) {
var filepath = path.resolve(__dirname + '/fixtures/' + filename + '.json');
var filepath = path.resolve(__dirname + '/fixtures/' + filename + '.json'),
readFile = Promise.promisify(fs.readFile);
return nodefn.call(fs.readFile, filepath).then(function (fileContents) {
return readFile(filepath).then(function (fileContents) {
var data;
// Parse the json data
try {
data = JSON.parse(fileContents);
} catch (e) {
return when.reject(new Error('Failed to parse the file'));
return new Error('Failed to parse the file');
}
return data;
@ -451,7 +451,6 @@ setup = function setup() {
// TODO make this do the DB init as well
doAuth = function doAuth() {
var options = arguments,
deferred = when.defer(),
request = arguments[0],
user = DataGenerator.forModel.users[0],
fixtureOps;
@ -466,19 +465,19 @@ doAuth = function doAuth() {
fixtureOps = getFixtureOps(options);
sequence(fixtureOps).then(function () {
return new Promise(function (resolve, reject) {
return sequence(fixtureOps).then(function () {
request.post('/ghost/api/v0.1/authentication/token/')
.send({ grant_type: 'password', username: user.email, password: user.password, client_id: 'ghost-admin'})
.end(function (err, res) {
if (err) {
deferred.reject(err);
return reject(err);
}
deferred.resolve(res.body.access_token);
resolve(res.body.access_token);
});
});
});
return deferred.promise;
};
teardown = function teardown(done) {

View File

@ -32,6 +32,7 @@
"engineStrict": true,
"dependencies": {
"bcryptjs": "0.7.10",
"bluebird": "2.3.0",
"body-parser": "1.6.3",
"bookshelf": "0.7.6",
"busboy": "0.2.3",
@ -63,7 +64,6 @@
"static-favicon": "1.0.2",
"unidecode": "0.1.3",
"validator": "3.4.0",
"when": "3.2.3",
"xml": "0.0.12"
},
"optionalDependencies": {