diff --git a/flask_security/core.py b/flask_security/core.py index 73a20e8..a086b37 100644 --- a/flask_security/core.py +++ b/flask_security/core.py @@ -45,6 +45,7 @@ _default_config = { 'POST_LOGIN_VIEW': '/', 'POST_LOGOUT_VIEW': '/', 'POST_FORGOT_VIEW': '/', + 'RESET_PASSWORD_ERROR_VIEW': '/', 'POST_REGISTER_VIEW': None, 'POST_CONFIRM_VIEW': None, 'DEFAULT_ROLES': [], @@ -244,6 +245,7 @@ class Security(object): self.post_register_view = utils.config_value(app, 'POST_REGISTER_VIEW') self.post_confirm_view = utils.config_value(app, 'POST_CONFIRM_VIEW') self.post_forgot_view = utils.config_value(app, 'POST_FORGOT_VIEW') + self.reset_password_error_view = utils.config_value(app, 'RESET_PASSWORD_ERROR_VIEW') self.default_roles = utils.config_value(app, "DEFAULT_ROLES") self.login_without_confirmation = utils.config_value(app, 'LOGIN_WITHOUT_CONFIRMATION') self.confirm_email = utils.config_value(app, 'CONFIRM_EMAIL') diff --git a/flask_security/views.py b/flask_security/views.py index d3fed60..09614f1 100644 --- a/flask_security/views.py +++ b/flask_security/views.py @@ -184,9 +184,9 @@ def reset(): password=form.password.data) except ResetPasswordError, e: - do_flash(str(e)) + do_flash(str(e), 'error') except TokenExpiredError, e: do_flash('You did not reset your password within %s.' % security.reset_password_within_text) - return redirect(request.referrer) + return redirect(request.referrer or security.reset_password_error_view) diff --git a/tests/functional_tests.py b/tests/functional_tests.py index 3dca3d9..059d842 100644 --- a/tests/functional_tests.py +++ b/tests/functional_tests.py @@ -263,6 +263,27 @@ class RecoverableTests(SecurityTest): r = self.authenticate('joe@lp.com', 'newpassword') self.assertIn('Hello joe@lp.com', r.data) + def test_reset_password_twice_flashes_invalid_token_msg(self): + u = None + with capture_reset_password_requests() as users: + r = self.client.post('/forgot', data=dict(email='joe@lp.com')) + u = users[0] + + self.client.post('/reset', data={ + 'email': u.email, + 'reset_password_token': u.reset_password_token, + 'password': 'newpassword', + 'password_confirm': 'newpassword' + }) + + r = self.client.post('/reset', data={ + 'email': u.email, + 'reset_password_token': u.reset_password_token, + 'password': 'newpassword', + 'password_confirm': 'newpassword' + }, follow_redirects=True) + self.assertIn('Invalid reset password token', r.data) + class MongoEngineSecurityTests(DefaultSecurityTests):