[snowy] Adding some files for django_openid_auth I forgot
- From: Jeff Schroeder <jschroeder src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [snowy] Adding some files for django_openid_auth I forgot
- Date: Mon, 10 Oct 2011 03:54:09 +0000 (UTC)
commit f7ed4e60992907c9a46cb661005b52260f7704f8
Author: Jeff Schroeder <jeffschroeder computer org>
Date: Sun Oct 9 20:53:30 2011 -0700
Adding some files for django_openid_auth I forgot
lib/django_openid_auth/MANIFEST.in | 8 +
lib/django_openid_auth/Makefile | 10 ++
lib/django_openid_auth/README.txt | 168 ++++++++++++++++++++
.../example_consumer/__init__.py | 28 ++++
.../example_consumer/settings.py | 143 +++++++++++++++++
lib/django_openid_auth/example_consumer/urls.py | 45 ++++++
lib/django_openid_auth/example_consumer/views.py | 57 +++++++
lib/django_openid_auth/exceptions.py | 68 ++++++++
lib/django_openid_auth/openid.html | 150 +++++++++++++++++
lib/django_openid_auth/openid.txt | 165 +++++++++++++++++++
lib/django_openid_auth/setup.py | 80 +++++++++
lib/django_openid_auth/signals.py | 34 ++++
lib/django_openid_auth/tests/test_auth.py | 155 ++++++++++++++++++
13 files changed, 1111 insertions(+), 0 deletions(-)
---
diff --git a/lib/django_openid_auth/MANIFEST.in b/lib/django_openid_auth/MANIFEST.in
new file mode 100644
index 0000000..acc52f6
--- /dev/null
+++ b/lib/django_openid_auth/MANIFEST.in
@@ -0,0 +1,8 @@
+include Makefile
+include MANIFEST.in
+include LICENSE.txt
+include README.txt
+include TODO.txt
+
+recursive-include django_openid_auth/templates *.html
+recursive-include example_consumer *.py
diff --git a/lib/django_openid_auth/Makefile b/lib/django_openid_auth/Makefile
new file mode 100644
index 0000000..d43e6cb
--- /dev/null
+++ b/lib/django_openid_auth/Makefile
@@ -0,0 +1,10 @@
+
+check:
+ PYTHONPATH=$(shell pwd) python example_consumer/manage.py test \
+ --verbosity=2 django_openid_auth
+
+run-example-consumer:
+ PYTHONPATH=$(shell pwd) python example_consumer/manage.py syncdb
+ PYTHONPATH=$(shell pwd) python example_consumer/manage.py runserver
+
+.PHONY: check run-example-consumer
diff --git a/lib/django_openid_auth/README.txt b/lib/django_openid_auth/README.txt
new file mode 100644
index 0000000..257ea09
--- /dev/null
+++ b/lib/django_openid_auth/README.txt
@@ -0,0 +1,168 @@
+= Django OpenID Authentication Support =
+
+This package provides integration between Django's authentication
+system and OpenID authentication. It also includes support for using
+a fixed OpenID server endpoint, which can be useful when implementing
+single signon systems.
+
+
+== Basic Installation ==
+
+ 1. Install the Jan Rain Python OpenID library. It can be found at:
+
+ http://openidenabled.com/python-openid/
+
+ It can also be found in most Linux distributions packaged as
+ "python-openid". You will need version 2.2.0 or later.
+
+ 2. Add 'django_openid_auth' to INSTALLED_APPS for your application.
+ At a minimum, you'll need the following in there:
+
+ INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django_openid_auth',
+ )
+
+ 3. Add 'django_auth_openid.auth.OpenIDBackend' to
+ AUTHENTICATION_BACKENDS. This should be in addition to the
+ default ModelBackend:
+
+ AUTHENTICATION_BACKENDS = (
+ 'django_openid_auth.auth.OpenIDBackend',
+ 'django.contrib.auth.backends.ModelBackend',
+ )
+
+ 4. To create users automatically when a new OpenID is used, add the
+ following to the settings:
+
+ OPENID_CREATE_USERS = True
+
+ 5. To have user details updated from OpenID Simple Registration or
+ Attribute Exchange extension data each time they log in, add the
+ following:
+
+ OPENID_UPDATE_DETAILS_FROM_SREG = True
+
+ 6. Hook up the login URLs to your application's urlconf with
+ something like:
+
+ urlpatterns = patterns('',
+ ...
+ (r'^openid/', include('django_openid_auth.urls')),
+ ...
+ )
+
+ 7. Configure the LOGIN_URL and LOGIN_REDIRECT_URL appropriately for
+ your site:
+
+ LOGIN_URL = '/openid/login/'
+ LOGIN_REDIRECT_URL = '/'
+
+ This will allow pages that use the standard @login_required
+ decorator to use the OpenID login page.
+
+ 8. Rerun "python manage.py syncdb" to add the UserOpenID table to
+ your database.
+
+
+== Configuring Single Sign-On ==
+
+If you only want to accept identities from a single OpenID server and
+that server implemnts OpenID 2.0 identifier select mode, add the
+following setting to your app:
+
+ OPENID_SSO_SERVER_URL = 'server-endpoint-url'
+
+With this setting enabled, the user will not be prompted to enter
+their identity URL, and instead an OpenID authentication request will
+be started with the given server URL.
+
+As an example, to use Launchpad accounts for SSO, you'd use:
+
+ OPENID_SSO_SERVER_URL = 'https://login.launchpad.net/'
+
+
+== Launchpad Teams Support ==
+
+This library supports the Launchpad Teams OpenID extension. Using
+this feature, it is possible to map Launchpad team memberships to
+Django group memberships. It can be configured with:
+
+ OPENID_SSO_SERVER_URL = 'https://login.launchpad.net/'
+ OPENID_LAUNCHPAD_TEAMS_MAPPING = {
+ 'launchpad-team-1': 'django-group-1',
+ 'launchpad-team-2': 'django-group-2',
+ }
+
+When a user logs in, they will be added or removed from the relevant
+teams listed in the mapping.
+
+If you have already django-groups and want to map these groups automatically, you can use the OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO variable in your settings.py file.
+
+ OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO = True
+
+If you use OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO, the variable OPENID_LAUNCHPAD_TEAMS_MAPPING will be ignored.
+If you want to exclude some groups from the auto mapping, use OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO_BLACKLIST. This variable has only an effect if OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO is True.
+
+ OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO_BLACKLIST = ['django-group1', 'django-group2']
+
+== External redirect domains ==
+
+By default, redirecting back to an external URL after auth is forbidden. To permit redirection to external URLs on a separate domain, define ALLOWED_EXTERNAL_OPENID_REDIRECT_DOMAINS in your settings.py file as a list of permitted domains:
+
+ ALLOWED_EXTERNAL_OPENID_REDIRECT_DOMAINS = ['example.com', 'example.org']
+
+and redirects to external URLs on those domains will additionally be permitted.
+
+== Use as /admin (django.admin.contrib) login ==
+
+If you require openid authentication into the admin application, add the following setting:
+
+ OPENID_USE_AS_ADMIN_LOGIN = True
+
+It is worth noting that a user needs to be be marked as a "staff user" to be able to access the admin interface. A new openid user will not normally be a "staff user".
+The easiest way to resolve this is to use traditional authentication (OPENID_USE_AS_ADMIN_LOGIN = False) to sign in as your first user with a password and authorise your
+openid user to be staff.
+
+== Change Django usernames if the nickname changes on the provider ==
+
+If you want your Django username to change when a user updates the nickname on their provider, add the following setting:
+
+ OPENID_FOLLOW_RENAMES = True
+
+If the new nickname is available as a Django username, the user is renamed.
+Otherwise the user will be renamed to nickname+i for an incrememnting value of i until no conflict occurs.
+If the user has already been renamed to nickname+1 due to a conflict, and the nickname is still not available, the user will keep their existing username.
+
+== Require a valid nickname ==
+
+If you must have a valid, unique nickname in order to create a user accont, add the following setting:
+
+ OPENID_STRICT_USERNAMES = True
+
+This will cause an OpenID login attempt to fail if the provider does not return a 'nickname' (username) for the user, or if the nickname conflicts with an existing user with a different openid identiy url.
+Without this setting, logins without a nickname will be given the username 'openiduser', and upon conflicts with existing username, an incrementing number will be appended to the username until it is unique.
+
+== Require Physical Multi-Factor Authentication ==
+
+If your users should use a physical multi-factor authentication method, such as RSA tokens or YubiKey, add the following setting:
+
+ OPENID_PHYSICAL_MULTIFACTOR_REQUIRED = True
+
+If the user's OpenID provider supports the PAPE extension and provides the Physical Multifactor authentication policy, this will
+cause the OpenID login to fail if the user does not provide valid physical authentication to the provider.
+
+== Override Login Failure Handling ==
+
+You can optionally provide your own handler for login failures by adding the following setting:
+
+ OPENID_RENDER_FAILURE = failure_handler_function
+
+Where failure_handler_function is a function reference that will take the following parameters:
+
+ def failure_handler_function(request, message, status=None, template_name=None, exception=None)
+
+This function must return a Django.http.HttpResponse instance.
+
diff --git a/lib/django_openid_auth/TODO.txt b/lib/django_openid_auth/TODO.txt
new file mode 100644
index 0000000..e69de29
diff --git a/lib/django_openid_auth/example_consumer/__init__.py b/lib/django_openid_auth/example_consumer/__init__.py
new file mode 100644
index 0000000..956164e
--- /dev/null
+++ b/lib/django_openid_auth/example_consumer/__init__.py
@@ -0,0 +1,28 @@
+# django-openid-auth - OpenID integration for django.contrib.auth
+#
+# Copyright (C) 2007 Simon Willison
+# Copyright (C) 2008-2010 Canonical Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/django_openid_auth/example_consumer/settings.py b/lib/django_openid_auth/example_consumer/settings.py
new file mode 100644
index 0000000..33ea110
--- /dev/null
+++ b/lib/django_openid_auth/example_consumer/settings.py
@@ -0,0 +1,143 @@
+# django-openid-auth - OpenID integration for django.contrib.auth
+#
+# Copyright (C) 2007 Simon Willison
+# Copyright (C) 2008-2010 Canonical Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# Django settings for example project.
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email domain com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
+DATABASE_NAME = 'sqlite.db' # Or path to database file if using sqlite3.
+DATABASE_USER = '' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+
+# Local time zone for this installation. Choices can be found here:
+# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
+# although not all variations may be possible on all operating systems.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
+# http://blogs.law.harvard.edu/tech/stories/storyReader$15
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT.
+# Example: "http://media.lawrence.com"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = '34958734985734985734985798437'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ 'django.template.loaders.app_directories.load_template_source',
+# 'django.template.loaders.eggs.load_template_source',
+)
+
+# django-openid-auth will *not* work with Django 1.1.1 or older, as it's
+# missing the csrf_token template tag. This will allow it to work with
+# Django 1.1.2 or later:
+try:
+ import django.middleware.csrf
+except ImportError:
+ csrf_middleware = 'django.contrib.csrf.middleware.CsrfViewMiddleware'
+else:
+ csrf_middleware = 'django.middleware.csrf.CsrfViewMiddleware'
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ csrf_middleware,
+)
+
+ROOT_URLCONF = 'example_consumer.urls'
+
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.admin',
+ 'django_openid_auth',
+)
+
+AUTHENTICATION_BACKENDS = (
+ 'django_openid_auth.auth.OpenIDBackend',
+ 'django.contrib.auth.backends.ModelBackend',
+)
+
+# Should users be created when new OpenIDs are used to log in?
+OPENID_CREATE_USERS = True
+
+# When logging in again, should we overwrite user details based on
+# data received via Simple Registration?
+OPENID_UPDATE_DETAILS_FROM_SREG = True
+
+# If set, always use this as the identity URL rather than asking the
+# user. This only makes sense if it is a server URL.
+OPENID_SSO_SERVER_URL = 'https://login.launchpad.net/'
+
+# Tell django.contrib.auth to use the OpenID signin URLs.
+LOGIN_URL = '/openid/login/'
+LOGIN_REDIRECT_URL = '/'
+
+# Should django_auth_openid be used to sign into the admin interface?
+OPENID_USE_AS_ADMIN_LOGIN = False
diff --git a/lib/django_openid_auth/example_consumer/urls.py b/lib/django_openid_auth/example_consumer/urls.py
new file mode 100644
index 0000000..74d2ec3
--- /dev/null
+++ b/lib/django_openid_auth/example_consumer/urls.py
@@ -0,0 +1,45 @@
+# django-openid-auth - OpenID integration for django.contrib.auth
+#
+# Copyright (C) 2007 Simon Willison
+# Copyright (C) 2008-2010 Canonical Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+from django.conf.urls.defaults import *
+from django.contrib import admin
+
+import views
+
+
+admin.autodiscover()
+
+urlpatterns = patterns('',
+ (r'^$', views.index),
+ (r'^openid/', include('django_openid_auth.urls')),
+ (r'^logout/$', 'django.contrib.auth.views.logout'),
+ (r'^private/$', views.require_authentication),
+
+ (r'^admin/(.*)', admin.site.root),
+)
diff --git a/lib/django_openid_auth/example_consumer/views.py b/lib/django_openid_auth/example_consumer/views.py
new file mode 100644
index 0000000..3e8c3ed
--- /dev/null
+++ b/lib/django_openid_auth/example_consumer/views.py
@@ -0,0 +1,57 @@
+# django-openid-auth - OpenID integration for django.contrib.auth
+#
+# Copyright (C) 2007 Simon Willison
+# Copyright (C) 2008-2010 Canonical Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+from django.contrib.auth.decorators import login_required
+from django.http import HttpResponse
+from django.utils.html import escape
+
+
+def index(request):
+ s = ['<p>']
+ if request.user.is_authenticated():
+ s.append('You are signed in as <strong>%s</strong> (%s)' % (
+ escape(request.user.username),
+ escape(request.user.get_full_name())))
+ s.append(' | <a href="/logout">Sign out</a>')
+ else:
+ s.append('<a href="/openid/login">Sign in with OpenID</a>')
+
+ s.append('</p>')
+
+ s.append('<p><a href="/private">This requires authentication</a></p>')
+ return HttpResponse('\n'.join(s))
+
+
+def next_works(request):
+ return HttpResponse('?next= bit works. <a href="/">Home</a>')
+
+
+ login_required
+def require_authentication(request):
+ return HttpResponse('This page requires authentication')
diff --git a/lib/django_openid_auth/exceptions.py b/lib/django_openid_auth/exceptions.py
new file mode 100644
index 0000000..08c970c
--- /dev/null
+++ b/lib/django_openid_auth/exceptions.py
@@ -0,0 +1,68 @@
+# django-openid-auth - OpenID integration for django.contrib.auth
+#
+# Copyright (C) 2008-2010 Canonical Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+"""Exception classes thrown by OpenID Authentication and Validation."""
+
+class DjangoOpenIDException(Exception):
+ pass
+
+class RequiredAttributeNotReturned(DjangoOpenIDException):
+ pass
+
+class IdentityAlreadyClaimed(DjangoOpenIDException):
+
+ def __init__(self, message=None):
+ if message is None:
+ self.message = "Another user already exists for your selected OpenID"
+ else:
+ self.message = message
+
+class DuplicateUsernameViolation(DjangoOpenIDException):
+
+ def __init__(self, message=None):
+ if message is None:
+ self.message = "Your desired username is already being used."
+ else:
+ self.message = message
+
+class MissingUsernameViolation(DjangoOpenIDException):
+
+ def __init__(self, message=None):
+ if message is None:
+ self.message = "No nickname given for your account."
+ else:
+ self.message = message
+
+class MissingPhysicalMultiFactor(DjangoOpenIDException):
+
+ def __init__(self, message=None):
+ if message is None:
+ self.message = "Login requires physical multi-factor authentication."
+ else:
+ self.message = message
+
diff --git a/lib/django_openid_auth/openid.html b/lib/django_openid_auth/openid.html
new file mode 100644
index 0000000..cd8004f
--- /dev/null
+++ b/lib/django_openid_auth/openid.html
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head><title>OpenID in Django</title></head>
+<body>
+<h1>OpenID in Django</h1>
+<p>The <tt class="docutils literal"><span class="pre">django_openidconsumer</span></tt> package contains all of the code needed to set up
+your Django application as an OpenID consumer. You can use it to allow OpenID
+users to sign in to your site without having to create a new username and
+password.</p>
+<div class="section">
+<h2><a id="overview">Overview</a></h2>
+<p>The OpenID consumer system consists of:</p>
+<ul class="simple">
+<li>Views for you to hook in to your application.</li>
+<li>Database models implementing the persistence layer of an OpenID consumer.</li>
+<li>Middleware that makes <tt class="docutils literal"><span class="pre">request.openid</span></tt> and <tt class="docutils literal"><span class="pre">request.openids</span></tt>
+properties available to your application views.</li>
+</ul>
+</div>
+<div class="section">
+<h2><a id="dependencies">Dependencies</a></h2>
+<p><tt class="docutils literal"><span class="pre">django_openidconsumer</span></tt> uses the <a class="reference" href="http://www.openidenabled.com/openid/libraries/python/">python-openid library</a>, which must be
+installed separately somewhere on the Python path. You should install the 1.2.0
+“combo” package which includes the <tt class="docutils literal"><span class="pre">yadis</span></tt> and <tt class="docutils literal"><span class="pre">urljr</span></tt> libraries.</p>
+<p>The package also depends on the availability of Django’s <a class="reference" href="http://www.djangoproject.com/documentation/sessions/">session support</a>.</p>
+</div>
+<div class="section">
+<h2><a id="installation">Installation</a></h2>
+<p>Having ensured that both the <tt class="docutils literal"><span class="pre">python-openid</span></tt> library and the <tt class="docutils literal"><span class="pre">django_openidconsumer</span></tt> package are available on your Python path, you can
+add OpenID consumer support to an application by doing the following:</p>
+<ol class="arabic">
+<li><p class="first">Put <tt class="docutils literal"><span class="pre">django_openidconsumer</span></tt> in your <tt class="docutils literal"><span class="pre">INSTALLED_APPS</span></tt> setting.</p>
+</li>
+<li><p class="first">Run the command <tt class="docutils literal"><span class="pre">manage.py</span> <span class="pre">syncdb</span></tt> to create the necessary tables.</p>
+</li>
+<li><p class="first">Add <tt class="docutils literal"><span class="pre">django_openidconsumer.middleware.OpenIDMiddleware</span></tt> to your list
+of <tt class="docutils literal"><span class="pre">MIDDLEWARE_CLASSES</span></tt>, somewhere after the Session middleware.</p>
+</li>
+<li><p class="first">Add the following views to your urlconf:</p>
+<pre class="literal-block">
+(r'^openid/$', 'django_openidconsumer.views.begin'),
+(r'^openid/complete/$', 'django_openidconsumer.views.complete'),
+(r'^openid/signout/$', 'django_openidconsumer.views.signout'),
+</pre>
+</li>
+</ol>
+<p>You will then be able to browse to <tt class="docutils literal"><span class="pre">example.com/openid/</span></tt> and sign in using
+an OpenID.</p>
+</div>
+<div class="section">
+<h2><a id="using-the-openid-middleware">Using the OpenID middleware</a></h2>
+<p>With the Middleware installed, your views will have access to the user’s OpenID
+as the <tt class="docutils literal"><span class="pre">request.openid</span></tt> property. This will be <tt class="docutils literal"><span class="pre">None</span></tt> if the user has not
+yet authenticated; otherwise it will be a <tt class="docutils literal"><span class="pre">django_openidconsumer.util.OpenID</span></tt>
+instance.</p>
+<p>If you want the user’s OpenID as a string, call the <tt class="docutils literal"><span class="pre">str()</span></tt> builtin on the
+OpenID instance:</p>
+<pre class="literal-block">
+def example_view(request):
+ if request.openid:
+ return HttpResponse("OpenID is %s" % escape(str(request.openid)))
+ else:
+ return HttpResponse("No OpenID")
+</pre>
+<p>Users can sign in with more than one OpenID. This is supported by the
+<tt class="docutils literal"><span class="pre">request.openids</span></tt> property, which is a list of <tt class="docutils literal"><span class="pre">OpenID</span></tt> objects in the order
+in which they were authenticated. <tt class="docutils literal"><span class="pre">request.openid</span></tt> merely returns the last
+item in this list.</p>
+</div>
+<div class="section">
+<h2><a id="using-simple-registration">Using simple registration</a></h2>
+<p>Simple registration (or <a class="reference" href="http://openid.net/specs/openid-simple-registration-extension-1_0.html">sreg</a>) is an extension to the OpenID specification
+that allows you to request extra details about a user from their OpenID
+provider. It is frequently used to pre-populate registration forms with
+information such as the user’s name, e-mail address or date of birth.</p>
+<p>Be aware that not all OpenID providers support sreg, and there is no guarantee
+that the information you have requested will be returned. Simple registration
+should be used as a convenience for your users rather than as a required step in
+your authentication process.</p>
+<p>Available simple registration fields are <tt class="docutils literal"><span class="pre">nickname</span></tt>, <tt class="docutils literal"><span class="pre">email</span></tt>, <tt class="docutils literal"><span class="pre">fullname</span></tt>,
+<tt class="docutils literal"><span class="pre">dob</span></tt>, <tt class="docutils literal"><span class="pre">gender</span></tt>, <tt class="docutils literal"><span class="pre">postcode</span></tt>, <tt class="docutils literal"><span class="pre">country</span></tt>, <tt class="docutils literal"><span class="pre">language</span></tt> and <tt class="docutils literal"><span class="pre">timezone</span></tt>.
+Full details are available in the <a class="reference" href="http://openid.net/specs/openid-simple-registration-extension-1_0.html">spec</a>.</p>
+<p>To request this information, pass the fields that you wish to retrieve as an
+additional <tt class="docutils literal"><span class="pre">sreg</span></tt> argument to the <tt class="docutils literal"><span class="pre">django_openidconsumer.views.begin</span></tt> view:</p>
+<pre class="literal-block">
+(r'^openid/$', 'django_openidconsumer.views.begin', {
+ 'sreg': 'email,nickname'
+}),
+</pre>
+<p>Any simple registration fields that are returned will be available in a
+dictionary as the <tt class="docutils literal"><span class="pre">sreg</span></tt> property of the OpenID object:</p>
+<pre class="literal-block">
+def example_sreg(request):
+ if request.openid and request.openid.sreg.has_key('email'):
+ return HttpResponse("Your e-mail address is: %s" % escape(
+ request.openid.sreg['email']
+ ))
+ else:
+ return HttpResponse("No e-mail address")
+</pre>
+</div>
+<div class="section">
+<h2><a id="customisation">Customisation</a></h2>
+<p><tt class="docutils literal"><span class="pre">django_openidconsumer</span></tt> uses two templates:</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">openid_signin.html</span></tt></dt>
+<dd>The form presented to the user when they sign in.</dd>
+<dt><tt class="docutils literal"><span class="pre">openid_failure.html</span></tt></dt>
+<dd>The template used to display an error message when something goes wrong.</dd>
+</dl>
+<p>You can over-ride the default templates by creating templates of the same name
+and placing them somewhere on your template path. You can find the example
+templates in the <tt class="docutils literal"><span class="pre">django_openidconsumer/templates</span></tt> directory.</p>
+<p>The OpenID specification strongly recommends that any OpenID registration form
+has a <tt class="docutils literal"><span class="pre">name</span></tt> attribute of <tt class="docutils literal"><span class="pre">openid_url</span></tt> to aid browser autocompletion, and
+displays the <a class="reference" href="http://openid.net/login-bg.gif">OpenID logo</a> inline in the form field using the following CSS:</p>
+<pre class="literal-block">
+input.openid {
+ background: url(/path/to/login-bg.gif) no-repeat;
+ background-position: 0 50%;
+ padding-left: 16px;
+}
+</pre>
+<p>By default, the package expects the <tt class="docutils literal"><span class="pre">django_openidconsumer.views.complete</span></tt>
+view to be located at <tt class="docutils literal"><span class="pre">/openid/complete/</span></tt>. This is the view that the OpenID
+provider will redirect the user to after they have authenticated. If you want to
+put it somewhere else you can either pass an extra <tt class="docutils literal"><span class="pre">redirect_to</span></tt> argument to
+<tt class="docutils literal"><span class="pre">django_openidconsumer.views.begin</span></tt> or add an <tt class="docutils literal"><span class="pre">OPENID_REDIRECT_TO</span></tt> setting
+to <tt class="docutils literal"><span class="pre">settings.py</span></tt>.</p>
+<p>You can pass a <tt class="docutils literal"><span class="pre">?next=</span></tt> query string argument containing a relative URL to
+the <tt class="docutils literal"><span class="pre">begin</span></tt> view to control where the user will be redirected to having
+returned to your site. You can also set the default redirection location
+using the <tt class="docutils literal"><span class="pre">OPENID_REDIRECT_NEXT</span></tt> setting; if you do set set a default the user
+will be redirected to your homepage.</p>
+</div>
+<div class="section">
+<h2><a id="i-names">i-names</a></h2>
+<p><a class="reference" href="http://www.inames.net/">i-names</a> are part of the OpenID 2.0 specification, which is currently being
+developed. They are supported by the python-openid library, and hence are also
+supported by <tt class="docutils literal"><span class="pre">django_openidconsumer</span></tt>. You can tell if an OpenID is an i-name
+by checking the <tt class="docutils literal"><span class="pre">request.openid.is_iname</span></tt> property.</p>
+<p>If you wish to disable i-name support, you can do so by adding the following to
+your <tt class="docutils literal"><span class="pre">settings.py</span></tt>:</p>
+<pre class="literal-block">
+OPENID_DISALLOW_INAMES = True
+</pre>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/lib/django_openid_auth/openid.txt b/lib/django_openid_auth/openid.txt
new file mode 100644
index 0000000..043cdfe
--- /dev/null
+++ b/lib/django_openid_auth/openid.txt
@@ -0,0 +1,165 @@
+================
+OpenID in Django
+================
+
+The ``django_openidconsumer`` package contains all of the code needed to set up
+your Django application as an OpenID consumer. You can use it to allow OpenID
+users to sign in to your site without having to create a new username and
+password.
+
+Overview
+========
+
+The OpenID consumer system consists of:
+
+ * Views for you to hook in to your application.
+ * Database models implementing the persistence layer of an OpenID consumer.
+ * Middleware that makes ``request.openid`` and ``request.openids``
+ properties available to your application views.
+
+Dependencies
+============
+
+``django_openidconsumer`` uses the `python-openid library`_, which must be
+installed separately somewhere on the Python path. You should install the 1.2.0
+"combo" package which includes the ``yadis`` and ``urljr`` libraries.
+
+The package also depends on the availability of Django's `session support`_.
+
+.. _python-openid library: http://www.openidenabled.com/openid/libraries/python/
+.. _session support: http://www.djangoproject.com/documentation/sessions/
+
+Installation
+============
+
+Having ensured that both the ``python-openid`` library and the ``django_openidconsumer`` package are available on your Python path, you can
+add OpenID consumer support to an application by doing the following:
+
+ 1. Put ``django_openidconsumer`` in your ``INSTALLED_APPS`` setting.
+ 2. Run the command ``manage.py syncdb`` to create the necessary tables.
+ 3. Add ``django_openidconsumer.middleware.OpenIDMiddleware`` to your list
+ of ``MIDDLEWARE_CLASSES``, somewhere after the Session middleware.
+ 4. Add the following views to your urlconf::
+
+ (r'^openid/$', 'django_openidconsumer.views.begin'),
+ (r'^openid/complete/$', 'django_openidconsumer.views.complete'),
+ (r'^openid/signout/$', 'django_openidconsumer.views.signout'),
+
+You will then be able to browse to ``example.com/openid/`` and sign in using
+an OpenID.
+
+Using the OpenID middleware
+===========================
+
+With the Middleware installed, your views will have access to the user's OpenID
+as the ``request.openid`` property. This will be ``None`` if the user has not
+yet authenticated; otherwise it will be a ``django_openidconsumer.util.OpenID``
+instance.
+
+If you want the user's OpenID as a string, call the ``str()`` builtin on the
+OpenID instance::
+
+ def example_view(request):
+ if request.openid:
+ return HttpResponse("OpenID is %s" % escape(str(request.openid)))
+ else:
+ return HttpResponse("No OpenID")
+
+Users can sign in with more than one OpenID. This is supported by the
+``request.openids`` property, which is a list of ``OpenID`` objects in the order
+in which they were authenticated. ``request.openid`` merely returns the last
+item in this list.
+
+Using simple registration
+=========================
+
+Simple registration (or `sreg`_) is an extension to the OpenID specification
+that allows you to request extra details about a user from their OpenID
+provider. It is frequently used to pre-populate registration forms with
+information such as the user's name, e-mail address or date of birth.
+
+.. _sreg: http://openid.net/specs/openid-simple-registration-extension-1_0.html
+
+Be aware that not all OpenID providers support sreg, and there is no guarantee
+that the information you have requested will be returned. Simple registration
+should be used as a convenience for your users rather than as a required step in
+your authentication process.
+
+Available simple registration fields are ``nickname``, ``email``, ``fullname``,
+``dob``, ``gender``, ``postcode``, ``country``, ``language`` and ``timezone``.
+Full details are available in the `spec`_.
+
+.. _spec: http://openid.net/specs/openid-simple-registration-extension-1_0.html
+
+To request this information, pass the fields that you wish to retrieve as an
+additional ``sreg`` argument to the ``django_openidconsumer.views.begin`` view::
+
+ (r'^openid/$', 'django_openidconsumer.views.begin', {
+ 'sreg': 'email,nickname'
+ }),
+
+Any simple registration fields that are returned will be available in a
+dictionary as the ``sreg`` property of the OpenID object::
+
+ def example_sreg(request):
+ if request.openid and request.openid.sreg.has_key('email'):
+ return HttpResponse("Your e-mail address is: %s" % escape(
+ request.openid.sreg['email']
+ ))
+ else:
+ return HttpResponse("No e-mail address")
+
+Customisation
+=============
+
+``django_openidconsumer`` uses two templates:
+
+``openid_signin.html``
+ The form presented to the user when they sign in.
+
+``openid_failure.html``
+ The template used to display an error message when something goes wrong.
+
+You can over-ride the default templates by creating templates of the same name
+and placing them somewhere on your template path. You can find the example
+templates in the ``django_openidconsumer/templates`` directory.
+
+The OpenID specification strongly recommends that any OpenID registration form
+has a ``name`` attribute of ``openid_url`` to aid browser autocompletion, and
+displays the `OpenID logo`_ inline in the form field using the following CSS::
+
+ input.openid {
+ background: url(/path/to/login-bg.gif) no-repeat;
+ background-position: 0 50%;
+ padding-left: 16px;
+ }
+
+.. _OpenID logo: http://openid.net/login-bg.gif
+
+By default, the package expects the ``django_openidconsumer.views.complete``
+view to be located at ``/openid/complete/``. This is the view that the OpenID
+provider will redirect the user to after they have authenticated. If you want to
+put it somewhere else you can either pass an extra ``redirect_to`` argument to
+``django_openidconsumer.views.begin`` or add an ``OPENID_REDIRECT_TO`` setting
+to ``settings.py``.
+
+You can pass a ``?next=`` query string argument containing a relative URL to
+the ``begin`` view to control where the user will be redirected to having
+returned to your site. You can also set the default redirection location
+using the ``OPENID_REDIRECT_NEXT`` setting; if you do set set a default the user
+will be redirected to your homepage.
+
+i-names
+=======
+
+`i-names`_ are part of the OpenID 2.0 specification, which is currently being
+developed. They are supported by the python-openid library, and hence are also
+supported by ``django_openidconsumer``. You can tell if an OpenID is an i-name
+by checking the ``request.openid.is_iname`` property.
+
+.. _i-names: http://www.inames.net/
+
+If you wish to disable i-name support, you can do so by adding the following to
+your ``settings.py``::
+
+ OPENID_DISALLOW_INAMES = True
diff --git a/lib/django_openid_auth/setup.py b/lib/django_openid_auth/setup.py
new file mode 100644
index 0000000..f408343
--- /dev/null
+++ b/lib/django_openid_auth/setup.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# django-openid-auth - OpenID integration for django.contrib.auth
+#
+# Copyright (C) 2009-2010 Canonical Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+"""OpenID integration for django.contrib.auth
+
+A library that can be used to add OpenID support to Django applications.
+The library integrates with Django's built in authentication system, so
+most applications require minimal changes to support OpenID llogin. The
+library also includes the following features:
+ * Basic user details are transferred from the OpenID server via the
+ Simple Registration extension or Attribute Exchange extension.
+ * can be configured to use a fixed OpenID server URL, for use in SSO.
+ * supports the launchpad.net teams extension to get team membership
+ info.
+"""
+
+from distutils.core import setup
+
+
+description, long_description = __doc__.split('\n\n', 1)
+VERSION = '0.4'
+
+setup(
+ name='django-openid-auth',
+ version=VERSION,
+ author='Canonical Ltd',
+ description=description,
+ long_description=long_description,
+ license='BSD',
+ platforms=['any'],
+ url='https://launchpad.net/django-openid-auth',
+ download_url=('http://launchpad.net/django-openid-auth/trunk/%s/+download'
+ '/django-openid-auth-%s.tar.gz' % (VERSION, VERSION)),
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'Environment :: Web Environment',
+ 'Framework :: Django',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Topic :: Software Development :: Libraries :: Python Modules'
+ ],
+ packages=[
+ 'django_openid_auth',
+ 'django_openid_auth.management',
+ 'django_openid_auth.management.commands',
+ 'django_openid_auth.tests',
+ ],
+ package_data={
+ 'django_openid_auth': ['templates/openid/*.html'],
+ },
+ provides=['django_openid_auth'],
+ requires=['django (>=1.1.2)', 'openid (>=2.2.0)'],
+ )
diff --git a/lib/django_openid_auth/signals.py b/lib/django_openid_auth/signals.py
new file mode 100644
index 0000000..4cdfdd3
--- /dev/null
+++ b/lib/django_openid_auth/signals.py
@@ -0,0 +1,34 @@
+# django-openid-auth - OpenID integration for django.contrib.auth
+#
+# Copyright (C) 2007 Simon Willison
+# Copyright (C) 2008-2010 Canonical Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import django.dispatch
+
+
+openid_login_complete = django.dispatch.Signal(providing_args=[
+ 'request', 'openid_response'])
diff --git a/lib/django_openid_auth/tests/test_auth.py b/lib/django_openid_auth/tests/test_auth.py
new file mode 100644
index 0000000..2ef3789
--- /dev/null
+++ b/lib/django_openid_auth/tests/test_auth.py
@@ -0,0 +1,155 @@
+# django-openid-auth - OpenID integration for django.contrib.auth
+#
+# Copyright (C) 2010 Canonical Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import unittest
+
+from django.contrib.auth.models import User
+from django.test import TestCase
+
+from django_openid_auth.auth import OpenIDBackend
+from openid.consumer.consumer import SuccessResponse
+from openid.consumer.discover import OpenIDServiceEndpoint
+from openid.message import Message, OPENID2_NS
+
+
+SREG_NS = "http://openid.net/sreg/1.0"
+AX_NS = "http://openid.net/srv/ax/1.0"
+
+class OpenIDBackendTests(TestCase):
+
+ def setUp(self):
+ super(OpenIDBackendTests, self).setUp()
+ self.backend = OpenIDBackend()
+
+ def test_extract_user_details_sreg(self):
+ endpoint = OpenIDServiceEndpoint()
+ message = Message(OPENID2_NS)
+ message.setArg(SREG_NS, "nickname", "someuser")
+ message.setArg(SREG_NS, "fullname", "Some User")
+ message.setArg(SREG_NS, "email", "foo example com")
+ response = SuccessResponse(
+ endpoint, message, signed_fields=message.toPostArgs().keys())
+
+ data = self.backend._extract_user_details(response)
+ self.assertEqual(data, {"nickname": "someuser",
+ "first_name": "Some",
+ "last_name": "User",
+ "email": "foo example com"})
+
+ def make_response_ax(self, schema="http://axschema.org/",
+ fullname="Some User", nickname="someuser", email="foo example com",
+ first=None, last=None):
+ endpoint = OpenIDServiceEndpoint()
+ message = Message(OPENID2_NS)
+ attributes = [
+ ("nickname", schema + "namePerson/friendly", nickname),
+ ("fullname", schema + "namePerson", fullname),
+ ("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")
+ for (alias, uri, value) in attributes:
+ message.setArg(AX_NS, "type.%s" % alias, uri)
+ message.setArg(AX_NS, "value.%s" % alias, value)
+ return SuccessResponse(
+ 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)
+
+ self.assertEqual(data, {"nickname": "someuser",
+ "first_name": "Some",
+ "last_name": "User",
+ "email": "foo example com"})
+
+ def test_extract_user_details_ax_split_name(self):
+ # Include fullname too to show that the split data takes
+ # precedence.
+ response = self.make_response_ax(
+ fullname="Bad Data", first="Some", last="User")
+
+ data = self.backend._extract_user_details(response)
+
+ self.assertEqual(data, {"nickname": "someuser",
+ "first_name": "Some",
+ "last_name": "User",
+ "email": "foo example com"})
+
+ def test_extract_user_details_ax_broken_myopenid(self):
+ response = self.make_response_ax(
+ schema="http://schema.openid.net/", fullname="Some User",
+ nickname="someuser", email="foo example com")
+
+ data = self.backend._extract_user_details(response)
+
+ self.assertEqual(data, {"nickname": "someuser",
+ "first_name": "Some",
+ "last_name": "User",
+ "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():
+ return unittest.TestLoader().loadTestsFromName(__name__)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]