Skip to content

Commit 789a542

Browse files
author
Pascal
committed
Added unicode check for mail and according test
Signed-off-by: Pascal <[email protected]>
1 parent 039f2c7 commit 789a542

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

django_rest_passwordreset/views.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import unicodedata
12
from datetime import timedelta
23

34
from django.conf import settings
@@ -34,6 +35,18 @@
3435
HTTP_IP_ADDRESS_HEADER = getattr(settings, 'DJANGO_REST_PASSWORDRESET_IP_ADDRESS_HEADER', 'REMOTE_ADDR')
3536

3637

38+
def _unicode_ci_compare(s1, s2):
39+
"""
40+
Perform case-insensitive comparison of two identifiers, using the
41+
recommended algorithm from Unicode Technical Report 36, section
42+
2.11.2(B)(2).
43+
"""
44+
normalized1 = unicodedata.normalize('NFKC', s1)
45+
normalized2 = unicodedata.normalize('NFKC', s2)
46+
47+
return normalized1.casefold() == normalized2.casefold()
48+
49+
3750
class ResetPasswordValidateToken(GenericAPIView):
3851
"""
3952
An Api View which provides a method to verify that a token is valid
@@ -139,7 +152,8 @@ def post(self, request, *args, **kwargs):
139152
# last but not least: iterate over all users that are active and can change their password
140153
# and create a Reset Password Token and send a signal with the created token
141154
for user in users:
142-
if user.eligible_for_reset():
155+
if user.eligible_for_reset() and \
156+
_unicode_ci_compare(email, getattr(user, get_password_reset_lookup_field())):
143157
# define the token as none for now
144158
token = None
145159

tests/test/test_auth_test_case.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def setUp(self):
1818
self.user2 = User.objects.create_user("user2", "[email protected]", "secret2")
1919
self.user3 = User.objects.create_user("[email protected]", "[email protected]", "secret3")
2020
self.user4 = User.objects.create_user("user4", "[email protected]")
21+
self.user5 = User.objects.create_user("user5", "uѕ[email protected]", "secret5") # email contains kyrillic s
2122

2223
def test_try_reset_password_email_does_not_exist(self):
2324
""" Tests requesting a token for an email that does not exist """
@@ -27,6 +28,13 @@ def test_try_reset_password_email_does_not_exist(self):
2728
# response should have "email" in it
2829
self.assertTrue("email" in decoded_response)
2930

31+
def test_unicode_email_reset(self):
32+
response = self.rest_do_request_reset_token(email="uѕ[email protected]")
33+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
34+
35+
decoded_response = json.loads(response.content.decode())
36+
self.assertEqual(decoded_response.get("email")[0], 'Enter a valid email address.')
37+
3038
@patch('django_rest_passwordreset.signals.reset_password_token_created.send')
3139
def test_validate_token(self, mock_reset_password_token_created):
3240
""" Tests validate token """

0 commit comments

Comments
 (0)