Commit 201c1f3a by Natalia Bidart Committed by Ricardo Kirkner

- Migrated base code to support Django 1.4-1.8.

- General code and tests cleanup, fixed all the pep8 errors.
parents 6f4e845e 0f5894bc
./django
./MANIFEST
./build
./dist
./sqlite.db
./.tox/
MANIFEST
build
dist
db.sqlite3
.tox
check:
PYTHONPATH=$(shell pwd) python example_consumer/manage.py test \
--verbosity=2 django_openid_auth
PYTHONPATH=$(shell pwd) python 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
PYTHONPATH=$(shell pwd) python manage.py syncdb --migrate
PYTHONPATH=$(shell pwd) python manage.py runserver
.PHONY: check run-example-consumer
......@@ -26,4 +26,3 @@
# 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.
......@@ -27,8 +27,15 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
from urllib import urlencode
from urlparse import parse_qsl, urlparse
from django.conf import settings
from django.contrib import admin
from django.http import HttpResponseRedirect
from django_openid_auth import views
from django_openid_auth.models import Nonce, Association, UserOpenID
from django_openid_auth.store import DjangoOpenIDStore
......@@ -69,22 +76,33 @@ class UserOpenIDAdmin(admin.ModelAdmin):
admin.site.register(UserOpenID, UserOpenIDAdmin)
# Support for allowing openid authentication for /admin (django.contrib.admin)
if getattr(settings, 'OPENID_USE_AS_ADMIN_LOGIN', False):
from django.http import HttpResponseRedirect
from django_openid_auth import views
def _openid_login(self, request, error_message='', extra_context=None):
if request.user.is_authenticated():
if not request.user.is_staff:
return views.default_render_failure(
request, "User %s does not have admin access."
% request.user.username)
assert error_message, "Unknown Error: %s" % error_message
else:
# Redirect to openid login path,
return HttpResponseRedirect(
settings.LOGIN_URL + "?next=" + request.get_full_path())
# Overide the standard admin login form.
admin.sites.AdminSite.login = _openid_login
# store a reference to the original admin login
original_admin_login = admin.sites.AdminSite.login
def _openid_login(instance, request, error_message='', extra_context=None):
# Support for allowing openid authentication for /admin
# (django.contrib.admin)
if not getattr(settings, 'OPENID_USE_AS_ADMIN_LOGIN', False):
return original_admin_login(
instance, request, extra_context=extra_context)
if not request.user.is_authenticated():
# Redirect to openid login path,
_, _, path, _, query, _ = urlparse(request.get_full_path())
qs = dict(parse_qsl(query))
qs.setdefault('next', path)
return HttpResponseRedirect(
settings.LOGIN_URL + "?" + urlencode(qs))
if not request.user.is_staff:
return views.default_render_failure(
request, "User %s does not have admin/staff access."
% request.user.username)
# No error message was supplied
assert error_message, "Unknown Error: %s" % error_message
# Overide the standard admin login form.
admin.sites.AdminSite.login = _openid_login
......@@ -28,6 +28,8 @@
"""Glue between OpenID and django.contrib.auth."""
from __future__ import unicode_literals
__metaclass__ = type
import re
......@@ -93,8 +95,9 @@ class OpenIDBackend:
if getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False):
pape_response = pape.Response.fromSuccessResponse(openid_response)
if pape_response is None or \
pape.AUTH_MULTI_FACTOR_PHYSICAL not in pape_response.auth_policies:
key = pape.AUTH_MULTI_FACTOR_PHYSICAL
if (pape_response is None or
key not in pape_response.auth_policies):
raise MissingPhysicalMultiFactor()
teams_response = teams.TeamsResponse.fromSuccessResponse(
......@@ -165,7 +168,7 @@ class OpenIDBackend:
if len(split_names) == 2:
first_name, last_name = split_names
else:
first_name = u''
first_name = ''
last_name = fullname
verification_scheme_map = getattr(
......@@ -194,12 +197,13 @@ class OpenIDBackend:
if nickname is None or nickname == '':
raise MissingUsernameViolation()
# If we don't have a nickname, and we're not being strict, use a default
# If we don't have a nickname, and we're not being strict, use a
# default
nickname = nickname or 'openiduser'
# See if we already have this nickname assigned to a username
try:
user = User.objects.get(username__exact=nickname)
User.objects.get(username__exact=nickname)
except User.DoesNotExist:
# No conflict, we can use this nickname
return nickname
......@@ -231,7 +235,6 @@ class OpenIDBackend:
# No user associated with this identity_url
pass
if getattr(settings, 'OPENID_STRICT_USERNAMES', False):
if User.objects.filter(username__exact=nickname).count() > 0:
raise DuplicateUsernameViolation(
......@@ -248,7 +251,7 @@ class OpenIDBackend:
if i > 1:
username += str(i)
try:
user = User.objects.get(username__exact=username)
User.objects.get(username__exact=username)
except User.DoesNotExist:
break
i += 1
......@@ -266,12 +269,12 @@ class OpenIDBackend:
"An attribute required for logging in was not "
"returned ({0}).".format(required_attr))
nickname = self._get_preferred_username(details['nickname'],
details['email'])
nickname = self._get_preferred_username(
details['nickname'], details['email'])
email = details['email'] or ''
username = self._get_available_username(nickname,
openid_response.identity_url)
username = self._get_available_username(
nickname, openid_response.identity_url)
user = User.objects.create_user(username, email, password=None)
self.associate_openid(user, openid_response)
......@@ -328,13 +331,16 @@ class OpenIDBackend:
user.save()
def get_teams_mapping(self):
teams_mapping_auto = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO', False)
teams_mapping_auto_blacklist = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO_BLACKLIST', [])
teams_mapping_auto = getattr(
settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO', False)
teams_mapping_auto_blacklist = getattr(
settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO_BLACKLIST', [])
teams_mapping = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING', {})
if teams_mapping_auto:
#ignore teams_mapping. use all django-groups
# ignore teams_mapping. use all django-groups
teams_mapping = dict()
all_groups = Group.objects.exclude(name__in=teams_mapping_auto_blacklist)
all_groups = Group.objects.exclude(
name__in=teams_mapping_auto_blacklist)
for group in all_groups:
teams_mapping[group.name] = group.name
return teams_mapping
......@@ -344,12 +350,12 @@ class OpenIDBackend:
if len(teams_mapping) == 0:
return
current_groups = set(user.groups.filter(
name__in=teams_mapping.values()))
desired_groups = set(Group.objects.filter(
name__in=[teams_mapping[lp_team]
for lp_team in teams_response.is_member
if lp_team in teams_mapping]))
mapping = [
teams_mapping[lp_team] for lp_team in teams_response.is_member
if lp_team in teams_mapping]
current_groups = set(
user.groups.filter(name__in=teams_mapping.values()))
desired_groups = set(Group.objects.filter(name__in=mapping))
for group in current_groups - desired_groups:
user.groups.remove(group)
for group in desired_groups - current_groups:
......
......@@ -28,20 +28,27 @@
"""Exception classes thrown by OpenID Authentication and Validation."""
from __future__ import unicode_literals
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"
self.message = (
"Another user already exists for your selected OpenID")
else:
self.message = message
class DuplicateUsernameViolation(DjangoOpenIDException):
def __init__(self, message=None):
......@@ -50,6 +57,7 @@ class DuplicateUsernameViolation(DjangoOpenIDException):
else:
self.message = message
class MissingUsernameViolation(DjangoOpenIDException):
def __init__(self, message=None):
......@@ -58,11 +66,12 @@ class MissingUsernameViolation(DjangoOpenIDException):
else:
self.message = message
class MissingPhysicalMultiFactor(DjangoOpenIDException):
def __init__(self, message=None):
if message is None:
self.message = "Login requires physical multi-factor authentication."
self.message = (
"Login requires physical multi-factor authentication.")
else:
self.message = message
......@@ -27,6 +27,8 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
from django import forms
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm
......@@ -49,6 +51,7 @@ def teams_new_unicode(self):
return "%s -> %s" % (name, ", ".join(group_teams))
else:
return name
Group.unicode_before_teams = Group.__unicode__
Group.__unicode__ = teams_new_unicode
......@@ -64,9 +67,11 @@ class UserChangeFormWithTeamRestriction(UserChangeForm):
user_groups = self.instance.groups.all()
for group in data:
if group.name in known_teams and group not in user_groups:
raise forms.ValidationError("""The group %s is mapped to an
external team. You cannot assign it manually.""" % group.name)
raise forms.ValidationError(
"The group %s is mapped to an external team. "
"You cannot assign it manually." % group.name)
return data
UserAdmin.form = UserChangeFormWithTeamRestriction
......@@ -78,10 +83,7 @@ class OpenIDLoginForm(forms.Form):
def clean_openid_identifier(self):
if 'openid_identifier' in self.cleaned_data:
openid_identifier = self.cleaned_data['openid_identifier']
if xri.identifierScheme(openid_identifier) == 'XRI' and getattr(
settings, 'OPENID_DISALLOW_INAMES', False
):
if (xri.identifierScheme(openid_identifier) == 'XRI' and
getattr(settings, 'OPENID_DISALLOW_INAMES', False)):
raise forms.ValidationError(_('i-names are not supported'))
return self.cleaned_data['openid_identifier']
......@@ -26,6 +26,8 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
from django.core.management.base import NoArgsCommand
from django_openid_auth.store import DjangoOpenIDStore
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Nonce'
db.create_table(u'django_openid_auth_nonce', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('server_url', self.gf('django.db.models.fields.CharField')(max_length=2047)),
('timestamp', self.gf('django.db.models.fields.IntegerField')()),
('salt', self.gf('django.db.models.fields.CharField')(max_length=40)),
))
db.send_create_signal(u'django_openid_auth', ['Nonce'])
# Adding model 'Association'
db.create_table(u'django_openid_auth_association', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('server_url', self.gf('django.db.models.fields.TextField')(max_length=2047)),
('handle', self.gf('django.db.models.fields.CharField')(max_length=255)),
('secret', self.gf('django.db.models.fields.TextField')(max_length=255)),
('issued', self.gf('django.db.models.fields.IntegerField')()),
('lifetime', self.gf('django.db.models.fields.IntegerField')()),
('assoc_type', self.gf('django.db.models.fields.TextField')(max_length=64)),
))
db.send_create_signal(u'django_openid_auth', ['Association'])
# Adding model 'UserOpenID'
db.create_table(u'django_openid_auth_useropenid', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('claimed_id', self.gf('django.db.models.fields.TextField')(unique=True, max_length=2047)),
('display_id', self.gf('django.db.models.fields.TextField')(max_length=2047)),
))
db.send_create_signal(u'django_openid_auth', ['UserOpenID'])
def backwards(self, orm):
# Deleting model 'Nonce'
db.delete_table(u'django_openid_auth_nonce')
# Deleting model 'Association'
db.delete_table(u'django_openid_auth_association')
# Deleting model 'UserOpenID'
db.delete_table(u'django_openid_auth_useropenid')
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'django_openid_auth.association': {
'Meta': {'object_name': 'Association'},
'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),
'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'issued': ('django.db.models.fields.IntegerField', [], {}),
'lifetime': ('django.db.models.fields.IntegerField', [], {}),
'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),
'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})
},
u'django_openid_auth.nonce': {
'Meta': {'object_name': 'Nonce'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'salt': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'server_url': ('django.db.models.fields.CharField', [], {'max_length': '2047'}),
'timestamp': ('django.db.models.fields.IntegerField', [], {})
},
u'django_openid_auth.useropenid': {
'Meta': {'object_name': 'UserOpenID'},
'claimed_id': ('django.db.models.fields.TextField', [], {'unique': 'True', 'max_length': '2047'}),
'display_id': ('django.db.models.fields.TextField', [], {'max_length': '2047'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
}
}
complete_apps = ['django_openid_auth']
\ No newline at end of file
from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Association',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('server_url', models.TextField(max_length=2047)),
('handle', models.CharField(max_length=255)),
('secret', models.TextField(max_length=255)),
('issued', models.IntegerField()),
('lifetime', models.IntegerField()),
('assoc_type', models.TextField(max_length=64)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Nonce',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('server_url', models.CharField(max_length=2047)),
('timestamp', models.IntegerField()),
('salt', models.CharField(max_length=40)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='UserOpenID',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('claimed_id', models.TextField(unique=True, max_length=2047)),
('display_id', models.TextField(max_length=2047)),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
],
options={
'permissions': (('account_verified', 'The OpenID has been verified'),),
},
bases=(models.Model,),
),
]
......@@ -27,11 +27,10 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from django.contrib.auth.models import (
Permission,
User,
)
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import Permission, User
class Nonce(models.Model):
......@@ -46,7 +45,7 @@ class Nonce(models.Model):
class Association(models.Model):
server_url = models.TextField(max_length=2047)
handle = models.CharField(max_length=255)
secret = models.TextField(max_length=255) # Stored base64 encoded
secret = models.TextField(max_length=255) # Stored base64 encoded
issued = models.IntegerField()
lifetime = models.IntegerField()
assoc_type = models.TextField(max_length=64)
......
......@@ -27,6 +27,8 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
import django.dispatch
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Nonce'
db.create_table(u'django_openid_auth_nonce', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('server_url', self.gf('django.db.models.fields.CharField')(max_length=2047)),
('timestamp', self.gf('django.db.models.fields.IntegerField')()),
('salt', self.gf('django.db.models.fields.CharField')(max_length=40)),
))
db.send_create_signal(u'django_openid_auth', ['Nonce'])
# Adding model 'Association'
db.create_table(u'django_openid_auth_association', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('server_url', self.gf('django.db.models.fields.TextField')(max_length=2047)),
('handle', self.gf('django.db.models.fields.CharField')(max_length=255)),
('secret', self.gf('django.db.models.fields.TextField')(max_length=255)),
('issued', self.gf('django.db.models.fields.IntegerField')()),
('lifetime', self.gf('django.db.models.fields.IntegerField')()),
('assoc_type', self.gf('django.db.models.fields.TextField')(max_length=64)),
))
db.send_create_signal(u'django_openid_auth', ['Association'])
# Adding model 'UserOpenID'
db.create_table(u'django_openid_auth_useropenid', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('claimed_id', self.gf('django.db.models.fields.TextField')(unique=True, max_length=2047)),
('display_id', self.gf('django.db.models.fields.TextField')(max_length=2047)),
))
db.send_create_signal(u'django_openid_auth', ['UserOpenID'])
def backwards(self, orm):
# Deleting model 'Nonce'
db.delete_table(u'django_openid_auth_nonce')
# Deleting model 'Association'
db.delete_table(u'django_openid_auth_association')
# Deleting model 'UserOpenID'
db.delete_table(u'django_openid_auth_useropenid')
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'django_openid_auth.association': {
'Meta': {'object_name': 'Association'},
'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),
'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'issued': ('django.db.models.fields.IntegerField', [], {}),
'lifetime': ('django.db.models.fields.IntegerField', [], {}),
'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),
'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})
},
u'django_openid_auth.nonce': {
'Meta': {'object_name': 'Nonce'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'salt': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'server_url': ('django.db.models.fields.CharField', [], {'max_length': '2047'}),
'timestamp': ('django.db.models.fields.IntegerField', [], {})
},
u'django_openid_auth.useropenid': {
'Meta': {'object_name': 'UserOpenID'},
'claimed_id': ('django.db.models.fields.TextField', [], {'unique': 'True', 'max_length': '2047'}),
'display_id': ('django.db.models.fields.TextField', [], {'max_length': '2047'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
}
}
complete_apps = ['django_openid_auth']
\ No newline at end of file
......@@ -27,6 +27,8 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
import base64
import time
......@@ -38,8 +40,10 @@ from django_openid_auth.models import Association, Nonce
class DjangoOpenIDStore(OpenIDStore):
def __init__(self):
self.max_nonce_age = 6 * 60 * 60 # Six hours
super(DjangoOpenIDStore, self).__init__()
self.max_nonce_age = 6 * 60 * 60 # Six hours
def storeAssociation(self, server_url, association):
try:
......
......@@ -64,31 +64,30 @@ will be provided:
@since: 2.1.1
"""
from openid.message import registerNamespaceAlias, \
NamespaceAliasRegistrationError
from openid.extension import Extension
from openid import oidutil
from __future__ import unicode_literals
try:
basestring #pylint:disable-msg=W0104
except NameError:
# For Python 2.2
basestring = (str, unicode) #pylint:disable-msg=W0622
from openid import oidutil
from openid.extension import Extension
from openid.message import (
registerNamespaceAlias,
NamespaceAliasRegistrationError,
)
__all__ = [
'TeamsRequest',
'TeamsResponse',
'ns_uri',
'supportsTeams',
]
]
ns_uri = 'http://ns.launchpad.net/2007/openid-teams'
try:
registerNamespaceAlias(ns_uri, 'lp')
except NamespaceAliasRegistrationError, e:
oidutil.log('registerNamespaceAlias(%r, %r) failed: %s' % (ns_uri,
'lp', str(e),))
oidutil.log(
'registerNamespaceAlias(%r, %r) failed: %s' % (ns_uri, 'lp', str(e)))
def supportsTeams(endpoint):
"""Does the given endpoint advertise support for Launchpad Teams?
......@@ -101,6 +100,7 @@ def supportsTeams(endpoint):
"""
return endpoint.usesExtension(ns_uri)
class TeamsNamespaceError(ValueError):
"""The Launchpad teams namespace was not found and could not
be created using the expected name (there's another extension
......@@ -115,6 +115,7 @@ class TeamsNamespaceError(ValueError):
the message that is being processed.
"""
def getTeamsNS(message):
"""Extract the Launchpad teams namespace URI from the given
OpenID message.
......@@ -145,7 +146,8 @@ def getTeamsNS(message):
# we know that ns_uri defined, because it's defined in the
# else clause of the loop as well, so disable the warning
return ns_uri #pylint:disable-msg=W0631
return ns_uri
class TeamsRequest(Extension):
"""An object to hold the state of a Launchpad teams request.
......@@ -154,7 +156,8 @@ class TeamsRequest(Extension):
names that the RP is interested in.
@type required: [str]
@group Consumer: requestField, requestTeams, getExtensionArgs, addToOpenIDRequest
@group Consumer: requestField, requestTeams, getExtensionArgs,
addToOpenIDRequest
@group Server: fromOpenIDRequest, parseExtensionArgs
"""
......@@ -308,6 +311,7 @@ class TeamsRequest(Extension):
return args
class TeamsResponse(Extension):
"""Represents the data returned in a Launchpad teams response
inside of an OpenID C{id_res} response. This object will be
......@@ -394,7 +398,6 @@ class TeamsResponse(Extension):
if "is_member" in args:
is_member_str = args["is_member"]
self.is_member = is_member_str.split(',')
#self.is_member = args["is_member"]
return self
......@@ -406,6 +409,5 @@ class TeamsResponse(Extension):
@see: openid.extension
"""
ns_args = {'is_member': ','.join(self.is_member),}
ns_args = {'is_member': ','.join(self.is_member)}
return ns_args
......@@ -26,18 +26,8 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import unittest
from test_views import *
from test_settings import *
from test_store import *
from test_auth import *
from test_admin import *
def suite():
suite = unittest.TestSuite()
for name in ['test_auth', 'test_models', 'test_settings', 'test_store',
'test_views', 'test_admin']:
mod = __import__('%s.%s' % (__name__, name), {}, {}, ['suite'])
suite.addTest(mod.suite())
return suite
from .test_views import * # flake8: noqa
from .test_settings import *
from .test_store import *
from .test_auth import *
from .test_admin import *
from __future__ import unicode_literals
from django.test.utils import override_settings
......
......@@ -25,35 +25,19 @@
# 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.
"""
Tests for the django_openid_auth Admin login form replacement.
"""
import unittest
"""Tests for the django_openid_auth Admin login form replacement."""
from django.conf import settings
from django.contrib.auth.models import User, AnonymousUser
from __future__ import unicode_literals
settings.OPENID_USE_AS_ADMIN_LOGIN = True
from django.conf import settings
from django.contrib.auth.models import User
from django.test import TestCase
from django.test.utils import override_settings
def create_user(is_staff=False, authenticated=True):
"""
Create and return a user, either the AnonymousUser or a normal Django user,
setting the is_staff attribute if appropriate.
"""
if not authenticated:
return AnonymousUser()
else:
user = User(
username=u'testing', email='testing@example.com',
is_staff=is_staff)
user.set_password(u'test')
user.save()
@override_settings(OPENID_USE_AS_ADMIN_LOGIN=True)
class SiteAdminTests(TestCase):
"""
TestCase for accessing /admin/ when the django_openid_auth form replacement
......@@ -65,23 +49,21 @@ class SiteAdminTests(TestCase):
If the request has an authenticated user, who is not flagged as a
staff member, then they get a failure response.
"""
create_user()
self.client.login(username='testing', password='test')
response = self.client.get('/admin/')
self.assertTrue('User testing does not have admin access.' in
response.content, 'Missing error message in response')
User.objects.create_user(
username='testing', email='testing@example.com', password='test')
assert self.client.login(username='testing', password='test')
response = self.client.get('/admin/', follow=True)
self.assertContains(
response,
'User testing does not have admin/staff access.', status_code=403)
def test_admin_site_with_openid_login_non_authenticated_user(self):
"""
Unauthenticated users accessing the admin page should be directed to
the OpenID login url.
"""
response = self.client.get('/admin/')
self.assertEqual(302, response.status_code)
self.assertEqual('http://testserver' + getattr(settings, 'LOGIN_URL',
'/openid/login') + '?next=/admin/',
response['Location'])
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
response = self.client.get('/admin/', follow=True)
self.assertRedirects(
response,
getattr(settings, 'LOGIN_URL', '/openid/login') +
'?next=%2Fadmin%2F')
......@@ -26,7 +26,7 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import unittest
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.test import TestCase
......@@ -72,7 +72,3 @@ class UserOpenIDModelTestCase(TestCase):
self.assertFalse(
User.objects.get(username='someuser').has_perm(
'django_openid_auth.account_verified'))
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
from unittest import skipIf, TestLoader
# django-openid-auth - OpenID integration for django.contrib.auth
#
# Copyright (C) 2013 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 __future__ import unicode_literals
from unittest import skipIf
from django import VERSION
from django.conf import settings
......@@ -16,20 +46,9 @@ class SessionSerializerTest(TestCase):
[0] https://bit.ly/1myzetd
[1] https://github.com/openid/python-openid/issues/17
"""
@skipIf(VERSION >= (1, 6, 0), "Old versions used the pickle serializer.")
def test_not_using_json_session_serializer(self):
# We use getattr because this setting did not exist in Django
# 1.4 (pickle serialization was hard coded)
serializer = getattr(settings, 'SESSION_SERIALIZER', '')
self.assertNotEqual(
serializer, 'django.contrib.sessions.serializers.JSONSerializer')
@skipIf(VERSION < (1, 6, 0), "Newer versions use JSON by default.")
def test_using_json_session_serializer(self):
@skipIf(VERSION < (1, 5), "Django 1.4 does not provide SESSION_SERIALIZER")
def test_using_pickle_session_serializer(self):
serializer = getattr(settings, 'SESSION_SERIALIZER', '')
self.assertEqual(
serializer, 'django.contrib.sessions.serializers.JSONSerializer')
def suite():
return TestLoader().loadTestsFromName(__name__)
serializer, 'django.contrib.sessions.serializers.PickleSerializer')
......@@ -26,8 +26,9 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
import time
import unittest
from django.test import TestCase
from openid.association import Association as OIDAssociation
......@@ -187,7 +188,3 @@ class OpenIDStoreTests(TestCase):
# The second (non-expired) association is left behind.
self.assertNotEqual(self.store.getAssociation('server-url', 'handle2'),
None)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
......@@ -26,14 +26,18 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
from django.conf.urls import patterns, include
from django.http import HttpResponse
from django.conf.urls import *
def get_user(request):
return HttpResponse(request.user.username)
urlpatterns = patterns('',
urlpatterns = patterns(
'',
(r'^getuser/$', get_user),
(r'^openid/', include('django_openid_auth.urls')),
)
......@@ -27,9 +27,12 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from django.conf.urls import *
from __future__ import unicode_literals
urlpatterns = patterns('django_openid_auth.views',
from django.conf.urls import patterns, url
urlpatterns = patterns(
'django_openid_auth.views',
url(r'^login/$', 'login_begin', name='openid-login'),
url(r'^complete/$', 'login_complete', name='openid-complete'),
url(r'^logo.gif$', 'logo', name='openid-logo'),
......
......@@ -27,6 +27,8 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
import re
import urllib
from urlparse import urlsplit
......@@ -62,6 +64,7 @@ from django_openid_auth.exceptions import (
next_url_re = re.compile('^/[-\w/]+$')
def is_valid_next_url(next):
# When we allow this:
# /openid/?next=/welcome/
......@@ -78,8 +81,8 @@ def sanitise_redirect_url(redirect_to):
is_valid = False
elif '//' in redirect_to:
# Allow the redirect URL to be external if it's a permitted domain
allowed_domains = getattr(settings,
"ALLOWED_EXTERNAL_OPENID_REDIRECT_DOMAINS", [])
allowed_domains = getattr(
settings, "ALLOWED_EXTERNAL_OPENID_REDIRECT_DOMAINS", [])
s, netloc, p, q, f = urlsplit(redirect_to)
# allow it if netloc is blank or if the domain is allowed
if netloc:
......@@ -113,11 +116,13 @@ def render_openid_request(request, openid_request, return_to, trust_root=None):
if openid_request.shouldSendRedirect():
redirect_url = openid_request.redirectURL(
trust_root, return_to)
return HttpResponseRedirect(redirect_url)
response = HttpResponseRedirect(redirect_url)
else:
form_html = openid_request.htmlMarkup(
trust_root, return_to, form_tag_attrs={'id': 'openid_message'})
return HttpResponse(form_html, content_type='text/html;charset=UTF-8')
response = HttpResponse(
form_html, content_type='text/html;charset=UTF-8')
return response
def default_render_failure(request, message, status=403,
......@@ -133,7 +138,7 @@ def default_render_failure(request, message, status=403,
def parse_openid_response(request):
"""Parse an OpenID response from a Django request."""
# Short cut if there is no request parameters.
#if len(request.REQUEST) == 0:
# if len(request.REQUEST) == 0:
# return None
current_url = request.build_absolute_uri()
......@@ -164,15 +169,15 @@ def login_begin(request, template_name='openid/login.html',
# Invalid or no form data:
if openid_url is None:
return render_to_response(template_name, {
'form': login_form,
redirect_field_name: redirect_to
}, context_instance=RequestContext(request))
context = {'form': login_form, redirect_field_name: redirect_to}
return render_to_response(
template_name, context,
context_instance=RequestContext(request))
consumer = make_consumer(request)
try:
openid_request = consumer.begin(openid_url)
except DiscoveryFailure, exc:
except DiscoveryFailure as exc:
return render_failure(
request, "OpenID discovery error: %s" % (str(exc),), status=500,
exception=exc)
......@@ -222,11 +227,11 @@ def login_begin(request, template_name='openid/login.html',
sreg_optional_fields.extend(
getattr(settings, 'OPENID_SREG_EXTRA_FIELDS', []))
sreg_optional_fields = [
field for field in sreg_optional_fields if (
not field in sreg_required_fields)]
field for field in sreg_optional_fields
if field not in sreg_required_fields]
openid_request.addExtension(
sreg.SRegRequest(optional=sreg_optional_fields,
required=sreg_required_fields))
required=sreg_required_fields))
if getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False):
preferred_auth = [
......@@ -236,13 +241,16 @@ def login_begin(request, template_name='openid/login.html',
openid_request.addExtension(pape_request)
# Request team info
teams_mapping_auto = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO', False)
teams_mapping_auto_blacklist = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO_BLACKLIST', [])
teams_mapping_auto = getattr(
settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO', False)
teams_mapping_auto_blacklist = getattr(
settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO_BLACKLIST', [])
launchpad_teams = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING', {})
if teams_mapping_auto:
#ignore launchpad teams. use all django-groups
# ignore launchpad teams. use all django-groups
launchpad_teams = dict()
all_groups = Group.objects.exclude(name__in=teams_mapping_auto_blacklist)
all_groups = Group.objects.exclude(
name__in=teams_mapping_auto_blacklist)
for group in all_groups:
launchpad_teams[group.name] = group.name
......@@ -270,9 +278,9 @@ def login_begin(request, template_name='openid/login.html',
def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME,
render_failure=None):
redirect_to = request.REQUEST.get(redirect_field_name, '')
render_failure = render_failure or \
getattr(settings, 'OPENID_RENDER_FAILURE', None) or \
default_render_failure
render_failure = (
render_failure or getattr(settings, 'OPENID_RENDER_FAILURE', None) or
default_render_failure)
openid_response = parse_openid_response(request)
if not openid_response:
......@@ -288,10 +296,12 @@ def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME,
if user is not None:
if user.is_active:
auth_login(request, user)
response = HttpResponseRedirect(sanitise_redirect_url(redirect_to))
response = HttpResponseRedirect(
sanitise_redirect_url(redirect_to))
# Notify any listeners that we successfully logged in.
openid_login_complete.send(sender=UserOpenID, request=request,
openid_login_complete.send(
sender=UserOpenID, request=request,
openid_response=openid_response)
return response
......
......@@ -27,91 +27,44 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Django settings for example project.
import django
django_version = django.get_version()
DEBUG = True
TEMPLATE_DEBUG = DEBUG
"""
Django settings for example_consumer project.
ADMINS = (
# ('Your Name', 'your_email@domain.com'),
)
For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/
MANAGERS = ADMINS
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
if django_version >= "1.2":
csrf_middleware = 'django.middleware.csrf.CsrfViewMiddleware'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'sqlite.db',
}
}
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
else:
csrf_middleware = 'django.contrib.csrf.middleware.CsrfViewMiddleware'
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source',
)
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'
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
import django
SITE_ID = 1
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# 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 = ''
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '34958734985734985734985798437'
# URL that handles the media served from MEDIA_ROOT.
# Example: "http://media.lawrence.com"
MEDIA_URL = ''
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# 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/'
TEMPLATE_DEBUG = True
# Make this unique, and don't share it with anybody.
SECRET_KEY = '34958734985734985734985798437'
ALLOWED_HOSTS = []
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
csrf_middleware,
'django.middleware.csrf.CsrfViewMiddleware',
)
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.
)
# Application definition
INSTALLED_APPS = (
'django.contrib.auth',
......@@ -119,9 +72,46 @@ INSTALLED_APPS = (
'django.contrib.sessions',
'django.contrib.admin',
'django_openid_auth',
'south',
)
if django.VERSION < (1, 7):
INSTALLED_APPS += ('south',)
ROOT_URLCONF = 'example_consumer.urls'
WSGI_APPLICATION = 'example_consumer.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/
STATIC_URL = '/static/'
# the library python-openid does not support a json session serializer
# <openid.yadis.manager.YadisServiceManager> is not JSON serializable
# https://github.com/openid/python-openid/issues/17
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
AUTHENTICATION_BACKENDS = (
'django_openid_auth.auth.OpenIDBackend',
'django.contrib.auth.backends.ModelBackend',
......@@ -144,7 +134,7 @@ OPENID_VALID_VERIFICATION_SCHEMES = {
# 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/'
OPENID_SSO_SERVER_URL = 'https://login.ubuntu.com/'
# Tell django.contrib.auth to use the OpenID signin URLs.
LOGIN_URL = '/openid/login/'
......
......@@ -27,7 +27,7 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from django.conf.urls import *
from django.conf.urls import patterns, include, url
from django.contrib import admin
import views
......@@ -35,11 +35,12 @@ 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),
urlpatterns = patterns(
'',
url(r'^$', views.index),
url(r'^openid/', include('django_openid_auth.urls')),
url(r'^logout/$', 'django.contrib.auth.views.logout'),
url(r'^private/$', views.require_authentication),
(r'^admin/', include(admin.site.urls)),
url(r'^admin/', include(admin.site.urls)),
)
"""
WSGI config for demo project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
"""
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
......@@ -3,7 +3,7 @@ import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example_consumer.settings")
from django.core.management import execute_from_command_line
......
......@@ -43,7 +43,7 @@ from distutils.core import setup
description, long_description = __doc__.split('\n\n', 1)
VERSION = '0.5'
VERSION = '0.6'
setup(
name='django-openid-auth',
......
[tox]
envlist =
py2.7-django1.4, py2.7-django1.5, py2.7-django1.6
py2.7-django1.4, py2.7-django1.5, py2.7-django1.6, py2.7-django1.7, py2.7-django1.8
[testenv]
commands = make check
commands = python manage.py test django_openid_auth
deps=
mock
python-openid
# Python 2.7
[testenv:py2.7-django1.4]
basepython = python2.7
deps = django >= 1.4, < 1.5
python-openid
south
deps =
django >= 1.4, < 1.5
{[testenv]deps}
south==1.0
[testenv:py2.7-django1.5]
basepython = python2.7
deps = django >= 1.5, < 1.6
python-openid
south
deps =
django >= 1.5, < 1.6
{[testenv]deps}
south==1.0
[testenv:py2.7-django1.6]
basepython = python2.7
deps = django >= 1.6, < 1.7
python-openid
south
deps =
django >= 1.6, < 1.7
{[testenv]deps}
south==1.0
[testenv:py2.7-django1.7]
basepython = python2.7
deps =
django >= 1.7, < 1.8
{[testenv]deps}
[testenv:py2.7-django1.8]
basepython = python2.7
deps =
django >= 1.8, < 1.9
{[testenv]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