Merge lp:~jamestait/django-openid-auth/revert-account-verified-model-change into lp:~django-openid-auth/django-openid-auth/trunk
- revert-account-verified-model-change
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Ricardo Kirkner |
Approved revision: | 120 |
Merged at revision: | 103 |
Proposed branch: | lp:~jamestait/django-openid-auth/revert-account-verified-model-change |
Merge into: | lp:~django-openid-auth/django-openid-auth/trunk |
Diff against target: |
521 lines (+86/-130) 5 files modified
django_openid_auth/auth.py (+16/-13) django_openid_auth/models.py (+1/-15) django_openid_auth/tests/test_auth.py (+37/-25) django_openid_auth/tests/test_models.py (+8/-26) django_openid_auth/tests/test_views.py (+24/-51) |
To merge this branch: | bzr merge lp:~jamestait/django-openid-auth/revert-account-verified-model-change |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ricardo Kirkner | Approve | ||
Review via email: mp+170885@code.launchpad.net |
Commit message
Revert the UserOpenID model change which added the account_verified flag. The intention was to allow for the support of multiple UserOpenIDs for a given User, but in reality the solution wouldn't have provided this, because we have no idea which OP provided the e-mail address associated with the account. In the meantime, allow for the simple case of handling account_verified for a single UserOpenID, while not ruling out future support for the complex case.
Description of the change
This branch reverts the addition of the account_verified flag to the
UserOpenID model.
The intention was to allow for the support of multiple UserOpenIDs for a
given User, but the solution as implemented would not have provided this.
If the OpenID response contains an e-mail address then we *do* know where
the e-mail address associated with the Django account came from - it came
from the same OP that's now making assertions as to the validity of the
address, because we're in the process of updating the user's details
with the ones in the OpenID response.
But this doesn't necessarily help us, because we don't maintain the link
between the e-mail address and the OpenID, so even if the same e-mail
address is used with two (trusted) OPs, if they differ in their opinion of
the validity of the address, we have no way of saying "but it's OK, because
the other OP has verified it."
Preview Diff
1 | === modified file 'django_openid_auth/auth.py' |
2 | --- django_openid_auth/auth.py 2013-05-16 17:30:45 +0000 |
3 | +++ django_openid_auth/auth.py 2013-06-21 17:58:35 +0000 |
4 | @@ -80,8 +80,7 @@ |
5 | claimed_id__exact=openid_response.identity_url) |
6 | except UserOpenID.DoesNotExist: |
7 | if getattr(settings, 'OPENID_CREATE_USERS', False): |
8 | - user, user_openid = self.create_user_from_openid( |
9 | - openid_response) |
10 | + user = self.create_user_from_openid(openid_response) |
11 | else: |
12 | user = user_openid.user |
13 | |
14 | @@ -90,7 +89,7 @@ |
15 | |
16 | if getattr(settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False): |
17 | details = self._extract_user_details(openid_response) |
18 | - self.update_user_details(user_openid, details, openid_response) |
19 | + self.update_user_details(user, details, openid_response) |
20 | |
21 | if getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False): |
22 | pape_response = pape.Response.fromSuccessResponse(openid_response) |
23 | @@ -275,10 +274,10 @@ |
24 | openid_response.identity_url) |
25 | |
26 | user = User.objects.create_user(username, email, password=None) |
27 | - user_openid = self.associate_openid(user, openid_response) |
28 | - self.update_user_details(user_openid, details, openid_response) |
29 | + self.associate_openid(user, openid_response) |
30 | + self.update_user_details(user, details, openid_response) |
31 | |
32 | - return user, user_openid |
33 | + return user |
34 | |
35 | def associate_openid(self, user, openid_response): |
36 | """Associate an OpenID with a user account.""" |
37 | @@ -300,8 +299,7 @@ |
38 | |
39 | return user_openid |
40 | |
41 | - def update_user_details(self, user_openid, details, openid_response): |
42 | - user = user_openid.user |
43 | + def update_user_details(self, user, details, openid_response): |
44 | updated = False |
45 | if details['first_name']: |
46 | user.first_name = details['first_name'][:30] |
47 | @@ -313,13 +311,18 @@ |
48 | user.email = details['email'] |
49 | updated = True |
50 | if getattr(settings, 'OPENID_FOLLOW_RENAMES', False): |
51 | - user.username = self._get_available_username(details['nickname'], openid_response.identity_url) |
52 | + user.username = self._get_available_username( |
53 | + details['nickname'], openid_response.identity_url) |
54 | updated = True |
55 | account_verified = details.get('account_verified', None) |
56 | - if (account_verified is not None and |
57 | - user_openid.account_verified != account_verified): |
58 | - user_openid.account_verified = account_verified |
59 | - user_openid.save() |
60 | + if (account_verified is not None): |
61 | + permission = Permission.objects.get(codename='account_verified') |
62 | + perm_label = '%s.%s' % (permission.content_type.app_label, |
63 | + permission.codename) |
64 | + if account_verified and not user.has_perm(perm_label): |
65 | + user.user_permissions.add(permission) |
66 | + elif not account_verified and user.has_perm(perm_label): |
67 | + user.user_permissions.remove(permission) |
68 | |
69 | if updated: |
70 | user.save() |
71 | |
72 | === modified file 'django_openid_auth/models.py' |
73 | --- django_openid_auth/models.py 2013-05-24 23:33:30 +0000 |
74 | +++ django_openid_auth/models.py 2013-06-21 17:58:35 +0000 |
75 | @@ -59,27 +59,13 @@ |
76 | user = models.ForeignKey(User) |
77 | claimed_id = models.TextField(max_length=2047, unique=True) |
78 | display_id = models.TextField(max_length=2047) |
79 | - account_verified = models.BooleanField(default=False) |
80 | |
81 | class Meta: |
82 | permissions = ( |
83 | ('account_verified', 'The OpenID has been verified'), |
84 | ) |
85 | |
86 | - def _get_permission(self): |
87 | - return Permission.objects.get(codename='account_verified') |
88 | - |
89 | - def save(self, force_insert=False, force_update=False, using=None): |
90 | - permission = self._get_permission() |
91 | - perm_label = '%s.%s' % (permission.content_type.app_label, |
92 | - permission.codename) |
93 | - if self.account_verified and not self.user.has_perm(perm_label): |
94 | - self.user.user_permissions.add(permission) |
95 | - elif not self.account_verified and self.user.has_perm(perm_label): |
96 | - self.user.user_permissions.remove(permission) |
97 | - super(UserOpenID, self).save(force_insert, force_update, using) |
98 | - |
99 | def delete(self, using=None): |
100 | - permission = self._get_permission() |
101 | + permission = Permission.objects.get(codename='account_verified') |
102 | self.user.user_permissions.remove(permission) |
103 | super(UserOpenID, self).delete(using) |
104 | |
105 | === modified file 'django_openid_auth/tests/test_auth.py' |
106 | --- django_openid_auth/tests/test_auth.py 2013-06-18 14:10:24 +0000 |
107 | +++ django_openid_auth/tests/test_auth.py 2013-06-21 17:58:35 +0000 |
108 | @@ -29,7 +29,11 @@ |
109 | import unittest |
110 | |
111 | from django.conf import settings |
112 | -from django.contrib.auth.models import Group, User |
113 | +from django.contrib.auth.models import ( |
114 | + Group, |
115 | + Permission, |
116 | + User, |
117 | +) |
118 | from django.test import TestCase |
119 | |
120 | from django_openid_auth.auth import OpenIDBackend |
121 | @@ -181,13 +185,12 @@ |
122 | user_openid, created = UserOpenID.objects.get_or_create( |
123 | user=user, |
124 | claimed_id='http://example.com/existing_identity', |
125 | - display_id='http://example.com/existing_identity', |
126 | - account_verified=False) |
127 | + display_id='http://example.com/existing_identity') |
128 | data = dict(first_name=u"Some56789012345678901234567890123", |
129 | last_name=u"User56789012345678901234567890123", |
130 | email=u"someotheruser@example.com", account_verified=False) |
131 | |
132 | - self.backend.update_user_details(user_openid, data, response) |
133 | + self.backend.update_user_details(user, data, response) |
134 | |
135 | self.assertEqual("Some56789012345678901234567890", user.first_name) |
136 | self.assertEqual("User56789012345678901234567890", user.last_name) |
137 | @@ -206,35 +209,44 @@ |
138 | user=user, claimed_id=claimed_id, display_id=display_id) |
139 | return user_openid |
140 | |
141 | - def _test_account_verified(self, user_openid, verified, expected): |
142 | + def _test_account_verified(self, user, initially_verified, expected): |
143 | # set user's verification status |
144 | - user_openid.account_verified = verified |
145 | + permission = Permission.objects.get(codename='account_verified') |
146 | + if initially_verified: |
147 | + user.user_permissions.add(permission) |
148 | + else: |
149 | + user.user_permissions.remove(permission) |
150 | + |
151 | + if hasattr(user, '_perm_cache'): |
152 | + del user._perm_cache |
153 | |
154 | # get a response including verification status |
155 | response = self.make_response_ax() |
156 | data = dict(first_name=u"Some56789012345678901234567890123", |
157 | - last_name=u"User56789012345678901234567890123", |
158 | - email=u"someotheruser@example.com", account_verified=expected) |
159 | - self.backend.update_user_details(user_openid, data, response) |
160 | + last_name=u"User56789012345678901234567890123", |
161 | + email=u"someotheruser@example.com", |
162 | + account_verified=expected) |
163 | + self.backend.update_user_details(user, data, response) |
164 | |
165 | # refresh object from the database |
166 | - user_openid = UserOpenID.objects.get(pk=user_openid.pk) |
167 | + user = User.objects.get(pk=user.pk) |
168 | # check the verification status |
169 | - self.assertEqual(user_openid.account_verified, expected) |
170 | - self.assertEqual(user_openid.user.has_perm( |
171 | - 'django_openid_auth.account_verified'), expected) |
172 | - |
173 | - def test_update_user_openid_unverified(self): |
174 | - user_openid = self.make_user_openid() |
175 | - |
176 | - for verified in (False, True): |
177 | - self._test_account_verified(user_openid, verified, expected=False) |
178 | - |
179 | - def test_update_user_openid_verified(self): |
180 | - user_openid = self.make_user_openid() |
181 | - |
182 | - for verified in (False, True): |
183 | - self._test_account_verified(user_openid, verified, expected=True) |
184 | + self.assertEqual(user.has_perm('django_openid_auth.account_verified'), |
185 | + expected) |
186 | + |
187 | + def test_update_user_perms_unverified(self): |
188 | + user_openid = self.make_user_openid() |
189 | + |
190 | + for initially_verified in (False, True): |
191 | + self._test_account_verified( |
192 | + user_openid.user, initially_verified, expected=False) |
193 | + |
194 | + def test_update_user_perms_verified(self): |
195 | + user_openid = self.make_user_openid() |
196 | + |
197 | + for initially_verified in (False, True): |
198 | + self._test_account_verified( |
199 | + user_openid.user, initially_verified, expected=True) |
200 | |
201 | def test_extract_user_details_name_with_trailing_space(self): |
202 | response = self.make_response_ax(fullname="SomeUser ") |
203 | |
204 | === modified file 'django_openid_auth/tests/test_models.py' |
205 | --- django_openid_auth/tests/test_models.py 2013-05-24 23:33:30 +0000 |
206 | +++ django_openid_auth/tests/test_models.py 2013-06-21 17:58:35 +0000 |
207 | @@ -31,7 +31,10 @@ |
208 | from django.contrib.auth.models import User |
209 | from django.test import TestCase |
210 | |
211 | -from django_openid_auth.models import UserOpenID |
212 | +from django_openid_auth.models import ( |
213 | + Permission, |
214 | + UserOpenID, |
215 | +) |
216 | |
217 | |
218 | class UserOpenIDModelTestCase(TestCase): |
219 | @@ -42,47 +45,26 @@ |
220 | user_openid, created = UserOpenID.objects.get_or_create( |
221 | user=user, |
222 | claimed_id='http://example.com/existing_identity', |
223 | - display_id='http://example.com/existing_identity', |
224 | - account_verified=False) |
225 | + display_id='http://example.com/existing_identity') |
226 | |
227 | self.assertEqual('someuser', user_openid.user.username) |
228 | self.assertEqual( |
229 | user_openid.claimed_id, 'http://example.com/existing_identity') |
230 | self.assertEqual( |
231 | user_openid.display_id, 'http://example.com/existing_identity') |
232 | - self.assertFalse(user_openid.account_verified) |
233 | self.assertFalse( |
234 | User.objects.get(username='someuser').has_perm( |
235 | 'django_openid_auth.account_verified')) |
236 | |
237 | - def test_create_verified_useropenid(self): |
238 | - user = User.objects.create_user('someuser', 'someuser@example.com', |
239 | - password=None) |
240 | - user_openid, created = UserOpenID.objects.get_or_create( |
241 | - user=user, |
242 | - claimed_id='http://example.com/existing_identity', |
243 | - display_id='http://example.com/existing_identity', |
244 | - account_verified=True) |
245 | - |
246 | - self.assertEqual('someuser', user_openid.user.username) |
247 | - self.assertEqual( |
248 | - user_openid.claimed_id, 'http://example.com/existing_identity') |
249 | - self.assertEqual( |
250 | - user_openid.display_id, 'http://example.com/existing_identity') |
251 | - self.assertTrue(user_openid.account_verified) |
252 | - self.assertTrue( |
253 | - User.objects.get(username='someuser').has_perm( |
254 | - 'django_openid_auth.account_verified')) |
255 | - |
256 | def test_delete_verified_useropenid(self): |
257 | user = User.objects.create_user('someuser', 'someuser@example.com', |
258 | password=None) |
259 | user_openid, created = UserOpenID.objects.get_or_create( |
260 | user=user, |
261 | claimed_id='http://example.com/existing_identity', |
262 | - display_id='http://example.com/existing_identity', |
263 | - account_verified=True) |
264 | - |
265 | + display_id='http://example.com/existing_identity') |
266 | + permission = Permission.objects.get(codename='account_verified') |
267 | + user.user_permissions.add(permission) |
268 | self.assertTrue( |
269 | User.objects.get(username='someuser').has_perm( |
270 | 'django_openid_auth.account_verified')) |
271 | |
272 | === modified file 'django_openid_auth/tests/test_views.py' |
273 | --- django_openid_auth/tests/test_views.py 2013-06-18 15:20:13 +0000 |
274 | +++ django_openid_auth/tests/test_views.py 2013-06-21 17:58:35 +0000 |
275 | @@ -259,8 +259,7 @@ |
276 | useropenid = UserOpenID( |
277 | user=user, |
278 | claimed_id='http://example.com/identity', |
279 | - display_id='http://example.com/identity', |
280 | - account_verified=False) |
281 | + display_id='http://example.com/identity') |
282 | useropenid.save() |
283 | |
284 | # The login form is displayed: |
285 | @@ -300,8 +299,7 @@ |
286 | useropenid = UserOpenID( |
287 | user=user, |
288 | claimed_id='http://example.com/identity', |
289 | - display_id='http://example.com/identity', |
290 | - account_verified=False) |
291 | + display_id='http://example.com/identity') |
292 | useropenid.save() |
293 | |
294 | settings.LOGIN_REDIRECT_URL = '/getuser/' |
295 | @@ -326,8 +324,7 @@ |
296 | useropenid = UserOpenID( |
297 | user=user, |
298 | claimed_id='http://example.com/identity', |
299 | - display_id='http://example.com/identity', |
300 | - account_verified=False) |
301 | + display_id='http://example.com/identity') |
302 | useropenid.save() |
303 | |
304 | # Requesting the login form immediately begins an |
305 | @@ -467,8 +464,7 @@ |
306 | useropenid = UserOpenID( |
307 | user=user, |
308 | claimed_id='http://example.com/identity', |
309 | - display_id='http://example.com/identity', |
310 | - account_verified=False) |
311 | + display_id='http://example.com/identity') |
312 | useropenid.save() |
313 | |
314 | openid_req = {'openid_identifier': 'http://example.com/identity', |
315 | @@ -512,8 +508,7 @@ |
316 | useropenid = UserOpenID( |
317 | user=user, |
318 | claimed_id='http://example.com/identity', |
319 | - display_id='http://example.com/identity', |
320 | - account_verified=False) |
321 | + display_id='http://example.com/identity') |
322 | useropenid.save() |
323 | |
324 | openid_req = {'openid_identifier': 'http://example.com/identity', |
325 | @@ -568,8 +563,7 @@ |
326 | useropenid = UserOpenID( |
327 | user=user, |
328 | claimed_id='http://example.com/identity', |
329 | - display_id='http://example.com/identity', |
330 | - account_verified=False) |
331 | + display_id='http://example.com/identity') |
332 | useropenid.save() |
333 | |
334 | openid_req = {'openid_identifier': 'http://example.com/identity', |
335 | @@ -723,8 +717,7 @@ |
336 | useropenid = UserOpenID( |
337 | user=user, |
338 | claimed_id='http://example.com/identity', |
339 | - display_id='http://example.com/identity', |
340 | - account_verified=False) |
341 | + display_id='http://example.com/identity') |
342 | useropenid.save() |
343 | |
344 | openid_req = {'openid_identifier': 'http://example.com/identity', |
345 | @@ -752,8 +745,7 @@ |
346 | useropenid = UserOpenID( |
347 | user=user, |
348 | claimed_id='http://example.com/identity', |
349 | - display_id='http://example.com/identity', |
350 | - account_verified=False) |
351 | + display_id='http://example.com/identity') |
352 | useropenid.save() |
353 | |
354 | openid_req = {'openid_identifier': 'http://example.com/identity', |
355 | @@ -780,16 +772,14 @@ |
356 | UserOpenID.objects.get_or_create( |
357 | user=user, |
358 | claimed_id='http://example.com/existing_identity', |
359 | - display_id='http://example.com/existing_identity', |
360 | - account_verified=False) |
361 | + display_id='http://example.com/existing_identity') |
362 | |
363 | # Setup user who is going to try to change username to 'testuser' |
364 | renamed_user = User.objects.create_user('renameuser', 'someone@example.com') |
365 | UserOpenID.objects.get_or_create( |
366 | user=renamed_user, |
367 | claimed_id='http://example.com/identity', |
368 | - display_id='http://example.com/identity', |
369 | - account_verified=False) |
370 | + display_id='http://example.com/identity') |
371 | |
372 | # identity url is for 'renameuser' |
373 | openid_req = {'openid_identifier': 'http://example.com/identity', |
374 | @@ -819,16 +809,14 @@ |
375 | UserOpenID.objects.get_or_create( |
376 | user=user, |
377 | claimed_id='http://example.com/existing_identity', |
378 | - display_id='http://example.com/existing_identity', |
379 | - account_verified=False) |
380 | + display_id='http://example.com/existing_identity') |
381 | |
382 | # Setup user who is going to try to change username to 'testuser' |
383 | renamed_user = User.objects.create_user('testuser2000eight', 'someone@example.com') |
384 | UserOpenID.objects.get_or_create( |
385 | user=renamed_user, |
386 | claimed_id='http://example.com/identity', |
387 | - display_id='http://example.com/identity', |
388 | - account_verified=False) |
389 | + display_id='http://example.com/identity') |
390 | |
391 | # identity url is for 'testuser2000eight' |
392 | openid_req = {'openid_identifier': 'http://example.com/identity', |
393 | @@ -861,16 +849,14 @@ |
394 | UserOpenID.objects.get_or_create( |
395 | user=user, |
396 | claimed_id='http://example.com/existing_identity', |
397 | - display_id='http://example.com/existing_identity', |
398 | - account_verified=False) |
399 | + display_id='http://example.com/existing_identity') |
400 | |
401 | # Setup user who is going to try to change username to 'testuser' |
402 | renamed_user = User.objects.create_user('testuser2000', 'someone@example.com') |
403 | UserOpenID.objects.get_or_create( |
404 | user=renamed_user, |
405 | claimed_id='http://example.com/identity', |
406 | - display_id='http://example.com/identity', |
407 | - account_verified=False) |
408 | + display_id='http://example.com/identity') |
409 | |
410 | # identity url is for 'testuser2000' |
411 | openid_req = {'openid_identifier': 'http://example.com/identity', |
412 | @@ -901,8 +887,7 @@ |
413 | UserOpenID.objects.get_or_create( |
414 | user=user, |
415 | claimed_id='http://example.com/identity', |
416 | - display_id='http://example.com/identity', |
417 | - account_verified=False) |
418 | + display_id='http://example.com/identity') |
419 | |
420 | # identity url is for 'testuser2' |
421 | openid_req = {'openid_identifier': 'http://example.com/identity', |
422 | @@ -996,8 +981,7 @@ |
423 | useropenid = UserOpenID( |
424 | user=user, |
425 | claimed_id='http://example.com/different_identity', |
426 | - display_id='http://example.com/different_identity', |
427 | - account_verified=False) |
428 | + display_id='http://example.com/different_identity') |
429 | useropenid.save() |
430 | |
431 | # Posting in an identity URL begins the authentication request: |
432 | @@ -1042,8 +1026,7 @@ |
433 | useropenid = UserOpenID( |
434 | user=user, |
435 | claimed_id='http://example.com/different_identity', |
436 | - display_id='http://example.com/different_identity', |
437 | - account_verified=False) |
438 | + display_id='http://example.com/different_identity') |
439 | useropenid.save() |
440 | |
441 | # Posting in an identity URL begins the authentication request: |
442 | @@ -1102,8 +1085,7 @@ |
443 | useropenid = UserOpenID( |
444 | user=user, |
445 | claimed_id='http://example.com/identity', |
446 | - display_id='http://example.com/identity', |
447 | - account_verified=False) |
448 | + display_id='http://example.com/identity') |
449 | useropenid.save() |
450 | |
451 | openid_req = {'openid_identifier': 'http://example.com/identity', |
452 | @@ -1128,8 +1110,7 @@ |
453 | useropenid = UserOpenID( |
454 | user=user, |
455 | claimed_id='http://example.com/identity', |
456 | - display_id='http://example.com/identity', |
457 | - account_verified=False) |
458 | + display_id='http://example.com/identity') |
459 | useropenid.save() |
460 | |
461 | # Posting in an identity URL begins the authentication request: |
462 | @@ -1149,8 +1130,7 @@ |
463 | useropenid = UserOpenID( |
464 | user=user, |
465 | claimed_id='http://example.com/identity', |
466 | - display_id='http://example.com/identity', |
467 | - account_verified=False) |
468 | + display_id='http://example.com/identity') |
469 | useropenid.save() |
470 | |
471 | # Posting in an identity URL begins the authentication request: |
472 | @@ -1246,9 +1226,6 @@ |
473 | # So have the user's permissions |
474 | self.assertEqual( |
475 | user.has_perm('django_openid_auth.account_verified'), is_verified) |
476 | - # And the verified status of their UserOpenID |
477 | - user_openid = UserOpenID.objects.get(user=user) |
478 | - self.assertEqual(user_openid.account_verified, is_verified) |
479 | |
480 | def test_login_attribute_exchange_with_verification(self): |
481 | settings.OPENID_VALID_VERIFICATION_SCHEMES = { |
482 | @@ -1314,8 +1291,7 @@ |
483 | useropenid = UserOpenID( |
484 | user=user, |
485 | claimed_id='http://example.com/identity', |
486 | - display_id='http://example.com/identity', |
487 | - account_verified=True) |
488 | + display_id='http://example.com/identity') |
489 | useropenid.save() |
490 | |
491 | # Posting in an identity URL begins the authentication request: |
492 | @@ -1359,8 +1335,7 @@ |
493 | useropenid = UserOpenID( |
494 | user=user, |
495 | claimed_id='http://example.com/identity', |
496 | - display_id='http://example.com/identity', |
497 | - account_verified=False) |
498 | + display_id='http://example.com/identity') |
499 | useropenid.save() |
500 | |
501 | # Posting in an identity URL begins the authentication request: |
502 | @@ -1412,8 +1387,7 @@ |
503 | useropenid = UserOpenID( |
504 | user=user, |
505 | claimed_id='http://example.com/identity', |
506 | - display_id='http://example.com/identity', |
507 | - account_verified=False) |
508 | + display_id='http://example.com/identity') |
509 | useropenid.save() |
510 | |
511 | # Posting in an identity URL begins the authentication request: |
512 | @@ -1437,8 +1411,7 @@ |
513 | useropenid = UserOpenID( |
514 | user=user, |
515 | claimed_id='http://example.com/identity', |
516 | - display_id='http://example.com/identity', |
517 | - account_verified=False) |
518 | + display_id='http://example.com/identity') |
519 | useropenid.save() |
520 | response = self.client.post('/openid/login/', |
521 | {'openid_identifier': 'http://example.com/identity'}) |
LGTM