Commit 8b210641 by bmedx

Update repo from upstream revision 128

- Previous pull was revision 115
- Diff of versions: http://bazaar.launchpad.net/~ubuntuone-pqm-team/django-openid-auth/trunk/revision/128?remember=115&compare_revid=115
- Should get us Py3 and Django up to 1.10 support
parent 86b822c2
# Created by .ignore support plugin (hsz.mobi)
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Django stuff:
*.log
local_settings.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
.gitignore
.idea/
django_openid_auth.egg-info/
...@@ -26,3 +26,6 @@ ...@@ -26,3 +26,6 @@
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE. # POSSIBILITY OF SUCH DAMAGE.
import sys
PY3 = sys.version_info.major >= 3
...@@ -29,8 +29,11 @@ ...@@ -29,8 +29,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from urllib import urlencode try:
from urlparse import parse_qsl, urlparse from urllib.parse import parse_qsl, urlencode, urlparse
except ImportError:
from urllib import urlencode
from urlparse import parse_qsl, urlparse
from django.conf import settings from django.conf import settings
from django.contrib import admin from django.contrib import admin
...@@ -50,6 +53,7 @@ class NonceAdmin(admin.ModelAdmin): ...@@ -50,6 +53,7 @@ class NonceAdmin(admin.ModelAdmin):
self.message_user(request, "%d expired nonces removed" % count) self.message_user(request, "%d expired nonces removed" % count)
cleanup_nonces.short_description = "Clean up expired nonces" cleanup_nonces.short_description = "Clean up expired nonces"
admin.site.register(Nonce, NonceAdmin) admin.site.register(Nonce, NonceAdmin)
...@@ -65,6 +69,7 @@ class AssociationAdmin(admin.ModelAdmin): ...@@ -65,6 +69,7 @@ class AssociationAdmin(admin.ModelAdmin):
self.message_user(request, "%d expired associations removed" % count) self.message_user(request, "%d expired associations removed" % count)
cleanup_associations.short_description = "Clean up expired associations" cleanup_associations.short_description = "Clean up expired associations"
admin.site.register(Association, AssociationAdmin) admin.site.register(Association, AssociationAdmin)
...@@ -73,6 +78,7 @@ class UserOpenIDAdmin(admin.ModelAdmin): ...@@ -73,6 +78,7 @@ class UserOpenIDAdmin(admin.ModelAdmin):
list_display = ('user', 'claimed_id') list_display = ('user', 'claimed_id')
search_fields = ('claimed_id',) search_fields = ('claimed_id',)
admin.site.register(UserOpenID, UserOpenIDAdmin) admin.site.register(UserOpenID, UserOpenIDAdmin)
......
...@@ -30,13 +30,12 @@ ...@@ -30,13 +30,12 @@
from __future__ import unicode_literals from __future__ import unicode_literals
__metaclass__ = type
import re import re
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission from django.contrib.auth.models import Group, Permission
from django.core.exceptions import ImproperlyConfigured
from openid.consumer.consumer import SUCCESS from openid.consumer.consumer import SUCCESS
from openid.extensions import ax, sreg, pape from openid.extensions import ax, sreg, pape
...@@ -49,12 +48,51 @@ from django_openid_auth.exceptions import ( ...@@ -49,12 +48,51 @@ from django_openid_auth.exceptions import (
MissingPhysicalMultiFactor, MissingPhysicalMultiFactor,
RequiredAttributeNotReturned, RequiredAttributeNotReturned,
) )
from django_openid_auth.signals import openid_duplicate_username
User = get_user_model() User = get_user_model()
class OpenIDBackend: def get_user_group_model():
"""Returns the model used for mapping users to groups."""
user_group_model_name = getattr(settings, 'AUTH_USER_GROUP_MODEL', None)
if user_group_model_name is None:
return User.groups.through
else:
try:
# django.apps available starting from django 1.7
from django.apps import apps
get_model = apps.get_model
args = (user_group_model_name,)
except ImportError:
# if we can't import, then it must be django 1.6, still using
# the old django.db.models.loading code
from django.db.models.loading import get_model
app_label, model_name = user_group_model_name.split('.', 1)
args = (app_label, model_name)
try:
model = get_model(*args)
if model is None:
# in django 1.6 referring to a non-installed app will
# return None for get_model, but in 1.7 onwards it will
# raise a LookupError exception.
raise LookupError()
return model
except ValueError:
raise ImproperlyConfigured(
"AUTH_USER_GROUP_MODEL must be of the form "
"'app_label.model_name'")
except LookupError:
raise ImproperlyConfigured(
"AUTH_USER_GROUP_MODEL refers to model '%s' that has not been "
"installed" % user_group_model_name)
UserGroup = get_user_group_model()
class OpenIDBackend(object):
"""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."""
...@@ -116,8 +154,9 @@ class OpenIDBackend: ...@@ -116,8 +154,9 @@ class OpenIDBackend:
teams_mapping = self.get_teams_mapping() teams_mapping = self.get_teams_mapping()
groups_required = [group for team, group in teams_mapping.items() groups_required = [group for team, group in teams_mapping.items()
if team in teams_required] if team in teams_required]
user_groups = UserGroup.objects.filter(user=user)
matches = set(groups_required).intersection( matches = set(groups_required).intersection(
user.groups.values_list('name', flat=True)) user_groups.values_list('group__name', flat=True))
if not matches: if not matches:
name = 'OPENID_EMAIL_WHITELIST_REGEXP_LIST' name = 'OPENID_EMAIL_WHITELIST_REGEXP_LIST'
whitelist_regexp_list = getattr(settings, name, []) whitelist_regexp_list = getattr(settings, name, [])
...@@ -194,28 +233,19 @@ class OpenIDBackend: ...@@ -194,28 +233,19 @@ class OpenIDBackend:
return suggestion return suggestion
return 'openiduser' return 'openiduser'
def _get_available_username(self, nickname, identity_url): def _get_available_username_for_nickname(self, nickname, identity_url):
# If we're being strict about usernames, throw an error if we didn't
# get one back from the provider
if getattr(settings, 'OPENID_STRICT_USERNAMES', False):
if nickname is None or nickname == '':
raise MissingUsernameViolation()
# If we don't have a nickname, and we're not being strict, use a # If we don't have a nickname, and we're not being strict, use a
# default # default
nickname = nickname or 'openiduser' nickname = nickname or 'openiduser'
# See if we already have this nickname assigned to a username # See if we already have this nickname assigned to a username
try: if not User.objects.filter(username=nickname).exists():
User.objects.get(username__exact=nickname)
except User.DoesNotExist:
# 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(
claimed_id__exact=identity_url, claimed_id=identity_url,
user__username__startswith=nickname) user__username__startswith=nickname)
# No exception means we have an existing user for this identity # No exception means we have an existing user for this identity
# that starts with this nickname. # that starts with this nickname.
...@@ -239,28 +269,48 @@ class OpenIDBackend: ...@@ -239,28 +269,48 @@ class OpenIDBackend:
# No user associated with this identity_url # No user associated with this identity_url
pass pass
if getattr(settings, 'OPENID_STRICT_USERNAMES', False):
if User.objects.filter(username__exact=nickname).count() > 0:
raise DuplicateUsernameViolation(
"The username (%s) with which you tried to log in is "
"already in use for a different account." % nickname)
# Pick a username for the user based on their nickname, # Pick a username for the user based on their nickname,
# checking for conflicts. Start with number of existing users who's # checking for conflicts. Start with number of existing users who's
# username starts with this nickname to avoid having to iterate over # username starts with this nickname to avoid having to iterate over
# all of the existing ones. # all of the existing ones.
i = User.objects.filter(username__startswith=nickname).count() + 1 i = User.objects.filter(username__startswith=nickname).count() + 1
while True: username = nickname
username = nickname while User.objects.filter(username=username).exists():
if i > 1: username = nickname + str(i)
username += str(i)
try:
User.objects.get(username__exact=username)
except User.DoesNotExist:
break
i += 1 i += 1
return username return username
def _ensure_available_username(self, nickname, identity_url):
if not nickname:
raise MissingUsernameViolation()
# As long as the `QuerySet` does not get evaluated, no
# caching should be involved in our multiple `exists()`
# calls. See docs for details: http://bit.ly/2aYCmkw
user_with_same_username = User.objects.exclude(
useropenid__claimed_id=identity_url
).filter(username=nickname)
if user_with_same_username.exists():
# Notify any listeners that a duplicated username was
# found and give the opportunity to handle conflict.
openid_duplicate_username.send(sender=User, username=nickname)
# Check for conflicts again as the signal could have handled it.
if user_with_same_username.exists():
raise DuplicateUsernameViolation(
"The username (%s) with which you tried to log in is "
"already in use for a different account." % nickname)
def _get_available_username(self, nickname, identity_url):
if getattr(settings, 'OPENID_STRICT_USERNAMES', False):
self._ensure_available_username(nickname, identity_url)
else:
nickname = self._get_available_username_for_nickname(
nickname, identity_url)
return nickname
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)
required_attrs = getattr(settings, 'OPENID_SREG_REQUIRED_FIELDS', []) required_attrs = getattr(settings, 'OPENID_SREG_REQUIRED_FIELDS', [])
...@@ -357,13 +407,17 @@ class OpenIDBackend: ...@@ -357,13 +407,17 @@ class OpenIDBackend:
mapping = [ mapping = [
teams_mapping[lp_team] for lp_team in teams_response.is_member teams_mapping[lp_team] for lp_team in teams_response.is_member
if lp_team in teams_mapping] if lp_team in teams_mapping]
user_groups = UserGroup.objects.filter(user=user)
matching_groups = user_groups.filter(
group__name__in=teams_mapping.values())
current_groups = set( current_groups = set(
user.groups.filter(name__in=teams_mapping.values())) user_group.group for user_group in matching_groups)
desired_groups = set(Group.objects.filter(name__in=mapping)) desired_groups = set(Group.objects.filter(name__in=mapping))
for group in current_groups - desired_groups: groups_to_remove = current_groups - desired_groups
user.groups.remove(group) groups_to_add = desired_groups - current_groups
for group in desired_groups - current_groups: user_groups.filter(group__in=groups_to_remove).delete()
user.groups.add(group) for group in groups_to_add:
UserGroup.objects.create(user=user, group=group)
def update_staff_status_from_teams(self, user, teams_response): def update_staff_status_from_teams(self, user, teams_response):
if not hasattr(settings, 'OPENID_LAUNCHPAD_STAFF_TEAMS'): if not hasattr(settings, 'OPENID_LAUNCHPAD_STAFF_TEAMS'):
......
...@@ -38,6 +38,8 @@ from django.conf import settings ...@@ -38,6 +38,8 @@ from django.conf import settings
from openid.yadis import xri from openid.yadis import xri
from django_openid_auth import PY3
def teams_new_unicode(self): def teams_new_unicode(self):
""" """
...@@ -52,8 +54,13 @@ def teams_new_unicode(self): ...@@ -52,8 +54,13 @@ def teams_new_unicode(self):
else: else:
return name return name
Group.unicode_before_teams = Group.__unicode__
Group.__unicode__ = teams_new_unicode if PY3:
Group.unicode_before_teams = Group.__str__
Group.__str__ = teams_new_unicode
else:
Group.unicode_before_teams = Group.__unicode__
Group.__unicode__ = teams_new_unicode
class UserChangeFormWithTeamRestriction(UserChangeForm): class UserChangeFormWithTeamRestriction(UserChangeForm):
...@@ -72,6 +79,7 @@ class UserChangeFormWithTeamRestriction(UserChangeForm): ...@@ -72,6 +79,7 @@ class UserChangeFormWithTeamRestriction(UserChangeForm):
"You cannot assign it manually." % group.name) "You cannot assign it manually." % group.name)
return data return data
UserAdmin.form = UserChangeFormWithTeamRestriction UserAdmin.form = UserChangeFormWithTeamRestriction
......
...@@ -34,3 +34,4 @@ import django.dispatch ...@@ -34,3 +34,4 @@ import django.dispatch
openid_login_complete = django.dispatch.Signal(providing_args=[ openid_login_complete = django.dispatch.Signal(providing_args=[
'request', 'openid_response']) 'request', 'openid_response'])
openid_duplicate_username = django.dispatch.Signal(providing_args=['username'])
...@@ -36,6 +36,7 @@ from openid.association import Association as OIDAssociation ...@@ -36,6 +36,7 @@ from openid.association import Association as OIDAssociation
from openid.store.interface import OpenIDStore from openid.store.interface import OpenIDStore
from openid.store.nonce import SKEW from openid.store.nonce import SKEW
from django_openid_auth import PY3
from django_openid_auth.models import Association, Nonce from django_openid_auth.models import Association, Nonce
...@@ -75,10 +76,15 @@ class DjangoOpenIDStore(OpenIDStore): ...@@ -75,10 +76,15 @@ class DjangoOpenIDStore(OpenIDStore):
expired = [] expired = []
for assoc in assocs: for assoc in assocs:
association = OIDAssociation( association = OIDAssociation(
assoc.handle, base64.decodestring(assoc.secret), assoc.issued, assoc.handle,
assoc.lifetime, assoc.assoc_type base64.decodestring(assoc.secret.encode('utf-8')),
assoc.issued, assoc.lifetime, assoc.assoc_type
) )
if association.getExpiresIn() == 0: if PY3:
expires_in = association.expiresIn
else:
expires_in = association.getExpiresIn()
if expires_in == 0:
expired.append(assoc) expired.append(assoc)
else: else:
associations.append((association.issued, association)) associations.append((association.issued, association))
......
...@@ -72,6 +72,7 @@ from openid.message import ( ...@@ -72,6 +72,7 @@ from openid.message import (
registerNamespaceAlias, registerNamespaceAlias,
NamespaceAliasRegistrationError, NamespaceAliasRegistrationError,
) )
from six import string_types
__all__ = [ __all__ = [
'TeamsRequest', 'TeamsRequest',
...@@ -84,7 +85,7 @@ ns_uri = 'http://ns.launchpad.net/2007/openid-teams' ...@@ -84,7 +85,7 @@ ns_uri = 'http://ns.launchpad.net/2007/openid-teams'
try: try:
registerNamespaceAlias(ns_uri, 'lp') registerNamespaceAlias(ns_uri, 'lp')
except NamespaceAliasRegistrationError, e: except NamespaceAliasRegistrationError as e:
oidutil.log( oidutil.log(
'registerNamespaceAlias(%r, %r) failed: %s' % (ns_uri, 'lp', str(e))) 'registerNamespaceAlias(%r, %r) failed: %s' % (ns_uri, 'lp', str(e)))
...@@ -139,7 +140,7 @@ def getTeamsNS(message): ...@@ -139,7 +140,7 @@ def getTeamsNS(message):
# There is no alias, so try to add one. (OpenID version 1) # There is no alias, so try to add one. (OpenID version 1)
try: try:
message.namespaces.addAlias(ns_uri, 'lp') message.namespaces.addAlias(ns_uri, 'lp')
except KeyError, why: except KeyError as why:
# An alias for the string 'lp' already exists, but it's # An alias for the string 'lp' already exists, but it's
# defined for something other than Launchpad teams # defined for something other than Launchpad teams
raise TeamsNamespaceError(why[0]) raise TeamsNamespaceError(why[0])
...@@ -287,7 +288,7 @@ class TeamsRequest(Extension): ...@@ -287,7 +288,7 @@ class TeamsRequest(Extension):
@raise ValueError: when a team requested is not a string @raise ValueError: when a team requested is not a string
or strict is set and a team was requested more than once or strict is set and a team was requested more than once
""" """
if isinstance(query_membership, basestring): if isinstance(query_membership, string_types):
raise TypeError('Teams should be passed as a list of ' raise TypeError('Teams should be passed as a list of '
'strings (not %r)' % (type(query_membership),)) 'strings (not %r)' % (type(query_membership),))
......
{% load i18n %} {% load i18n %}
{% load url from future %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html> <html>
<head> <head>
......
from django.conf import settings
from django.contrib.auth.models import Group
from django.db import models
class UserGroup(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
group = models.ForeignKey(Group)
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import base64
import time import time
from django.test import TestCase from django.test import TestCase
...@@ -52,7 +53,8 @@ class OpenIDStoreTests(TestCase): ...@@ -52,7 +53,8 @@ class OpenIDStoreTests(TestCase):
server_url='server-url', handle='handle') server_url='server-url', handle='handle')
self.assertEquals(dbassoc.server_url, 'server-url') self.assertEquals(dbassoc.server_url, 'server-url')
self.assertEquals(dbassoc.handle, 'handle') self.assertEquals(dbassoc.handle, 'handle')
self.assertEquals(dbassoc.secret, 'secret'.encode('base-64')) self.assertEquals(
dbassoc.secret, base64.encodestring(b'secret').decode('utf-8'))
self.assertEquals(dbassoc.issued, 42) self.assertEquals(dbassoc.issued, 42)
self.assertEquals(dbassoc.lifetime, 600) self.assertEquals(dbassoc.lifetime, 600)
self.assertEquals(dbassoc.assoc_type, 'HMAC-SHA1') self.assertEquals(dbassoc.assoc_type, 'HMAC-SHA1')
...@@ -66,7 +68,8 @@ class OpenIDStoreTests(TestCase): ...@@ -66,7 +68,8 @@ class OpenIDStoreTests(TestCase):
self.store.storeAssociation('server-url', assoc) self.store.storeAssociation('server-url', assoc)
dbassoc = Association.objects.get( dbassoc = Association.objects.get(
server_url='server-url', handle='handle') server_url='server-url', handle='handle')
self.assertEqual(dbassoc.secret, 'secret2'.encode('base-64')) self.assertEqual(
dbassoc.secret, base64.encodestring(b'secret2').decode('utf-8'))
self.assertEqual(dbassoc.issued, 420) self.assertEqual(dbassoc.issued, 420)
self.assertEqual(dbassoc.lifetime, 900) self.assertEqual(dbassoc.lifetime, 900)
self.assertEqual(dbassoc.assoc_type, 'HMAC-SHA256') self.assertEqual(dbassoc.assoc_type, 'HMAC-SHA256')
...@@ -80,7 +83,7 @@ class OpenIDStoreTests(TestCase): ...@@ -80,7 +83,7 @@ class OpenIDStoreTests(TestCase):
self.assertTrue(isinstance(assoc, OIDAssociation)) self.assertTrue(isinstance(assoc, OIDAssociation))
self.assertEquals(assoc.handle, 'handle') self.assertEquals(assoc.handle, 'handle')
self.assertEquals(assoc.secret, 'secret') self.assertEquals(assoc.secret, b'secret')
self.assertEquals(assoc.issued, timestamp) self.assertEquals(assoc.issued, timestamp)
self.assertEquals(assoc.lifetime, 600) self.assertEquals(assoc.lifetime, 600)
self.assertEquals(assoc.assoc_type, 'HMAC-SHA1') self.assertEquals(assoc.assoc_type, 'HMAC-SHA1')
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf.urls import patterns, include from django.conf.urls import include, url
from django.http import HttpResponse from django.http import HttpResponse
...@@ -36,8 +36,7 @@ def get_user(request): ...@@ -36,8 +36,7 @@ def get_user(request):
return HttpResponse(request.user.username) return HttpResponse(request.user.username)
urlpatterns = patterns( urlpatterns = [
'', url(r'^getuser/$', get_user),
(r'^getuser/$', get_user), url(r'^openid/', include('django_openid_auth.urls')),
(r'^openid/', include('django_openid_auth.urls')), ]
)
...@@ -29,11 +29,17 @@ ...@@ -29,11 +29,17 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf.urls import patterns, url from django.conf.urls import url
urlpatterns = patterns( from django_openid_auth.views import (
'django_openid_auth.views', login_begin,
url(r'^login/$', 'login_begin', name='openid-login'), login_complete,
url(r'^complete/$', 'login_complete', name='openid-complete'), logo,
url(r'^logo.gif$', 'logo', name='openid-logo'),
) )
urlpatterns = [
url(r'^login/$', login_begin, name='openid-login'),
url(r'^complete/$', login_complete, name='openid-complete'),
url(r'^logo.gif$', logo, name='openid-logo'),
]
...@@ -30,8 +30,11 @@ ...@@ -30,8 +30,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import re import re
import urllib try:
from urlparse import urlsplit from urllib.parse import urlencode, urlsplit
except ImportError:
from urllib import urlencode
from urlparse import urlsplit
from django.conf import settings from django.conf import settings
from django.contrib.auth import ( from django.contrib.auth import (
...@@ -39,6 +42,7 @@ from django.contrib.auth import ( ...@@ -39,6 +42,7 @@ from django.contrib.auth import (
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.http.request import QueryDict
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template import RequestContext from django.template import RequestContext
from django.template.loader import render_to_string from django.template.loader import render_to_string
...@@ -129,22 +133,27 @@ def default_render_failure(request, message, status=403, ...@@ -129,22 +133,27 @@ def default_render_failure(request, message, status=403,
template_name='openid/failure.html', template_name='openid/failure.html',
exception=None): exception=None):
"""Render an error page to the user.""" """Render an error page to the user."""
data = render_to_string( context = RequestContext(request)
template_name, dict(message=message, exception=exception), context.update(dict(message=message, exception=exception))
context_instance=RequestContext(request)) data = render_to_string(template_name, context)
return HttpResponse(data, status=status) return HttpResponse(data, status=status)
def parse_openid_response(request): def parse_openid_response(request):
"""Parse an OpenID response from a Django request.""" """Parse an OpenID response from a Django request."""
# Short cut if there is no request parameters.
# if len(request.REQUEST) == 0:
# return None
current_url = request.build_absolute_uri() current_url = request.build_absolute_uri()
consumer = make_consumer(request) consumer = make_consumer(request)
return consumer.complete(dict(request.REQUEST.items()), current_url) data = get_request_data(request)
return consumer.complete(data, current_url)
def get_request_data(request):
# simulate old request.REQUEST for backwards compatibility
data = QueryDict(query_string=None, mutable=True)
data.update(request.GET)
data.update(request.POST)
return data
def login_begin(request, template_name='openid/login.html', def login_begin(request, template_name='openid/login.html',
...@@ -153,7 +162,8 @@ def login_begin(request, template_name='openid/login.html', ...@@ -153,7 +162,8 @@ def login_begin(request, template_name='openid/login.html',
render_failure=default_render_failure, render_failure=default_render_failure,
redirect_field_name=REDIRECT_FIELD_NAME): redirect_field_name=REDIRECT_FIELD_NAME):
"""Begin an OpenID login request, possibly asking for an identity URL.""" """Begin an OpenID login request, possibly asking for an identity URL."""
redirect_to = request.REQUEST.get(redirect_field_name, '') data = get_request_data(request)
redirect_to = data.get(redirect_field_name, '')
# Get the OpenID URL to try. First see if we've been configured # Get the OpenID URL to try. First see if we've been configured
# to use a fixed server URL. # to use a fixed server URL.
...@@ -169,10 +179,12 @@ def login_begin(request, template_name='openid/login.html', ...@@ -169,10 +179,12 @@ def login_begin(request, template_name='openid/login.html',
# Invalid or no form data: # Invalid or no form data:
if openid_url is None: if openid_url is None:
context = {'form': login_form, redirect_field_name: redirect_to} context = RequestContext(request)
return render_to_response( context.update({
template_name, context, 'form': login_form,
context_instance=RequestContext(request)) redirect_field_name: redirect_to,
})
return render_to_response(template_name, context)
consumer = make_consumer(request) consumer = make_consumer(request)
try: try:
...@@ -268,7 +280,7 @@ def login_begin(request, template_name='openid/login.html', ...@@ -268,7 +280,7 @@ def login_begin(request, template_name='openid/login.html',
# Django gives us Unicode, which is great. We must encode URI. # Django gives us Unicode, which is great. We must encode URI.
# urllib enforces str. We can't trust anything about the default # urllib enforces str. We can't trust anything about the default
# encoding inside str(foo) , so we must explicitly make foo a str. # encoding inside str(foo) , so we must explicitly make foo a str.
return_to += urllib.urlencode( return_to += urlencode(
{redirect_field_name: redirect_to.encode("UTF-8")}) {redirect_field_name: redirect_to.encode("UTF-8")})
return render_openid_request(request, openid_request, return_to) return render_openid_request(request, openid_request, return_to)
...@@ -277,7 +289,8 @@ def login_begin(request, template_name='openid/login.html', ...@@ -277,7 +289,8 @@ def login_begin(request, template_name='openid/login.html',
@csrf_exempt @csrf_exempt
def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME, def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME,
render_failure=None): render_failure=None):
redirect_to = request.REQUEST.get(redirect_field_name, '') data = get_request_data(request)
redirect_to = data.get(redirect_field_name, '')
render_failure = ( render_failure = (
render_failure or getattr(settings, 'OPENID_RENDER_FAILURE', None) or render_failure or getattr(settings, 'OPENID_RENDER_FAILURE', None) or
default_render_failure) default_render_failure)
...@@ -290,8 +303,9 @@ def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME, ...@@ -290,8 +303,9 @@ def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME,
if openid_response.status == SUCCESS: if openid_response.status == SUCCESS:
try: try:
user = authenticate(openid_response=openid_response) user = authenticate(openid_response=openid_response)
except DjangoOpenIDException, e: except DjangoOpenIDException as e:
return render_failure(request, e.message, exception=e) return render_failure(
request, getattr(e, 'message', str(e)), exception=e)
if user is not None: if user is not None:
if user.is_active: if user.is_active:
...@@ -325,6 +339,7 @@ def logo(request): ...@@ -325,6 +339,7 @@ def logo(request):
OPENID_LOGO_BASE_64.decode('base64'), mimetype='image/gif' OPENID_LOGO_BASE_64.decode('base64'), mimetype='image/gif'
) )
# Logo from http://openid.net/login-bg.gif # Logo from http://openid.net/login-bg.gif
# Embedded here for convenience; you should serve this as a static file # Embedded here for convenience; you should serve this as a static file
OPENID_LOGO_BASE_64 = """ OPENID_LOGO_BASE_64 = """
......
...@@ -54,6 +54,24 @@ SECRET_KEY = '34958734985734985734985798437' ...@@ -54,6 +54,24 @@ SECRET_KEY = '34958734985734985734985798437'
DEBUG = True DEBUG = True
TEMPLATE_DEBUG = True TEMPLATE_DEBUG = True
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
]
}
}
]
ALLOWED_HOSTS = [] ALLOWED_HOSTS = []
......
...@@ -27,20 +27,20 @@ ...@@ -27,20 +27,20 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE. # POSSIBILITY OF SUCH DAMAGE.
from django.conf.urls import patterns, include, url from django.conf.urls import include, url
from django.contrib import admin from django.contrib import admin
from django.contrib.auth import views as auth_views
import views from example_consumer import views
admin.autodiscover() admin.autodiscover()
urlpatterns = patterns( urlpatterns = [
'',
url(r'^$', views.index), url(r'^$', views.index),
url(r'^openid/', include('django_openid_auth.urls')), url(r'^openid/', include('django_openid_auth.urls')),
url(r'^logout/$', 'django.contrib.auth.views.logout'), url(r'^logout/$', auth_views.logout),
url(r'^private/$', views.require_authentication), url(r'^private/$', views.require_authentication),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
) ]
...@@ -39,21 +39,28 @@ library also includes the following features: ...@@ -39,21 +39,28 @@ library also includes the following features:
info. info.
""" """
import sys
from setuptools import find_packages, setup from setuptools import find_packages, setup
PY3 = sys.version_info.major >= 3
description, long_description = __doc__.split('\n\n', 1) description, long_description = __doc__.split('\n\n', 1)
VERSION = '0.8' VERSION = '0.14'
install_requires = ['django>=1.6', 'six']
if PY3:
install_requires.append('python3-openid')
else:
install_requires.append('python-openid>=2.2.0')
setup( setup(
name='django-openid-auth', name='django-openid-auth',
version=VERSION, version=VERSION,
packages=find_packages(), packages=find_packages(),
install_requires=[ install_requires=install_requires,
'django>=1.5',
'python-openid>=2.2.0',
],
package_data={ package_data={
'django_openid_auth': ['templates/openid/*.html'], 'django_openid_auth': ['templates/openid/*.html'],
}, },
......
[tox] [tox]
envlist = envlist =
py2.7-django1.5, py2.7-django1.6, py2.7-django1.7, py2.7-django1.8 py27-django{1.8,1.9,1.10}
# py3-django{1.11}
[testenv] [testenv]
commands = python manage.py test django_openid_auth commands = python manage.py test django_openid_auth
deps= deps =
mock mock
python-openid
[testenv:py2.7-django1.5] [testenv:py27]
basepython = python2.7 basepython = python2.7
deps = deps =
django >= 1.5, < 1.6 python-openid
{[testenv]deps} {[testenv]deps}
south==1.0
[testenv:py2.7-django1.6] [testenv:py3]
basepython = python2.7 basepython = python3
deps = deps =
django >= 1.6, < 1.7 python3-openid
{[testenv]deps} {[testenv]deps}
south==1.0
[testenv:py2.7-django1.7] [testenv:py27-django1.8]
basepython = python2.7
deps = deps =
django >= 1.7, < 1.8 django >= 1.8, < 1.9
{[testenv]deps} {[testenv:py27]deps}
[testenv:py2.7-django1.8] [testenv:py27-django1.9]
basepython = python2.7
deps = deps =
django >= 1.8, < 1.9 django >= 1.9, < 1.10
{[testenv]deps} {[testenv:py27]deps}
[testenv:py27-django1.10]
deps =
django >= 1.10, < 1.11
{[testenv:py27]deps}
[testenv:py27-django1.11]
deps =
django >= 1.11, < 2
{[testenv:py27]deps}
[testenv:py3-django1.11]
deps =
django >= 1.11, < 2
{[testenv:py3]deps}
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