This commit is contained in:
Benjamin Dauvergne 2016-02-12 17:22:48 +01:00
parent e641c6ec96
commit fc7fd250cd
9 changed files with 57 additions and 51 deletions

View File

@ -41,8 +41,8 @@ class DefaultAdapter(object):
except ValueError:
self.logger.error(u'invalid username template %r', username_template)
except (AttributeError, KeyError, IndexError), e:
self.logger.error(u'invalid reference in username template %r: %s',
username_template, e)
self.logger.error(
u'invalid reference in username template %r: %s', username_template, e)
except Exception, e:
self.logger.exception(u'unknown error when formatting username')
else:
@ -89,7 +89,8 @@ class DefaultAdapter(object):
except ValueError:
self.logger.warning(u'invalid attribute mapping template %r', tpl)
except (AttributeError, KeyError, IndexError, ValueError), e:
self.logger.warning(u'invalid reference in attribute mapping template %r: %s', tpl, e)
self.logger.warning(
u'invalid reference in attribute mapping template %r: %s', tpl, e)
else:
attribute_set = True
model_field = user._meta.get_field(field)
@ -142,9 +143,11 @@ class DefaultAdapter(object):
continue
groups.append(group)
for group in Group.objects.filter(pk__in=[g.pk for g in groups]).exclude(user=user):
self.logger.info(u'adding group %s (%s) to user %s (%s)', group, group.pk, user, user.pk)
self.logger.info(
u'adding group %s (%s) to user %s (%s)', group, group.pk, user, user.pk)
User.groups.through.objects.get_or_create(group=group, user=user)
qs = User.groups.through.objects.exclude(group__pk__in=[g.pk for g in groups]).filter(user=user)
qs = User.groups.through.objects.exclude(
group__pk__in=[g.pk for g in groups]).filter(user=user)
for rel in qs:
self.logger.info(u'removing group %s (%s) from user %s (%s)', rel.group,
rel.group.pk, rel.user, rel.user.pk)

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -1,34 +1,35 @@
import sys
from django.core.exceptions import ImproperlyConfigured
class AppSettings(object):
__PREFIX = 'MELLON_'
__DEFAULTS = {
'PUBLIC_KEYS': (),
'PRIVATE_KEY': None,
'PRIVATE_KEYS': (),
'PRIVATE_KEY_PASSWORD': None,
'NAME_ID_FORMATS': (),
'NAME_ID_POLICY_FORMAT': None,
'NAME_ID_POLICY_ALLOW_CREATE': True,
'FORCE_AUTHN': False,
'ADAPTER': (
'mellon.adapters.DefaultAdapter',
),
'REALM': 'saml',
'PROVISION': True,
'USERNAME_TEMPLATE': '{attributes[name_id_content]}@{realm}',
'ATTRIBUTE_MAPPING': {},
'SUPERUSER_MAPPING': {},
'AUTHN_CLASSREF': (),
'GROUP_ATTRIBUTE': None,
'CREATE_GROUP': True,
'ERROR_URL': None,
'ERROR_REDIRECT_AFTER_TIMEOUT': 120,
'DEFAULT_ASSERTION_CONSUMER_BINDING': 'post', # or artifact
'VERIFY_SSL_CERTIFICATE': True,
'OPENED_SESSION_COOKIE_NAME': None,
'OPENED_SESSION_COOKIE_DOMAIN': None,
'PUBLIC_KEYS': (),
'PRIVATE_KEY': None,
'PRIVATE_KEYS': (),
'PRIVATE_KEY_PASSWORD': None,
'NAME_ID_FORMATS': (),
'NAME_ID_POLICY_FORMAT': None,
'NAME_ID_POLICY_ALLOW_CREATE': True,
'FORCE_AUTHN': False,
'ADAPTER': (
'mellon.adapters.DefaultAdapter',
),
'REALM': 'saml',
'PROVISION': True,
'USERNAME_TEMPLATE': '{attributes[name_id_content]}@{realm}',
'ATTRIBUTE_MAPPING': {},
'SUPERUSER_MAPPING': {},
'AUTHN_CLASSREF': (),
'GROUP_ATTRIBUTE': None,
'CREATE_GROUP': True,
'ERROR_URL': None,
'ERROR_REDIRECT_AFTER_TIMEOUT': 120,
'DEFAULT_ASSERTION_CONSUMER_BINDING': 'post', # or artifact
'VERIFY_SSL_CERTIFICATE': True,
'OPENED_SESSION_COOKIE_NAME': None,
'OPENED_SESSION_COOKIE_DOMAIN': None,
}
@property

View File

@ -21,7 +21,7 @@ class SAMLBackend(ModelBackend):
user = adapter.lookup_user(idp, saml_attributes)
if user:
break
else: # no user found
else: # no user found
return
for adapter in adapters:
if not hasattr(adapter, 'provision'):

View File

@ -2,5 +2,6 @@ from django.contrib.sessions.backends.db import SessionStore
from . import db
class SessionStore(db.SessionStore, SessionStore):
pass

View File

@ -2,8 +2,8 @@ from django.contrib.sessions.backends.db import SessionStore
from mellon import utils
class SessionStore(SessionStore):
class SessionStore(SessionStore):
def get_session_not_on_or_after(self):
session_not_on_or_after = self.get('mellon_session', {}).get('session_not_on_or_after')
if session_not_on_or_after:

View File

@ -77,4 +77,4 @@ class Migration(SchemaMigration):
}
}
complete_apps = ['mellon']
complete_apps = ['mellon']

View File

@ -8,9 +8,10 @@ import subprocess
from setuptools import setup, find_packages
from setuptools.command.install_lib import install_lib as _install_lib
from distutils.command.build import build as _build
from distutils.command.sdist import sdist as _sdist
from distutils.command.sdist import sdist as _sdist
from distutils.cmd import Command
class compile_translations(Command):
description = 'compile message catalogs to MO files via django compilemessages'
user_options = []
@ -33,9 +34,11 @@ class compile_translations(Command):
call_command('compilemessages')
os.chdir(curdir)
class build(_build):
sub_commands = [('compile_translations', None)] + _build.sub_commands
class eo_sdist(_sdist):
sub_commands = [('compile_translations', None)] + _build.sub_commands
@ -52,11 +55,13 @@ class eo_sdist(_sdist):
if os.path.exists('VERSION'):
os.remove('VERSION')
class install_lib(_install_lib):
def run(self):
self.run_command('compile_translations')
_install_lib.run(self)
def get_version():
'''Use the VERSION, if absent generates a version with git describe, if not
tag exists, take 0.0.0- and add the length of the commit log.
@ -65,15 +70,14 @@ def get_version():
with open('VERSION', 'r') as v:
return v.read()
if os.path.exists('.git'):
p = subprocess.Popen(['git','describe','--dirty','--match=v*'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = subprocess.Popen(['git', 'describe', '--dirty', '--match=v*'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result = p.communicate()[0]
if p.returncode == 0:
return result.split()[0][1:].replace('-', '.')
else:
return '0.0.0-%s' % len(
subprocess.check_output(
['git', 'rev-list', 'HEAD']).splitlines())
return '0.0.0-%s' % len(subprocess.check_output(
['git', 'rev-list', 'HEAD']).splitlines())
return '0.0.0'
setup(name="django-mellon",
@ -103,5 +107,4 @@ setup(name="django-mellon",
'install_lib': install_lib,
'compile_translations': compile_translations,
'sdist': eo_sdist,
},
)
})

View File

@ -1,7 +1,6 @@
import threading
import pytest
from django.conf import settings
from django.contrib import auth
from django.db import connection
@ -11,7 +10,7 @@ pytestmark = pytest.mark.django_db
idp = {}
saml_attributes = {
'name_id_content': 'x'*32,
'name_id_content': 'x' * 32,
'issuer': 'https://idp.example.net/saml/metadata',
'username': ['foobar'],
'email': ['test@example.net'],
@ -21,15 +20,17 @@ saml_attributes = {
'group': ['GroupA', 'GroupB', 'GroupC'],
}
def test_format_username(settings):
adapter = DefaultAdapter()
assert adapter.format_username(idp, {}) == None
assert adapter.format_username(idp, saml_attributes) == ('x'*32 + '@saml')[:30]
assert adapter.format_username(idp, {}) is None
assert adapter.format_username(idp, saml_attributes) == ('x' * 32 + '@saml')[:30]
settings.MELLON_USERNAME_TEMPLATE = '{attributes[name_id_content]}'
assert adapter.format_username(idp, saml_attributes) == ('x'*32)[:30]
assert adapter.format_username(idp, saml_attributes) == ('x' * 32)[:30]
settings.MELLON_USERNAME_TEMPLATE = '{attributes[username][0]}'
assert adapter.format_username(idp, saml_attributes) == 'foobar'
def test_lookup_user(settings):
User = auth.get_user_model()
adapter = DefaultAdapter()
@ -83,7 +84,7 @@ def test_provision(settings):
assert user.first_name == 'Foo'
assert user.last_name == 'Bar'
assert user.email == 'test@example.net'
assert user.is_superuser == False
assert user.is_superuser is False
assert user.groups.count() == 3
assert set(user.groups.values_list('name', flat=True)) == set(saml_attributes['group'])
saml_attributes2 = saml_attributes.copy()
@ -99,7 +100,7 @@ def test_provision(settings):
user = User(username='xx')
user.save()
adapter.provision(user, idp, saml_attributes)
assert user.is_superuser == True
assert user.is_superuser is True
User.objects.all().delete()
local_saml_attributes = saml_attributes.copy()