Skip to content

Instantly share code, notes, and snippets.

@naz
Last active March 5, 2020 09:19
Show Gist options
  • Save naz/c21f2069e176daaafe897718ce62c8fa to your computer and use it in GitHub Desktop.
Save naz/c21f2069e176daaafe897718ce62c8fa to your computer and use it in GitHub Desktop.
Script that closely resembles Ghost User model update process which aimed to help tracking down the bug when using 'edit' method and 'password' attribute not being update
/**
* First create following schema in the db
CREATE TABLE `users` (
`id` varchar(24) NOT NULL,
`email` varchar(191) NOT NULL,
`password` varchar(60) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
*/
const assert = require('assert').strict;
const ObjectId = require('bson-objectid');
const knex = require('knex')({
client: 'mysql',
debug: true,
connection: {
host: '127.0.0.1',
user: 'gargol',
password: 'gargol',
database: 'bookshelf_bug',
charset: 'utf8'
}
});
const bookshelf = require('bookshelf')(knex);
const onSaving = function (newObje, attrs, options) {
this.attributes = this.pick(['id', 'email', 'password']);
};
let User = bookshelf.Model.extend({
tableName: 'users',
initialize() {
this.constructor.__super__.initialize.apply(this, arguments)
this.on('saving', function(newObj, attrs, options) {
if (options.method === 'insert') {
if (!newObj.id) {
this.set('id', ObjectId.generate());
}
}
});
this.on('saving', function (newObj, attrs, options) {
onSaving.apply(this, arguments);
this.set('password', 'HASHED_' + this.get('password'));
})
},
}, {
edit: function edit(data, options) {
const id = options.id;
const model = this.forge({id: id});
return model
.fetch(options)
.then((object) => {
if (object) {
options.method = 'update';
return object.save(data, options);
}
throw 'pass the id!';
});
},
});
Promise.resolve()
.then(() => {
return new User({ email: 'test@something.com', password: 'hash_me'}).save();
})
.then(() => {
return User.where('email', 'test@something.com').fetch();
})
.then((user) => {
// Strangely the behavior for insert works because it still relies on `this.attributes` instead of
// passed in `attributesToSave` when performing it
// ref_1: https://github.com/bookshelf/bookshelf/blob/0.15.1/lib/model.js#L1047
// ref_2: https://github.com/bookshelf/bookshelf/blob/0.15.1/lib/sync.js#L206
assert.equal(user.get('password'), 'HASHED_hash_me');
return User.edit({password: 'hash_again'}, {id: user.id});
})
.then(() => {
return User.where('email', 'test@something.com').fetch();
})
.then((user) => {
assert.equal(user.get('password'), 'HASHED_hash_again');
})
.then(() => {
process.exit(0);
})
.catch((err) => {
console.error(err);
process.exit(err);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment