Permalink
Browse files

Update to latest django-browserid (0.6).

  • Loading branch information...
1 parent 1191311 commit 1c485522ecdfee166fc4ef1909dfdceb6a6edc2e @Osmose Osmose committed Jun 28, 2012
@@ -1,2 +1,9 @@
+"""
+django-browserid
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
from django_browserid.auth import BrowserIDBackend
-from django_browserid.base import get_audience, verify
+from django_browserid.base import get_audience, verify
@@ -1,3 +1,8 @@
+"""
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
import base64
import hashlib
import logging
@@ -9,6 +14,8 @@
from django.utils.importlib import import_module
from django_browserid.base import get_audience as base_get_audience, verify
+from django_browserid.signals import user_created
+
log = logging.getLogger(__name__)
@@ -30,6 +37,7 @@ def default_username_algo(email):
class BrowserIDBackend(object):
supports_anonymous_user = False
+ supports_inactive_user = True
supports_object_permissions = False
def verify(self, *args):
@@ -81,11 +89,16 @@ def authenticate(self, assertion=None, audience=None):
create_user = getattr(settings, 'BROWSERID_CREATE_USER', True)
if not create_user:
return None
- elif create_user == True:
- return self.create_user(email)
else:
- # Find the function to call, call it and throw in the email.
- return self._load_module(create_user)(email)
+ if create_user == True:
+ create_function = self.create_user
+ else:
+ # Find the function to call.
+ create_function = self._load_module(create_user)
+
+ user = create_function(email)
+ user_created.send(create_function, user=user)
+ return user
def get_user(self, user_id):
try:
@@ -1,3 +1,8 @@
+"""
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
import logging
import urllib
from warnings import warn
@@ -1,3 +1,8 @@
+"""
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
from django_browserid.forms import BrowserIDForm
@@ -1,8 +1,13 @@
+"""
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
from django import forms
class BrowserIDForm(forms.Form):
assertion = forms.CharField(widget=forms.HiddenInput())
-
+
class Media:
js = ('browserid/browserid.js', 'https://browserid.org/include.js')
@@ -0,0 +1,15 @@
+"""
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.. data:: user_created
+
+ Signal triggered when the BrowserID authentication backend creates a new
+ user. Sender is the function that created the user, user is the new user
+ instance.
+"""
+from django.dispatch import Signal
+
+
+user_created = Signal(providing_args=['user'])
@@ -1,4 +1,7 @@
-$(document).ready(function() {
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ $(document).ready(function() {
$('#browserid').bind('click', function(e) {
e.preventDefault();
navigator.id.getVerifiedEmail(function(assertion) {
@@ -0,0 +1,50 @@
+"""
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
+from django.utils.functional import wraps
+
+from mock import patch
+
+
+def fake_create_user(email):
+ pass
+
+
+class mock_browserid(object):
+ """
+ Mocks django_browserid verification. Can be used as a context manager or
+ as a decorator:
+
+ with mock_browserid('a@b.com'):
+ django_browserid.verify('random-token') # = {'status': 'okay',
+ # 'email': 'a@b.com',
+ # ...}
+
+ @mock_browserid(None)
+ def browserid_test():
+ django_browserid.verify('random-token') # = False
+ """
+ def __init__(self, email=None, audience=None):
+ self.patcher = patch('django_browserid.base._verify_http_request')
+ self.return_value = {
+ u'audience': audience,
+ u'email': email,
+ u'issuer': u'browserid.org:443',
+ u'status': u'okay' if email is not None else u'failure',
+ u'valid-until': 1311377222765
+ }
+
+ def __enter__(self):
+ self.patcher.start().return_value = self.return_value
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.patcher.stop()
+
+ def __call__(self, func):
+ @wraps(func)
+ def inner(*args, **kwargs):
+ with self:
+ return func(*args, **kwargs)
+ return inner
@@ -0,0 +1,32 @@
+"""
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
+TEST_RUNNER = 'django_nose.runner.NoseTestSuiteRunner'
+
+DATABASES = {
+ 'default': {
+ 'NAME': 'test.db',
+ 'ENGINE': 'django.db.backends.sqlite3',
+ }
+}
+
+INSTALLED_APPS = (
+ 'django_nose',
+ 'django_browserid',
+
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+)
+
+ROOT_URLCONF = 'django_browserid.tests.urls'
+
+AUTHENTICATION_BACKENDS = (
+ 'django_browserid.auth.BrowserIDBackend',
+)
+
+SITE_URL = 'http://testserver'
+
+BROWSERID_CREATE_USER = True
+BROWSERID_USERNAME_ALGO = None
@@ -0,0 +1,96 @@
+"""
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.test import TestCase
+
+from mock import patch
+
+from django_browserid.auth import BrowserIDBackend, default_username_algo
+from django_browserid.tests import mock_browserid
+
+
+def new_user(email, username=None):
+ """Creates a user with the specified email for testing."""
+ if username is None:
+ username = default_username_algo(email)
+ return User.objects.create_user(username, email)
+
+
+class BrowserIDBackendTests(TestCase):
+ def auth(self, verified_email=None):
+ """
+ Attempt to authenticate a user with BrowserIDBackend.
+
+ If verified_email is None, verification will fail, otherwise it will pass
+ and return the specified email.
+ """
+ with mock_browserid(verified_email):
+ backend = BrowserIDBackend()
+ return backend.authenticate(assertion='asdf', audience='asdf')
+
+ def test_failed_verification(self):
+ """If verification fails, return None."""
+ assert self.auth(None) is None
+
+ def test_duplicate_emails(self):
+ """If there are two users with the same email address, return None."""
+ new_user('a@example.com', 'test1')
+ new_user('a@example.com', 'test2')
+ assert self.auth('a@example.com') is None
+
+ def test_auth_success(self):
+ """
+ If a single user is found with the verified email, return an instance of
+ their user object.
+ """
+ user = new_user('a@example.com')
+ assert self.auth('a@example.com') == user
+
+ @patch.object(settings, 'BROWSERID_CREATE_USER', False)
+ def test_no_create_user(self):
+ """If user creation is disabled and no user is found, return None."""
+ assert self.auth('a@example.com') is None
+
+ @patch.object(settings, 'BROWSERID_CREATE_USER', True)
+ def test_create_user(self):
+ """
+ If user creation is enabled and no user is found, return a new
+ User.
+ """
+ user = self.auth('a@example.com')
+ assert user is not None
+ assert isinstance(user, User)
+ assert user.email == 'a@example.com'
+
+ @patch.object(settings, 'BROWSERID_CREATE_USER',
+ 'django_browserid.tests.test_auth.new_user')
+ @patch('django_browserid.tests.test_auth.new_user')
+ def test_custom_create_user(self, create_user):
+ """
+ If user creation is enabled with a custom create function and no user
+ is found, return the new user created with the custom function.
+ """
+ create_user.return_value = 'test'
+ assert self.auth('a@example.com') == 'test'
+ assert create_user.called_with('a@example.com')
+
+ @patch.object(settings, 'BROWSERID_USERNAME_ALGO')
+ @patch.object(settings, 'BROWSERID_CREATE_USER', True)
+ def test_custom_username_algorithm(self, username_algo):
+ """If a custom username algorithm is specified, use it!"""
+ username_algo.return_value = 'test'
+ user = self.auth('a@b.com')
+ assert user.username == 'test'
+
+ @patch('django_browserid.signals.user_created')
+ @patch.object(settings, 'BROWSERID_CREATE_USER', True)
+ def test_user_created_signal(self, user_created):
+ """
+ Test that the user_created signal is called when a new user is created.
+ """
+ user = self.auth('a@b.com')
+ assert user_created.call.called_with(user=user)
Oops, something went wrong.

0 comments on commit 1c48552

Please sign in to comment.