From a94c33fd6ef143e7487b9e31cfb06193245daf6b Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Sat, 25 Feb 2017 15:50:47 +0000 Subject: [PATCH] Added an alert on the login form, to be shown if a user's password has been cleared. Adjusted url reverse strings to match the changed view function. - Legacy-Id: 12918 --- ietf/ietfauth/tests.py | 14 ++++----- ietf/ietfauth/urls.py | 4 +-- ietf/ietfauth/views.py | 30 ++++++++++++++++++- ietf/meeting/tests_js.py | 5 ++-- .../registration/confirm_account.html | 2 +- ietf/templates/registration/login.html | 7 +++++ 6 files changed, 48 insertions(+), 14 deletions(-) diff --git a/ietf/ietfauth/tests.py b/ietf/ietfauth/tests.py index f1e8184ff..363d140a2 100644 --- a/ietf/ietfauth/tests.py +++ b/ietf/ietfauth/tests.py @@ -62,10 +62,10 @@ class IetfAuthTests(TestCase): make_test_data() # try logging in without a next - r = self.client.get(urlreverse(django.contrib.auth.views.login)) + r = self.client.get(urlreverse(ietf.ietfauth.views.login)) self.assertEqual(r.status_code, 200) - r = self.client.post(urlreverse(django.contrib.auth.views.login), {"username":"plain", "password":"plain+password"}) + r = self.client.post(urlreverse(ietf.ietfauth.views.login), {"username":"plain", "password":"plain+password"}) self.assertEqual(r.status_code, 302) self.assertEqual(urlsplit(r["Location"])[2], urlreverse(ietf.ietfauth.views.profile)) @@ -75,10 +75,10 @@ class IetfAuthTests(TestCase): r = self.client.get(urlreverse(ietf.ietfauth.views.profile)) self.assertEqual(r.status_code, 302) - self.assertEqual(urlsplit(r["Location"])[2], urlreverse(django.contrib.auth.views.login)) + self.assertEqual(urlsplit(r["Location"])[2], urlreverse(ietf.ietfauth.views.login)) # try logging in with a next - r = self.client.post(urlreverse(django.contrib.auth.views.login) + "?next=/foobar", {"username":"plain", "password":"plain+password"}) + r = self.client.post(urlreverse(ietf.ietfauth.views.login) + "?next=/foobar", {"username":"plain", "password":"plain+password"}) self.assertEqual(r.status_code, 302) self.assertEqual(urlsplit(r["Location"])[2], "/foobar") @@ -153,7 +153,7 @@ class IetfAuthTests(TestCase): email = "new-account@example.com" # add whitelist entry - r = self.client.post(urlreverse(django.contrib.auth.views.login), {"username":"secretary", "password":"secretary+password"}) + r = self.client.post(urlreverse(ietf.ietfauth.views.login), {"username":"secretary", "password":"secretary+password"}) self.assertEqual(r.status_code, 302) self.assertEqual(urlsplit(r["Location"])[2], urlreverse(ietf.ietfauth.views.profile)) @@ -406,7 +406,7 @@ class IetfAuthTests(TestCase): chpw_url = urlreverse(ietf.ietfauth.views.change_password) prof_url = urlreverse(ietf.ietfauth.views.profile) - login_url = urlreverse(django.contrib.auth.views.login) + login_url = urlreverse(ietf.ietfauth.views.login) redir_url = '%s?next=%s' % (login_url, chpw_url) # get without logging in @@ -453,7 +453,7 @@ class IetfAuthTests(TestCase): chun_url = urlreverse(ietf.ietfauth.views.change_username) prof_url = urlreverse(ietf.ietfauth.views.profile) - login_url = urlreverse(django.contrib.auth.views.login) + login_url = urlreverse(ietf.ietfauth.views.login) redir_url = '%s?next=%s' % (login_url, chun_url) # get without logging in diff --git a/ietf/ietfauth/urls.py b/ietf/ietfauth/urls.py index 280ae7f4c..5efbb4b38 100644 --- a/ietf/ietfauth/urls.py +++ b/ietf/ietfauth/urls.py @@ -1,6 +1,6 @@ # Copyright The IETF Trust 2007, 2009, All Rights Reserved -from django.contrib.auth.views import login, logout +from django.contrib.auth.views import logout from ietf.ietfauth import views from ietf.utils.urls import url @@ -10,7 +10,7 @@ urlpatterns = [ url(r'^confirmnewemail/(?P[^/]+)/$', views.confirm_new_email), url(r'^create/$', views.create_account), url(r'^create/confirm/(?P[^/]+)/$', views.confirm_account), - url(r'^login/$', login), + url(r'^login/$', views.login), url(r'^logout/$', logout), url(r'^password/$', views.change_password), url(r'^profile/$', views.profile), diff --git a/ietf/ietfauth/views.py b/ietf/ietfauth/views.py index c1424d0b7..adcf10399 100644 --- a/ietf/ietfauth/views.py +++ b/ietf/ietfauth/views.py @@ -43,7 +43,10 @@ from django.contrib import messages from django.conf import settings from django.contrib.auth import update_session_auth_hash from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.hashers import identify_hasher from django.contrib.auth.models import User +from django.contrib.auth.views import login as django_login from django.contrib.sites.models import Site from django.core.urlresolvers import reverse as urlreverse from django.http import Http404, HttpResponseRedirect #, HttpResponse, @@ -565,4 +568,29 @@ def change_username(request): 'user': user, }) - + + +def login(request, extra_context=None): + """ + This login function is a wrapper around django's login() for the purpose + of providing a notification if the user's password has been cleared. The + warning will be triggered if the password field has been set to something + which is not recognized as a valid password hash. + """ + + if request.method == "POST": + form = AuthenticationForm(request, data=request.POST) + username = form.data.get('username') + user = User.objects.filter(username=username).first() + if user: + try: + identify_hasher(user.password) + except ValueError: + extra_context = {"alert": + "Note: Your password has been cleared because " + "of possible password leakage. " + "Please use the password reset link below " + "to set a new password for your account.", + } + + return django_login(request, extra_context=extra_context) diff --git a/ietf/meeting/tests_js.py b/ietf/meeting/tests_js.py index 97e0af95d..c0f411061 100644 --- a/ietf/meeting/tests_js.py +++ b/ietf/meeting/tests_js.py @@ -5,7 +5,6 @@ import time from pyquery import PyQuery from unittest import skipIf -import django.contrib.auth.views from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.core.urlresolvers import reverse as urlreverse #from django.test.utils import override_settings @@ -73,7 +72,7 @@ class ScheduleEditTests(StaticLiveServerTestCase): return '%s%s'%(self.live_server_url,urlreverse(*args,**kwargs)) def login(self): - url = '%s%s'%(self.live_server_url, urlreverse('django.contrib.auth.views.login')) + url = '%s%s'%(self.live_server_url, urlreverse('ietf.ietfauth.views.login')) self.driver.get(url) self.driver.find_element_by_name('username').send_keys('plain') self.driver.find_element_by_name('password').send_keys('plain+password') @@ -127,7 +126,7 @@ class SlideReorderTests(StaticLiveServerTestCase): return '%s%s'%(self.live_server_url,urlreverse(*args,**kwargs)) def secr_login(self): - url = '%s%s'%(self.live_server_url, urlreverse(django.contrib.auth.views.login)) + url = '%s%s'%(self.live_server_url, urlreverse('ietf.ietfauth.views.login')) self.driver.get(url) self.driver.find_element_by_name('username').send_keys('secretary') self.driver.find_element_by_name('password').send_keys('secretary+password') diff --git a/ietf/templates/registration/confirm_account.html b/ietf/templates/registration/confirm_account.html index 7ace0d32c..edbee4c97 100644 --- a/ietf/templates/registration/confirm_account.html +++ b/ietf/templates/registration/confirm_account.html @@ -20,7 +20,7 @@

Account creation successful

Your account with login {{ email }} has been created, using the password you have selected.

- Sign in + Sign in {% else %}

Complete account creation

diff --git a/ietf/templates/registration/login.html b/ietf/templates/registration/login.html index 732426cad..925f2e8b4 100644 --- a/ietf/templates/registration/login.html +++ b/ietf/templates/registration/login.html @@ -12,10 +12,17 @@

Sign in

+
{% csrf_token %} {% bootstrap_form form %} + {% if alert %} +

+ {{ alert }} +

+ {% endif %} + {% buttons %}