From f65d4b90ca7343f919b4072dbb3f97d4daf17368 Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Mon, 7 Aug 2017 16:38:48 +0300 Subject: [PATCH] feat(user): Add email support to forgot password (#1834) Adds support for recovering users account using email and username. Previously only username worked. --- .../password/forgot-password.client.view.html | 10 +-- .../users/users.password.server.controller.js | 16 +++-- .../tests/server/user.server.routes.tests.js | 70 ++++++++++++++++--- 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/modules/users/client/views/password/forgot-password.client.view.html b/modules/users/client/views/password/forgot-password.client.view.html index 47a6fa83a1..5a82256b41 100644 --- a/modules/users/client/views/password/forgot-password.client.view.html +++ b/modules/users/client/views/password/forgot-password.client.view.html @@ -1,17 +1,17 @@

Restore your password

-

Enter your account username.

- -
-

Enter a username.

+ + +
+

Enter a username or email.

- +
diff --git a/modules/users/server/controllers/users/users.password.server.controller.js b/modules/users/server/controllers/users/users.password.server.controller.js index c5c9be86b5..d6dc1a4c7e 100644 --- a/modules/users/server/controllers/users/users.password.server.controller.js +++ b/modules/users/server/controllers/users/users.password.server.controller.js @@ -28,17 +28,23 @@ exports.forgot = function (req, res, next) { }, // Lookup user by username function (token, done) { - if (req.body.username) { + if (req.body.usernameOrEmail) { + + var usernameOrEmail = String(req.body.usernameOrEmail).toLowerCase(); + User.findOne({ - username: req.body.username.toLowerCase() + $or: [ + { username: usernameOrEmail }, + { email: usernameOrEmail } + ] }, '-salt -password', function (err, user) { if (err || !user) { return res.status(400).send({ - message: 'No account with that username has been found' + message: 'No account with that username or email has been found' }); } else if (user.provider !== 'local') { return res.status(400).send({ - message: 'It seems like you signed up using your ' + user.provider + ' account' + message: 'It seems like you signed up using your ' + user.provider + ' account, please sign in using that provider.' }); } else { user.resetPasswordToken = token; @@ -51,7 +57,7 @@ exports.forgot = function (req, res, next) { }); } else { return res.status(422).send({ - message: 'Username field must not be blank' + message: 'Username/email field must not be blank' }); } }, diff --git a/modules/users/tests/server/user.server.routes.tests.js b/modules/users/tests/server/user.server.routes.tests.js index 2dd8441d64..2613a5402c 100644 --- a/modules/users/tests/server/user.server.routes.tests.js +++ b/modules/users/tests/server/user.server.routes.tests.js @@ -325,7 +325,7 @@ describe('User CRUD tests', function () { should.not.exist(err); agent.post('/api/auth/forgot') .send({ - username: 'some_username_that_doesnt_exist' + usernameOrEmail: 'some_username_that_doesnt_exist' }) .expect(400) .end(function (err, res) { @@ -334,13 +334,13 @@ describe('User CRUD tests', function () { return done(err); } - res.body.message.should.equal('No account with that username has been found'); + res.body.message.should.equal('No account with that username or email has been found'); return done(); }); }); }); - it('forgot password should return 400 for no username provided', function (done) { + it('forgot password should return 400 for empty username/email', function (done) { var provider = 'facebook'; user.provider = provider; user.roles = ['user']; @@ -349,7 +349,7 @@ describe('User CRUD tests', function () { should.not.exist(err); agent.post('/api/auth/forgot') .send({ - username: '' + usernameOrEmail: '' }) .expect(422) .end(function (err, res) { @@ -358,7 +358,29 @@ describe('User CRUD tests', function () { return done(err); } - res.body.message.should.equal('Username field must not be blank'); + res.body.message.should.equal('Username/email field must not be blank'); + return done(); + }); + }); + }); + + it('forgot password should return 400 for no username or email provided', function (done) { + var provider = 'facebook'; + user.provider = provider; + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/forgot') + .send({}) + .expect(422) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + res.body.message.should.equal('Username/email field must not be blank'); return done(); }); }); @@ -373,7 +395,7 @@ describe('User CRUD tests', function () { should.not.exist(err); agent.post('/api/auth/forgot') .send({ - username: user.username + usernameOrEmail: user.username }) .expect(400) .end(function (err, res) { @@ -382,20 +404,46 @@ describe('User CRUD tests', function () { return done(err); } - res.body.message.should.equal('It seems like you signed up using your ' + user.provider + ' account'); + res.body.message.should.equal('It seems like you signed up using your ' + user.provider + ' account, please sign in using that provider.'); return done(); }); }); }); - it('forgot password should be able to reset password for user password reset request', function (done) { + it('forgot password should be able to reset password for user password reset request using username', function (done) { + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/forgot') + .send({ + usernameOrEmail: user.username + }) + .expect(400) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + User.findOne({ username: user.username.toLowerCase() }, function(err, userRes) { + userRes.resetPasswordToken.should.not.be.empty(); + should.exist(userRes.resetPasswordExpires); + res.body.message.should.be.equal('Failure sending email'); + return done(); + }); + }); + }); + }); + + it('forgot password should be able to reset password for user password reset request using email', function (done) { user.roles = ['user']; user.save(function (err) { should.not.exist(err); agent.post('/api/auth/forgot') .send({ - username: user.username + usernameOrEmail: user.email }) .expect(400) .end(function (err, res) { @@ -421,7 +469,7 @@ describe('User CRUD tests', function () { should.not.exist(err); agent.post('/api/auth/forgot') .send({ - username: user.username + usernameOrEmail: user.username }) .expect(400) .end(function (err, res) { @@ -458,7 +506,7 @@ describe('User CRUD tests', function () { should.not.exist(err); agent.post('/api/auth/forgot') .send({ - username: user.username + usernameOrEmail: user.username }) .expect(400) .end(function (err, res) {