This is an automated email from the ASF dual-hosted git repository. kentontaylor pushed a commit to branch kt/8393 in repository https://gitbox.apache.org/repos/asf/allura.git
commit 64b4ce0142f1afdcf971024f9c155388f0e83b4d Author: Kenton Taylor <[email protected]> AuthorDate: Thu Jul 15 20:39:55 2021 +0000 [#8393] For password recovery, resend account verification email if user is not yet confirmed --- Allura/allura/controllers/auth.py | 11 +++++++++-- Allura/allura/lib/plugin.py | 6 ++++++ Allura/allura/model/auth.py | 10 +++++++--- Allura/allura/tests/functional/test_auth.py | 9 +++++++-- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py index 8e59949..ce43f12 100644 --- a/Allura/allura/controllers/auth.py +++ b/Allura/allura/controllers/auth.py @@ -222,14 +222,21 @@ class AuthController(BaseController): if not email: redirect('/') - user_record = M.User.by_email_address(email) + user_record = M.User.by_email_address(email, only_confirmed=False) allow_non_primary_email_reset = asbool(config.get('auth.allow_non_primary_email_password_reset', True)) if not re.match(r"[^@]+@[^@]+\.[^@]+", email): flash('Enter email in correct format!', 'error') redirect('/auth/forgotten_password') - if not allow_non_primary_email_reset: + if user_record and user_record.pending: + message = 'If the given email address is on record, '\ + 'an email has been sent to the account\'s primary email address.' + email_record = M.EmailAddress.get(email=provider.get_primary_email_address(user_record=user_record), + confirmed=False) + provider.resend_verification_link(user_record.get_tool_data('sfx', 'userid')) + + elif not allow_non_primary_email_reset: message = 'If the given email address is on record, '\ 'a password reset email has been sent to the account\'s primary email address.' email_record = M.EmailAddress.get(email=provider.get_primary_email_address(user_record=user_record), diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py index b257198..be930de 100644 --- a/Allura/allura/lib/plugin.py +++ b/Allura/allura/lib/plugin.py @@ -307,6 +307,9 @@ class AuthenticationProvider(object): ''' raise NotImplementedError('set_password') + def resend_verification_link(em): + em.send_verification_link() + def upload_sshkey(self, username, pubkey): ''' Upload an SSH Key. Providers do not necessarily need to implement this. @@ -826,6 +829,9 @@ class LdapAuthenticationProvider(AuthenticationProvider): def get_last_password_updated(self, user): return LocalAuthenticationProvider(None).get_last_password_updated(user) + def recover_password(self, user): + return super().recover_password(user) + class ProjectRegistrationProvider(object): ''' diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py index 01b6572..f696b7f 100644 --- a/Allura/allura/model/auth.py +++ b/Allura/allura/model/auth.py @@ -19,6 +19,7 @@ from __future__ import unicode_literals from __future__ import absolute_import import logging import calendar +from typing import ClassVar import six from markupsafe import Markup @@ -650,9 +651,12 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable): return u @classmethod - def by_email_address(cls, addr): - addrs = EmailAddress.find(dict(email=addr, confirmed=True)) - users = [ea.claimed_by_user() for ea in addrs] + def by_email_address(cls, addr, only_confirmed=True): + q = dict(email=addr) + if only_confirmed: + q['confirmed'] = True + addrs = EmailAddress.find(q) + users = [ea.claimed_by_user(not only_confirmed) for ea in addrs] users = [u for u in users if u is not None] if len(users) > 1: log.warn('Multiple active users matching confirmed email %s %s. ' diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py index c581a96..05e11e2 100644 --- a/Allura/allura/tests/functional/test_auth.py +++ b/Allura/allura/tests/functional/test_auth.py @@ -1532,10 +1532,13 @@ class TestPasswordReset(TestController): # so test-admin isn't automatically logged in for all requests self.app.extra_environ = {'disable_auth_magic': str('True')} + @patch('allura.model.User.send_password_reset_email') + @patch('allura.lib.plugin.LocalAuthenticationProvider.resend_verification_link') @patch('allura.tasks.mail_tasks.sendmail') @patch('allura.lib.helpers.gen_message_id') - def test_email_unconfirmed(self, gen_message_id, sendmail): + def test_email_unconfirmed(self, gen_message_id, sendmail, p_sendlink, p_sendpwd): user = M.User.query.get(username='test-admin') + user.pending = True email = M.EmailAddress.find( {'claimed_by_user_id': user._id}).first() email.confirmed = False @@ -1546,6 +1549,8 @@ class TestPasswordReset(TestController): }) hash = user.get_tool_data('AuthPasswordReset', 'hash') assert hash is None + p_sendlink.assert_called_once() + p_sendpwd.assert_not_called() @patch('allura.tasks.mail_tasks.sendmail') @patch('allura.lib.helpers.gen_message_id') @@ -1649,7 +1654,7 @@ To update your password on %s, please visit the following URL: with td.audits('Password changed \(through recovery process\)', user=True): # escape parentheses, so they would not be treated as regex group r = form.submit() - + # verify 'Password Changed' email sent args, kwargs = sendsimplemail.post.call_args assert_equal(kwargs['toaddr'], user._id)
