Commit 82283370 by Will Daly

Allow inactive users to request a password reset

Internationalize error messages for password reset on the new login page.
parent 68b18a20
...@@ -136,7 +136,7 @@ class LoginFromCombinedPageTest(UniqueCourseTest): ...@@ -136,7 +136,7 @@ class LoginFromCombinedPageTest(UniqueCourseTest):
# Expect that we're shown a failure message # Expect that we're shown a failure message
self.assertIn( self.assertIn(
"No active user with the provided email address exists.", "No user with the provided email address exists.",
self.login_page.wait_for_errors() self.login_page.wait_for_errors()
) )
......
...@@ -289,7 +289,11 @@ class StudentAccountUpdateTest(UrlResetMixin, TestCase): ...@@ -289,7 +289,11 @@ class StudentAccountUpdateTest(UrlResetMixin, TestCase):
# Send the view the email address tied to the inactive user # Send the view the email address tied to the inactive user
response = self._change_password(email=self.NEW_EMAIL) response = self._change_password(email=self.NEW_EMAIL)
self.assertEqual(response.status_code, 400)
# Expect that the activation email is still sent,
# since the user may have lost the original activation email.
self.assertEqual(response.status_code, 200)
self.assertEqual(len(mail.outbox), 1)
def test_password_change_no_user(self): def test_password_change_no_user(self):
# Log out the user created during test setup # Log out the user created during test setup
......
...@@ -9,6 +9,7 @@ from django.http import ( ...@@ -9,6 +9,7 @@ from django.http import (
from django.shortcuts import redirect from django.shortcuts import redirect
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.mail import send_mail from django.core.mail import send_mail
from django.utils.translation import ugettext as _
from django_future.csrf import ensure_csrf_cookie from django_future.csrf import ensure_csrf_cookie
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods from django.views.decorators.http import require_http_methods
...@@ -261,11 +262,11 @@ def password_change_request_handler(request): ...@@ -261,11 +262,11 @@ def password_change_request_handler(request):
# Increment the rate limit counter # Increment the rate limit counter
limiter.tick_bad_request_counter(request) limiter.tick_bad_request_counter(request)
return HttpResponseBadRequest("No active user with the provided email address exists.") return HttpResponseBadRequest(_("No user with the provided email address exists."))
return HttpResponse(status=200) return HttpResponse(status=200)
else: else:
return HttpResponseBadRequest("No email address provided.") return HttpResponseBadRequest(_("No email address provided."))
def _third_party_auth_context(request): def _third_party_auth_context(request):
......
...@@ -9,8 +9,8 @@ information and preferences). ...@@ -9,8 +9,8 @@ information and preferences).
from django.conf import settings from django.conf import settings
from django.db import transaction, IntegrityError from django.db import transaction, IntegrityError
from django.core.validators import validate_email, validate_slug, ValidationError from django.core.validators import validate_email, validate_slug, ValidationError
from django.contrib.auth.forms import PasswordResetForm
from ..forms import PasswordResetFormNoActive
from ..models import User, UserProfile, Registration, PendingEmailChange from ..models import User, UserProfile, Registration, PendingEmailChange
from ..helpers import intercept_errors from ..helpers import intercept_errors
...@@ -353,9 +353,9 @@ def request_password_change(email, orig_host, is_secure): ...@@ -353,9 +353,9 @@ def request_password_change(email, orig_host, is_secure):
""" """
# Binding data to a form requires that the data be passed as a dictionary # Binding data to a form requires that the data be passed as a dictionary
# to the Form class constructor. # to the Form class constructor.
form = PasswordResetForm({'email': email}) form = PasswordResetFormNoActive({'email': email})
# Validate that an active user exists with the given email address. # Validate that a user exists with the given email address.
if form.is_valid(): if form.is_valid():
# Generate a single-use link for performing a password reset # Generate a single-use link for performing a password reset
# and email it to the user. # and email it to the user.
...@@ -365,7 +365,7 @@ def request_password_change(email, orig_host, is_secure): ...@@ -365,7 +365,7 @@ def request_password_change(email, orig_host, is_secure):
use_https=is_secure use_https=is_secure
) )
else: else:
# No active user with the provided email address exists. # No user with the provided email address exists.
raise AccountUserNotFound raise AccountUserNotFound
......
# TODO: eventually move this implementation into the user_api
from student.forms import PasswordResetFormNoActive
...@@ -292,18 +292,24 @@ class AccountApiTest(TestCase): ...@@ -292,18 +292,24 @@ class AccountApiTest(TestCase):
result = re.search('(?P<url>https?://[^\s]+)', email_body) result = re.search('(?P<url>https?://[^\s]+)', email_body)
self.assertIsNot(result, None) self.assertIsNot(result, None)
@raises(account_api.AccountUserNotFound) @skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS')
@ddt.data(True, False) def test_request_password_change_invalid_user(self):
def test_request_password_change_invalid_user(self, create_inactive_account): with self.assertRaises(account_api.AccountUserNotFound):
if create_inactive_account: account_api.request_password_change(self.EMAIL, self.ORIG_HOST, self.IS_SECURE)
# Create an account, but do not activate it
account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
account_api.request_password_change(self.EMAIL, self.ORIG_HOST, self.IS_SECURE)
# Verify that no email messages have been sent # Verify that no email messages have been sent
self.assertEqual(len(mail.outbox), 0) self.assertEqual(len(mail.outbox), 0)
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS')
def test_request_password_change_inactive_user(self):
# Create an account, but do not activate it
account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
account_api.request_password_change(self.EMAIL, self.ORIG_HOST, self.IS_SECURE)
# Verify that the activation email was still sent
self.assertEqual(len(mail.outbox), 1)
def _assert_is_datetime(self, timestamp): def _assert_is_datetime(self, timestamp):
if not timestamp: if not timestamp:
return False return False
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment