[#8393] For password recovery, resend account verification email if user is not yet confirmed
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 @@
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 @@
'''
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 @@
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 absolute_import
import logging
import calendar
+from typing import ClassVar
import six
from markupsafe import Markup
@@ -650,9 +651,12 @@
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 @@
# 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 @@
})
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 @@
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)