mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Disable user validation and errors on login
fixes #3658 - Catch any errors from user.save() events during login - Prevent validation from happening at all when only updating status/last_login - Fixes a problem I introduced with errors which are arrays in logError
This commit is contained in:
parent
4b83dfd6ab
commit
8d46705dbb
2 changed files with 46 additions and 9 deletions
|
@ -84,15 +84,20 @@ errors = {
|
||||||
},
|
},
|
||||||
|
|
||||||
logError: function (err, context, help) {
|
logError: function (err, context, help) {
|
||||||
|
var self = this,
|
||||||
|
origArgs = _.toArray(arguments).slice(1),
|
||||||
|
stack,
|
||||||
|
msgs;
|
||||||
|
|
||||||
if (_.isArray(err)) {
|
if (_.isArray(err)) {
|
||||||
_.each(err, function (e) {
|
_.each(err, function (e) {
|
||||||
errors.logError(e);
|
var newArgs = [e].concat(origArgs);
|
||||||
|
errors.logError.apply(self, newArgs);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var stack = err ? err.stack : null,
|
stack = err ? err.stack : null;
|
||||||
msgs;
|
|
||||||
|
|
||||||
err = _.isString(err) ? err : (_.isObject(err) ? err.message : 'An unknown error occurred.');
|
err = _.isString(err) ? err : (_.isObject(err) ? err.message : 'An unknown error occurred.');
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ var _ = require('lodash'),
|
||||||
http = require('http'),
|
http = require('http'),
|
||||||
crypto = require('crypto'),
|
crypto = require('crypto'),
|
||||||
validator = require('validator'),
|
validator = require('validator'),
|
||||||
|
validation = require('../data/validation'),
|
||||||
Role = require('./role').Role,
|
Role = require('./role').Role,
|
||||||
|
|
||||||
tokenSecurity = {},
|
tokenSecurity = {},
|
||||||
|
@ -55,6 +56,17 @@ User = ghostBookshelf.Model.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// For the user model ONLY it is possible to disable validations.
|
||||||
|
// This is used to bypass validation during the credential check, and must never be done with user-provided data
|
||||||
|
// Should be removed when #3691 is done
|
||||||
|
validate: function () {
|
||||||
|
var opts = arguments[1];
|
||||||
|
if (opts && _.has(opts, 'validate') && opts.validate === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return validation.validateSchema(this.tableName, this.toJSON());
|
||||||
|
},
|
||||||
|
|
||||||
// Get the user from the options object
|
// Get the user from the options object
|
||||||
contextUser: function (options) {
|
contextUser: function (options) {
|
||||||
// Default to context user
|
// Default to context user
|
||||||
|
@ -561,7 +573,7 @@ User = ghostBookshelf.Model.extend({
|
||||||
return when.reject();
|
return when.reject();
|
||||||
},
|
},
|
||||||
|
|
||||||
setWarning: function (user) {
|
setWarning: function (user, options) {
|
||||||
var status = user.get('status'),
|
var status = user.get('status'),
|
||||||
regexp = /warn-(\d+)/i,
|
regexp = /warn-(\d+)/i,
|
||||||
level;
|
level;
|
||||||
|
@ -577,7 +589,7 @@ User = ghostBookshelf.Model.extend({
|
||||||
user.set('status', 'warn-' + level);
|
user.set('status', 'warn-' + level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return when(user.save()).then(function () {
|
return when(user.save(options)).then(function () {
|
||||||
return 5 - level;
|
return 5 - level;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -598,16 +610,36 @@ User = ghostBookshelf.Model.extend({
|
||||||
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) {
|
||||||
return when(self.setWarning(user)).then(function (remaining) {
|
return when(self.setWarning(user, {validate: false})).then(function (remaining) {
|
||||||
s = (remaining > 1) ? 's' : '';
|
s = (remaining > 1) ? 's' : '';
|
||||||
return when.reject(new errors.UnauthorizedError('Your password is incorrect.<br>' +
|
return when.reject(new errors.UnauthorizedError('Your password is incorrect.<br>' +
|
||||||
remaining + ' attempt' + s + ' remaining!'));
|
remaining + ' attempt' + s + ' remaining!'));
|
||||||
|
|
||||||
|
// Use comma structure, not .catch, because we don't want to catch incorrect passwords
|
||||||
|
}, 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.
|
||||||
|
errors.logError(
|
||||||
|
error,
|
||||||
|
'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 when(user.set({status : 'active', last_login : new Date()}).save()).then(function (user) {
|
return when(user.set({status : 'active', last_login : new Date()}).save({validate: false}))
|
||||||
return user;
|
.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.
|
||||||
|
errors.logError(
|
||||||
|
error,
|
||||||
|
'Error thrown from user update during login',
|
||||||
|
'Visit and save your profile after logging in to check for problems.'
|
||||||
|
);
|
||||||
|
return user;
|
||||||
|
});
|
||||||
}, errors.logAndThrowError);
|
}, errors.logAndThrowError);
|
||||||
}
|
}
|
||||||
return when.reject(new errors.NoPermissionError('Your account is locked due to too many ' +
|
return when.reject(new errors.NoPermissionError('Your account is locked due to too many ' +
|
||||||
|
|
Loading…
Add table
Reference in a new issue