mirror of
https://github.com/TryGhost/Ghost.git
synced 2023-12-13 21:00:40 +01:00
Optimize model class methods
No Issue - Reorder promise chains to defer database queries until they are needed. - Execute database queries that are not dependent on each other in parallel instead of sequentially. - Reduce the number of variables used to hold state across multiple promise blocks. - Do not go async unless necessary.
This commit is contained in:
parent
8ceb896e96
commit
5c6d45f258
3 changed files with 193 additions and 207 deletions
|
@ -340,8 +340,7 @@ Post = ghostBookshelf.Model.extend({
|
|||
findPage: function (options) {
|
||||
options = options || {};
|
||||
|
||||
var postCollection = Posts.forge(),
|
||||
tagInstance = options.tag !== undefined ? ghostBookshelf.model('Tag').forge({slug: options.tag}) : false,
|
||||
var tagInstance = options.tag !== undefined ? ghostBookshelf.model('Tag').forge({slug: options.tag}) : false,
|
||||
authorInstance = options.author !== undefined ? ghostBookshelf.model('User').forge({slug: options.author}) : false;
|
||||
|
||||
if (options.limit && options.limit !== 'all') {
|
||||
|
@ -379,12 +378,6 @@ Post = ghostBookshelf.Model.extend({
|
|||
options.where.status = options.status;
|
||||
}
|
||||
|
||||
// If there are where conditionals specified, add those
|
||||
// to the query.
|
||||
if (options.where) {
|
||||
postCollection.query('where', options.where);
|
||||
}
|
||||
|
||||
// Add related objects
|
||||
options.withRelated = _.union(options.withRelated, options.include);
|
||||
|
||||
|
@ -405,12 +398,21 @@ Post = ghostBookshelf.Model.extend({
|
|||
}
|
||||
|
||||
return Promise.join(fetchTagQuery(), fetchAuthorQuery())
|
||||
|
||||
// Set the limit & offset for the query, fetching
|
||||
// with the opts (to specify any eager relations, etc.)
|
||||
// Omitting the `page`, `limit`, `where` just to be sure
|
||||
// aren't used for other purposes.
|
||||
.then(function () {
|
||||
var postCollection = Posts.forge(),
|
||||
collectionPromise,
|
||||
countPromise,
|
||||
qb;
|
||||
|
||||
// If there are where conditionals specified, add those
|
||||
// to the query.
|
||||
if (options.where) {
|
||||
postCollection.query('where', options.where);
|
||||
}
|
||||
// If we have a tag instance we need to modify our query.
|
||||
// We need to ensure we only select posts that contain
|
||||
// the tag given in the query param.
|
||||
|
@ -431,22 +433,15 @@ Post = ghostBookshelf.Model.extend({
|
|||
.query('offset', options.limit * (options.page - 1));
|
||||
}
|
||||
|
||||
return postCollection
|
||||
collectionPromise = postCollection
|
||||
.query('orderBy', 'status', 'ASC')
|
||||
.query('orderBy', 'published_at', 'DESC')
|
||||
.query('orderBy', 'updated_at', 'DESC')
|
||||
.fetch(_.omit(options, 'page', 'limit'));
|
||||
})
|
||||
|
||||
// Fetch pagination information
|
||||
.then(function () {
|
||||
var qb,
|
||||
tableName = _.result(postCollection, 'tableName'),
|
||||
idAttribute = _.result(postCollection, 'idAttribute');
|
||||
// Find the total number of posts
|
||||
|
||||
// After we're done, we need to figure out what
|
||||
// the limits are for the pagination values.
|
||||
qb = ghostBookshelf.knex(tableName);
|
||||
qb = ghostBookshelf.knex('posts');
|
||||
|
||||
if (options.where) {
|
||||
qb.where(options.where);
|
||||
|
@ -460,13 +455,13 @@ Post = ghostBookshelf.Model.extend({
|
|||
qb.where('author_id', '=', authorInstance.id);
|
||||
}
|
||||
|
||||
return qb.count(tableName + '.' + idAttribute + ' as aggregate');
|
||||
})
|
||||
countPromise = qb.count('posts.id as aggregate');
|
||||
|
||||
// Format response of data
|
||||
.then(function (resp) {
|
||||
var totalPosts = parseInt(resp[0].aggregate, 10),
|
||||
return Promise.join(collectionPromise, countPromise);
|
||||
}).then(function (results) {
|
||||
var totalPosts = parseInt(results[1][0].aggregate, 10),
|
||||
calcPages = Math.ceil(totalPosts / options.limit) || 0,
|
||||
postCollection = results[0],
|
||||
pagination = {},
|
||||
meta = {},
|
||||
data = {};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var _ = require('lodash'),
|
||||
Promise = require('bluebird'),
|
||||
errors = require('../errors'),
|
||||
ghostBookshelf = require('./base'),
|
||||
sitemap = require('../data/sitemap'),
|
||||
|
@ -73,7 +74,10 @@ Tag = ghostBookshelf.Model.extend({
|
|||
options = options || {};
|
||||
|
||||
var tagCollection = Tags.forge(),
|
||||
tagTotal;
|
||||
collectionPromise,
|
||||
totalPromise,
|
||||
countPromise,
|
||||
qb;
|
||||
|
||||
if (options.limit && options.limit !== 'all') {
|
||||
options.limit = parseInt(options.limit, 10) || 15;
|
||||
|
@ -98,43 +102,32 @@ Tag = ghostBookshelf.Model.extend({
|
|||
.query('offset', options.limit * (options.page - 1));
|
||||
}
|
||||
|
||||
return tagCollection
|
||||
.fetch(_.omit(options, 'page', 'limit'))
|
||||
// Fetch pagination information
|
||||
.then(function () {
|
||||
var qb,
|
||||
tableName = _.result(tagCollection, 'tableName'),
|
||||
idAttribute = _.result(tagCollection, 'idAttribute');
|
||||
collectionPromise = tagCollection.fetch(_.omit(options, 'page', 'limit'));
|
||||
|
||||
// After we're done, we need to figure out what
|
||||
// the limits are for the pagination values.
|
||||
qb = ghostBookshelf.knex(tableName);
|
||||
// Find total number of tags
|
||||
|
||||
if (options.where) {
|
||||
qb.where(options.where);
|
||||
qb = ghostBookshelf.knex('tags');
|
||||
|
||||
if (options.where) {
|
||||
qb.where(options.where);
|
||||
}
|
||||
|
||||
totalPromise = qb.count('tags.id as aggregate');
|
||||
|
||||
// Fetch post count information
|
||||
|
||||
if (options.include) {
|
||||
if (options.include.indexOf('post_count') > -1) {
|
||||
qb = ghostBookshelf.knex('posts_tags');
|
||||
countPromise = qb.select('tag_id').count('* as postCount').groupBy('tag_id');
|
||||
}
|
||||
}
|
||||
|
||||
return qb.count(tableName + '.' + idAttribute + ' as aggregate');
|
||||
})
|
||||
// Fetch post count information
|
||||
.then(function (resp) {
|
||||
var qb;
|
||||
tagTotal = resp;
|
||||
|
||||
if (options.include) {
|
||||
if (options.include.indexOf('post_count') > -1) {
|
||||
qb = ghostBookshelf.knex('posts_tags');
|
||||
|
||||
return qb.select('tag_id').count('* as postCount').groupBy('tag_id');
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
// Format response of data
|
||||
.then(function (postsPerTagCollection) {
|
||||
var totalTags = parseInt(tagTotal[0].aggregate, 10),
|
||||
return Promise.join(collectionPromise, totalPromise, countPromise).then(function (results) {
|
||||
var totalTags = results[1][0].aggregate,
|
||||
calcPages = Math.ceil(totalTags / options.limit) || 0,
|
||||
tagCollection = results[0],
|
||||
postsPerTagCollection = results[2],
|
||||
pagination = {},
|
||||
meta = {},
|
||||
data = {};
|
||||
|
@ -148,12 +141,12 @@ Tag = ghostBookshelf.Model.extend({
|
|||
|
||||
data.tags = tagCollection.toJSON();
|
||||
|
||||
if (postsPerTagCollection !== null) {
|
||||
if (postsPerTagCollection) {
|
||||
// Merge two result sets
|
||||
_.each(data.tags, function (tag) {
|
||||
var postsPerTag = _.find(postsPerTagCollection, function (obj) { return obj.tag_id === tag.id; });
|
||||
if (postsPerTag) {
|
||||
tag.post_count = parseInt(postsPerTag.postCount, 10);
|
||||
tag.post_count = postsPerTag.postCount;
|
||||
} else {
|
||||
tag.post_count = 0;
|
||||
}
|
||||
|
|
|
@ -22,14 +22,7 @@ var _ = require('lodash'),
|
|||
Users;
|
||||
|
||||
function validatePasswordLength(password) {
|
||||
try {
|
||||
if (!validator.isLength(password, 8)) {
|
||||
throw new errors.ValidationError('Your password must be at least 8 characters long.');
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
return Promise.resolve();
|
||||
return validator.isLength(password, 8);
|
||||
}
|
||||
|
||||
function generatePasswordHash(password) {
|
||||
|
@ -271,44 +264,46 @@ User = ghostBookshelf.Model.extend({
|
|||
|
||||
return Promise.resolve(fetchRoleQuery())
|
||||
.then(function () {
|
||||
if (roleInstance) {
|
||||
userCollection
|
||||
.query('join', 'roles_users', 'roles_users.user_id', '=', 'users.id')
|
||||
.query('where', 'roles_users.role_id', '=', roleInstance.id);
|
||||
function fetchCollection() {
|
||||
if (roleInstance) {
|
||||
userCollection
|
||||
.query('join', 'roles_users', 'roles_users.user_id', '=', 'users.id')
|
||||
.query('where', 'roles_users.role_id', '=', roleInstance.id);
|
||||
}
|
||||
|
||||
return userCollection
|
||||
.query('orderBy', 'last_login', 'DESC')
|
||||
.query('orderBy', 'name', 'ASC')
|
||||
.query('orderBy', 'created_at', 'DESC')
|
||||
.fetch(_.omit(options, 'page', 'limit'));
|
||||
}
|
||||
|
||||
return userCollection
|
||||
.query('orderBy', 'last_login', 'DESC')
|
||||
.query('orderBy', 'name', 'ASC')
|
||||
.query('orderBy', 'created_at', 'DESC')
|
||||
.fetch(_.omit(options, 'page', 'limit'));
|
||||
function fetchPaginationData() {
|
||||
var qb,
|
||||
tableName = _.result(userCollection, 'tableName'),
|
||||
idAttribute = _.result(userCollection, 'idAttribute');
|
||||
|
||||
// After we're done, we need to figure out what
|
||||
// the limits are for the pagination values.
|
||||
qb = ghostBookshelf.knex(tableName);
|
||||
|
||||
if (options.where) {
|
||||
qb.where(options.where);
|
||||
}
|
||||
|
||||
if (roleInstance) {
|
||||
qb.join('roles_users', 'roles_users.user_id', '=', 'users.id');
|
||||
qb.where('roles_users.role_id', '=', roleInstance.id);
|
||||
}
|
||||
|
||||
return qb.count(tableName + '.' + idAttribute + ' as aggregate');
|
||||
}
|
||||
|
||||
return Promise.join(fetchCollection(), fetchPaginationData());
|
||||
})
|
||||
|
||||
// Fetch pagination information
|
||||
.then(function () {
|
||||
var qb,
|
||||
tableName = _.result(userCollection, 'tableName'),
|
||||
idAttribute = _.result(userCollection, 'idAttribute');
|
||||
|
||||
// After we're done, we need to figure out what
|
||||
// the limits are for the pagination values.
|
||||
qb = ghostBookshelf.knex(tableName);
|
||||
|
||||
if (options.where) {
|
||||
qb.where(options.where);
|
||||
}
|
||||
|
||||
if (roleInstance) {
|
||||
qb.join('roles_users', 'roles_users.user_id', '=', 'users.id');
|
||||
qb.where('roles_users.role_id', '=', roleInstance.id);
|
||||
}
|
||||
|
||||
return qb.count(tableName + '.' + idAttribute + ' as aggregate');
|
||||
})
|
||||
|
||||
// Format response of data
|
||||
.then(function (resp) {
|
||||
var totalUsers = parseInt(resp[0].aggregate, 10),
|
||||
.then(function (results) {
|
||||
var totalUsers = parseInt(results[1][0].aggregate, 10),
|
||||
calcPages = Math.ceil(totalUsers / options.limit) || 0,
|
||||
pagination = {},
|
||||
meta = {},
|
||||
|
@ -412,40 +407,41 @@ User = ghostBookshelf.Model.extend({
|
|||
var self = this,
|
||||
roleId;
|
||||
|
||||
if (data.roles && data.roles.length > 1) {
|
||||
return Promise.reject(
|
||||
new errors.ValidationError('Only one role per user is supported at the moment.')
|
||||
);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.withRelated = _.union(options.withRelated, options.include);
|
||||
|
||||
return ghostBookshelf.Model.edit.call(this, data, options).then(function (user) {
|
||||
if (data.roles) {
|
||||
roleId = parseInt(data.roles[0].id || data.roles[0], 10);
|
||||
|
||||
if (data.roles.length > 1) {
|
||||
return Promise.reject(
|
||||
new errors.ValidationError('Only one role per user is supported at the moment.')
|
||||
);
|
||||
}
|
||||
|
||||
return user.roles().fetch().then(function (roles) {
|
||||
// return if the role is already assigned
|
||||
if (roles.models[0].id === roleId) {
|
||||
return;
|
||||
}
|
||||
return ghostBookshelf.model('Role').findOne({id: roleId});
|
||||
}).then(function (roleToAssign) {
|
||||
if (roleToAssign && roleToAssign.get('name') === 'Owner') {
|
||||
return Promise.reject(
|
||||
new errors.ValidationError('This method does not support assigning the owner role')
|
||||
);
|
||||
} else {
|
||||
// assign all other roles
|
||||
return user.roles().updatePivot({role_id: roleId});
|
||||
}
|
||||
}).then(function () {
|
||||
options.status = 'all';
|
||||
return self.findOne({id: user.id}, options);
|
||||
});
|
||||
if (!data.roles) {
|
||||
return user;
|
||||
}
|
||||
return user;
|
||||
|
||||
roleId = parseInt(data.roles[0].id || data.roles[0], 10);
|
||||
|
||||
return user.roles().fetch().then(function (roles) {
|
||||
// return if the role is already assigned
|
||||
if (roles.models[0].id === roleId) {
|
||||
return;
|
||||
}
|
||||
return ghostBookshelf.model('Role').findOne({id: roleId});
|
||||
}).then(function (roleToAssign) {
|
||||
if (roleToAssign && roleToAssign.get('name') === 'Owner') {
|
||||
return Promise.reject(
|
||||
new errors.ValidationError('This method does not support assigning the owner role')
|
||||
);
|
||||
} else {
|
||||
// assign all other roles
|
||||
return user.roles().updatePivot({role_id: roleId});
|
||||
}
|
||||
}).then(function () {
|
||||
options.status = 'all';
|
||||
return self.findOne({id: user.id}, options);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -467,26 +463,27 @@ User = ghostBookshelf.Model.extend({
|
|||
options = this.filterOptions(options, 'add');
|
||||
options.withRelated = _.union(options.withRelated, options.include);
|
||||
|
||||
return ghostBookshelf.model('Role').findOne({name: 'Author'}, _.pick(options, 'transacting')).then(function (authorRole) {
|
||||
// Get the role we're going to assign to this user, or the author role if there isn't one
|
||||
roles = data.roles || [authorRole.get('id')];
|
||||
// check for too many roles
|
||||
if (data.roles && data.roles.length > 1) {
|
||||
return Promise.reject(new errors.ValidationError('Only one role per user is supported at the moment.'));
|
||||
}
|
||||
|
||||
// check for too many roles
|
||||
if (roles.length > 1) {
|
||||
return Promise.reject(new errors.ValidationError('Only one role per user is supported at the moment.'));
|
||||
}
|
||||
// remove roles from the object
|
||||
delete data.roles;
|
||||
if (!validatePasswordLength(userData.password)) {
|
||||
return Promise.reject(new errors.ValidationError('Your password must be at least 8 characters long.'));
|
||||
}
|
||||
|
||||
return validatePasswordLength(userData.password);
|
||||
}).then(function () {
|
||||
return self.forge().fetch(options);
|
||||
}).then(function () {
|
||||
// Generate a new password hash
|
||||
return generatePasswordHash(data.password);
|
||||
}).then(function (hash) {
|
||||
function getAuthorRole() {
|
||||
return ghostBookshelf.model('Role').findOne({name: 'Author'}, _.pick(options, 'transacting')).then(function (authorRole) {
|
||||
return [authorRole.get('id')];
|
||||
});
|
||||
}
|
||||
|
||||
roles = data.roles || getAuthorRole();
|
||||
delete data.roles;
|
||||
|
||||
return generatePasswordHash(userData.password).then(function (results) {
|
||||
// Assign the hashed password
|
||||
userData.password = hash;
|
||||
userData.password = results[1];
|
||||
// LookupGravatar
|
||||
return self.gravatarLookup(userData);
|
||||
}).then(function (userData) {
|
||||
|
@ -496,17 +493,19 @@ User = ghostBookshelf.Model.extend({
|
|||
// Assign the userData to our created user so we can pass it back
|
||||
userData = addedUser;
|
||||
// if we are given a "role" object, only pass in the role ID in place of the full object
|
||||
roles = _.map(roles, function (role) {
|
||||
if (_.isString(role)) {
|
||||
return parseInt(role, 10);
|
||||
} else if (_.isNumber(role)) {
|
||||
return role;
|
||||
} else {
|
||||
return parseInt(role.id, 10);
|
||||
}
|
||||
});
|
||||
return Promise.resolve(roles).then(function (roles) {
|
||||
roles = _.map(roles, function (role) {
|
||||
if (_.isString(role)) {
|
||||
return parseInt(role, 10);
|
||||
} else if (_.isNumber(role)) {
|
||||
return role;
|
||||
} else {
|
||||
return parseInt(role.id, 10);
|
||||
}
|
||||
});
|
||||
|
||||
return userData.roles().attach(roles, options);
|
||||
return addedUser.roles().attach(roles, options);
|
||||
});
|
||||
}).then(function () {
|
||||
// find and return the added user
|
||||
return self.findOne({id: userData.id, status: 'all'}, options);
|
||||
|
@ -517,25 +516,24 @@ User = ghostBookshelf.Model.extend({
|
|||
var self = this,
|
||||
userData = this.filterData(data);
|
||||
|
||||
if (!validatePasswordLength(userData.password)) {
|
||||
return Promise.reject(new errors.ValidationError('Your password must be at least 8 characters long.'));
|
||||
}
|
||||
|
||||
options = this.filterOptions(options, 'setup');
|
||||
options.withRelated = _.union(options.withRelated, options.include);
|
||||
options.shortSlug = true;
|
||||
|
||||
return validatePasswordLength(userData.password).then(function () {
|
||||
// Generate a new password hash
|
||||
return generatePasswordHash(data.password);
|
||||
}).then(function (hash) {
|
||||
return generatePasswordHash(data.password).then(function (hash) {
|
||||
// Assign the hashed password
|
||||
userData.password = hash;
|
||||
// LookupGravatar
|
||||
return self.gravatarLookup(userData);
|
||||
}).then(function (userWithGravatar) {
|
||||
userData = userWithGravatar;
|
||||
// Generate a new slug
|
||||
return ghostBookshelf.Model.generateSlug.call(this, User, userData.name, options);
|
||||
}).then(function (slug) {
|
||||
// Assign slug and save the updated user
|
||||
userData.slug = slug;
|
||||
|
||||
return Promise.join(self.gravatarLookup(userData),
|
||||
ghostBookshelf.Model.generateSlug.call(this, User, userData.name, options));
|
||||
}).then(function (results) {
|
||||
userData = results[0];
|
||||
userData.slug = results[1];
|
||||
|
||||
return self.edit.call(self, userData, options);
|
||||
});
|
||||
},
|
||||
|
@ -692,7 +690,7 @@ User = ghostBookshelf.Model.extend({
|
|||
*/
|
||||
changePassword: function (oldPassword, newPassword, ne2Password, userId, options) {
|
||||
var self = this,
|
||||
user = null;
|
||||
user;
|
||||
|
||||
if (newPassword !== ne2Password) {
|
||||
return Promise.reject(new errors.ValidationError('Your new passwords do not match'));
|
||||
|
@ -702,9 +700,11 @@ User = ghostBookshelf.Model.extend({
|
|||
return Promise.reject(new errors.ValidationError('Password is required for this operation'));
|
||||
}
|
||||
|
||||
return validatePasswordLength(newPassword).then(function () {
|
||||
return self.forge({id: userId}).fetch({require: true});
|
||||
}).then(function (_user) {
|
||||
if (!validatePasswordLength(newPassword)) {
|
||||
return Promise.reject(new errors.ValidationError('Your password must be at least 8 characters long.'));
|
||||
}
|
||||
|
||||
return self.forge({id: userId}).fetch({require: true}).then(function (_user) {
|
||||
user = _user;
|
||||
if (userId === options.context.user) {
|
||||
return bcryptCompare(oldPassword, user.get('password'));
|
||||
|
@ -715,12 +715,10 @@ User = ghostBookshelf.Model.extend({
|
|||
if (!matched) {
|
||||
return Promise.reject(new errors.ValidationError('Your password is incorrect'));
|
||||
}
|
||||
return bcryptGenSalt();
|
||||
}).then(function (salt) {
|
||||
return bcryptHash(newPassword, salt);
|
||||
|
||||
return generatePasswordHash(newPassword);
|
||||
}).then(function (hash) {
|
||||
user.save({password: hash});
|
||||
return user;
|
||||
return user.save({password: hash});
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -811,10 +809,12 @@ User = ghostBookshelf.Model.extend({
|
|||
return Promise.reject(new Error('Your new passwords do not match'));
|
||||
}
|
||||
|
||||
return validatePasswordLength(newPassword).then(function () {
|
||||
// Validate the token; returns the email address from token
|
||||
return self.validateToken(utils.decodeBase64URLsafe(token), dbHash);
|
||||
}).then(function (email) {
|
||||
if (!validatePasswordLength(newPassword)) {
|
||||
return Promise.reject(new errors.ValidationError('Your password must be at least 8 characters long.'));
|
||||
}
|
||||
|
||||
// Validate the token; returns the email address from token
|
||||
return self.validateToken(utils.decodeBase64URLsafe(token), dbHash).then(function (email) {
|
||||
// Fetch the user by email, and hash the password at the same time.
|
||||
return Promise.join(
|
||||
self.getByEmail(email),
|
||||
|
@ -834,41 +834,39 @@ User = ghostBookshelf.Model.extend({
|
|||
},
|
||||
|
||||
transferOwnership: function (object, options) {
|
||||
var adminRole,
|
||||
ownerRole,
|
||||
contextUser,
|
||||
assignUser;
|
||||
var ownerRole,
|
||||
contextUser;
|
||||
|
||||
return Promise.join(ghostBookshelf.model('Role').findOne({name: 'Owner'}),
|
||||
User.findOne({id: options.context.user}, {include: ['roles']}))
|
||||
.then(function (results) {
|
||||
ownerRole = results[0];
|
||||
contextUser = results[1];
|
||||
|
||||
// Get admin role
|
||||
return ghostBookshelf.model('Role').findOne({name: 'Administrator'}).then(function (result) {
|
||||
adminRole = result;
|
||||
return ghostBookshelf.model('Role').findOne({name: 'Owner'});
|
||||
}).then(function (result) {
|
||||
ownerRole = result;
|
||||
return User.findOne({id: options.context.user}, {include: ['roles']});
|
||||
}).then(function (ctxUser) {
|
||||
// check if user has the owner role
|
||||
var currentRoles = ctxUser.toJSON().roles;
|
||||
var currentRoles = contextUser.toJSON().roles;
|
||||
if (!_.any(currentRoles, {id: ownerRole.id})) {
|
||||
return Promise.reject(new errors.NoPermissionError('Only owners are able to transfer the owner role.'));
|
||||
}
|
||||
contextUser = ctxUser;
|
||||
return User.findOne({id: object.id}, {include: ['roles']});
|
||||
}).then(function (user) {
|
||||
var currentRoles = user.toJSON().roles;
|
||||
|
||||
return Promise.join(ghostBookshelf.model('Role').findOne({name: 'Administrator'}),
|
||||
User.findOne({id: object.id}, {include: ['roles']}));
|
||||
}).then(function (results) {
|
||||
var adminRole = results[0],
|
||||
user = results[1],
|
||||
currentRoles = user.toJSON().roles;
|
||||
|
||||
if (!_.any(currentRoles, {id: adminRole.id})) {
|
||||
return Promise.reject(new errors.ValidationError('Only administrators can be assigned the owner role.'));
|
||||
}
|
||||
|
||||
assignUser = user;
|
||||
// convert owner to admin
|
||||
return contextUser.roles().updatePivot({role_id: adminRole.id});
|
||||
}).then(function () {
|
||||
// assign owner role to a new user
|
||||
return assignUser.roles().updatePivot({role_id: ownerRole.id});
|
||||
}).then(function () {
|
||||
return Promise.join(contextUser.roles().updatePivot({role_id: adminRole.id}),
|
||||
user.roles().updatePivot({role_id: ownerRole.id}),
|
||||
user.id);
|
||||
}).then(function (results) {
|
||||
return Users.forge()
|
||||
.query('whereIn', 'id', [contextUser.id, assignUser.id])
|
||||
.query('whereIn', 'id', [contextUser.id, results[2]])
|
||||
.fetch({withRelated: ['roles']});
|
||||
}).then(function (users) {
|
||||
return users.toJSON({include: ['roles']});
|
||||
|
|
Loading…
Reference in a new issue