Merge lp:~jaboing/canonical-identity-provider/debug_paper_codes into lp:canonical-identity-provider/release

Proposed by Julien Funk
Status: Rejected
Rejected by: Natalia Bidart
Proposed branch: lp:~jaboing/canonical-identity-provider/debug_paper_codes
Merge into: lp:canonical-identity-provider/release
Diff against target: 323 lines (+182/-48)
6 files modified
acceptance/pages.py (+96/-0)
acceptance/tests/devices/scripts/test_device_login.py (+79/-46)
webui/models.py (+1/-0)
webui/templates/account/edit.html (+1/-1)
webui/templates/account/suspended.html (+2/-0)
webui/templates/ubuntu/registration/twofactor.html (+3/-1)
To merge this branch: bzr merge lp:~jaboing/canonical-identity-provider/debug_paper_codes
Reviewer Review Type Date Requested Status
Leo Arias (community) Needs Fixing
Review via email: mp+165489@code.launchpad.net

Commit message

Refactored login.py to test_device_login.py now uses the testclass format.

Description of the change

Refactored login.py to test_device_login.py now uses the testclass format.

To post a comment you must log in.
Revision history for this message
Leo Arias (elopio) wrote :

<elopio> jfunk: why did you add
<elopio> 239␉+# -*- coding: utf-8 -*-
<elopio> ?
<jfunk> elopio, I never added that actually, don't know how or why
<jfunk> sometimes my trackpad does interesting things
<jfunk> I can delete that
<elopio> jfunk: did you merge with trunk?
<jfunk> elopio, yes
<elopio> weird then.
<elopio> jfunk: well, the thing with the encoding is that the pep says it should be added just if required.
<elopio> some people prefer to add it always.
<elopio> so we don't have a real preference on that. It just looked weird on your mp.
<jfunk> yeah agree
<elopio> jfunk: I would rename go_to_edit_preferences to go_to_your_account, as it has preferences and other information.
<jfunk> elopio, sure
<jfunk> elopio, the reason why I called it that is because the template is named 'edit.html'
<elopio> jfunk: on TwoFactorVerify, the title is not being used if you define the qa_anchor.
<elopio> jfunk: l. 101 is not aligned. It will fail on the pep8 test.
<jfunk> weird, I checked that out, thanks
<elopio> according to the clean code book, functions that receive booleans are terrible.
<elopio> on python I think they are not so bad, because we have keyword arguments, so I try no to use them a lot but I still find them useful
<elopio> on your branch, a nice example is self._set_twofactor(True)
<elopio> it will be more readable if you do self._set_twofactor(always_required=True)
<elopio> I think attempt_unverified_account_access shouldn't be part of the page.
<elopio> I think it will be only used once, by the test. So I'll move it to the test.
<elopio> and, I would keep the comment about bug #923814
<hal> Bug #923814: "Always require an auth device" doesn't! <http://launchpad.net/bugs/923814>
<elopio> jfunk: those are all my comments. Tests look really nice. Thanks again.
<elopio> and they will look even nicer tomorrow when I land the fixtures.
<jfunk> elopio, cool! I am going to try hard to get the rest of devices done this week

review: Needs Fixing
880. By Julien Funk

Merging with trunk.

881. By Julien Funk

resolved conflict with merge

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Setting MP as Rejected to reduce numbers of landing candidates in @reviewlist. Change status again if this MP is still current.

Unmerged revisions

881. By Julien Funk

resolved conflict with merge

880. By Julien Funk

Merging with trunk.

879. By Julien Funk

merging with latest

878. By Julien Funk

refactored the 2F tests from login.py to use the testcase class format

877. By Julien Funk

updating my branch with latest from trunk

876. By Julien Funk

merging after new pull

875. By Julien Funk

In progress of writing test_device_login with changes to pages.py

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'acceptance/pages.py'
2--- acceptance/pages.py 2013-05-28 07:18:34 +0000
3+++ acceptance/pages.py 2013-05-30 22:51:25 +0000
4@@ -33,6 +33,16 @@
5 sst.actions.click_link('devices-link')
6 return YourAuthenticationDevices()
7
8+ @log_action(logging.info)
9+ def go_to_your_account(self):
10+ sst.actions.click_link('account-link')
11+ return YourAccount(self.get_user_name())
12+
13+ @log_action(logging.info)
14+ def log_out(self):
15+ sst.actions.click_link('logout-link')
16+ return YouHaveBeenLoggedOut()
17+
18
19 class PageWithUsernameInTitle(PageWithUserSubheader):
20
21@@ -50,6 +60,9 @@
22
23 """
24
25+ url_path = '(/|/\+login)'
26+ is_url_path_regex = True
27+
28 @log_action(logging.info)
29 def log_in_to_site_recognized(self, user=None):
30 """Fill the log in form and continue to the site that requested it.
31@@ -64,6 +77,71 @@
32 self._log_in(user)
33 return YourAccount()
34
35+ @log_action(logging.info)
36+ def log_in_with_two_factor(self, user=None):
37+ """Fill the log in form and continue to two factor authentication."""
38+ self._log_in(user)
39+ return TwoFactorVerify()
40+
41+
42+class TwoFactorVerify(PageWithUserSubheader):
43+ """The page where customer is prompted for a 2FA key"""
44+
45+ url_path = '/two_factor_auth.*'
46+ is_url_path_regex = True
47+ qa_anchor = 'two_factor_verify'
48+
49+ @log_action(logging.info)
50+ def two_factor_authentication(self, one_time_password):
51+ self._fill_one_time_password_form(one_time_password)
52+ self._click_authenticate()
53+ return YourAccount(self.subheader.get_user_name())
54+
55+ @log_action(logging.info)
56+ def authenticate_2F_with_error(self, bad_password):
57+ self._fill_one_time_password_form(bad_password)
58+ self._click_authenticate()
59+ return TwoFactorVerify()
60+
61+ @log_action(logging.info)
62+ def last_2F_attempt_with_error(self, bad_password):
63+ self._fill_one_time_password_form(bad_password)
64+ self._click_authenticate()
65+ return YouAreSuspendedSucka()
66+
67+ def _fill_one_time_password_form(self, one_time_password):
68+ sst.actions.write_textfield('id_oath_token', one_time_password)
69+
70+ def _click_authenticate(self):
71+ auth_button = sst.actions.get_element_by_css(
72+ '*[data-qa-id="auth_button"]')
73+ sst.actions.click_button(auth_button)
74+
75+ def get_form_errors(self):
76+ try:
77+ one_time_password_error = sst.actions.get_element(
78+ css_class='error').text
79+ except AssertionError:
80+ one_time_password_error = None
81+ return one_time_password_error
82+
83+
84+class YouHaveBeenLoggedOut(u1testutils.sso.sst.pages.YouHaveBeenLoggedOut):
85+ """The logged out landing page of the Ubuntu Single Sign On website."""
86+
87+ @log_action(logging.info)
88+ def click_log_in_or_create_account(self):
89+ sst.actions.click_link('login-link')
90+ return LogIn()
91+
92+
93+class YouAreSuspendedSucka(u1testutils.sst.Page):
94+ """This is the page you are given if you fail 2 Factor 18 times."""
95+
96+ title = 'Rate limit exceeded'
97+ url_path = '/+suspended'
98+ qa_anchor = 'account_suspended'
99+
100
101 class YourAccount(PageWithUserSubheader):
102 """Your account page of the Ubuntu Single Sign On website.
103@@ -76,6 +154,24 @@
104 url_path = '/'
105 qa_anchor = 'edit_account'
106
107+ def _set_twofactor(self, required):
108+ radio = sst.actions.get_element(tag="input", name="twofactor_required",
109+ value=required)
110+ sst.actions.set_radio_value(radio)
111+
112+ @log_action(logging.info)
113+ def set_twofactor_to_always_required(self):
114+ self._set_twofactor(always_required=True)
115+
116+ @log_action(logging.info)
117+ def set_twofactor_to_required_as_needed(self):
118+ self._set_twofactor(always_required=False)
119+
120+ @log_action(logging.info)
121+ def click_update_button(self):
122+ sst.actions.click_button(sst.actions.get_element_by_css(
123+ '*[data-qa-id="update_preferences"]'))
124+
125
126 class YourEmailAddresses(u1testutils.sso.sst.pages.PageWithUserSubheader):
127
128
129=== renamed file 'acceptance/tests/devices/scripts/login.py' => 'acceptance/tests/devices/scripts/test_device_login.py'
130--- acceptance/tests/devices/scripts/login.py 2013-05-27 17:53:40 +0000
131+++ acceptance/tests/devices/scripts/test_device_login.py 2013-05-30 22:51:25 +0000
132@@ -1,57 +1,90 @@
133-# Test logging in with two factor authentication
134+# Copyright 2012, 2013 Canonical Ltd.
135+# This software is licensed under the GNU Affero General Public License
136+# version 3 (see the file LICENSE).
137+
138 from sst.actions import (
139 assert_displayed,
140- assert_text,
141- assert_url,
142- click_link,
143- get_base_url,
144- get_element,
145- go_to,
146+ assert_element,
147+ wait_for,
148 )
149 from u1testutils.sst import config
150
151+from acceptance import helpers
152 from acceptance.devices import (
153 add_device,
154- authenticate,
155 enter_otp,
156 )
157-from acceptance import helpers
158-
159-
160-config.set_base_url_from_env()
161-base_url = get_base_url()
162-
163-email = helpers.login_or_register_account(device_cleanup=True)
164-
165-# Go to the authentication devices page
166-click_link('devices-link')
167-
168-# Add an authentication device
169-add_device('login')
170-
171-# Change the preference to always require 2 factor authentication and save
172-helpers.set_twofactor_to_always_required()
173-
174-# Logout and attempt to log back in
175-helpers.logout_and_in()
176-
177-# Should insist on 2F and not give access to '/'
178-# In response to defect #923814
179-go_to(base_url)
180-
181-# Check we are on the 2-factor login page
182-assert_displayed('id_oath_token')
183-
184-# Enter an invalid password and submit
185-enter_otp('foo bar baz')
186-
187-# Check an error message is shown and we are not logged in
188-assert_displayed('id_oath_token')
189-assert_text(get_element(css_class='error'),
190+
191+import pdb
192+
193+import sst.actions
194+
195+from oath import hotp
196+
197+from acceptance import base
198+
199+
200+class TestDeviceLogin(base.SSTTestCaseWithLogIn):
201+
202+ def navigate_to_page(self):
203+ """Go to the AddNewAuthenticationDevice page.
204+
205+ It will be accessible for the tests from the page attribute.
206+
207+ """
208+ # 'start' is the base YourAccount page object.
209+ start = super(TestDeviceLogin, self).navigate_to_page()
210+ auth_devices = start.subheader.go_to_authentication_devices()
211+ return auth_devices.add_new_authentication_device()
212+
213+ def test_account_suspension(self):
214+ pdb.set_trace()
215+ from time import sleep
216+ two_f_page = self._set_two_factor_required_then_logout_and_in()
217+ for _ in range(17):
218+ two_f_page = two_f_page.authenticate_2F_with_error('bad pass')
219+ suspended_page = two_f_page.last_2F_attempt_with_error('bad pass')
220+ self.assertEqual(suspended_page.qa_anchor, 'account_suspended')
221+
222+ #for _ in range(18):
223+ ## Check we are on the 2-factor login page
224+ #wait_for(assert_displayed, 'id_oath_token')
225+ ## Enter an incorrect password and submit
226+ #enter_otp('12345678')
227+ ## The account is now suspended
228+ #assert_element(tag='h1', text='Account suspended')
229+
230+ def _set_two_factor_required_then_logout_and_in(self):
231+ add_generic_device_page = self.page.add_generic_device()
232+ self.aes_key = add_generic_device_page.get_key()
233+ one_time_pass = hotp.hotp(self.aes_key, 0)
234+ auth_devices_page = add_generic_device_page.add_device(
235+ 'Test generic device', one_time_pass)
236+ your_account_page = auth_devices_page.subheader.go_to_your_account()
237+ your_account_page.set_twofactor_to_always_required()
238+ your_account_page.click_update_button()
239+ logout_landing_page = your_account_page.subheader.log_out()
240+ login_page = logout_landing_page.click_log_in_or_create_account()
241+ return login_page.log_in_with_two_factor(self.user)
242+"""
243+ def test_login_with_generic_device(self):
244+ two_factor_page = self._set_two_factor_required_then_logout_and_in()
245+ one_time_pass = hotp.hotp(self.aes_key, 1)
246+ account_page = two_factor_page.two_factor_authentication(one_time_pass)
247+ self.assertEqual(account_page.qa_anchor, 'edit_account')
248+
249+ def test_invalid_two_factor_password(self):
250+ two_factor_page = self._set_two_factor_required_then_logout_and_in()
251+ two_factor_page = two_factor_page.authenticate_2F_with_error('bad pass')
252+ one_time_password_error = two_factor_page.get_form_errors()
253+ self.assertEqual(
254+ one_time_password_error,
255 'Please enter a 6-digit or 8-digit one-time password.')
256
257-# Enter a valid one time password
258-authenticate('login')
259-
260-# Check we are now logged in
261-assert_url('/')
262+ def test_attempt_skipping_two_factor_prompt(self):
263+ two_factor_page = self._set_two_factor_required_then_logout_and_in()
264+ # Should insist on 2F and not give access to '/'
265+ # In response to defect 923814
266+ sst.actions.go_to('/')
267+ self.assertEqual(two_factor_page.qa_anchor, 'two_factor_verify')
268+"""
269\ No newline at end of file
270
271=== modified file 'webui/models.py'
272--- webui/models.py 2012-12-03 17:50:53 +0000
273+++ webui/models.py 2013-05-30 22:51:25 +0000
274@@ -0,0 +1,1 @@
275+# -*- coding: utf-8 -*-
276
277=== modified file 'webui/templates/account/edit.html'
278--- webui/templates/account/edit.html 2013-05-15 07:47:10 +0000
279+++ webui/templates/account/edit.html 2013-05-30 22:51:25 +0000
280@@ -145,7 +145,7 @@
281
282 <p class="actions">
283 {% if not readonly %}
284- <button type="submit" class="btn" name="update"><span><span>{% trans "Update" %}</span></span></button>
285+ <button type="submit" class="btn" name="update" data-qa-id="update_preferences"><span><span>{% trans "Update" %}</span></span></button>
286 {% endif %}
287 {% if token %}
288 {% trans "or" %}
289
290=== modified file 'webui/templates/account/suspended.html'
291--- webui/templates/account/suspended.html 2010-07-12 19:11:15 +0000
292+++ webui/templates/account/suspended.html 2013-05-30 22:51:25 +0000
293@@ -6,6 +6,8 @@
294 GNU Affero General Public License version 3 (see the file LICENSE).
295 {% endcomment %}
296
297+{% block html_extra %}data-qa-id="account_suspended"{% endblock %}
298+
299 {% block title %}{% trans "Account suspended" %}{% endblock %}
300
301 {% block text_title %}
302
303=== modified file 'webui/templates/ubuntu/registration/twofactor.html'
304--- webui/templates/ubuntu/registration/twofactor.html 2013-04-17 13:23:35 +0000
305+++ webui/templates/ubuntu/registration/twofactor.html 2013-05-30 22:51:25 +0000
306@@ -3,6 +3,8 @@
307 {% load i18n %}
308 {% load static_url %}
309
310+{% block html_extra %}data-qa-id="two_factor_verify"{% endblock %}
311+
312 {% block leftcol %}
313 <div id="auth">
314 {% if rpconfig %}
315@@ -40,7 +42,7 @@
316
317 <div class="actions">
318 {% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
319- <button type="submit" class="btn" name="continue"><span><span>{% trans "Authenticate" %}</span></span></button>
320+ <button type="submit" class="btn" name="continue" data-qa-id="auth_button"><span><span>{% trans "Authenticate" %}</span></span></button>
321 {% if token %}{% trans "or" %}
322 {% include "common/cancel_link.html" %}{% endif %}
323 </div>