Merge lp:~mhall119/django-openid-auth/fixes-642132 into lp:~django-openid-auth/django-openid-auth/trunk

Proposed by Michael Hall
Status: Superseded
Proposed branch: lp:~mhall119/django-openid-auth/fixes-642132
Merge into: lp:~django-openid-auth/django-openid-auth/trunk
Diff against target: 391 lines (+267/-31)
2 files modified
django_openid_auth/auth.py (+50/-10)
django_openid_auth/tests/test_views.py (+217/-21)
To merge this branch: bzr merge lp:~mhall119/django-openid-auth/fixes-642132
Reviewer Review Type Date Requested Status
James Henstridge Needs Fixing
Review via email: mp+38335@code.launchpad.net

This proposal has been superseded by a proposal from 2011-03-21.

Description of the change

Adds a new settings paramater: OPENID_FOLLOW_RENAMES

When set to True, and when OPENID_UPDATE_DETAILS_FROM_SREG is also True, the django User.username for the User with a matching identity_url will be updated with the nickname from the OpenID response.

To post a comment you must log in.
Revision history for this message
Michael Hall (mhall119) wrote :

Can somebody please review this, it is needed for loco.ubuntu.com and summit.ubuntu.com

Revision history for this message
Anthony Lenton (elachuni) wrote :

Hi Michael,

Thanks for your work on this. The code around lines 8-10 of the diff would need to be a bit more robust when updating the User's username, as there might be some other user in the system with the new username already.

I think the underlying problem is what we really want to do in this case (ie if 'joesmith' changes his openid username to 'joebobs', but you already have a 'joebobs' in your system). Skipping the username update in that case would work but it'll leave you with out-of-sync data. Refusing to sign the user in would be quite violent, and merging the two accounts would be definitely a bad idea. What would work in your use case?

Sites with a single OpenID provider would be less affected by this issue, but it could still bite you.

Otoh, I'm not sure why django-openid-auth doesn't currently update username together with fullname and email when OPENID_UPDATE_DETAILS_FROM_SREG is True, but using a second setting for this as your code does seems like a good way to make it work for everybody.

Revision history for this message
Michael Hall (mhall119) wrote :

I think in the case of an existing username conflict, then we could go back to $username+1 increments until we find a unique one. Unfortunately it would do this incrementing process every time the user logged in, until their new LP username is available in Django, but I don't think that would be such a performance hit.

Revision history for this message
James Henstridge (jamesh) wrote :

This should do the check to see if anyone else has the same user name, and should ideally use the same name checking code as create_user_from_openid() does (that way we only need to update the algorithm once if we want to change it).

I would suggest only changing the user name if the existing user name does not have the sreg nickname as a prefix. This should prevent us from trying to change the nickname on every login if there is a duplicate nickname.

With respect to the tests, how about factoring out the body of test_login_update_details() into a helper method, from the first client.post() call and returning the response object returned by client.get('/getuser/'). That helper could then be used to run both tests. I'd also like to see a test of when there is a conflict for the new nickname.

Lastly, a more basic question: do we want to have a setting for this behaviour? If it has minimal overhead and is something most people would want, is there any reason not to always do this?

review: Needs Fixing
Revision history for this message
Michael Hall (mhall119) wrote :

There may be cases where renames aren't desirable, for example if the username is used to link tables, rather than a constant user id.

Revision history for this message
Ronnie (ronnie.vd.c) wrote :

I would suggest checking the OpenId-Provider (url like: https://login.launchpad.net/) from the claimed id.

If the new username exists, but claimed_id does not match (but is from the same provider), The old username should be called OpenIdUserX,

OPENIDPROVIDER1 (Google)
    - {'nickname': 'Ben', 'claimed_id': 'http://login.google.com/ABCD', 'display_id': '...'}

OPENIDPROVIDER2 (Launchpad)
    - {'nickname': 'Ben', 'claimed_id': 'https://login.launchpad.net/+id/AAAA', 'display_id': '...'}
    - {'nickname': 'Cees', 'claimed_id': 'https://login.launchpad.net/+id/ABCD', 'display_id': '...'}
======
    - Ben deletes his account on launchpad
    - Cees changed name to Ben

OPENIDCONSUMER
    - Ben (http://login.google.com/ABCD) register => username 'Ben'
    - Ben (https://login.launchpad.net/+id/AAAA) registers => username 'Ben1'
    - Cees (https://login.launchpad.net/+id/ABCD) registers => username 'Cees'
=======
    - Ben (previous Cees | https://login.launchpad.net/+id/ABCD) logs in =>
        -- user 'Ben1' should be renamed to 'OpenIdUserX'
        -- user Cees should be renamed to 'Ben1'

small catch: What to do if Ben (https://login.launchpad.net/+id/AAAA) changes his name to 'Ben1' on the openid-provider?

Revision history for this message
Ronnie (ronnie.vd.c) wrote :

A more general approach, which also solves the small catch:

The username should always be renamed if it has changed, one exception for this is when the same username exists for another openid-provider. If there is already an user with that username (same provider) then the old_user should be renamed to the name without number (if available) else to the name + first_available_number.

If the same username is kept by another openid-provider, the user should keep its old username (if exists), if a new user is created, it should be username1 (username2 etc which first is available)

Therefore in the example above:
  OPENIDPROVIDER
    User Ben(https://login.launchpad.net/+id/AAAA) change name to Ben1
    User Cees(https://login.launchpad.net/+id/ABCD) change name to Ben
  OPENIDCONSUMER
    Ben (previous Cees | https://login.launchpad.net/+id/ABCD) logs in =>
       user 'Ben1' (https://login.launchpad.net/+id/AAAA) should be renamed to 'Ben2'
       user 'Cees' should be renamed to 'Ben1'
    Ben2 (https://login.launchpad.net/+id/AAAA) logs in with username 'Ben1'
       user 'Ben1' (previous Cees | https://login.launchpad.net/+id/ABCD) should be renamed to 'Ben3'
       user 'Ben2' should be renamed to 'Ben1'

All next logins for Ben3 (Cees/Ben (https://login.launchpad.net/+id/ABCD)) should check if 'Ben' is available. If not, keep the old username

80. By Michael Hall

Merge from trunk

81. By Michael Hall

Extra renaming considerations and tests for conflicts and false positives

82. By Michael Hall

Add another test to make sure renaming doesn't get confused by not-quite nickna me+1 usernames

83. By Michael Hall

Finish new test and altered comments

84. By Michael Hall

Add new option to README.txt and removed an unecessary check in _get_available_username()

85. By Michael Hall

Updates from trunk

86. By Michael Hall

Check for STRICT_USERNAMES before defaulting the nickname to openiduser

87. By Michael Hall

Make sure auto-mapping is turned off when testing teams->group

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'django_openid_auth/auth.py'
--- django_openid_auth/auth.py 2010-10-15 09:08:10 +0000
+++ django_openid_auth/auth.py 2011-03-21 11:58:29 +0000
@@ -81,7 +81,7 @@
8181
82 if getattr(settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False):82 if getattr(settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False):
83 details = self._extract_user_details(openid_response)83 details = self._extract_user_details(openid_response)
84 self.update_user_details(user, details)84 self.update_user_details(user, details, openid_response)
8585
86 teams_response = teams.TeamsResponse.fromSuccessResponse(86 teams_response = teams.TeamsResponse.fromSuccessResponse(
87 openid_response)87 openid_response)
@@ -98,7 +98,6 @@
98 email = sreg_response.get('email')98 email = sreg_response.get('email')
99 fullname = sreg_response.get('fullname')99 fullname = sreg_response.get('fullname')
100 nickname = sreg_response.get('nickname')100 nickname = sreg_response.get('nickname')
101
102 # If any attributes are provided via Attribute Exchange, use101 # If any attributes are provided via Attribute Exchange, use
103 # them in preference.102 # them in preference.
104 fetch_response = ax.FetchResponse.fromSuccessResponse(openid_response)103 fetch_response = ax.FetchResponse.fromSuccessResponse(openid_response)
@@ -137,10 +136,36 @@
137 return dict(email=email, nickname=nickname,136 return dict(email=email, nickname=nickname,
138 first_name=first_name, last_name=last_name)137 first_name=first_name, last_name=last_name)
139138
140 def create_user_from_openid(self, openid_response):139 def _get_available_username(self, nickname, identity_url):
141 details = self._extract_user_details(openid_response)140 nickname = nickname or 'openiduser'
142 nickname = details['nickname'] or 'openiduser'141 # See if we already have this nickname assigned to a username
143 email = details['email'] or ''142 try:
143 user = User.objects.get(username__exact=nickname)
144 except User.DoesNotExist:
145 # No conflict, we can use this nickname
146 return nickname
147
148 # Check if we already have nickname+i for this identity_url
149 try:
150 user_openid = UserOpenID.objects.get(
151 claimed_id__exact=identity_url,
152 user__username__startswith=nickname)
153 # No exception means we have an existing user for this identity
154 # that starts with this nickname, so it's possible we've had to
155 # assign them to nickname+i already.
156 oid_username = user_openid.user.username
157 if len(oid_username) > len(nickname):
158 try:
159 # check that it ends with a number
160 int(oid_username[len(nickname):])
161 return oid_username
162 except ValueError:
163 # username starts with nickname, but isn't nickname+#
164 pass
165 except UserOpenID.DoesNotExist:
166 # No user associated with this identity_url
167 pass
168
144169
145 # Pick a username for the user based on their nickname,170 # Pick a username for the user based on their nickname,
146 # checking for conflicts.171 # checking for conflicts.
@@ -150,15 +175,27 @@
150 if i > 1:175 if i > 1:
151 username += str(i)176 username += str(i)
152 try:177 try:
153 User.objects.get(username__exact=username)178 user = User.objects.get(username__exact=username)
179 if user.useropenid_set.filter(claimed_id__exact=identity_url).count() > 0:
180 # username already belongs to this openid user, so it's okay
181 return username
182
154 except User.DoesNotExist:183 except User.DoesNotExist:
155 break184 break
156 i += 1185 i += 1
186 return username
187
188 def create_user_from_openid(self, openid_response):
189 details = self._extract_user_details(openid_response)
190 nickname = details['nickname'] or 'openiduser'
191 email = details['email'] or ''
192
193 username = self._get_available_username(details['nickname'], openid_response.identity_url)
157194
158 user = User.objects.create_user(username, email, password=None)195 user = User.objects.create_user(username, email, password=None)
159 self.update_user_details(user, details)
160
161 self.associate_openid(user, openid_response)196 self.associate_openid(user, openid_response)
197 self.update_user_details(user, details, openid_response)
198
162 return user199 return user
163200
164 def associate_openid(self, user, openid_response):201 def associate_openid(self, user, openid_response):
@@ -181,7 +218,7 @@
181218
182 return user_openid219 return user_openid
183220
184 def update_user_details(self, user, details):221 def update_user_details(self, user, details, openid_response):
185 updated = False222 updated = False
186 if details['first_name']:223 if details['first_name']:
187 user.first_name = details['first_name']224 user.first_name = details['first_name']
@@ -192,6 +229,9 @@
192 if details['email']:229 if details['email']:
193 user.email = details['email']230 user.email = details['email']
194 updated = True231 updated = True
232 if getattr(settings, 'OPENID_FOLLOW_RENAMES', False):
233 user.username = self._get_available_username(details['nickname'], openid_response.identity_url)
234 updated = True
195235
196 if updated:236 if updated:
197 user.save()237 user.save()
198238
=== modified file 'django_openid_auth/tests/test_views.py'
--- django_openid_auth/tests/test_views.py 2011-01-13 08:38:01 +0000
+++ django_openid_auth/tests/test_views.py 2011-03-21 11:58:29 +0000
@@ -135,12 +135,14 @@
135 self.old_sso_server_url = getattr(settings, 'OPENID_SSO_SERVER_URL', None)135 self.old_sso_server_url = getattr(settings, 'OPENID_SSO_SERVER_URL', None)
136 self.old_teams_map = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING', {})136 self.old_teams_map = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING', {})
137 self.old_use_as_admin_login = getattr(settings, 'OPENID_USE_AS_ADMIN_LOGIN', False)137 self.old_use_as_admin_login = getattr(settings, 'OPENID_USE_AS_ADMIN_LOGIN', False)
138 self.old_follow_renames = getattr(settings, 'OPENID_FOLLOW_RENAMES', False)
138139
139 settings.OPENID_CREATE_USERS = False140 settings.OPENID_CREATE_USERS = False
140 settings.OPENID_UPDATE_DETAILS_FROM_SREG = False141 settings.OPENID_UPDATE_DETAILS_FROM_SREG = False
141 settings.OPENID_SSO_SERVER_URL = None142 settings.OPENID_SSO_SERVER_URL = None
142 settings.OPENID_LAUNCHPAD_TEAMS_MAPPING = {}143 settings.OPENID_LAUNCHPAD_TEAMS_MAPPING = {}
143 settings.OPENID_USE_AS_ADMIN_LOGIN = False144 settings.OPENID_USE_AS_ADMIN_LOGIN = False
145 settings.OPENID_FOLLOW_RENAMES = False
144146
145 def tearDown(self):147 def tearDown(self):
146 settings.LOGIN_REDIRECT_URL = self.old_login_redirect_url148 settings.LOGIN_REDIRECT_URL = self.old_login_redirect_url
@@ -149,6 +151,7 @@
149 settings.OPENID_SSO_SERVER_URL = self.old_sso_server_url151 settings.OPENID_SSO_SERVER_URL = self.old_sso_server_url
150 settings.OPENID_LAUNCHPAD_TEAMS_MAPPING = self.old_teams_map152 settings.OPENID_LAUNCHPAD_TEAMS_MAPPING = self.old_teams_map
151 settings.OPENID_USE_AS_ADMIN_LOGIN = self.old_use_as_admin_login153 settings.OPENID_USE_AS_ADMIN_LOGIN = self.old_use_as_admin_login
154 settings.OPENID_FOLLOW_RENAMES = self.old_follow_renames
152155
153 setDefaultFetcher(None)156 setDefaultFetcher(None)
154 super(RelyingPartyTests, self).tearDown()157 super(RelyingPartyTests, self).tearDown()
@@ -286,6 +289,213 @@
286 self.assertEquals(user.last_name, 'User')289 self.assertEquals(user.last_name, 'User')
287 self.assertEquals(user.email, 'foo@example.com')290 self.assertEquals(user.email, 'foo@example.com')
288291
292 def _do_user_login(self, openid_req, openid_resp):
293 # Posting in an identity URL begins the authentication request:
294 response = self.client.post('/openid/login/', openid_req)
295 self.assertContains(response, 'OpenID transaction in progress')
296
297 # Complete the request, passing back some simple registration
298 # data. The user is redirected to the next URL.
299 openid_request = self.provider.parseFormPost(response.content)
300 sreg_request = sreg.SRegRequest.fromOpenIDRequest(openid_request)
301 openid_response = openid_request.answer(True)
302 sreg_response = sreg.SRegResponse.extractResponse(
303 sreg_request, openid_resp)
304 openid_response.addExtension(sreg_response)
305 response = self.complete(openid_response)
306 self.assertRedirects(response, 'http://testserver/getuser/')
307
308 def test_login_without_nickname(self):
309 settings.OPENID_CREATE_USERS = True
310
311 openid_req = {'openid_identifier': 'http://example.com/identity',
312 'next': '/getuser/'}
313 openid_resp = {'nickname': '', 'fullname': 'Openid User',
314 'email': 'foo@example.com'}
315 self._do_user_login(openid_req, openid_resp)
316 response = self.client.get('/getuser/')
317
318 # username defaults to 'openiduser'
319 self.assertEquals(response.content, 'openiduser')
320
321 # The user's full name and email have been updated.
322 user = User.objects.get(username=response.content)
323 self.assertEquals(user.first_name, 'Openid')
324 self.assertEquals(user.last_name, 'User')
325 self.assertEquals(user.email, 'foo@example.com')
326
327 def test_login_follow_rename(self):
328 settings.OPENID_FOLLOW_RENAMES = True
329 settings.OPENID_UPDATE_DETAILS_FROM_SREG = True
330 user = User.objects.create_user('testuser', 'someone@example.com')
331 useropenid = UserOpenID(
332 user=user,
333 claimed_id='http://example.com/identity',
334 display_id='http://example.com/identity')
335 useropenid.save()
336
337 openid_req = {'openid_identifier': 'http://example.com/identity',
338 'next': '/getuser/'}
339 openid_resp = {'nickname': 'someuser', 'fullname': 'Some User',
340 'email': 'foo@example.com'}
341 self._do_user_login(openid_req, openid_resp)
342 response = self.client.get('/getuser/')
343
344 # If OPENID_FOLLOW_RENAMES, they are logged in as
345 # someuser (the passed in nickname has changed the username)
346 self.assertEquals(response.content, 'someuser')
347
348 # The user's full name and email have been updated.
349 user = User.objects.get(username=response.content)
350 self.assertEquals(user.first_name, 'Some')
351 self.assertEquals(user.last_name, 'User')
352 self.assertEquals(user.email, 'foo@example.com')
353
354 def test_login_follow_rename_conflict(self):
355 settings.OPENID_FOLLOW_RENAMES = True
356 settings.OPENID_UPDATE_DETAILS_FROM_SREG = True
357 # Setup existing user who's name we're going to switch to
358 user = User.objects.create_user('testuser', 'someone@example.com')
359 UserOpenID.objects.get_or_create(
360 user=user,
361 claimed_id='http://example.com/existing_identity',
362 display_id='http://example.com/existing_identity')
363
364 # Setup user who is going to try to change username to 'testuser'
365 renamed_user = User.objects.create_user('renameuser', 'someone@example.com')
366 UserOpenID.objects.get_or_create(
367 user=renamed_user,
368 claimed_id='http://example.com/identity',
369 display_id='http://example.com/identity')
370
371 # identity url is for 'renameuser'
372 openid_req = {'openid_identifier': 'http://example.com/identity',
373 'next': '/getuser/'}
374 # but returned username is for 'testuser', which already exists for another identity
375 openid_resp = {'nickname': 'testuser', 'fullname': 'Rename User',
376 'email': 'rename@example.com'}
377 self._do_user_login(openid_req, openid_resp)
378 response = self.client.get('/getuser/')
379
380 # If OPENID_FOLLOW_RENAMES, attempt to change username to 'testuser'
381 # but since that username is already taken by someone else, we go through
382 # the process of adding +i to it, and get testuser2.
383 self.assertEquals(response.content, 'testuser2')
384
385 # The user's full name and email have been updated.
386 user = User.objects.get(username=response.content)
387 self.assertEquals(user.first_name, 'Rename')
388 self.assertEquals(user.last_name, 'User')
389 self.assertEquals(user.email, 'rename@example.com')
390
391 def test_login_follow_rename_false_onlyonce(self):
392 settings.OPENID_FOLLOW_RENAMES = True
393 settings.OPENID_UPDATE_DETAILS_FROM_SREG = True
394 # Setup existing user who's name we're going to switch to
395 user = User.objects.create_user('testuser', 'someone@example.com')
396 UserOpenID.objects.get_or_create(
397 user=user,
398 claimed_id='http://example.com/existing_identity',
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('testuser2000eight', '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
408 # identity url is for 'testuser2000eight'
409 openid_req = {'openid_identifier': 'http://example.com/identity',
410 'next': '/getuser/'}
411 # but returned username is for 'testuser', which already exists for another identity
412 openid_resp = {'nickname': 'testuser2', 'fullname': 'Rename User',
413 'email': 'rename@example.com'}
414 self._do_user_login(openid_req, openid_resp)
415 response = self.client.get('/getuser/')
416
417 # If OPENID_FOLLOW_RENAMES, attempt to change username to 'testuser'
418 # but since that username is already taken by someone else, we go through
419 # the process of adding +i to it. Even though it looks like the username
420 # follows the nickname+i scheme, it has non-numbers in the suffix, so
421 # it's not an auto-generated one. The regular process of renaming to
422 # 'testuser' has a conflict, so we get +2 at the end.
423 self.assertEquals(response.content, 'testuser2')
424
425 # The user's full name and email have been updated.
426 user = User.objects.get(username=response.content)
427 self.assertEquals(user.first_name, 'Rename')
428 self.assertEquals(user.last_name, 'User')
429 self.assertEquals(user.email, 'rename@example.com')
430
431 def test_login_follow_rename_conflict_onlyonce(self):
432 settings.OPENID_FOLLOW_RENAMES = True
433 settings.OPENID_UPDATE_DETAILS_FROM_SREG = True
434 # Setup existing user who's name we're going to switch to
435 user = User.objects.create_user('testuser', 'someone@example.com')
436 UserOpenID.objects.get_or_create(
437 user=user,
438 claimed_id='http://example.com/existing_identity',
439 display_id='http://example.com/existing_identity')
440
441 # Setup user who is going to try to change username to 'testuser'
442 renamed_user = User.objects.create_user('testuser2000', 'someone@example.com')
443 UserOpenID.objects.get_or_create(
444 user=renamed_user,
445 claimed_id='http://example.com/identity',
446 display_id='http://example.com/identity')
447
448 # identity url is for 'testuser2000'
449 openid_req = {'openid_identifier': 'http://example.com/identity',
450 'next': '/getuser/'}
451 # but returned username is for 'testuser', which already exists for another identity
452 openid_resp = {'nickname': 'testuser', 'fullname': 'Rename User',
453 'email': 'rename@example.com'}
454 self._do_user_login(openid_req, openid_resp)
455 response = self.client.get('/getuser/')
456
457 # If OPENID_FOLLOW_RENAMES, attempt to change username to 'testuser'
458 # but since that username is already taken by someone else, we go through
459 # the process of adding +i to it. Since the user for this identity url
460 # already has a name matching that pattern, check if first.
461 self.assertEquals(response.content, 'testuser2000')
462
463 # The user's full name and email have been updated.
464 user = User.objects.get(username=response.content)
465 self.assertEquals(user.first_name, 'Rename')
466 self.assertEquals(user.last_name, 'User')
467 self.assertEquals(user.email, 'rename@example.com')
468
469 def test_login_follow_rename_false_conflict(self):
470 settings.OPENID_FOLLOW_RENAMES = True
471 settings.OPENID_UPDATE_DETAILS_FROM_SREG = True
472 # Setup existing user who's username matches the name+i pattern
473 user = User.objects.create_user('testuser2', 'someone@example.com')
474 UserOpenID.objects.get_or_create(
475 user=user,
476 claimed_id='http://example.com/identity',
477 display_id='http://example.com/identity')
478
479 # identity url is for 'testuser2'
480 openid_req = {'openid_identifier': 'http://example.com/identity',
481 'next': '/getuser/'}
482 # but returned username is for 'testuser', which looks like we've done
483 # a username+1 for them already, but 'testuser' isn't actually taken
484 openid_resp = {'nickname': 'testuser', 'fullname': 'Same User',
485 'email': 'same@example.com'}
486 self._do_user_login(openid_req, openid_resp)
487 response = self.client.get('/getuser/')
488
489 # If OPENID_FOLLOW_RENAMES, username should be changed to 'testuser'
490 # because it wasn't currently taken
491 self.assertEquals(response.content, 'testuser')
492
493 # The user's full name and email have been updated.
494 user = User.objects.get(username=response.content)
495 self.assertEquals(user.first_name, 'Same')
496 self.assertEquals(user.last_name, 'User')
497 self.assertEquals(user.email, 'same@example.com')
498
289 def test_login_update_details(self):499 def test_login_update_details(self):
290 settings.OPENID_UPDATE_DETAILS_FROM_SREG = True500 settings.OPENID_UPDATE_DETAILS_FROM_SREG = True
291 user = User.objects.create_user('testuser', 'someone@example.com')501 user = User.objects.create_user('testuser', 'someone@example.com')
@@ -295,31 +505,17 @@
295 display_id='http://example.com/identity')505 display_id='http://example.com/identity')
296 useropenid.save()506 useropenid.save()
297507
298 # Posting in an identity URL begins the authentication request:508 openid_req = {'openid_identifier': 'http://example.com/identity',
299 response = self.client.post('/openid/login/',509 'next': '/getuser/'}
300 {'openid_identifier': 'http://example.com/identity',510 openid_resp = {'nickname': 'testuser', 'fullname': 'Some User',
301 'next': '/getuser/'})511 'email': 'foo@example.com'}
302 self.assertContains(response, 'OpenID transaction in progress')512 self._do_user_login(openid_req, openid_resp)
303
304 # Complete the request, passing back some simple registration
305 # data. The user is redirected to the next URL.
306 openid_request = self.provider.parseFormPost(response.content)
307 sreg_request = sreg.SRegRequest.fromOpenIDRequest(openid_request)
308 openid_response = openid_request.answer(True)
309 sreg_response = sreg.SRegResponse.extractResponse(
310 sreg_request, {'nickname': 'someuser', 'fullname': 'Some User',
311 'email': 'foo@example.com'})
312 openid_response.addExtension(sreg_response)
313 response = self.complete(openid_response)
314 self.assertRedirects(response, 'http://testserver/getuser/')
315
316 # And they are now logged in as testuser (the passed in
317 # nickname has not caused the username to change).
318 response = self.client.get('/getuser/')513 response = self.client.get('/getuser/')
514
319 self.assertEquals(response.content, 'testuser')515 self.assertEquals(response.content, 'testuser')
320516
321 # The user's full name and email have been updated.517 # The user's full name and email have been updated.
322 user = User.objects.get(username='testuser')518 user = User.objects.get(username=response.content)
323 self.assertEquals(user.first_name, 'Some')519 self.assertEquals(user.first_name, 'Some')
324 self.assertEquals(user.last_name, 'User')520 self.assertEquals(user.last_name, 'User')
325 self.assertEquals(user.email, 'foo@example.com')521 self.assertEquals(user.email, 'foo@example.com')

Subscribers

People subscribed via source and target branches