diff --git a/common/models/user.js b/common/models/user.js index a65059a8..665d4531 100644 --- a/common/models/user.js +++ b/common/models/user.js @@ -1358,7 +1358,14 @@ module.exports = function(User) { }); var emailChanged; if (ctx.instance) { - emailChanged = ctx.instance.email !== ctx.hookState.originalUserData[0].email; + // Check if map does not return an empty array + // Fix server crashes when try to PUT a non existent id + if (ctx.hookState.originalUserData.length > 0) { + emailChanged = ctx.instance.email !== ctx.hookState.originalUserData[0].email; + } else { + emailChanged = true; + } + if (emailChanged && ctx.Model.settings.emailVerificationRequired) { ctx.instance.emailVerified = false; } diff --git a/test/user.integration.js b/test/user.integration.js index 4862c472..37896580 100644 --- a/test/user.integration.js +++ b/test/user.integration.js @@ -63,6 +63,39 @@ describe('users - integration', function() { }); }); + it('returns error when replacing user that does not exist', function() { + const credentials = {email: 'temp@example.com', password: 'pass'}; + const User = app.models.User; + let user; + + let hookEnabled = true; + User.beforeRemote('replaceOrCreate', (ctx, unused, next) => { + // don't affect subsequent tests! + if (!hookEnabled) return; + hookEnabled = false; + + // Delete the user *AFTER* the PUT request was authorized + // but *BEFORE* replaceOrCreate is invoked + User.deleteById(user.id, next); + }); + + return User.create(credentials) + .then(u => { + user = u; + return User.login(credentials); + }) + .then(token => { + return this.put('/api/users') + .set('Authorization', token.id) + .send({ + id: user.id, + email: 'x@x.com', + password: 'x', + }) + .expect(404); + }); + }); + it('should create post for a given user', function(done) { var url = '/api/users/' + userId + '/posts?access_token=' + accessToken; this.post(url)