Merge lp:~matiasb/canonical-identity-provider/more-on-password-validation into lp:canonical-identity-provider/release

Proposed by Matias Bordese
Status: Merged
Approved by: Ricardo Kirkner
Approved revision: no longer in the source branch.
Merged at revision: 563
Proposed branch: lp:~matiasb/canonical-identity-provider/more-on-password-validation
Merge into: lp:canonical-identity-provider/release
Diff against target: 1031 lines (+190/-97)
23 files modified
api/tests/test_handlers.py (+22/-10)
identityprovider/fixtures/test.json (+3/-3)
identityprovider/models/account.py (+20/-8)
identityprovider/tests/__init__.py (+5/-0)
identityprovider/tests/factory.py (+7/-2)
identityprovider/tests/functional/__init__.py (+0/-11)
identityprovider/tests/unit/test_auth.py (+15/-7)
identityprovider/tests/unit/test_command_add_to_team.py (+2/-1)
identityprovider/tests/unit/test_command_upload_fobs.py (+2/-1)
identityprovider/tests/unit/test_forms.py (+6/-3)
identityprovider/tests/unit/test_middleware.py (+3/-2)
identityprovider/tests/unit/test_models_account.py (+31/-8)
identityprovider/tests/unit/test_models_team.py (+2/-2)
identityprovider/tests/unit/test_validators.py (+4/-0)
identityprovider/tests/unit/test_views_preflight.py (+8/-4)
identityprovider/tests/unit/test_views_server.py (+17/-10)
identityprovider/tests/utils.py (+2/-1)
webui/tests/test_static.py (+5/-2)
webui/tests/test_views_account.py (+3/-1)
webui/tests/test_views_devices.py (+8/-7)
webui/tests/test_views_i18n.py (+4/-2)
webui/tests/test_views_ui.py (+18/-12)
webui/views/ui.py (+3/-0)
To merge this branch: bzr merge lp:~matiasb/canonical-identity-provider/more-on-password-validation
Reviewer Review Type Date Requested Status
Ricardo Kirkner (community) Approve
Review via email: mp+140244@code.launchpad.net

Commit message

Forced password and email address (ie, looks like an email address) validation on account creation through AccountManager.

Description of the change

Forced password and email address validation on account creation through AccountManager.
Refactored tests accordingly; added a DEFAULT_USER_PASSWORD constant, policy compliant, to reuse in tests.
Functional tests temporarily disabled (nessita is working on those and will update them during the process).

To post a comment you must log in.
Revision history for this message
Ricardo Kirkner (ricardokirkner) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'api/tests/test_handlers.py'
2--- api/tests/test_handlers.py 2012-12-13 20:19:19 +0000
3+++ api/tests/test_handlers.py 2012-12-17 20:24:41 +0000
4@@ -27,6 +27,10 @@
5 EmailStatus,
6 LoginTokenType,
7 )
8+from identityprovider.tests import (
9+ DEFAULT_API_PASSWORD,
10+ DEFAULT_USER_PASSWORD,
11+)
12 from identityprovider.validators import PASSWORD_POLICY_ERROR
13
14 from api.tests.utils import (
15@@ -35,8 +39,8 @@
16 )
17
18
19-def http_authorization_extra(email_address):
20- email_address = base64.b64encode(email_address + ':test')
21+def http_authorization_extra(email_address, password):
22+ email_address = base64.b64encode('%s:%s' % (email_address, password))
23 return {'HTTP_AUTHORIZATION': 'basic ' + email_address}
24
25 AUTHTOKEN = 'identityprovider.models.authtoken.%s'
26@@ -262,7 +266,8 @@
27 if token is not None:
28 data['token'] = token
29
30- extra = http_authorization_extra(self.email_address)
31+ extra = http_authorization_extra(self.email_address,
32+ password=DEFAULT_USER_PASSWORD)
33 dispatcher = getattr(self.client, method.lower())
34 response = dispatcher("/api/%s/authentications" % api_version, data,
35 **extra)
36@@ -277,7 +282,8 @@
37 }
38 if max_age is not None:
39 data['max_age'] = max_age
40- extra = http_authorization_extra(self.apiuser.username)
41+ extra = http_authorization_extra(self.apiuser.username,
42+ password=DEFAULT_API_PASSWORD)
43 response = self.client.get('/api/1.0/authentications', data, **extra)
44 content = simplejson.loads(response.content)
45 return content
46@@ -355,7 +361,8 @@
47 self.assertEqual(token1[key], token2[key])
48
49 def test_authenticate_refresh_account_has_no_tokens(self):
50- extra = http_authorization_extra(self.email_address)
51+ extra = http_authorization_extra(self.email_address,
52+ password=DEFAULT_USER_PASSWORD)
53 data = {
54 'ws.op': 'authenticate',
55 'token_name': 'some-token',
56@@ -369,7 +376,8 @@
57 self.assertEqual(response.status_code, 404)
58
59 def test_authenticate_refresh_token_is_not_owned(self):
60- extra = http_authorization_extra(self.email_address)
61+ extra = http_authorization_extra(self.email_address,
62+ password=DEFAULT_USER_PASSWORD)
63 data = {
64 'ws.op': 'authenticate',
65 'token_name': 'some-token',
66@@ -405,7 +413,8 @@
67 self.factory.add_account_to_team(account, team)
68
69 # Request membership via API
70- extra = http_authorization_extra('foobar')
71+ extra = http_authorization_extra('foobar',
72+ password=DEFAULT_API_PASSWORD)
73 data = {
74 'ws.op': 'team_memberships',
75 'team_names': '["%s", "%s"]' % (team.name, otherteam.name),
76@@ -422,7 +431,8 @@
77 self.factory.add_account_to_team(account, team)
78
79 # Request membership via API
80- extra = http_authorization_extra('foobar')
81+ extra = http_authorization_extra('foobar',
82+ password=DEFAULT_API_PASSWORD)
83 data = {
84 'ws.op': 'team_memberships',
85 'team_names': '["%s"]' % team.name,
86@@ -443,7 +453,8 @@
87 def test_team_membership_fails_for_regular_user(self):
88 email_address = self.factory.make_email_address()
89 self.factory.make_account(email=email_address)
90- extra = http_authorization_extra(email_address)
91+ extra = http_authorization_extra(email_address,
92+ password=DEFAULT_USER_PASSWORD)
93 data = {
94 'ws.op': 'team_memberships',
95 'team_names': '["something"]',
96@@ -499,7 +510,8 @@
97
98 def test_me_is_oauth_protected(self):
99 email_address = self.factory.make_email_address()
100- extra = http_authorization_extra(email_address)
101+ extra = http_authorization_extra(email_address,
102+ password=DEFAULT_USER_PASSWORD)
103 data = {'ws.op': 'me'}
104 response = self.client.get('/api/1.0/accounts', data, **extra)
105 self.assertEqual(401, response.status_code)
106
107=== modified file 'identityprovider/fixtures/test.json'
108--- identityprovider/fixtures/test.json 2012-01-20 17:50:59 +0000
109+++ identityprovider/fixtures/test.json 2012-12-17 20:24:41 +0000
110@@ -91,7 +91,7 @@
111 "model": "identityprovider.accountpassword",
112 "fields": {
113 "account": 1,
114- "password": "K7Qmeansl6RbuPfulfcmyDQOzp70OxVh5Fcf"
115+ "password": "7whYlTsp37YAwPVAzJmQ5T6+3jKRglh4Vv1Empr/ek2S87QzkJDHQQ=="
116 }
117 },
118 {
119@@ -99,7 +99,7 @@
120 "model": "identityprovider.accountpassword",
121 "fields": {
122 "account": 12,
123- "password": "K7Qmeansl6RbuPfulfcmyDQOzp70OxVh5Fcf"
124+ "password": "7whYlTsp37YAwPVAzJmQ5T6+3jKRglh4Vv1Empr/ek2S87QzkJDHQQ=="
125 }
126 },
127 {
128@@ -107,7 +107,7 @@
129 "model": "identityprovider.accountpassword",
130 "fields": {
131 "account": 243610,
132- "password": "9I7bMpJUcBH+edfXjswjdo7nC6iuoTU6YAqolznT59Q1h9v+z9pdVQ=="
133+ "password": "7whYlTsp37YAwPVAzJmQ5T6+3jKRglh4Vv1Empr/ek2S87QzkJDHQQ=="
134 }
135 },
136
137
138=== modified file 'identityprovider/models/account.py'
139--- identityprovider/models/account.py 2012-12-12 19:49:16 +0000
140+++ identityprovider/models/account.py 2012-12-17 20:24:41 +0000
141@@ -21,6 +21,7 @@
142 generate_openid_identifier,
143 get_object_or_none,
144 )
145+from identityprovider.validators import validate_password_policy
146
147 __all__ = [
148 'Account',
149@@ -44,24 +45,35 @@
150 password_encrypted=False, email_validated=True,
151 openid_identifier=None):
152 from identityprovider.models import EmailAddress
153+
154+ # do validation before account (and related) creation/save
155+ if not password_encrypted:
156+ # an encrypted password is assumed to be valid
157+ # this will raise a ValidationError if password does not
158+ # complies with policy
159+ validate_password_policy(password)
160+ password = encrypt_launchpad_password(password, salt=salt)
161+
162+ email_status = (
163+ EmailStatus.PREFERRED if email_validated else EmailStatus.NEW)
164+ email = EmailAddress(email=email_address, status=email_status)
165+ email.full_clean()
166+
167 if creation_rationale is None:
168 creation_rationale = (
169 AccountCreationRationale.OWNER_CREATED_LAUNCHPAD)
170+
171 kwargs = {
172 'displayname': displayname,
173 'creation_rationale': creation_rationale,
174 'status': AccountStatus.ACTIVE}
175+
176 if openid_identifier is not None:
177 kwargs['openid_identifier'] = openid_identifier
178+
179 account = Account.objects.create(**kwargs)
180- email_status = (
181- EmailStatus.PREFERRED if email_validated else EmailStatus.NEW)
182- EmailAddress.objects.create(
183- email=email_address,
184- account=account,
185- status=email_status)
186- if not password_encrypted:
187- password = encrypt_launchpad_password(password, salt=salt)
188+ email.account = account
189+ email.save()
190 password = AccountPassword.objects.create(
191 account=account,
192 password=password)
193
194=== modified file 'identityprovider/tests/__init__.py'
195--- identityprovider/tests/__init__.py 2012-12-03 17:50:53 +0000
196+++ identityprovider/tests/__init__.py 2012-12-17 20:24:41 +0000
197@@ -8,3 +8,8 @@
198
199 # Disable writing OpenID messaged to stderr
200 oidutil.log = logging.debug
201+
202+# default api/account passwords, policy compliant
203+DEFAULT_API_PASSWORD = 'test'
204+# when changing, make sure to update test fixture with the encrypted password
205+DEFAULT_USER_PASSWORD = 'test1Test'
206
207=== modified file 'identityprovider/tests/factory.py'
208--- identityprovider/tests/factory.py 2012-10-29 17:55:56 +0000
209+++ identityprovider/tests/factory.py 2012-12-17 20:24:41 +0000
210@@ -19,6 +19,10 @@
211 TeamParticipation,
212 )
213 from identityprovider.models.const import EmailStatus, LoginTokenType
214+from identityprovider.tests import (
215+ DEFAULT_API_PASSWORD,
216+ DEFAULT_USER_PASSWORD,
217+)
218
219
220 class SSOObjectFactory(object):
221@@ -37,7 +41,7 @@
222 """Return a unique integer for the test run."""
223 return self.counter.next()
224
225- def make_apiuser(self, username=None, password='test'):
226+ def make_apiuser(self, username=None, password=DEFAULT_API_PASSWORD):
227 if username is None:
228 username = self.get_unique_string(prefix='apiuser-')
229 user, created = APIUser.objects.get_or_create(username=username)
230@@ -45,7 +49,8 @@
231 user.save()
232 return user
233
234- def make_account(self, displayname=None, email=None, password='test',
235+ def make_account(self, displayname=None, email=None,
236+ password=DEFAULT_USER_PASSWORD,
237 creation_rationale=None, salt=None,
238 password_encrypted=False, email_validated=True,
239 openid_identifier=None):
240
241=== removed file 'identityprovider/tests/functional/__init__.py'
242--- identityprovider/tests/functional/__init__.py 2012-01-06 20:28:28 +0000
243+++ identityprovider/tests/functional/__init__.py 1970-01-01 00:00:00 +0000
244@@ -1,11 +0,0 @@
245-from wsgi_intercept import add_wsgi_intercept
246-from wsgi_intercept.urllib2_intercept import install_opener
247-
248-from identityprovider.wsgi import make_app
249-
250-
251-install_opener()
252-
253-add_wsgi_intercept('openid.launchpad.dev', 80, make_app)
254-add_wsgi_intercept('launchpad.dev', 80, make_app)
255-add_wsgi_intercept('localhost', 80, make_app)
256
257=== modified file 'identityprovider/tests/unit/test_auth.py'
258--- identityprovider/tests/unit/test_auth.py 2012-10-29 16:06:36 +0000
259+++ identityprovider/tests/unit/test_auth.py 2012-12-17 20:24:41 +0000
260@@ -20,6 +20,7 @@
261 SSOOAuthAuthentication,
262 oauth_authenticate,
263 )
264+from identityprovider.tests import DEFAULT_USER_PASSWORD
265 from identityprovider.tests.utils import SSOBaseTestCase
266
267
268@@ -36,7 +37,8 @@
269 email_address.status = EmailStatus.OLD
270 email_address.save()
271
272- result = self.backend.authenticate('mark@example.com', 'test')
273+ result = self.backend.authenticate('mark@example.com',
274+ DEFAULT_USER_PASSWORD)
275
276 self.assertTrue(result is None)
277
278@@ -46,11 +48,13 @@
279
280 def test_authenticate_with_email_case_insensitive(self):
281 # Make sure authentication works as expected
282- account1 = self.backend.authenticate('mark@example.com', 'test')
283+ account1 = self.backend.authenticate('mark@example.com',
284+ DEFAULT_USER_PASSWORD)
285 self.assertTrue(account1 is not None)
286
287 # Try using different case for email
288- account2 = self.backend.authenticate('Mark@Example.com', 'test')
289+ account2 = self.backend.authenticate('Mark@Example.com',
290+ DEFAULT_USER_PASSWORD)
291 self.assertTrue(account2 is not None)
292
293 # Make sure both accounts are the same
294@@ -61,11 +65,13 @@
295 # make sure account is active
296 self.assertEqual(account.status, AccountStatus.ACTIVE)
297 # make sure authentication succeeds
298- response = self.backend.authenticate('mark@example.com', 'test')
299+ response = self.backend.authenticate('mark@example.com',
300+ DEFAULT_USER_PASSWORD)
301 self.assertEqual(response, account)
302
303 def test_authenticate_by_token_missing_account(self):
304- user = User.objects.create_user('test', 'test', password='test')
305+ user = User.objects.create_user('test', 'test',
306+ password=DEFAULT_USER_PASSWORD)
307 consumer = Consumer.objects.create(user=user)
308 token = Token.objects.create(consumer=consumer, name='test')
309
310@@ -84,7 +90,8 @@
311 account.save()
312
313 # make sure authentication fails
314- response = self.backend.authenticate('mark@example.com', 'test')
315+ response = self.backend.authenticate('mark@example.com',
316+ DEFAULT_USER_PASSWORD)
317 self.assertEqual(response, None)
318
319 # leave everything as it was
320@@ -95,7 +102,8 @@
321 account = Account.objects.get_by_email('mark@example.com')
322 account.accountpassword.delete()
323
324- response = self.backend.authenticate('mark@example.com', 'test')
325+ response = self.backend.authenticate('mark@example.com',
326+ DEFAULT_USER_PASSWORD)
327
328 self.assertTrue(response is None)
329 account = Account.objects.get_by_email('mark@example.com')
330
331=== modified file 'identityprovider/tests/unit/test_command_add_to_team.py'
332--- identityprovider/tests/unit/test_command_add_to_team.py 2012-10-29 16:06:36 +0000
333+++ identityprovider/tests/unit/test_command_add_to_team.py 2012-12-17 20:24:41 +0000
334@@ -6,6 +6,7 @@
335 from mock import patch
336
337 from identityprovider.models import Account, Person
338+from identityprovider.tests import DEFAULT_USER_PASSWORD
339 from identityprovider.utils import get_object_or_none
340
341
342@@ -13,7 +14,7 @@
343
344 def setUp(self):
345 self.account = Account.objects.create_account(
346- 'test', 'test@canonical.com', 'Test123',
347+ 'test', 'test@canonical.com', DEFAULT_USER_PASSWORD,
348 openid_identifier='openid')
349 self.team = Person.objects.create(name='TeamA')
350
351
352=== modified file 'identityprovider/tests/unit/test_command_upload_fobs.py'
353--- identityprovider/tests/unit/test_command_upload_fobs.py 2012-10-29 16:06:36 +0000
354+++ identityprovider/tests/unit/test_command_upload_fobs.py 2012-12-17 20:24:41 +0000
355@@ -11,6 +11,7 @@
356 LPOpenIdIdentifier,
357 Person,
358 )
359+from identityprovider.tests import DEFAULT_USER_PASSWORD
360
361
362 def mock_open(data):
363@@ -28,7 +29,7 @@
364
365 def setUp(self):
366 account = Account.objects.create_account(
367- test_username, test_username, 'Abcdef0')
368+ test_username, 'test@canonical.com', DEFAULT_USER_PASSWORD)
369 p = Person.objects.create(name=test_username)
370 p.lp_account = account.id
371 p.save()
372
373=== modified file 'identityprovider/tests/unit/test_forms.py'
374--- identityprovider/tests/unit/test_forms.py 2012-12-03 16:51:35 +0000
375+++ identityprovider/tests/unit/test_forms.py 2012-12-17 20:24:41 +0000
376@@ -19,6 +19,7 @@
377 TokenForm,
378 )
379 from identityprovider.models.openidmodels import OpenIDRPConfig
380+from identityprovider.tests import DEFAULT_USER_PASSWORD
381 from identityprovider.tests.utils import SSOBaseTestCase
382
383
384@@ -157,7 +158,7 @@
385
386 def setUp(self):
387 self.test_user = Account.objects.create_account(
388- 'My name', 'me@test.com', 'password')
389+ 'My name', 'me@test.com', DEFAULT_USER_PASSWORD)
390 self.rpconfig = OpenIDRPConfig.objects.create(
391 trust_root='http://localhost/', description="Some description")
392
393@@ -407,11 +408,13 @@
394 class LoginFormTestCase(SSOBaseTestCase):
395 def test_clean_email_mixed_case(self):
396 self.factory.make_account(email='Test.User@test.com')
397- data = {'email': 'Test.User@test.com', 'password': 'test'}
398+ data = {'email': 'Test.User@test.com',
399+ 'password': DEFAULT_USER_PASSWORD}
400 form = LoginForm(data=data)
401 self.assertTrue(form.is_valid())
402
403- data = {'email': 'test.user@test.com', 'password': 'test'}
404+ data = {'email': 'test.user@test.com',
405+ 'password': DEFAULT_USER_PASSWORD}
406 form = LoginForm(data=data)
407 self.assertTrue(form.is_valid())
408
409
410=== modified file 'identityprovider/tests/unit/test_middleware.py'
411--- identityprovider/tests/unit/test_middleware.py 2012-12-04 18:51:42 +0000
412+++ identityprovider/tests/unit/test_middleware.py 2012-12-17 20:24:41 +0000
413@@ -19,6 +19,7 @@
414 from identityprovider.middleware.useraccount import (
415 UserAccountConversionMiddleware)
416 from identityprovider.models import Account, EmailAddress, OpenIDRPConfig
417+from identityprovider.tests import DEFAULT_USER_PASSWORD
418 from identityprovider.tests.utils import MockRequest, SSOBaseTestCase
419 from identityprovider.views import testing as test_views
420
421@@ -197,7 +198,7 @@
422 def _login(self, client=None, csrf_token=None):
423 client = client or self.client
424 client.handler.enforce_csrf_checks = True
425- form = {'email': 'mark@example.com', 'password': 'test'}
426+ form = {'email': 'mark@example.com', 'password': DEFAULT_USER_PASSWORD}
427 if not csrf_token:
428 # get the token from the login page
429 r, csrf_token = self._land()
430@@ -340,7 +341,7 @@
431 # continue back to RP.
432 data = {
433 'email': 'mark@example.com',
434- 'password': 'test'
435+ 'password': DEFAULT_USER_PASSWORD
436 }
437 r = self.client.post('/%s/+login' % oid_token, data, follow=True)
438 self.assertTemplateUsed(r, 'server/decide.html')
439
440=== modified file 'identityprovider/tests/unit/test_models_account.py'
441--- identityprovider/tests/unit/test_models_account.py 2012-10-29 16:06:36 +0000
442+++ identityprovider/tests/unit/test_models_account.py 2012-12-17 20:24:41 +0000
443@@ -5,6 +5,7 @@
444
445 from django.conf import settings
446 from django.contrib.auth.models import User
447+from django.core.exceptions import ValidationError
448 from django.test import TestCase
449
450 from mock import patch
451@@ -20,6 +21,7 @@
452 from identityprovider.models.const import AccountCreationRationale, EmailStatus
453 from identityprovider.readonly import ReadOnlyManager
454 from identityprovider.utils import encrypt_launchpad_password, generate_salt
455+from identityprovider.tests import DEFAULT_USER_PASSWORD
456 from identityprovider.tests.utils import SSOBaseTestCase
457
458
459@@ -202,7 +204,7 @@
460 self.assertEqual(emails[1].status, EmailStatus.VALIDATED)
461
462 def test_account_suspend_reset_password(self):
463- account = self.factory.make_account(password='valid')
464+ account = self.factory.make_account(password=DEFAULT_USER_PASSWORD)
465 account.status = AccountStatus.SUSPENDED
466 account.save()
467
468@@ -241,11 +243,29 @@
469 self.assertEqual(
470 AccountPassword.objects.filter(account=account).count(), 0)
471
472+ def test_create_account_with_invalid_password(self):
473+ salt = generate_salt()
474+ kwargs = dict(
475+ displayname='displayname', email='email@host.local',
476+ password='test', salt=salt,
477+ creation_rationale=AccountCreationRationale.USER_CREATED,
478+ )
479+ self.assertRaises(ValidationError, self.factory.make_account, **kwargs)
480+
481+ def test_create_account_with_invalid_email_address(self):
482+ salt = generate_salt()
483+ kwargs = dict(
484+ displayname='displayname', email='not_an_email',
485+ password=DEFAULT_USER_PASSWORD, salt=salt,
486+ creation_rationale=AccountCreationRationale.USER_CREATED,
487+ )
488+ self.assertRaises(ValidationError, self.factory.make_account, **kwargs)
489+
490 def test_create_account_with_rationale(self):
491 salt = generate_salt()
492 account = self.factory.make_account(
493 displayname='displayname', email='email@host.local',
494- password='password',
495+ password=DEFAULT_USER_PASSWORD,
496 creation_rationale=AccountCreationRationale.USER_CREATED,
497 salt=salt,
498 )
499@@ -265,13 +285,14 @@
500 self.assertEqual(passwords.count(), 1)
501 password = passwords[0]
502 self.assertEqual(password.password,
503- encrypt_launchpad_password('password', salt=salt))
504+ encrypt_launchpad_password(DEFAULT_USER_PASSWORD,
505+ salt=salt))
506
507 def test_create_account_with_no_rationale(self):
508 salt = generate_salt()
509 account = self.factory.make_account(
510 displayname='displayname', email='email@host.local',
511- password='password', salt=salt)
512+ password=DEFAULT_USER_PASSWORD, salt=salt)
513
514 self.assertEqual(account.displayname, 'displayname')
515 self.assertEqual(account.creation_rationale,
516@@ -288,13 +309,14 @@
517 self.assertEqual(passwords.count(), 1)
518 password = passwords[0]
519 self.assertEqual(password.password,
520- encrypt_launchpad_password('password', salt=salt))
521+ encrypt_launchpad_password(DEFAULT_USER_PASSWORD,
522+ salt=salt))
523
524 def test_create_account_with_email_validated(self):
525 salt = generate_salt()
526 account = self.factory.make_account(
527 displayname='displayname', email='email@host.local',
528- password='password', salt=salt, email_validated=False)
529+ password=DEFAULT_USER_PASSWORD, salt=salt, email_validated=False)
530
531 self.assertEqual(account.displayname, 'displayname')
532 self.assertEqual(account.creation_rationale,
533@@ -311,7 +333,8 @@
534 self.assertEqual(passwords.count(), 1)
535 password = passwords[0]
536 self.assertEqual(password.password,
537- encrypt_launchpad_password('password', salt=salt))
538+ encrypt_launchpad_password(DEFAULT_USER_PASSWORD,
539+ salt=salt))
540
541 def test_sites_with_active_sessions_when_returns_empty_result(self):
542 account = self.factory.make_account()
543@@ -396,7 +419,7 @@
544 def setUp(self):
545 self.account = self.factory.make_account(
546 displayname='test', email='test-oauth@example.com',
547- password='password')
548+ password=DEFAULT_USER_PASSWORD)
549 self.user = User.objects.create_user(
550 self.account.openid_identifier,
551 'test@example.com', 'password')
552
553=== modified file 'identityprovider/tests/unit/test_models_team.py'
554--- identityprovider/tests/unit/test_models_team.py 2012-10-19 21:30:41 +0000
555+++ identityprovider/tests/unit/test_models_team.py 2012-12-17 20:24:41 +0000
556@@ -11,7 +11,7 @@
557 TeamParticipation,
558 get_team_memberships_for_user,
559 )
560-
561+from identityprovider.tests import DEFAULT_USER_PASSWORD
562 from identityprovider.tests.utils import SSOBaseTestCase
563
564
565@@ -44,7 +44,7 @@
566
567 def test_get_team_memberships_on_personless_account(self):
568 account = Account.objects.create_account('test', 'x@example.com',
569- 'password')
570+ DEFAULT_USER_PASSWORD)
571 memberships = get_team_memberships_for_user(
572 ['ubuntu-team'], account, False)
573 self.assertEqual(memberships, [])
574
575=== modified file 'identityprovider/tests/unit/test_validators.py'
576--- identityprovider/tests/unit/test_validators.py 2012-12-13 20:19:19 +0000
577+++ identityprovider/tests/unit/test_validators.py 2012-12-17 20:24:41 +0000
578@@ -1,5 +1,6 @@
579 from django.core.exceptions import ValidationError
580
581+from identityprovider.tests import DEFAULT_USER_PASSWORD
582 from identityprovider.tests.utils import SSOBaseTestCase
583 from identityprovider.validators import validate_password_policy
584
585@@ -24,3 +25,6 @@
586
587 def test_valid_password(self):
588 self.assertEqual(validate_password_policy('abcD3fgh'), None)
589+
590+ def test_default_password_is_validated(self):
591+ self.assertEqual(validate_password_policy(DEFAULT_USER_PASSWORD), None)
592
593=== modified file 'identityprovider/tests/unit/test_views_preflight.py'
594--- identityprovider/tests/unit/test_views_preflight.py 2012-12-05 18:25:00 +0000
595+++ identityprovider/tests/unit/test_views_preflight.py 2012-12-17 20:24:41 +0000
596@@ -2,6 +2,7 @@
597
598 from identityprovider.gargoyle import LPTeamConditionSet
599 from identityprovider.models.account import Account
600+from identityprovider.tests import DEFAULT_USER_PASSWORD
601 from identityprovider.tests.utils import SSOBaseTestCase
602 from identityprovider.utils import add_user_to_team
603
604@@ -23,15 +24,17 @@
605
606 def test_account_without_person_receives_404(self):
607 account = Account.objects.create_account(
608- "test", "abcd@example.com", "test")
609- self.client.login(username="abcd@example.com", password="test")
610+ "test", "abcd@example.com", DEFAULT_USER_PASSWORD)
611+ self.client.login(username="abcd@example.com",
612+ password=DEFAULT_USER_PASSWORD)
613 r = self.client.get(self.URL)
614 self.assertEqual(r.status_code, 404)
615 account.emailaddress_set.all().delete()
616 account.delete()
617
618 def test_person_not_in_the_required_team_will_get_404(self):
619- self.client.login(username="test@canonical.com", password="test")
620+ self.client.login(username="test@canonical.com",
621+ password=DEFAULT_USER_PASSWORD)
622 r = self.client.get(self.URL)
623 self.assertEqual(r.status_code, 404)
624
625@@ -51,7 +54,8 @@
626 )
627
628 # test flag
629- self.client.login(username="member@canonical.com", password="test")
630+ self.client.login(username="member@canonical.com",
631+ password=DEFAULT_USER_PASSWORD)
632 r = self.client.get(self.URL)
633
634 self.assertTemplateUsed(r, "preflight/overview.html")
635
636=== modified file 'identityprovider/tests/unit/test_views_server.py'
637--- identityprovider/tests/unit/test_views_server.py 2012-12-04 18:51:42 +0000
638+++ identityprovider/tests/unit/test_views_server.py 2012-12-17 20:24:41 +0000
639@@ -47,6 +47,7 @@
640 from identityprovider.models.person import PersonLocation
641 from identityprovider.models.authtoken import create_token
642 from identityprovider.views import server
643+from identityprovider.tests import DEFAULT_USER_PASSWORD
644 from identityprovider.tests.utils import (
645 AuthenticatedTestCase,
646 SSOBaseTestCase,
647@@ -158,7 +159,8 @@
648 self.rpconfig.save()
649
650 account = Account.objects.get_by_email('mark@example.com')
651- self.client.login(username='mark@example.com', password='test')
652+ self.client.login(username='mark@example.com',
653+ password=DEFAULT_USER_PASSWORD)
654 r = self.client.get('/+openid', self.params)
655 query = self.get_query(r)
656 self.assertEqual(r.status_code, 302)
657@@ -172,7 +174,8 @@
658
659 self.params['openid.identity'] = \
660 settings.SSO_ROOT_URL + '+id/mark_oid'
661- self.client.login(username='mark@example.com', password='test')
662+ self.client.login(username='mark@example.com',
663+ password=DEFAULT_USER_PASSWORD)
664 r = self.client.get('/+openid', self.params)
665 query = self.get_query(r)
666 self.assertEqual(r.status_code, 302)
667@@ -183,7 +186,8 @@
668 def test_handle_user_response_user_is_authenticated(self):
669 self.params['openid.identity'] = \
670 settings.SSO_ROOT_URL + '+id/other_oid'
671- self.client.login(username='mark@example.com', password='test')
672+ self.client.login(username='mark@example.com',
673+ password=DEFAULT_USER_PASSWORD)
674 r = self.client.get('/+openid', self.params)
675 query = self.get_query(r)
676 self.assertEqual(r.status_code, 302)
677@@ -463,7 +467,7 @@
678 def test_decide_team_membership_with_auto_authorize(self):
679 # make sure rpconfig is set to auto authorize
680 self.client.login(username='mark@example.com',
681- password='test')
682+ password=DEFAULT_USER_PASSWORD)
683
684 rpconfig = OpenIDRPConfig(trust_root='http://localhost/',
685 auto_authorize=True)
686@@ -504,7 +508,7 @@
687
688 def test_list_of_details_is_complete(self):
689 self.client.login(username='mark@example.com',
690- password='test')
691+ password=DEFAULT_USER_PASSWORD)
692
693 # create a trusted rpconfig
694 rpconfig = OpenIDRPConfig(
695@@ -527,7 +531,7 @@
696
697 def test_state_of_checkboxes_and_data_formats_trusted(self):
698 self.client.login(username='mark@example.com',
699- password='test')
700+ password=DEFAULT_USER_PASSWORD)
701
702 # create a trusted rpconfig
703 rpconfig = OpenIDRPConfig(
704@@ -577,7 +581,7 @@
705
706 def test_state_of_checkboxes_and_data_formats_untrusted(self):
707 self.client.login(username='mark@example.com',
708- password='test')
709+ password=DEFAULT_USER_PASSWORD)
710
711 # create a trusted rpconfig
712 trust_root = 'http://untrusted/'
713@@ -949,7 +953,8 @@
714 'http://localhost/')
715
716 # login and redirect to pre-authorize again
717- data.update({'email': 'mark@example.com', 'password': 'test',
718+ data.update({'email': 'mark@example.com',
719+ 'password': DEFAULT_USER_PASSWORD,
720 'next': '/+pre-authorize-rp'})
721 r = self.client.post('/+login', data, **extra)
722 r = self.client.post('/+pre-authorize-rp', data, **extra)
723@@ -1304,7 +1309,8 @@
724 token = create_token(16)
725
726 # call up a session-modifying view to get a real session object
727- r = self.client.login(username='mark@example.com', password='test')
728+ r = self.client.login(username='mark@example.com',
729+ password=DEFAULT_USER_PASSWORD)
730 self.assertTrue(r)
731
732 session = self.client.session
733@@ -1353,7 +1359,8 @@
734 fixtures = ["test"]
735
736 def test_untrusted_rp_properly_shows_markup(self):
737- self.client.login(username='mark@example.com', password='test')
738+ self.client.login(username='mark@example.com',
739+ password=DEFAULT_USER_PASSWORD)
740 self.rpconfig = OpenIDRPConfig(
741 trust_root='http://localhost/',
742 displayname="MYSITE"
743
744=== modified file 'identityprovider/tests/utils.py'
745--- identityprovider/tests/utils.py 2012-12-13 11:37:21 +0000
746+++ identityprovider/tests/utils.py 2012-12-17 20:24:41 +0000
747@@ -27,6 +27,7 @@
748
749 from identityprovider import signed
750 from identityprovider.models.authtoken import create_token
751+from identityprovider.tests import DEFAULT_USER_PASSWORD
752 from identityprovider.tests.factory import SSOObjectFactory
753 from identityprovider.views import server
754
755@@ -223,7 +224,7 @@
756 old_middlewares)
757
758 self.login_email = "test@canonical.com"
759- self.login_password = "test"
760+ self.login_password = DEFAULT_USER_PASSWORD
761
762 self.client.login(username=self.login_email,
763 password=self.login_password)
764
765=== modified file 'webui/tests/test_static.py'
766--- webui/tests/test_static.py 2012-12-07 13:08:43 +0000
767+++ webui/tests/test_static.py 2012-12-17 20:24:41 +0000
768@@ -3,6 +3,7 @@
769
770 from django.conf import settings
771
772+from identityprovider.tests import DEFAULT_USER_PASSWORD
773 from identityprovider.tests.utils import SSOBaseTestCase, patch_settings
774
775
776@@ -33,7 +34,8 @@
777 self.assertAvailable('/+description', "What's this?")
778
779 def test_applications_page(self):
780- self.client.login(username='mark@example.com', password='test')
781+ self.client.login(username='mark@example.com',
782+ password=DEFAULT_USER_PASSWORD)
783 self.assertAvailable('/+applications', 'Applications you use')
784
785
786@@ -72,5 +74,6 @@
787 self.assertNotAvailable('/+description')
788
789 def test_applications_page(self):
790- self.client.login(username='mark@example.com', password='test')
791+ self.client.login(username='mark@example.com',
792+ password=DEFAULT_USER_PASSWORD)
793 self.assertNotAvailable('/+applications')
794
795=== modified file 'webui/tests/test_views_account.py'
796--- webui/tests/test_views_account.py 2012-12-03 17:50:53 +0000
797+++ webui/tests/test_views_account.py 2012-12-17 20:24:41 +0000
798@@ -21,6 +21,7 @@
799 AccountStatus,
800 EmailStatus,
801 )
802+from identityprovider.tests import DEFAULT_USER_PASSWORD
803 from identityprovider.tests.utils import (
804 MISSING_BACKUP_DEVICE,
805 AuthenticatedTestCase,
806@@ -461,7 +462,8 @@
807 fixtures = ["test"]
808
809 def setUp(self):
810- self.client.login(username="mark@example.com", password="test")
811+ self.client.login(username="mark@example.com",
812+ password=DEFAULT_USER_PASSWORD)
813 self.disable_csrf()
814 self.addCleanup(self.reset_csrf)
815
816
817=== modified file 'webui/tests/test_views_devices.py'
818--- webui/tests/test_views_devices.py 2012-12-05 16:35:55 +0000
819+++ webui/tests/test_views_devices.py 2012-12-17 20:24:41 +0000
820@@ -15,6 +15,7 @@
821
822 from identityprovider.models import Account, AuthenticationDevice
823 from identityprovider.models.const import AccountStatus
824+from identityprovider.tests import DEFAULT_USER_PASSWORD
825 from identityprovider.tests.factory import SSOObjectFactory
826 from identityprovider.tests.utils import (
827 MISSING_BACKUP_DEVICE,
828@@ -32,11 +33,11 @@
829
830 def setUp(self):
831 super(DeviceViewsTestCaseBase, self).setUp()
832- self.account = account = self.factory.make_account(password='test')
833+ self.account = account = self.factory.make_account()
834 self.device = self.factory.make_device(account, name='foo')
835
836 self.client.login(username=account.preferredemail.email,
837- password='test')
838+ password=DEFAULT_USER_PASSWORD)
839
840 self.patch_is_upgraded = mock.patch(
841 'identityprovider.models.twofactor.is_upgraded')
842@@ -161,19 +162,19 @@
843 self.assertEqual(device.name, 'bar')
844
845 def test_device_rename_get_when_invalid_user(self):
846- new_account = self.factory.make_account(password='test2')
847+ new_account = self.factory.make_account()
848 self.client.logout()
849 self.client.login(username=new_account.preferredemail.email,
850- password='test2')
851+ password=DEFAULT_USER_PASSWORD)
852 # post as new user
853 response = self.client.get(self.rename_view)
854 self.assertEqual(response.status_code, 404)
855
856 def test_device_rename_post_when_invalid_user(self):
857- new_account = self.factory.make_account(password='test2')
858+ new_account = self.factory.make_account()
859 self.client.logout()
860 self.client.login(username=new_account.preferredemail.email,
861- password='test2')
862+ password=DEFAULT_USER_PASSWORD)
863 # post as new user
864 response = self.client.post(self.rename_view, {'name': 'bar'})
865 self.assertEqual(response.status_code, 404)
866@@ -270,7 +271,7 @@
867 url = reverse('twofactor')
868
869 factory = SSOObjectFactory()
870- account = factory.make_account(email='foo@test.com', password='test')
871+ account = factory.make_account(email='foo@test.com')
872 device = factory.make_device(account, name='foo')
873
874 @test_concurrently(2)
875
876=== modified file 'webui/tests/test_views_i18n.py'
877--- webui/tests/test_views_i18n.py 2012-12-03 17:50:53 +0000
878+++ webui/tests/test_views_i18n.py 2012-12-17 20:24:41 +0000
879@@ -1,5 +1,6 @@
880+from identityprovider.models.account import Account
881 from identityprovider.tests.utils import SSOBaseTestCase
882-from identityprovider.models.account import Account
883+from identityprovider.tests import DEFAULT_USER_PASSWORD
884
885
886 class SetLanguageTestCase(SSOBaseTestCase):
887@@ -41,7 +42,8 @@
888 self.assertTemplateUsed(r, 'select_language.html')
889
890 def test_setting_language_for_authenticated_users_updates_db(self):
891- self.client.login(username='mark@example.com', password='test')
892+ self.client.login(username='mark@example.com',
893+ password=DEFAULT_USER_PASSWORD)
894 self.client.post('/set_language', {'language': 'es', 'next': '/'})
895
896 account = Account.objects.get_by_email('mark@example.com')
897
898=== modified file 'webui/tests/test_views_ui.py'
899--- webui/tests/test_views_ui.py 2012-12-03 20:19:22 +0000
900+++ webui/tests/test_views_ui.py 2012-12-17 20:24:41 +0000
901@@ -42,6 +42,7 @@
902 )
903 from identityprovider.models.captcha import Captcha
904 from identityprovider.models.const import AccountStatus, LoginTokenType
905+from identityprovider.tests import DEFAULT_USER_PASSWORD
906 from identityprovider.tests.utils import (
907 MockHandler,
908 SSOBaseTestCase,
909@@ -151,13 +152,14 @@
910 return '/token/%s/%s/%s' % (token_string, view, quoted_email)
911
912 def authenticate(self):
913- self.client.login(username='mark@example.com', password='test')
914+ self.client.login(username='mark@example.com',
915+ password=DEFAULT_USER_PASSWORD)
916
917
918 class UIViewsTestCase(UIViewsBaseTestCase):
919 def test_login_with_unicode_email(self):
920 email = u'mark@客example.com'
921- password = 'test'
922+ password = DEFAULT_USER_PASSWORD
923 Account.objects.create_account('Mark Shuttleworth', email, password)
924 r = self.client.post(
925 '/+login',
926@@ -178,7 +180,7 @@
927
928 def test_login_with_next(self):
929 r = self.client.post('/+login', {'email': 'mark@example.com',
930- 'password': 'test',
931+ 'password': DEFAULT_USER_PASSWORD,
932 'next': '/+edit'})
933 self.assertRedirects(r, '/+edit')
934
935@@ -199,7 +201,7 @@
936 account.accountpassword.save()
937
938 r = self.client.post('/+login', {'email': 'mark@example.com',
939- 'password': 'test',
940+ 'password': DEFAULT_USER_PASSWORD,
941 'next': '/+edit'})
942
943 if status == AccountStatus.SUSPENDED:
944@@ -214,13 +216,14 @@
945 def test_login_without_next_with_token(self):
946 token = 'a' * 16
947 r = self.client.post("/%s/+login" % token,
948- {'email': 'mark@example.com', 'password': 'test'})
949+ {'email': 'mark@example.com',
950+ 'password': DEFAULT_USER_PASSWORD})
951 self.assertEqual(r.status_code, 302)
952 self.assertEqual(r['Location'], "http://testserver/%s/" % token)
953
954 def test_login_without_next_nor_token(self):
955 r = self.client.post('/+login', {'email': 'mark@example.com',
956- 'password': 'test'})
957+ 'password': DEFAULT_USER_PASSWORD})
958 self.assertRedirects(r, '/')
959
960 def test_login_with_not_validated_email(self):
961@@ -229,7 +232,7 @@
962 account.emailaddress_set.create(
963 email="mark-2@example.com", status=EmailStatus.NEW)
964 r = self.client.post('/+login', {'email': 'mark-2@example.com',
965- 'password': 'test'})
966+ 'password': DEFAULT_USER_PASSWORD})
967 self.assertFormError(r, 'form', None, "Password didn't match.")
968
969 def test_logout(self):
970@@ -762,7 +765,7 @@
971
972 def test_edit_account_template(self):
973 r = self.client.post('/+login', {'email': 'mark@example.com',
974- 'password': 'test',
975+ 'password': DEFAULT_USER_PASSWORD,
976 'next': '/+edit'})
977 r = self.client.get('/+edit')
978 self.assertTemplateUsed(r, 'account/edit.html')
979@@ -953,7 +956,8 @@
980 account.preferredlanguage = 'es'
981 account.save()
982
983- self.client.login(username='mark@example.com', password='test')
984+ self.client.login(username='mark@example.com',
985+ password=DEFAULT_USER_PASSWORD)
986 r = self.client.get('/')
987 self.assertContains(r, 'es.png')
988
989@@ -967,7 +971,8 @@
990 self.assertNotContains(self.client.get('/'), 'es.png')
991 self.client.post('/set_language', {'language': 'es'})
992 self.assertContains(self.client.get('/'), 'es.png')
993- self.client.login(username='mark@example.com', password='test')
994+ self.client.login(username='mark@example.com',
995+ password=DEFAULT_USER_PASSWORD)
996 self.assertContains(self.client.get('/'), 'es.png')
997
998 self.reset_csrf()
999@@ -1030,7 +1035,8 @@
1000 def test_login_stats(self, mock_increment):
1001 self.client.get('/+login')
1002 self.client.post('/+login',
1003- {'email': 'mark@example.com', 'password': 'test'})
1004+ {'email': 'mark@example.com',
1005+ 'password': DEFAULT_USER_PASSWORD})
1006 self.assertEqual(mock_increment.call_args_list, self.args_list())
1007
1008 @patch('webui.views.ui.stats.increment')
1009@@ -1164,7 +1170,7 @@
1010
1011 class TwoFactorLoginTestCase(SSOBaseTestCase):
1012 email = 'user2f@example.com'
1013- password = 'test'
1014+ password = DEFAULT_USER_PASSWORD
1015 logout_link = 'a[href="/+logout"]'
1016
1017 def setUp(self):
1018
1019=== modified file 'webui/views/ui.py'
1020--- webui/views/ui.py 2012-12-12 19:00:43 +0000
1021+++ webui/views/ui.py 2012-12-17 20:24:41 +0000
1022@@ -645,6 +645,9 @@
1023 email = form.cleaned_data['email']
1024 password = form.cleaned_data.get('password', None)
1025 if password is not None:
1026+ # password validation enforced by the form
1027+ # at this point, password complies with policy since
1028+ # form.is_valid() is True
1029 encrypted_password = encrypt_launchpad_password(password)
1030 else:
1031 encrypted_password = password