Merge lp:~maxiberta/canonical-identity-provider/smarter-forget-password-link into lp:canonical-identity-provider/release

Proposed by Maximiliano Bertacchini on 2019-01-09
Status: Merged
Approved by: Maximiliano Bertacchini on 2019-01-15
Approved revision: 1676
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: lp:~maxiberta/canonical-identity-provider/smarter-forget-password-link
Merge into: lp:canonical-identity-provider/release
Diff against target: 143 lines (+34/-22)
7 files modified
src/identityprovider/tests/openid_server/per_version/test_sso_workflow_reset_password.py (+6/-9)
src/identityprovider/tests/sso_server/test_prefilled_email.py (+5/-4)
src/webui/templates/common/forgot_password_link.html (+0/-5)
src/webui/templates/registration/_login_form.html (+5/-1)
src/webui/templates/registration/login.html (+1/-1)
src/webui/tests/test_views_registration.py (+14/-0)
src/webui/views/registration.py (+3/-2)
To merge this branch: bzr merge lp:~maxiberta/canonical-identity-provider/smarter-forget-password-link
Reviewer Review Type Date Requested Status
Tom Wardill 2019-01-09 Approve on 2019-01-14
Review via email: mp+361579@code.launchpad.net

Commit message

Pre-fill forgot password form with email value entered in the login form.

To post a comment you must log in.
Maximiliano Bertacchini (maxiberta) wrote :

Some notes:
- Turned login's "Forgot your password?" into <input> so that it can POST the current value of the email field.
- The new <input> link has the "formnovalidate" attribute set to skip client-side form validations, e.g. non-empty password. Thus whatever value is currently set in the email field is POSTed to and validated by the forgot-password view.
- The new <input> link has the "formaction" attribute defined to make its destination URL more explicit and easier to test.
- The new <input> link has some css magic to make it look like an <a>.

Tom Wardill (twom) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/identityprovider/tests/openid_server/per_version/test_sso_workflow_reset_password.py'
--- src/identityprovider/tests/openid_server/per_version/test_sso_workflow_reset_password.py 2018-02-08 15:12:52 +0000
+++ src/identityprovider/tests/openid_server/per_version/test_sso_workflow_reset_password.py 2019-01-09 18:49:43 +0000
@@ -21,9 +21,8 @@
21 # At this point, we are at the login page. Lets try to recover a21 # At this point, we are at the login page. Lets try to recover a
22 # password for an unregistered email.22 # password for an unregistered email.
23 link = self.get_attribute_from_response(23 link = self.get_attribute_from_response(
24 response,24 response, 'input[name="forgot_password"]', 'formaction')
25 'a[data-qa-id="forgot_password_link"]',25
26 'href')
27 data = dict(email='no-account@example.com')26 data = dict(email='no-account@example.com')
28 response = self.client.post(link, data=data, follow=True)27 response = self.client.post(link, data=data, follow=True)
2928
@@ -36,9 +35,8 @@
36 response = self.do_openid_dance()35 response = self.do_openid_dance()
3736
38 link = self.get_attribute_from_response(37 link = self.get_attribute_from_response(
39 response,38 response, 'input[name="forgot_password"]', 'formaction')
40 'a[data-qa-id="forgot_password_link"]',39
41 'href')
42 data = dict(email='support@ubuntu.com')40 data = dict(email='support@ubuntu.com')
43 response = self.client.post(link, data=data, follow=True)41 response = self.client.post(link, data=data, follow=True)
4442
@@ -51,9 +49,8 @@
5149
52 response = self.do_openid_dance()50 response = self.do_openid_dance()
53 link = self.get_attribute_from_response(51 link = self.get_attribute_from_response(
54 response,52 response, 'input[name="forgot_password"]', 'formaction')
55 'a[data-qa-id="forgot_password_link"]',53
56 'href')
57 data = dict(email=self.default_email)54 data = dict(email=self.default_email)
58 response = self.client.post(link, data=data, follow=True)55 response = self.client.post(link, data=data, follow=True)
5956
6057
=== modified file 'src/identityprovider/tests/sso_server/test_prefilled_email.py'
--- src/identityprovider/tests/sso_server/test_prefilled_email.py 2013-11-12 13:44:06 +0000
+++ src/identityprovider/tests/sso_server/test_prefilled_email.py 2019-01-09 18:49:43 +0000
@@ -13,11 +13,12 @@
13 """Forgot Password form."""13 """Forgot Password form."""
14 response = self.login(email=self.new_email)14 response = self.login(email=self.new_email)
1515
16 email = self.get_attribute_from_response(
17 response, 'input[name="email"]', 'value')
16 link = self.get_attribute_from_response(18 link = self.get_attribute_from_response(
17 response,19 response, 'input[name="forgot_password"]', 'formaction')
18 'a[data-qa-id="forgot_password_link"]',
19 'href')
2020
21 response = self.client.get(link)21 response = self.client.post(
22 link, data={'email': email, 'forgot_password': ''})
22 email_field = self.get_from_response(response, 'input[name="email"]')23 email_field = self.get_from_response(response, 'input[name="email"]')
23 self.assertEqual(email_field[0].get('value'), self.new_email)24 self.assertEqual(email_field[0].get('value'), self.new_email)
2425
=== removed file 'src/webui/templates/common/forgot_password_link.html'
--- src/webui/templates/common/forgot_password_link.html 2017-02-26 01:29:52 +0000
+++ src/webui/templates/common/forgot_password_link.html 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
1{% load i18n url_with_token %}
2{% if not readonly %}
3 <a href="{% url_with_token 'forgot_password' %}{% if form.email.data %}?email={{ form.email.data|urlencode }}{% endif %}"
4 id="forgotpw-link" data-qa-id="forgot_password_link">{% trans "Forgot your password?" %}</a>
5{% endif %}
60
=== modified file 'src/webui/templates/registration/_login_form.html'
--- src/webui/templates/registration/_login_form.html 2017-02-26 01:29:52 +0000
+++ src/webui/templates/registration/_login_form.html 2019-01-09 18:49:43 +0000
@@ -43,7 +43,11 @@
43 <button type="submit" class="btn cta" name="continue" data-qa-id="login_button">43 <button type="submit" class="btn cta" name="continue" data-qa-id="login_button">
44 <span>{% trans "Log in" %}</span>44 <span>{% trans "Log in" %}</span>
45 </button>45 </button>
46 <p class="forgot-password">{% include "common/forgot_password_link.html" %}</p>46 {% if not readonly %}
47 <input type="submit" class="forgot-password" name="forgot_password" formnovalidate formaction="{% url_with_token 'forgot_password' %}"
48 style="border:none; outline:none; background:none; cursor:pointer; color:#dd4814;"
49 value="{% trans 'Forgot your password?' %}">
50 {% endif %}
4751
48 {% comment %}52 {% comment %}
49 {% if token %}{% trans "or" %}53 {% if token %}{% trans "or" %}
5054
=== modified file 'src/webui/templates/registration/login.html'
--- src/webui/templates/registration/login.html 2014-12-10 15:30:54 +0000
+++ src/webui/templates/registration/login.html 2019-01-09 18:49:43 +0000
@@ -26,7 +26,7 @@
26 <h1 class="u1-h-main">{% trans "One account to log in to everything on Ubuntu" %}</h1>26 <h1 class="u1-h-main">{% trans "One account to log in to everything on Ubuntu" %}</h1>
27{% endblock %}27{% endblock %}
2828
29/div>29</div>
3030
31{% block extra_css %}31{% block extra_css %}
32 {% if rpconfig and rpconfig.logo_url %}32 {% if rpconfig and rpconfig.logo_url %}
3333
=== modified file 'src/webui/tests/test_views_registration.py'
--- src/webui/tests/test_views_registration.py 2018-12-20 18:23:07 +0000
+++ src/webui/tests/test_views_registration.py 2019-01-09 18:49:43 +0000
@@ -496,6 +496,20 @@
496 ctx = response.context_data496 ctx = response.context_data
497 self.assertEqual(ctx['form']['email'].value(), 'test@test.com')497 self.assertEqual(ctx['form']['email'].value(), 'test@test.com')
498498
499 def test_post_with_initial_data(self):
500 data = dict(email='test@test.com', forgot_password='')
501 response = self.post(data=data)
502 self.assert_form_displayed(response)
503 ctx = response.context_data
504 self.assertEqual(ctx['form']['email'].value(), 'test@test.com')
505
506 def test_post_with_initial_data_no_email(self):
507 data = dict(forgot_password='')
508 response = self.post(data=data)
509 self.assert_form_displayed(response)
510 ctx = response.context_data
511 self.assertIsNone(ctx['form']['email'].value())
512
499 def test_post_required_fields(self):513 def test_post_required_fields(self):
500 response = self.post()514 response = self.post()
501 self.assert_form_displayed(response, email=FIELD_REQUIRED)515 self.assert_form_displayed(response, email=FIELD_REQUIRED)
502516
=== modified file 'src/webui/views/registration.py'
--- src/webui/views/registration.py 2018-12-20 18:23:07 +0000
+++ src/webui/views/registration.py 2019-01-09 18:49:43 +0000
@@ -186,10 +186,11 @@
186 def collect_stats(key):186 def collect_stats(key):
187 stats.increment('flows.forgot_password', key=key, rpconfig=rpconfig)187 stats.increment('flows.forgot_password', key=key, rpconfig=rpconfig)
188188
189 if request.method == 'GET':189 if request.method == 'GET' or 'forgot_password' in request.POST:
190 # track forgot password requests190 # track forgot password requests
191 collect_stats('requested')191 collect_stats('requested')
192 form = GenericEmailForm(initial={'email': request.GET.get('email')})192 email = request.GET.get('email', request.POST.get('email'))
193 form = GenericEmailForm(initial={'email': email})
193194
194 elif request.method == 'POST':195 elif request.method == 'POST':
195 form = GenericEmailForm(request.POST)196 form = GenericEmailForm(request.POST)