Commit bef0509f by Michael Hall

Extra renaming considerations and tests for conflicts and false positives

parent 4f029169
......@@ -81,7 +81,7 @@ class OpenIDBackend:
if getattr(settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False):
details = self._extract_user_details(openid_response)
self.update_user_details(user, details)
self.update_user_details(user, details, openid_response)
teams_response = teams.TeamsResponse.fromSuccessResponse(
openid_response)
......@@ -98,7 +98,6 @@ class OpenIDBackend:
email = sreg_response.get('email')
fullname = sreg_response.get('fullname')
nickname = sreg_response.get('nickname')
# If any attributes are provided via Attribute Exchange, use
# them in preference.
fetch_response = ax.FetchResponse.fromSuccessResponse(openid_response)
......@@ -137,10 +136,36 @@ class OpenIDBackend:
return dict(email=email, nickname=nickname,
first_name=first_name, last_name=last_name)
def create_user_from_openid(self, openid_response):
details = self._extract_user_details(openid_response)
nickname = details['nickname'] or 'openiduser'
email = details['email'] or ''
def _get_available_username(self, nickname, identity_url):
nickname = nickname or 'openiduser'
# See if we already have this nickname assigned to a username
try:
user = User.objects.get(username__exact=nickname)
except User.DoesNotExist:
# No conflict, we can use this nickname
return nickname
# Check if we already have nickname+i for this identity_url
try:
user_openid = UserOpenID.objects.get(
claimed_id__exact=identity_url,
user__username__startswith=nickname)
# No exception means we have an existing user for this identity
# that starts with this nickname, so it's possible we've had to
# assign them to nickname+i already.
oid_username = user_openid.user.username
if len(oid_username) > len(nickname):
try:
# check that it ends with a number
int(oid_username[len(nickname):])
return oid_username
except ValueError:
# username starts with nickname, but isn't nickname+#
pass
except UserOpenID.DoesNotExist:
# No user associated with this identity_url
pass
# Pick a username for the user based on their nickname,
# checking for conflicts.
......@@ -150,15 +175,27 @@ class OpenIDBackend:
if i > 1:
username += str(i)
try:
User.objects.get(username__exact=username)
user = User.objects.get(username__exact=username)
if user.useropenid_set.filter(claimed_id__exact=identity_url).count() > 0:
# username already belongs to this openid user, so it's okay
return username
except User.DoesNotExist:
break
i += 1
return username
def create_user_from_openid(self, openid_response):
details = self._extract_user_details(openid_response)
nickname = details['nickname'] or 'openiduser'
email = details['email'] or ''
user = User.objects.create_user(username, email, password=None)
self.update_user_details(user, details)
username = self._get_available_username(details['nickname'], openid_response.identity_url)
user = User.objects.create_user(username, email, password=None)
self.associate_openid(user, openid_response)
self.update_user_details(user, details, openid_response)
return user
def associate_openid(self, user, openid_response):
......@@ -181,7 +218,7 @@ class OpenIDBackend:
return user_openid
def update_user_details(self, user, details):
def update_user_details(self, user, details, openid_response):
updated = False
if details['first_name']:
user.first_name = details['first_name']
......@@ -193,7 +230,7 @@ class OpenIDBackend:
user.email = details['email']
updated = True
if getattr(settings, 'OPENID_FOLLOW_RENAMES', False):
user.username = details['nickname']
user.username = self._get_available_username(details['nickname'], openid_response.identity_url)
updated = True
if updated:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment