Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions hypha/apply/users/forms.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import unicodedata

from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.forms import PasswordResetForm as DJPasswordResetForm
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from rolepermissions import roles
Expand Down Expand Up @@ -302,3 +305,40 @@ def clean_confirmation_text(self):
code="confirmation_text_incorrect",
)
return text


class PasswordResetForm(DJPasswordResetForm):
@staticmethod
def _unicode_ci_compare(s1, s2):
"""
Perform case-insensitive comparison of two identifiers, using the
recommended algorithm from Unicode Technical Report 36, section
2.11.2(B)(2).

Pulled directly from django.contrib.auth.forms
"""
return (
unicodedata.normalize("NFKC", s1).casefold()
== unicodedata.normalize("NFKC", s2).casefold()
)

def get_users(self, email):
"""Given an email, return matching user(s) who should receive a reset.

This allows subclasses to more easily customize the default policies
that prevent inactive users and users with unusable passwords from
resetting their password.
"""
UserModel = get_user_model()
email_field_name = UserModel.get_email_field_name()
active_users = UserModel._default_manager.filter(
**{
"%s__iexact" % email_field_name: email,
"is_active": True,
}
)
return (
u
for u in active_users
if self._unicode_ci_compare(email, getattr(u, email_field_name))
)
4 changes: 2 additions & 2 deletions hypha/apply/users/templates/users/password_reset/confirm.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{% if validlink %}

<h2 class="text-2xl">{% trans "Reset password" %}</h2>
<p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>
<p class="text-sm whitespace-normal label">{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>

<form class="form" method="post" novalidate>
{% csrf_token %}
Expand Down Expand Up @@ -39,7 +39,7 @@ <h2 class="text-2xl">{% trans "Reset password" %}</h2>
{% include "forms/includes/field.html" %}
{% endfor %}

<button class="btn btn-primary btn-wide" type="submit">{% trans 'Reset' %}</button>
<button class="mt-4 btn btn-wide btn-primary" type="submit">{% trans 'Reset' %}</button>
</form>
{% else %}
<p>{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}</p>
Expand Down
6 changes: 3 additions & 3 deletions hypha/apply/users/templates/users/password_reset/done.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

<div class="mt-12 w-full max-w-xl">

<h2 class="text-xl">
<h2 class="text-2xl">
{% trans "Check your inbox for a password reset email!" %}
</h2>
<p>
<p class="text-sm whitespace-normal label">
{% blocktrans %}We have sent an email to you with a password recovery link, open the link in the email to change your password.{% endblocktrans %}
</p>
<p>
<p class="text-sm whitespace-normal label">
{% blocktrans %}Check your "Spam" folder, if you don't find the email in your inbox.{% endblocktrans %}
</p>
</div>
Expand Down
2 changes: 2 additions & 0 deletions hypha/apply/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
CustomAuthenticationForm,
Disable2FAConfirmationForm,
PasswordlessAuthForm,
PasswordResetForm,
ProfileForm,
)
from .models import ConfirmAccessToken, PendingSignup
Expand Down Expand Up @@ -383,6 +384,7 @@ class PasswordResetView(DjPasswordResetView):
email_template_name = "users/password_reset/email.txt"
template_name = "users/password_reset/form.html"
success_url = reverse_lazy("users:password_reset_done")
form_class = PasswordResetForm

def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
Expand Down
Loading