0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Improved importer logic for password in users (#9161)

refs #9150

- move data manipulation for importing users from `importers/data/users` to `model/user` for more consistency (see behaviour of post imports)
- changed importing logic in `onSaving` fn for user model:
   - when importing, we set the password to a random uid and don't validate, just hash it and lock the user
   - when importing with `importPersistUser` we check if the password is a bcrypt hash already and fall back to normal behaviour if not (set random password, lock user, and hash password)
   - don't run validations when importing
This commit is contained in:
Aileen Nowak 2017-10-19 16:43:52 +07:00 committed by Hannah Wolfe
parent 958544ae90
commit d4b6390fd6
2 changed files with 24 additions and 17 deletions

View file

@ -2,8 +2,7 @@
const debug = require('ghost-ignition').debug('importer:users'),
_ = require('lodash'),
BaseImporter = require('./base'),
globalUtils = require('../../../../utils');
BaseImporter = require('./base');
class UsersImporter extends BaseImporter {
constructor(options) {
@ -29,7 +28,7 @@ class UsersImporter extends BaseImporter {
*
* If importOptions object is supplied with a property of importPersistUser then the user status is not locked
*/
beforeImport(importOptions) {
beforeImport() {
debug('beforeImport');
let self = this, role, lookup = {};
@ -41,15 +40,6 @@ class UsersImporter extends BaseImporter {
this.dataToImport = this.dataToImport.map(self.legacyMapper);
if (importOptions.importPersistUser !== true) {
_.each(this.dataToImport, function (model) {
model.password = globalUtils.uid(50);
if (model.status !== 'inactive') {
model.status = 'locked';
}
});
}
// NOTE: sort out duplicated roles based on incremental id
_.each(this.roles_users, function (attachedRole) {
if (lookup.hasOwnProperty(attachedRole.user_id)) {

View file

@ -146,17 +146,34 @@ User = ghostBookshelf.Model.extend({
* Important:
* - Password hashing happens when we import a database
* - we do some pre-validation checks, because onValidate is called AFTER onSaving
* - when importing, we set the password to a random uid and don't validate, just hash it and lock the user
* - when importing with `importPersistUser` we check if the password is a bcrypt hash already and fall back to
* normal behaviour if not (set random password, lock user, and hash password)
* - no validations should run, when importing
*/
if (self.isNew() || self.hasChanged('password')) {
this.set('password', String(this.get('password')));
if (!validatePasswordLength(this.get('password'))) {
return Promise.reject(new errors.ValidationError({message: i18n.t('errors.models.user.passwordDoesNotComplyLength', {minLength: 10})}));
if (options.importing) {
// CASE: import with `importPersistUser` should always be an bcrypt password already,
// and won't re-hash or overwrite it.
// In case the password is not bcrypt hashed we fall back to the standard behaviour.
if (options.importPersistUser && this.get('password').match(/^\$2[ayb]\$.{56}$/i)) {
return;
}
// always set password to a random uid when importing
this.set('password', utils.uid(50));
// lock users so they have to follow the password reset flow
if (this.get('status') !== 'inactive') {
this.set('status', 'locked');
}
}
// An import with importOptions supplied can prevent re-hashing a user password
if (options.importPersistUser) {
return;
// don't ever validate passwords when importing
if (!options.importing && !validatePasswordLength(this.get('password'))) {
return Promise.reject(new errors.ValidationError({message: i18n.t('errors.models.user.passwordDoesNotComplyLength', {minLength: 10})}));
}
tasks.hashPassword = (function hashPassword() {