Commit 7a6469f5 by Anthony Lenton

Added a settings, OPENID_USE_EMAIL_FOR_USERNAME to use a stripped version of the…

Added a settings, OPENID_USE_EMAIL_FOR_USERNAME to use a stripped version of the user's email for generating the username, if no nick is provided by the OpenID server.
parent 691ecea9
......@@ -146,6 +146,16 @@ class OpenIDBackend:
return dict(email=email, nickname=nickname,
first_name=first_name, last_name=last_name)
def _get_preferred_username(self, nickname, email):
if nickname:
return nickname
if email and getattr(settings, 'OPENID_USE_EMAIL_FOR_USERNAME',
False):
suggestion = ''.join([x for x in email if x.isalnum()])
if suggestion:
return suggestion
return 'openiduser'
def _get_available_username(self, nickname, identity_url):
# If we're being strict about usernames, throw an error if we didn't
# get one back from the provider
......@@ -225,10 +235,12 @@ class OpenIDBackend:
"An attribute required for logging in was not "
"returned ({0}).".format(required_attr))
nickname = details['nickname'] or 'openiduser'
nickname = self._get_preferred_username(details['nickname'],
details['email'])
email = details['email'] or ''
username = self._get_available_username(details['nickname'], openid_response.identity_url)
username = self._get_available_username(nickname,
openid_response.identity_url)
user = User.objects.create_user(username, email, password=None)
self.associate_openid(user, openid_response)
......
......@@ -28,6 +28,7 @@
import unittest
from django.conf import settings
from django.contrib.auth.models import User
from django.test import TestCase
......@@ -45,6 +46,12 @@ class OpenIDBackendTests(TestCase):
def setUp(self):
super(OpenIDBackendTests, self).setUp()
self.backend = OpenIDBackend()
self.old_openid_use_email_for_username = getattr(settings,
'OPENID_USE_EMAIL_FOR_USERNAME', False)
def tearDown(self):
settings.OPENID_USE_EMAIL_FOR_USERNAME = \
self.old_openid_use_email_for_username
def test_extract_user_details_sreg(self):
endpoint = OpenIDServiceEndpoint()
......@@ -150,6 +157,29 @@ class OpenIDBackendTests(TestCase):
self.assertEqual("Some", data['first_name'])
self.assertEqual("User", data['last_name'])
def test_preferred_username_email_munging(self):
settings.OPENID_USE_EMAIL_FOR_USERNAME = True
for nick, email, expected in [
('nickcomesfirst', 'foo@example.com', 'nickcomesfirst'),
('', 'foo@example.com', 'fooexamplecom'),
('noemail', '', 'noemail'),
('', '@%.-', 'openiduser'),
('', '', 'openiduser'),
(None, None, 'openiduser')]:
self.assertEqual(expected,
self.backend._get_preferred_username(nick, email))
def test_preferred_username_no_email_munging(self):
for nick, email, expected in [
('nickcomesfirst', 'foo@example.com', 'nickcomesfirst'),
('', 'foo@example.com', 'openiduser'),
('noemail', '', 'noemail'),
('', '@%.-', 'openiduser'),
('', '', 'openiduser'),
(None, None, 'openiduser')]:
self.assertEqual(expected,
self.backend._get_preferred_username(nick, email))
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
......@@ -42,7 +42,7 @@ from openid.fetchers import (
from openid.oidutil import importElementTree
from openid.server.server import BROWSER_REQUEST_MODES, ENCODE_URL, Server
from openid.store.memstore import MemoryStore
from openid.message import OPENID1_URL_LIMIT, IDENTIFIER_SELECT
from openid.message import IDENTIFIER_SELECT
from django_openid_auth import teams
from django_openid_auth.models import UserOpenID
......@@ -50,7 +50,6 @@ from django_openid_auth.views import (
sanitise_redirect_url,
make_consumer,
)
from django_openid_auth.auth import OpenIDBackend
from django_openid_auth.signals import openid_login_complete
from django_openid_auth.store import DjangoOpenIDStore
from django_openid_auth.exceptions import (
......@@ -185,6 +184,8 @@ class RelyingPartyTests(TestCase):
self.old_physical_multifactor = getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False)
self.old_login_render_failure = getattr(settings, 'OPENID_RENDER_FAILURE', None)
self.old_consumer_complete = Consumer.complete
self.old_openid_use_email_for_username = getattr(settings,
'OPENID_USE_EMAIL_FOR_USERNAME', False)
self.old_required_fields = getattr(
settings, 'OPENID_SREG_REQUIRED_FIELDS', [])
......@@ -198,6 +199,7 @@ class RelyingPartyTests(TestCase):
settings.OPENID_FOLLOW_RENAMES = False
settings.OPENID_PHYSICAL_MULTIFACTOR_REQUIRED = False
settings.OPENID_SREG_REQUIRED_FIELDS = []
settings.OPENID_USE_EMAIL_FOR_USERNAME = False
def tearDown(self):
settings.LOGIN_REDIRECT_URL = self.old_login_redirect_url
......@@ -212,6 +214,7 @@ class RelyingPartyTests(TestCase):
settings.OPENID_RENDER_FAILURE = self.old_login_render_failure
Consumer.complete = self.old_consumer_complete
settings.OPENID_SREG_REQUIRED_FIELDS = self.old_required_fields
settings.OPENID_USE_EMAIL_FOR_USERNAME = self.old_openid_use_email_for_username
setDefaultFetcher(None)
super(RelyingPartyTests, self).tearDown()
......@@ -569,6 +572,20 @@ class RelyingPartyTests(TestCase):
self.assertEquals(user.last_name, 'User')
self.assertEquals(user.email, 'foo@example.com')
def test_login_without_nickname_with_email_suggestion(self):
settings.OPENID_CREATE_USERS = True
settings.OPENID_USE_EMAIL_FOR_USERNAME = True
openid_req = {'openid_identifier': 'http://example.com/identity',
'next': '/getuser/'}
openid_resp = {'nickname': '', 'fullname': 'Openid User',
'email': 'foo@example.com'}
self._do_user_login(openid_req, openid_resp)
response = self.client.get('/getuser/')
# username defaults to a munged version of the email
self.assertEquals(response.content, 'fooexamplecom')
def test_login_duplicate_username_numbering(self):
settings.OPENID_FOLLOW_RENAMES = False
settings.OPENID_CREATE_USERS = True
......
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