mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-24 06:35:49 +03:00
commit
28b3dc57d7
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
var dataProvider = require('../models'),
|
var dataProvider = require('../models'),
|
||||||
settings = require('./settings'),
|
settings = require('./settings'),
|
||||||
mail = require('./mail'),
|
mail = require('./mail'),
|
||||||
@ -6,7 +5,7 @@ var dataProvider = require('../models'),
|
|||||||
when = require('when'),
|
when = require('when'),
|
||||||
errors = require('../errors'),
|
errors = require('../errors'),
|
||||||
config = require('../config'),
|
config = require('../config'),
|
||||||
ONE_DAY = 86400000,
|
ONE_DAY = 60 * 60 * 24 * 1000,
|
||||||
authentication;
|
authentication;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,6 +24,7 @@ authentication = {
|
|||||||
generateResetToken: function generateResetToken(object) {
|
generateResetToken: function generateResetToken(object) {
|
||||||
var expires = Date.now() + ONE_DAY,
|
var expires = Date.now() + ONE_DAY,
|
||||||
email;
|
email;
|
||||||
|
|
||||||
return utils.checkObject(object, 'passwordreset').then(function (checkedPasswordReset) {
|
return utils.checkObject(object, 'passwordreset').then(function (checkedPasswordReset) {
|
||||||
if (checkedPasswordReset.passwordreset[0].email) {
|
if (checkedPasswordReset.passwordreset[0].email) {
|
||||||
email = checkedPasswordReset.passwordreset[0].email;
|
email = checkedPasswordReset.passwordreset[0].email;
|
||||||
@ -34,37 +34,35 @@ authentication = {
|
|||||||
|
|
||||||
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
||||||
var dbHash = response.settings[0].value;
|
var dbHash = response.settings[0].value;
|
||||||
|
return dataProvider.User.generateResetToken(email, expires, dbHash);
|
||||||
|
}).then(function (resetToken) {
|
||||||
|
var baseUrl = config().forceAdminSSL ? (config().urlSSL || config().url) : config().url,
|
||||||
|
siteLink = '<a href="' + baseUrl + '">' + baseUrl + '</a>',
|
||||||
|
resetUrl = baseUrl.replace(/\/$/, '') + '/ghost/reset/' + resetToken + '/',
|
||||||
|
resetLink = '<a href="' + resetUrl + '">' + resetUrl + '</a>',
|
||||||
|
payload = {
|
||||||
|
mail: [{
|
||||||
|
message: {
|
||||||
|
to: email,
|
||||||
|
subject: 'Reset Password',
|
||||||
|
html: '<p><strong>Hello!</strong></p>' +
|
||||||
|
'<p>A request has been made to reset the password on the site ' + siteLink + '.</p>' +
|
||||||
|
'<p>Please follow the link below to reset your password:<br><br>' + resetLink + '</p>' +
|
||||||
|
'<p>Ghost</p>'
|
||||||
|
},
|
||||||
|
options: {}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
return dataProvider.User.generateResetToken(email, expires, dbHash).then(function (resetToken) {
|
return mail.send(payload);
|
||||||
var baseUrl = config().forceAdminSSL ? (config().urlSSL || config().url) : config().url,
|
}).then(function () {
|
||||||
siteLink = '<a href="' + baseUrl + '">' + baseUrl + '</a>',
|
return when.resolve({passwordreset: [{message: 'Check your email for further instructions.'}]});
|
||||||
resetUrl = baseUrl.replace(/\/$/, '') + '/ghost/reset/' + resetToken + '/',
|
}).otherwise(function (error) {
|
||||||
resetLink = '<a href="' + resetUrl + '">' + resetUrl + '</a>',
|
// TODO: This is kind of sketchy, depends on magic string error.message from Bookshelf.
|
||||||
payload = {
|
if (error && error.message === 'NotFound') {
|
||||||
mail: [{
|
error = new errors.UnauthorizedError('Invalid email address');
|
||||||
message: {
|
}
|
||||||
to: email,
|
return when.reject(error);
|
||||||
subject: 'Reset Password',
|
|
||||||
html: '<p><strong>Hello!</strong></p>' +
|
|
||||||
'<p>A request has been made to reset the password on the site ' + siteLink + '.</p>' +
|
|
||||||
'<p>Please follow the link below to reset your password:<br><br>' + resetLink + '</p>' +
|
|
||||||
'<p>Ghost</p>'
|
|
||||||
},
|
|
||||||
options: {}
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
|
|
||||||
return mail.send(payload);
|
|
||||||
}).then(function () {
|
|
||||||
return when.resolve({passwordreset: [{message: 'Check your email for further instructions.'}]});
|
|
||||||
}).otherwise(function (error) {
|
|
||||||
// TODO: This is kind of sketchy, depends on magic string error.message from Bookshelf.
|
|
||||||
if (error && error.message === 'NotFound') {
|
|
||||||
error.message = "Invalid email address";
|
|
||||||
}
|
|
||||||
|
|
||||||
return when.reject(new errors.UnauthorizedError(error.message));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -7,9 +7,12 @@ var when = require('when'),
|
|||||||
canThis = require('../permissions').canThis,
|
canThis = require('../permissions').canThis,
|
||||||
errors = require('../errors'),
|
errors = require('../errors'),
|
||||||
utils = require('./utils'),
|
utils = require('./utils'),
|
||||||
|
globalUtils = require('../utils'),
|
||||||
|
config = require('../config'),
|
||||||
|
mail = require('./mail'),
|
||||||
|
|
||||||
docName = 'users',
|
docName = 'users',
|
||||||
ONE_DAY = 86400000,
|
ONE_DAY = 60 * 60 * 24 * 1000,
|
||||||
users;
|
users;
|
||||||
|
|
||||||
|
|
||||||
@ -130,6 +133,80 @@ users = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### Invite user
|
||||||
|
* @param {User} object the user to create
|
||||||
|
* @returns {Promise(User}} Newly created user
|
||||||
|
*/
|
||||||
|
invite: function invite(object, options) {
|
||||||
|
var newUser,
|
||||||
|
user;
|
||||||
|
|
||||||
|
return canThis(options.context).add.user().then(function () {
|
||||||
|
return utils.checkObject(object, docName).then(function (checkedUserData) {
|
||||||
|
newUser = checkedUserData.users[0];
|
||||||
|
|
||||||
|
if (newUser.email) {
|
||||||
|
newUser.name = object.users[0].email.substring(0, newUser.email.indexOf("@"));
|
||||||
|
newUser.password = globalUtils.uid(50);
|
||||||
|
newUser.status = 'invited';
|
||||||
|
// TODO: match user role with db and enforce permissions
|
||||||
|
newUser.role = 3;
|
||||||
|
} else {
|
||||||
|
return when.reject(new errors.BadRequestError('No email provided.'));
|
||||||
|
}
|
||||||
|
}).then(function () {
|
||||||
|
return dataProvider.User.getByEmail(newUser.email);
|
||||||
|
}).then(function (foundUser) {
|
||||||
|
if (!foundUser) {
|
||||||
|
return dataProvider.User.add(newUser, options);
|
||||||
|
} else {
|
||||||
|
// only invitations for already invited users are resent
|
||||||
|
if (foundUser.toJSON().status === 'invited') {
|
||||||
|
return foundUser;
|
||||||
|
} else {
|
||||||
|
return when.reject(new errors.BadRequestError('User is already registered.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(function (invitedUser) {
|
||||||
|
user = invitedUser.toJSON();
|
||||||
|
return settings.read({context: {internal: true}, key: 'dbHash'});
|
||||||
|
}).then(function (response) {
|
||||||
|
var expires = Date.now() + (14 * ONE_DAY),
|
||||||
|
dbHash = response.settings[0].value;
|
||||||
|
return dataProvider.User.generateResetToken(user.email, expires, dbHash);
|
||||||
|
}).then(function (resetToken) {
|
||||||
|
var baseUrl = config().forceAdminSSL ? (config().urlSSL || config().url) : config().url,
|
||||||
|
siteLink = '<a href="' + baseUrl + '">' + baseUrl + '</a>',
|
||||||
|
resetUrl = baseUrl.replace(/\/$/, '') + '/ghost/signup/' + resetToken + '/',
|
||||||
|
resetLink = '<a href="' + resetUrl + '">' + resetUrl + '</a>',
|
||||||
|
payload = {
|
||||||
|
mail: [{
|
||||||
|
message: {
|
||||||
|
to: user.email,
|
||||||
|
subject: 'Invitation',
|
||||||
|
html: '<p><strong>Hello!</strong></p>' +
|
||||||
|
'<p>You have been invited to ' + siteLink + '.</p>' +
|
||||||
|
'<p>Please follow the link to sign up and publish your ideas:<br><br>' + resetLink + '</p>' +
|
||||||
|
'<p>Ghost</p>'
|
||||||
|
},
|
||||||
|
options: {}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
return mail.send(payload);
|
||||||
|
}).then(function () {
|
||||||
|
return when.resolve({users: [user]});
|
||||||
|
}).otherwise(function (error) {
|
||||||
|
if (error && error.type === 'EmailError') {
|
||||||
|
error.message = 'Error sending email: ' + error.message + ' Please check your email settings and resend the invitation.';
|
||||||
|
}
|
||||||
|
return when.reject(error);
|
||||||
|
});
|
||||||
|
}, function () {
|
||||||
|
return when.reject(new errors.NoPermissionError('You do not have permission to add a users.'));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ### Register
|
* ### Register
|
||||||
* Allow to register a user using the API without beeing authenticated in. Needed to set up the first user.
|
* Allow to register a user using the API without beeing authenticated in. Needed to set up the first user.
|
||||||
|
@ -9,7 +9,7 @@ function BadRequestError(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BadRequestError.prototype = Object.create(Error.prototype);
|
BadRequestError.prototype = Object.create(Error.prototype);
|
||||||
BadRequestError.prototype.name = "BadRequestError";
|
BadRequestError.prototype.name = 'BadRequestError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = BadRequestError;
|
module.exports = BadRequestError;
|
@ -9,7 +9,7 @@ function EmailError(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EmailError.prototype = Object.create(Error.prototype);
|
EmailError.prototype = Object.create(Error.prototype);
|
||||||
EmailError.prototype.name = "EmailError";
|
EmailError.prototype.name = 'EmailError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = EmailError;
|
module.exports = EmailError;
|
@ -9,7 +9,7 @@ function InternalServerError(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InternalServerError.prototype = Object.create(Error.prototype);
|
InternalServerError.prototype = Object.create(Error.prototype);
|
||||||
InternalServerError.prototype.name = "InternalServerError";
|
InternalServerError.prototype.name = 'InternalServerError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = InternalServerError;
|
module.exports = InternalServerError;
|
@ -9,7 +9,7 @@ function NoPermissionError(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NoPermissionError.prototype = Object.create(Error.prototype);
|
NoPermissionError.prototype = Object.create(Error.prototype);
|
||||||
NoPermissionError.prototype.name = "NoPermissionError";
|
NoPermissionError.prototype.name = 'NoPermissionError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = NoPermissionError;
|
module.exports = NoPermissionError;
|
@ -9,7 +9,7 @@ function NotFoundError(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NotFoundError.prototype = Object.create(Error.prototype);
|
NotFoundError.prototype = Object.create(Error.prototype);
|
||||||
NotFoundError.prototype.name = "NotFoundError";
|
NotFoundError.prototype.name = 'NotFoundError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = NotFoundError;
|
module.exports = NotFoundError;
|
@ -9,7 +9,7 @@ function RequestEntityTooLargeError(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RequestEntityTooLargeError.prototype = Object.create(Error.prototype);
|
RequestEntityTooLargeError.prototype = Object.create(Error.prototype);
|
||||||
RequestEntityTooLargeError.prototype.name = "RequestEntityTooLargeError";
|
RequestEntityTooLargeError.prototype.name = 'RequestEntityTooLargeError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = RequestEntityTooLargeError;
|
module.exports = RequestEntityTooLargeError;
|
@ -9,7 +9,7 @@ function UnauthorizedError(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UnauthorizedError.prototype = Object.create(Error.prototype);
|
UnauthorizedError.prototype = Object.create(Error.prototype);
|
||||||
UnauthorizedError.prototype.name = "UnauthorizedError";
|
UnauthorizedError.prototype.name = 'UnauthorizedError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = UnauthorizedError;
|
module.exports = UnauthorizedError;
|
@ -9,7 +9,7 @@ function UnsupportedMediaTypeError(message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UnsupportedMediaTypeError.prototype = Object.create(Error.prototype);
|
UnsupportedMediaTypeError.prototype = Object.create(Error.prototype);
|
||||||
UnsupportedMediaTypeError.prototype.name = "UnsupportedMediaTypeError";
|
UnsupportedMediaTypeError.prototype.name = 'UnsupportedMediaTypeError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = UnsupportedMediaTypeError;
|
module.exports = UnsupportedMediaTypeError;
|
@ -12,7 +12,7 @@ function ValidationError(message, offendingProperty) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ValidationError.prototype = Object.create(Error.prototype);
|
ValidationError.prototype = Object.create(Error.prototype);
|
||||||
ValidationError.prototype.name = "ValidationError";
|
ValidationError.prototype.name = 'ValidationError';
|
||||||
|
|
||||||
|
|
||||||
module.exports = ValidationError;
|
module.exports = ValidationError;
|
||||||
|
@ -1,44 +1,10 @@
|
|||||||
var oauth2orize = require('oauth2orize'),
|
var oauth2orize = require('oauth2orize'),
|
||||||
models = require('../models'),
|
models = require('../models'),
|
||||||
|
utils = require('../utils'),
|
||||||
|
|
||||||
oauth;
|
oauth;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a random int, used by `utils.uid()`
|
|
||||||
*
|
|
||||||
* @param {Number} min
|
|
||||||
* @param {Number} max
|
|
||||||
* @return {Number}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
function getRandomInt(min, max) {
|
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a unique identifier with the given `len`.
|
|
||||||
*
|
|
||||||
* utils.uid(10);
|
|
||||||
* // => "FDaS435D2z"
|
|
||||||
*
|
|
||||||
* @param {Number} len
|
|
||||||
* @return {String}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
function uid(len) {
|
|
||||||
var buf = [],
|
|
||||||
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
|
|
||||||
charlen = chars.length,
|
|
||||||
i;
|
|
||||||
|
|
||||||
for (i = 1; i < len; i = i + 1) {
|
|
||||||
buf.push(chars[getRandomInt(0, charlen - 1)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
oauth = {
|
oauth = {
|
||||||
|
|
||||||
init: function (oauthServer) {
|
init: function (oauthServer) {
|
||||||
@ -65,8 +31,8 @@ oauth = {
|
|||||||
return models.User.check({email: username, password: password}).then(function (user) {
|
return models.User.check({email: username, password: password}).then(function (user) {
|
||||||
|
|
||||||
//Everything validated, return the access- and refreshtoken
|
//Everything validated, return the access- and refreshtoken
|
||||||
var accessToken = uid(256),
|
var accessToken = utils.uid(256),
|
||||||
refreshToken = uid(256),
|
refreshToken = utils.uid(256),
|
||||||
accessExpires = Date.now() + 3600 * 1000,
|
accessExpires = Date.now() + 3600 * 1000,
|
||||||
refreshExpires = Date.now() + 3600 * 24 * 1000;
|
refreshExpires = Date.now() + 3600 * 24 * 1000;
|
||||||
|
|
||||||
@ -95,7 +61,7 @@ oauth = {
|
|||||||
return done(null, false);
|
return done(null, false);
|
||||||
} else {
|
} else {
|
||||||
var token = model.toJSON(),
|
var token = model.toJSON(),
|
||||||
accessToken = uid(256),
|
accessToken = utils.uid(256),
|
||||||
accessExpires = Date.now() + 3600 * 1000;
|
accessExpires = Date.now() + 3600 * 1000;
|
||||||
|
|
||||||
if (token.expires > Date.now()) {
|
if (token.expires > Date.now()) {
|
||||||
|
@ -116,7 +116,6 @@ User = ghostBookshelf.Model.extend({
|
|||||||
* **See:** [ghostBookshelf.Model.add](base.js.html#Add)
|
* **See:** [ghostBookshelf.Model.add](base.js.html#Add)
|
||||||
*/
|
*/
|
||||||
add: function (data, options) {
|
add: function (data, options) {
|
||||||
|
|
||||||
var self = this,
|
var self = this,
|
||||||
// Clone the _user so we don't expose the hashed password unnecessarily
|
// Clone the _user so we don't expose the hashed password unnecessarily
|
||||||
userData = this.filterData(data);
|
userData = this.filterData(data);
|
||||||
@ -130,11 +129,6 @@ User = ghostBookshelf.Model.extend({
|
|||||||
*/
|
*/
|
||||||
return validatePasswordLength(userData.password).then(function () {
|
return validatePasswordLength(userData.password).then(function () {
|
||||||
return self.forge().fetch();
|
return self.forge().fetch();
|
||||||
}).then(function (user) {
|
|
||||||
// Check if user exists
|
|
||||||
if (user) {
|
|
||||||
return when.reject(new Error('A user is already registered. Only one user for now!'));
|
|
||||||
}
|
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
// Generate a new password hash
|
// Generate a new password hash
|
||||||
return generatePasswordHash(data.password);
|
return generatePasswordHash(data.password);
|
||||||
@ -150,31 +144,16 @@ User = ghostBookshelf.Model.extend({
|
|||||||
|
|
||||||
// Assign the userData to our created user so we can pass it back
|
// Assign the userData to our created user so we can pass it back
|
||||||
userData = addedUser;
|
userData = addedUser;
|
||||||
// Add this user to the admin role (assumes admin = role_id: 1)
|
if (!data.role) {
|
||||||
return userData.roles().attach(1);
|
// TODO: needs change when owner role is introduced and setup is changed
|
||||||
|
data.role = 1;
|
||||||
|
}
|
||||||
|
return userData.roles().attach(data.role);
|
||||||
}).then(function (addedUserRole) {
|
}).then(function (addedUserRole) {
|
||||||
/*jshint unused:false*/
|
/*jshint unused:false*/
|
||||||
// find and return the added user
|
// find and return the added user
|
||||||
return self.findOne({id: userData.id}, options);
|
return self.findOne({id: userData.id}, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporarily replacing the function below with another one that checks
|
|
||||||
* whether there's anyone registered at all. This is due to #138
|
|
||||||
* @author javorszky
|
|
||||||
*/
|
|
||||||
|
|
||||||
// return this.forge({email: userData.email}).fetch().then(function (user) {
|
|
||||||
// if (user !== null) {
|
|
||||||
// return when.reject(new Error('A user with that email address already exists.'));
|
|
||||||
// }
|
|
||||||
// return nodefn.call(bcrypt.hash, _user.password, null, null).then(function (hash) {
|
|
||||||
// userData.password = hash;
|
|
||||||
// ghostBookshelf.Model.add.call(UserRole, userRoles);
|
|
||||||
// return ghostBookshelf.Model.add.call(User, userData);
|
|
||||||
// }, errors.logAndThrowError);
|
|
||||||
// }, errors.logAndThrowError);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
permissable: function (userModelOrId, context, loadedPermissions, hasUserPermission, hasAppPermission) {
|
permissable: function (userModelOrId, context, loadedPermissions, hasUserPermission, hasAppPermission) {
|
||||||
@ -233,8 +212,11 @@ User = ghostBookshelf.Model.extend({
|
|||||||
check: function (object) {
|
check: function (object) {
|
||||||
var self = this,
|
var self = this,
|
||||||
s;
|
s;
|
||||||
|
|
||||||
return this.getByEmail(object.email).then(function (user) {
|
return this.getByEmail(object.email).then(function (user) {
|
||||||
|
if (!user || user.get('status') === 'invited') {
|
||||||
|
return when.reject(new Error('NotFound'));
|
||||||
|
}
|
||||||
|
|
||||||
if (user.get('status') !== 'locked') {
|
if (user.get('status') !== 'locked') {
|
||||||
return nodefn.call(bcrypt.compare, object.password, user.get('password')).then(function (matched) {
|
return nodefn.call(bcrypt.compare, object.password, user.get('password')).then(function (matched) {
|
||||||
if (!matched) {
|
if (!matched) {
|
||||||
@ -296,6 +278,10 @@ User = ghostBookshelf.Model.extend({
|
|||||||
|
|
||||||
generateResetToken: function (email, expires, dbHash) {
|
generateResetToken: function (email, expires, dbHash) {
|
||||||
return this.getByEmail(email).then(function (foundUser) {
|
return this.getByEmail(email).then(function (foundUser) {
|
||||||
|
if (!foundUser) {
|
||||||
|
return when.reject(new Error('NotFound'));
|
||||||
|
}
|
||||||
|
|
||||||
var hash = crypto.createHash('sha256'),
|
var hash = crypto.createHash('sha256'),
|
||||||
text = "";
|
text = "";
|
||||||
|
|
||||||
@ -398,8 +384,8 @@ User = ghostBookshelf.Model.extend({
|
|||||||
|
|
||||||
gravatarLookup: function (userData) {
|
gravatarLookup: function (userData) {
|
||||||
var gravatarUrl = '//www.gravatar.com/avatar/' +
|
var gravatarUrl = '//www.gravatar.com/avatar/' +
|
||||||
crypto.createHash('md5').update(userData.email.toLowerCase().trim()).digest('hex') +
|
crypto.createHash('md5').update(userData.email.toLowerCase().trim()).digest('hex') +
|
||||||
"?d=404",
|
"?d=404",
|
||||||
checkPromise = when.defer();
|
checkPromise = when.defer();
|
||||||
|
|
||||||
http.get('http:' + gravatarUrl, function (res) {
|
http.get('http:' + gravatarUrl, function (res) {
|
||||||
@ -427,12 +413,9 @@ User = ghostBookshelf.Model.extend({
|
|||||||
var userWithEmail = users.find(function (user) {
|
var userWithEmail = users.find(function (user) {
|
||||||
return user.get('email').toLowerCase() === email.toLowerCase();
|
return user.get('email').toLowerCase() === email.toLowerCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (userWithEmail) {
|
if (userWithEmail) {
|
||||||
return when.resolve(userWithEmail);
|
return when.resolve(userWithEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
return when.reject(new Error('NotFound'));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -22,6 +22,7 @@ apiRoutes = function (middleware) {
|
|||||||
router.get('/ghost/api/v0.1/users/:id/', api.http(api.users.read));
|
router.get('/ghost/api/v0.1/users/:id/', api.http(api.users.read));
|
||||||
router.put('/ghost/api/v0.1/users/password/', api.http(api.users.changePassword));
|
router.put('/ghost/api/v0.1/users/password/', api.http(api.users.changePassword));
|
||||||
router.put('/ghost/api/v0.1/users/:id/', api.http(api.users.edit));
|
router.put('/ghost/api/v0.1/users/:id/', api.http(api.users.edit));
|
||||||
|
router.post('/ghost/api/v0.1/users/', api.http(api.users.invite));
|
||||||
router['delete']('/ghost/api/v0.1/users/:id/', api.http(api.users.destroy));
|
router['delete']('/ghost/api/v0.1/users/:id/', api.http(api.users.destroy));
|
||||||
|
|
||||||
// ## Tags
|
// ## Tags
|
||||||
|
38
core/server/utils/index.js
Normal file
38
core/server/utils/index.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Return a random int, used by `utils.uid()`
|
||||||
|
*
|
||||||
|
* @param {Number} min
|
||||||
|
* @param {Number} max
|
||||||
|
* @return {Number}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function getRandomInt(min, max) {
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
var utils = {
|
||||||
|
/**
|
||||||
|
* Return a unique identifier with the given `len`.
|
||||||
|
*
|
||||||
|
* utils.uid(10);
|
||||||
|
* // => "FDaS435D2z"
|
||||||
|
*
|
||||||
|
* @param {Number} len
|
||||||
|
* @return {String}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
uid: function (len) {
|
||||||
|
var buf = [],
|
||||||
|
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
|
||||||
|
charlen = chars.length,
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 1; i < len; i = i + 1) {
|
||||||
|
buf.push(chars[getRandomInt(0, charlen - 1)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.join('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = utils;
|
@ -150,15 +150,6 @@ describe('User Model', function run() {
|
|||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can\'t add second', function (done) {
|
|
||||||
var userData = testUtils.DataGenerator.forModel.users[1];
|
|
||||||
|
|
||||||
return UserModel.add(userData, {user: 1}).then(done, function (failure) {
|
|
||||||
failure.message.should.eql('A user is already registered. Only one user for now!');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can findAll', function (done) {
|
it('can findAll', function (done) {
|
||||||
|
|
||||||
UserModel.findAll().then(function (results) {
|
UserModel.findAll().then(function (results) {
|
||||||
|
Loading…
Reference in New Issue
Block a user