From e2616e8010dfb24f007e5b5ca629258cd172ccdb Mon Sep 17 00:00:00 2001 From: Avital Oliver Date: Wed, 3 Jun 2015 19:49:04 -0700 Subject: [PATCH] Test that password reset links are bound to emails This adds a test to verify that a password reset link won't work if a user changed their password after the reset link was sent. This was reported by a user, but the bug wasn't actually real. But I finished writing the test, so I thought it's worth committing. --- packages/accounts-password/email_tests.js | 2 +- packages/accounts-password/password_tests.js | 34 +++++++++++++++++++ .../accounts-password/password_tests_setup.js | 6 ++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/accounts-password/email_tests.js b/packages/accounts-password/email_tests.js index ba37c19a40..83f24898af 100644 --- a/packages/accounts-password/email_tests.js +++ b/packages/accounts-password/email_tests.js @@ -33,7 +33,7 @@ testAsyncMulti("accounts emails - reset password flow", [ test.equal(result.length, 2); // the first is the email verification var options = result[1]; - var re = new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)") + var re = new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)"); var match = options.text.match(re); test.isTrue(match); resetPasswordToken = match[1]; diff --git a/packages/accounts-password/password_tests.js b/packages/accounts-password/password_tests.js index c5203c8099..b8890dcc38 100644 --- a/packages/accounts-password/password_tests.js +++ b/packages/accounts-password/password_tests.js @@ -1033,4 +1033,38 @@ if (Meteor.isServer) (function () { ); } ); + + Tinytest.add( + 'passwords - reset password doesn\t work if email changed after email sent', + function (test) { + var username = Random.id(); + var email = username + '-intercept@example.com'; + + var userId = Accounts.createUser({ + username: username, + email: email, + password: "old-password" + }); + + var user = Meteor.users.findOne(userId); + + Accounts.sendResetPasswordEmail(userId, email); + + var resetPasswordEmailOptions = Meteor.call("getInterceptedEmails", email)[0]; + + var re = new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)"); + var match = resetPasswordEmailOptions.text.match(re); + test.isTrue(match); + var resetPasswordToken = match[1]; + + var newEmail = Random.id() + '-new@example.com'; + Meteor.users.update(userId, {$set: {"emails.0.address": newEmail}}); + + test.throws(function () { + Meteor.call("resetPassword", resetPasswordToken, "new-password"); + }, /Token has invalid email address/); + test.throws(function () { + Meteor.call("login", {user: {username: username}, password: "new-password"}); + }, /Incorrect password/); + }); }) (); diff --git a/packages/accounts-password/password_tests_setup.js b/packages/accounts-password/password_tests_setup.js index fa4432f097..9f46f7f79a 100644 --- a/packages/accounts-password/password_tests_setup.js +++ b/packages/accounts-password/password_tests_setup.js @@ -66,6 +66,9 @@ Meteor.methods({ }); Accounts.onLogin(function (attempt) { + if (!attempt.connection) // if login method called from the server + return; + if (capturedLogins[attempt.connection.id]) capturedLogins[attempt.connection.id].push({ successful: true, @@ -74,6 +77,9 @@ Accounts.onLogin(function (attempt) { }); Accounts.onLoginFailure(function (attempt) { + if (!attempt.connection) // if login method called from the server + return; + if (capturedLogins[attempt.connection.id]) { capturedLogins[attempt.connection.id].push({ successful: false,