Commit 1bbcbd7b by Anthony Lenton

Merged in lp:~michael.nelson/django-openid-auth/801499-check-name-length

parents dd89937e 24006f81
...@@ -44,7 +44,7 @@ class IdentityAlreadyClaimed(Exception): ...@@ -44,7 +44,7 @@ class IdentityAlreadyClaimed(Exception):
class StrictUsernameViolation(Exception): class StrictUsernameViolation(Exception):
pass pass
class OpenIDBackend: class OpenIDBackend:
"""A django.contrib.auth backend that authenticates the user based on """A django.contrib.auth backend that authenticates the user based on
an OpenID response.""" an OpenID response."""
...@@ -132,8 +132,10 @@ class OpenIDBackend: ...@@ -132,8 +132,10 @@ class OpenIDBackend:
if fullname and not (first_name or last_name): if fullname and not (first_name or last_name):
# Django wants to store first and last names separately, # Django wants to store first and last names separately,
# so we do our best to split the full name. # so we do our best to split the full name.
if ' ' in fullname: fullname = fullname.strip()
first_name, last_name = fullname.rsplit(None, 1) split_names = fullname.rsplit(None, 1)
if len(split_names) == 2:
first_name, last_name = split_names
else: else:
first_name = u'' first_name = u''
last_name = fullname last_name = fullname
...@@ -147,7 +149,7 @@ class OpenIDBackend: ...@@ -147,7 +149,7 @@ class OpenIDBackend:
if getattr(settings, 'OPENID_STRICT_USERNAMES', False): if getattr(settings, 'OPENID_STRICT_USERNAMES', False):
if nickname is None or nickname == '': if nickname is None or nickname == '':
raise StrictUsernameViolation("No username") raise StrictUsernameViolation("No username")
# If we don't have a nickname, and we're not being strict, use a default # If we don't have a nickname, and we're not being strict, use a default
nickname = nickname or 'openiduser' nickname = nickname or 'openiduser'
...@@ -157,7 +159,7 @@ class OpenIDBackend: ...@@ -157,7 +159,7 @@ class OpenIDBackend:
except User.DoesNotExist: except User.DoesNotExist:
# No conflict, we can use this nickname # No conflict, we can use this nickname
return nickname return nickname
# Check if we already have nickname+i for this identity_url # Check if we already have nickname+i for this identity_url
try: try:
user_openid = UserOpenID.objects.get( user_openid = UserOpenID.objects.get(
...@@ -178,7 +180,7 @@ class OpenIDBackend: ...@@ -178,7 +180,7 @@ class OpenIDBackend:
except UserOpenID.DoesNotExist: except UserOpenID.DoesNotExist:
# No user associated with this identity_url # No user associated with this identity_url
pass pass
if getattr(settings, 'OPENID_STRICT_USERNAMES', False): if getattr(settings, 'OPENID_STRICT_USERNAMES', False):
if User.objects.filter(username__exact=nickname).count() > 0: if User.objects.filter(username__exact=nickname).count() > 0:
...@@ -197,7 +199,7 @@ class OpenIDBackend: ...@@ -197,7 +199,7 @@ class OpenIDBackend:
break break
i += 1 i += 1
return username return username
def create_user_from_openid(self, openid_response): def create_user_from_openid(self, openid_response):
details = self._extract_user_details(openid_response) details = self._extract_user_details(openid_response)
nickname = details['nickname'] or 'openiduser' nickname = details['nickname'] or 'openiduser'
...@@ -234,10 +236,10 @@ class OpenIDBackend: ...@@ -234,10 +236,10 @@ class OpenIDBackend:
def update_user_details(self, user, details, openid_response): def update_user_details(self, user, details, openid_response):
updated = False updated = False
if details['first_name']: if details['first_name']:
user.first_name = details['first_name'] user.first_name = details['first_name'][:30]
updated = True updated = True
if details['last_name']: if details['last_name']:
user.last_name = details['last_name'] user.last_name = details['last_name'][:30]
updated = True updated = True
if details['email']: if details['email']:
user.email = details['email'] user.email = details['email']
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
import unittest import unittest
from django.contrib.auth.models import User
from django.test import TestCase from django.test import TestCase
from django_openid_auth.auth import OpenIDBackend from django_openid_auth.auth import OpenIDBackend
...@@ -60,74 +61,95 @@ class OpenIDBackendTests(TestCase): ...@@ -60,74 +61,95 @@ class OpenIDBackendTests(TestCase):
"last_name": "User", "last_name": "User",
"email": "foo@example.com"}) "email": "foo@example.com"})
def test_extract_user_details_ax(self): def make_response_ax(self, schema="http://axschema.org/",
fullname="Some User", nickname="someuser", email="foo@example.com",
first=None, last=None):
endpoint = OpenIDServiceEndpoint() endpoint = OpenIDServiceEndpoint()
message = Message(OPENID2_NS) message = Message(OPENID2_NS)
attributes = [ attributes = [
("nickname", "http://axschema.org/namePerson/friendly", "someuser"), ("nickname", schema + "namePerson/friendly", nickname),
("fullname", "http://axschema.org/namePerson", "Some User"), ("fullname", schema + "namePerson", fullname),
("email", "http://axschema.org/contact/email", "foo@example.com"), ("email", schema + "contact/email", email),
] ]
if first:
attributes.append(
("first", "http://axschema.org/namePerson/first", first))
if last:
attributes.append(
("last", "http://axschema.org/namePerson/last", last))
message.setArg(AX_NS, "mode", "fetch_response") message.setArg(AX_NS, "mode", "fetch_response")
for (alias, uri, value) in attributes: for (alias, uri, value) in attributes:
message.setArg(AX_NS, "type.%s" % alias, uri) message.setArg(AX_NS, "type.%s" % alias, uri)
message.setArg(AX_NS, "value.%s" % alias, value) message.setArg(AX_NS, "value.%s" % alias, value)
response = SuccessResponse( return SuccessResponse(
endpoint, message, signed_fields=message.toPostArgs().keys()) endpoint, message, signed_fields=message.toPostArgs().keys())
def test_extract_user_details_ax(self):
response = self.make_response_ax(fullname="Some User",
nickname="someuser", email="foo@example.com")
data = self.backend._extract_user_details(response) data = self.backend._extract_user_details(response)
self.assertEqual(data, {"nickname": "someuser", self.assertEqual(data, {"nickname": "someuser",
"first_name": "Some", "first_name": "Some",
"last_name": "User", "last_name": "User",
"email": "foo@example.com"}) "email": "foo@example.com"})
def test_extract_user_details_ax_split_name(self): def test_extract_user_details_ax_split_name(self):
endpoint = OpenIDServiceEndpoint() # Include fullname too to show that the split data takes
message = Message(OPENID2_NS) # precedence.
attributes = [ response = self.make_response_ax(
("nickname", "http://axschema.org/namePerson/friendly", "someuser"), fullname="Bad Data", first="Some", last="User")
# Include this key too to show that the split data takes
# precedence.
("fullname", "http://axschema.org/namePerson", "Bad Data"),
("first", "http://axschema.org/namePerson/first", "Some"),
("last", "http://axschema.org/namePerson/last", "User"),
("email", "http://axschema.org/contact/email", "foo@example.com"),
]
message.setArg(AX_NS, "mode", "fetch_response")
for (alias, uri, value) in attributes:
message.setArg(AX_NS, "type.%s" % alias, uri)
message.setArg(AX_NS, "value.%s" % alias, value)
response = SuccessResponse(
endpoint, message, signed_fields=message.toPostArgs().keys())
data = self.backend._extract_user_details(response) data = self.backend._extract_user_details(response)
self.assertEqual(data, {"nickname": "someuser", self.assertEqual(data, {"nickname": "someuser",
"first_name": "Some", "first_name": "Some",
"last_name": "User", "last_name": "User",
"email": "foo@example.com"}) "email": "foo@example.com"})
def test_extract_user_details_ax_broken_myopenid(self): def test_extract_user_details_ax_broken_myopenid(self):
endpoint = OpenIDServiceEndpoint() response = self.make_response_ax(
message = Message(OPENID2_NS) schema="http://schema.openid.net/", fullname="Some User",
attributes = [ nickname="someuser", email="foo@example.com")
("nickname", "http://schema.openid.net/namePerson/friendly",
"someuser"),
("fullname", "http://schema.openid.net/namePerson", "Some User"),
("email", "http://schema.openid.net/contact/email",
"foo@example.com"),
]
message.setArg(AX_NS, "mode", "fetch_response")
for (alias, uri, value) in attributes:
message.setArg(AX_NS, "type.%s" % alias, uri)
message.setArg(AX_NS, "value.%s" % alias, value)
response = SuccessResponse(
endpoint, message, signed_fields=message.toPostArgs().keys())
data = self.backend._extract_user_details(response) data = self.backend._extract_user_details(response)
self.assertEqual(data, {"nickname": "someuser", self.assertEqual(data, {"nickname": "someuser",
"first_name": "Some", "first_name": "Some",
"last_name": "User", "last_name": "User",
"email": "foo@example.com"}) "email": "foo@example.com"})
def test_update_user_details_long_names(self):
response = self.make_response_ax()
user = User.objects.create_user('someuser', 'someuser@example.com',
password=None)
data = dict(first_name=u"Some56789012345678901234567890123",
last_name=u"User56789012345678901234567890123",
email=u"someotheruser@example.com")
self.backend.update_user_details(user, data, response)
self.assertEqual("Some56789012345678901234567890", user.first_name)
self.assertEqual("User56789012345678901234567890", user.last_name)
def test_extract_user_details_name_with_trailing_space(self):
response = self.make_response_ax(fullname="SomeUser ")
data = self.backend._extract_user_details(response)
self.assertEqual("", data['first_name'])
self.assertEqual("SomeUser", data['last_name'])
def test_extract_user_details_name_with_thin_space(self):
response = self.make_response_ax(fullname=u"Some\u2009User")
data = self.backend._extract_user_details(response)
self.assertEqual("Some", data['first_name'])
self.assertEqual("User", data['last_name'])
def suite(): def suite():
return unittest.TestLoader().loadTestsFromName(__name__) return unittest.TestLoader().loadTestsFromName(__name__)
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