Skip to content

Commit

Permalink
Merge pull request #2130 into dev
Browse files Browse the repository at this point in the history
As discussed in #1291, the ResetPassword form only works for primary
email addresses. This is confusing for users who try to reset their
password using a non-primary email address (i.e. they do not receive a
password reset email, and they are unable to register because the
registration form rejects the email address).

This update addresses the issue by informing the user of the primary
email address linked to their account. Now, when a user tries to reset
their password using a secondary email address, they receive the
following email:

Subject: Primary email address on DataShare
From: PhysioNet Automated System <[email protected]>
To: [email protected]
Date: Sun, 12 Nov 2023 11:27:57 -0000

You are receiving this email because you requested a password reset
for your account at DataShare.

Only your primary email address can be used for resetting your
password. Your primary email address is [email protected].

Regards
The DataShare Team
  • Loading branch information
Benjamin Moody committed Nov 15, 2023
2 parents cece757 + 6abc773 commit b713147
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
16 changes: 16 additions & 0 deletions physionet-django/notification/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -1023,3 +1023,19 @@ def notify_event_participant_application(request, user, registered_user, event):
body = loader.render_to_string('events/email/event_registration.html', context)
# Not resend the email if there was an integrity error
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)


def notify_primary_email(associated_email):
"""
Inform a user of the primary email address linked to their account.
Must only be used when the email address is verified.
"""
if associated_email.is_verified:
subject = f"Primary email address on {settings.SITE_NAME}"
context = {
'name': associated_email.user.get_full_name(),
'primary_email': associated_email.user.email,
'SITE_NAME': settings.SITE_NAME,
}
body = loader.render_to_string('user/email/notify_primary_email.html', context)
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [associated_email.email], fail_silently=False)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% load i18n %}{% autoescape off %}{% filter wordwrap:70 %}
You are receiving this email because you requested a password reset for your account at {{ SITE_NAME }}.

Only your primary email address can be used for resetting your password. Your primary email address is {{ primary_email }}.

Regards
The {{ SITE_NAME }} Team
{% endfilter %}{% endautoescape %}
18 changes: 17 additions & 1 deletion physionet-django/user/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError
Expand All @@ -29,6 +30,7 @@
credential_application_request,
get_url_prefix,
notify_account_registration,
notify_primary_email,
process_credential_complete,
training_application_request,
)
Expand Down Expand Up @@ -95,13 +97,27 @@ class LogoutView(auth_views.LogoutView):
pass


class CustomPasswordResetForm(PasswordResetForm):
def clean_email(self):
"""
Override the clean_email method to allow for secondary email checks.
"""
email = self.cleaned_data['email']
secondary_email = AssociatedEmail.objects.filter(is_verified=True, is_primary_email=False, email=email).first()

if secondary_email:
notify_primary_email(secondary_email)

return email


# Request password reset
class PasswordResetView(auth_views.PasswordResetView):
template_name = 'user/reset_password_request.html'
success_url = reverse_lazy('reset_password_sent')
email_template_name = 'user/email/reset_password_email.html'
extra_email_context = {'SITE_NAME': settings.SITE_NAME}

form_class = CustomPasswordResetForm

# Page shown after reset email has been sent
class PasswordResetDoneView(auth_views.PasswordResetDoneView):
Expand Down

0 comments on commit b713147

Please sign in to comment.