doc/build
doc/pip-log.txt
dist
+
+.tox
+.coverage
+htmlcov
+1.19
+----
+
+* ajouts tests
+
+* mise à jour doc intégration
+
+* fix settings
+
+* incompatible avec Django < 1.3 (takes_context - simple_tag)
+
1.18
----
recursive-include auf/django/saml/templates *
recursive-include auf/django/saml/static *
+recursive-include auf/django/saml/tests/templates *
from views import redirect_to_login, redirect_to_logout
from django.contrib.admin import site
+
def saml_login(request, extra_context=None):
return redirect_to_login(request)
+
def saml_logout(request, extra_context=None):
return redirect_to_logout(request)
# l'authentification pour communiquer avec l'IdP
site.login = saml_login
site.logout = saml_logout
-
logger.info(info)
return clean_username
+
class FakeSPBackend(_BackendMixin, ModelBackend,):
"""
On autentifie uniquement sur le username
"""
Backend reposant sur le id.auf.org
"""
- create_unknown_user = getattr(settings, 'SAML_AUTO_CREATION', True)
+ create_unknown_user = settings.SAML_AUTO_CREATION
if settings.SAML_AUTH:
from settings import SAML_REDIRECT_FIELD_NAME
-def employe_required(function=None,
+def employe_required(
+ function=None,
redirect_field_name=SAML_REDIRECT_FIELD_NAME,
login_url=None):
"""
return _wrapped_view
-def login_required(function=None,
+def login_required(
+ function=None,
redirect_field_name=SAML_REDIRECT_FIELD_NAME,
login_url=None):
"""
raise forms.ValidationError("Aucun utilisateur\
local.")
return self.cleaned_data
-
LOGOUT_URL = '/sandbox/logout'
info += u"\n* LOGIN_URL: %s" % LOGIN_URL
info += u"\n* LOGOUT_URL: %s" % LOGOUT_URL
- info += u"\n* REDIRECT_FIELD_NAME: %s" % saml_settings.SAML_REDIRECT_FIELD_NAME
+ info += u"\n* REDIRECT_FIELD_NAME: %s" % \
+ saml_settings.SAML_REDIRECT_FIELD_NAME
django.contrib.auth.REDIRECT_FIELD_NAME = \
saml_settings.SAML_REDIRECT_FIELD_NAME
"""
if not self.has_permission(request):
return HttpResponseForbidden(
- _(u"Votre compte ne permet pas d'accéder à cette page"))
+ _(u"Votre compte ne permet pas d'accéder à cette page"))
return view(request, *args, **kwargs)
if view.__name__ == 'index':
else:
return original_admin_view(self, view, cacheable=False)
-logger.info(u"Patch de la admin.site pour gérer le login forcé de la page d'index")
+logger.info(u"Patch de la admin.site pour \
+ gérer le login forcé de la page d'index")
site.__class__.admin_view = custom_admin_view
# -*- coding: utf-8 -*-
"""
-Ce module définit toutes les constantes utilisées par le paquet
+Ce module définit toutes les constantes utilisées par le paquet
auf.django.saml. Chacune peut être surchargée dans les settings
chargés par Django, typiquement le fichier project/conf.py.
"""
# Variable utilisée pour fournir au serveur d'identités les
# adresses de retour du site.
-SAML_REDIRECT_FIELD_NAME = getattr(settings, '', 'ReturnTo')
+SAML_REDIRECT_FIELD_NAME = getattr(
+ settings, 'SAML_REDIRECT_FIELD_NAME', 'ReturnTo')
# URL de la page où l'utilisateur sera redirigé après déconnexion
-SAML_LOGOUT_REDIRECT_URL = getattr(settings,'', '/')
+SAML_LOGOUT_REDIRECT_URL = getattr(settings, 'SAML_LOGOUT_REDIRECT_URL', '/')
# URL où est mappée la fonction login du module Apache Mellon
-SAML_MELLON_LOGIN_URL = getattr(settings, '', '/mellon/login')
+SAML_MELLON_LOGIN_URL = getattr(
+ settings, 'SAML_MELLON_LOGIN_URL', '/mellon/login')
# URL où est mappée la fonction logout du module Apache Mellon
-SAML_MELLON_LOGOUT_URL = getattr(settings, '', '/mellon/logout')
+SAML_MELLON_LOGOUT_URL = getattr(
+ settings, 'SAML_MELLON_LOGOUT_URL', '/mellon/logout')
-# URL où l'utilisateur peut modifier les propriétés globales de son profil
-SAML_CHANGE_PASSWORD_URL = getattr(settings, '', 'http://id.auf.org/profile')
+# URL où l'utilisateur peut modifier les propriétés globales de son profil
+SAML_CHANGE_PASSWORD_URL = getattr(
+ settings, 'SAML_CHANGE_PASSWORD_URL', 'http://id.auf.org/profile')
+
+# Si l'auth passe, mais que le user n'existe pas ce flag pilote la création
+# locale dans l'application
+SAML_AUTO_CREATION = getattr(settings, 'SAML_AUTO_CREATION', True)
# -*- coding: utf-8 -*-
-from django import template
-from auf.django.saml.views import redirect_to_login, redirect_to_logout
-
-register = template.Library()
-
-
-class UrlNode(template.Node):
-
- def __init__(self, fct, url):
- self.fct = fct
- self.url = url
-
- def render(self, context):
- return self.fct(context['request'], self.url, do_redirect=False)
-
-
-def mellon_login_url(parser, token):
- try:
- tag_name, url, = token.split_contents()
- except:
- url = None
- return UrlNode(redirect_to_login, url)
-register.tag('mellon_login_url', mellon_login_url)
-
-
-def mellon_logout_url(parser, token):
- try:
- tag_name, url, = token.split_contents()
- except:
- url = None
- return UrlNode(redirect_to_logout, url)
-register.tag('mellon_logout_url', mellon_logout_url)
+# backward compatibilty
+from .saml_tags import * # noqa
--- /dev/null
+# -*- coding: utf-8 -*-
+
+from django import template
+
+from auf.django.saml.views import redirect_to_login, redirect_to_logout
+
+register = template.Library()
+
+
+@register.simple_tag(takes_context=True, name='mellon_login_url')
+def mellon_login_url(context, url=None):
+ request = context['request']
+ return redirect_to_login(request, redirect_to=url, do_redirect=False)
+
+
+@register.simple_tag(takes_context=True, name='mellon_logout_url')
+def mellon_logout_url(context, url=None):
+ request = context['request']
+ return redirect_to_logout(request, redirect_to=url, do_redirect=False)
--- /dev/null
+from .saml import TemplateTagTest # flake8: noqa
--- /dev/null
+# -*- coding: utf-8 -*-
+
+from django.test import TestCase
+from django.test.client import Client
+
+
+class CommonTest(TestCase):
+
+ def setUp(self):
+ self.client = Client()
--- /dev/null
+# -*- coding: utf-8 -*-
+
+import re
+
+from django.core.urlresolvers import reverse
+
+from auf.django.saml import settings
+
+from .common import CommonTest
+
+
+class TemplateTagTest(CommonTest):
+ """
+ Teste les fonctionnalités des templatetags SAML.
+ """
+ url = reverse('test_tags')
+
+ def setUp(self):
+ super(TemplateTagTest, self).setUp()
+ self.url = reverse('test_tags')
+ self.response = self.client.get(self.url)
+
+ def test_templatetag_login_var(self):
+ """
+ Test le rendu du templatetag *mellon_login_url* avec une variable en
+ paramètre.
+ """
+ regex = "test_templatetag_login_var:(.*)\?%s=(.*)\n" % (
+ settings.SAML_REDIRECT_FIELD_NAME, )
+ m = re.search(regex, self.response.content)
+ login_url, redirect_url = m.groups()
+ self.assertEqual(login_url, settings.SAML_MELLON_LOGIN_URL)
+ self.assertEqual(redirect_url, self.url)
+
+ def test_templatetag_login_default(self):
+ """
+ Test le rendu du templatetag *mellon_login_url* sans paramètre.
+ """
+ regex = "test_templatetag_login_default:(.*)\?%s=(.*)\n" % (
+ settings.SAML_REDIRECT_FIELD_NAME, )
+ m = re.search(regex, self.response.content)
+ login_url, redirect_url = m.groups()
+ self.assertEqual(login_url, settings.SAML_MELLON_LOGIN_URL)
+ self.assertEqual(redirect_url, self.url)
+
+ def test_templatetag_login_string(self):
+ """
+ Test le rendu du templatetag *mellon_login_url* avec paramètre string.
+ """
+ regex = "test_templatetag_login_string:(.*)\?%s=(.*)\n" % (
+ settings.SAML_REDIRECT_FIELD_NAME, )
+ m = re.search(regex, self.response.content)
+ login_url, redirect_url = m.groups()
+ self.assertEqual(login_url, settings.SAML_MELLON_LOGIN_URL)
+ self.assertEqual(redirect_url, '/admin')
+
+ def test_templatetag_logout_var(self):
+ """
+ Test le rendu du templatetag *mellon_logout_url* avec une variable en
+ paramètre.
+ """
+ regex = "test_templatetag_logout_var:(.*)\?%s=(.*)\n" % (
+ settings.SAML_REDIRECT_FIELD_NAME, )
+ m = re.search(regex, self.response.content)
+ logout_url, redirect_url = m.groups()
+ self.assertEqual(logout_url, reverse('local_logout'))
+ self.assertEqual(redirect_url, self.url)
+
+ def test_templatetag_logout_default(self):
+ """
+ Test le rendu du templatetag *mellon_logout_url* sans paramètre.
+ """
+ regex = "test_templatetag_logout_default:(.*)\?%s=(.*)\n" % (
+ settings.SAML_REDIRECT_FIELD_NAME, )
+ m = re.search(regex, self.response.content)
+ logout_url, redirect_url = m.groups()
+ self.assertEqual(logout_url, reverse('local_logout'))
+ self.assertEqual(redirect_url, settings.SAML_LOGOUT_REDIRECT_URL)
+
+ def test_templatetag_logout_string(self):
+ """
+ Test le rendu du templatetag *mellon_logout_url* avec paramètre string.
+ """
+ regex = "test_templatetag_logout_string:(.*)\?%s=(.*)\n" % (
+ settings.SAML_REDIRECT_FIELD_NAME, )
+ m = re.search(regex, self.response.content)
+ logout_url, redirect_url = m.groups()
+ self.assertEqual(logout_url, reverse('local_logout'))
+ self.assertEqual(redirect_url, '/admin')
--- /dev/null
+# -*- coding: utf-8 -*-
+
+import os
+
+
+USE_I18N = False
+
+SECRET_KEY = 'secret'
+
+ROOT_URLCONF = 'auf.django.saml.tests.urls'
+
+DATABASES = {'default':
+ {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:', }}
+
+INSTALLED_APPS = ('django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.admin',
+ 'auf.django.saml', )
+
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'auf.django.saml.middleware.SPMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+)
+
+TEMPLATE_CONTEXT_PROCESSORS = (
+ 'django.contrib.auth.context_processors.auth',
+ 'django.core.context_processors.debug',
+ 'django.core.context_processors.i18n',
+ 'django.core.context_processors.media',
+ 'django.core.context_processors.static',
+ 'django.core.context_processors.request',
+ 'django.core.context_processors.tz',
+ 'django.contrib.messages.context_processors.messages',
+ )
+
+TEMPLATE_DIRS = (
+ os.path.join(os.path.dirname(__file__), 'templates'),
+ )
--- /dev/null
+{% load saml_tags %}
+
+test_templatetag_login_default:{% mellon_login_url %}
+
+test_templatetag_login_string:{% mellon_login_url '/admin' %}
+
+test_templatetag_login_var:{% mellon_login_url request.get_full_path %}
+
+
+test_templatetag_logout_default:{% mellon_logout_url %}
+
+test_templatetag_logout_string:{% mellon_logout_url '/admin' %}
+
+test_templatetag_logout_var:{% mellon_logout_url request.get_full_path %}
--- /dev/null
+# -*- coding: utf-8 -*-
+
+from django.conf.urls.defaults import patterns, include, url
+from django.views.generic import TemplateView
+
+from django.contrib import admin
+
+
+admin.autodiscover()
+
+urlpatterns = patterns(
+ '',
+ (r'^', include('auf.django.saml.urls')),
+ (r'^admin/', include(admin.site.urls)),
+ url(r'^test_tags/', TemplateView.as_view(template_name="test_tags.html"),
+ name='test_tags'),
+ )
from django.contrib.auth import logout as auth_logout
from django.template import RequestContext
from django.shortcuts import render_to_response, redirect
+
from forms import RemoteUserForm
+
from settings import SAML_REDIRECT_FIELD_NAME,\
- SAML_MELLON_LOGIN_URL,\
- SAML_MELLON_LOGOUT_URL,\
- SAML_CHANGE_PASSWORD_URL,\
- SAML_LOGOUT_REDIRECT_URL, \
- SAML_AUTH
+ SAML_MELLON_LOGIN_URL,\
+ SAML_MELLON_LOGOUT_URL,\
+ SAML_CHANGE_PASSWORD_URL,\
+ SAML_LOGOUT_REDIRECT_URL, \
+ SAML_AUTH
def redirect_to_login(request, redirect_to=None, do_redirect=True):
base_url = SAML_MELLON_LOGIN_URL
else:
base_url = reverse('sandbox_login')
- url = "%s?%s=%s" % (base_url,
- SAML_REDIRECT_FIELD_NAME,
- redirect_to,
- )
+ url = "%s?%s=%s" % (
+ base_url,
+ SAML_REDIRECT_FIELD_NAME,
+ redirect_to,
+ )
if do_redirect:
return redirect(url)
else:
def redirect_to_logout(request, redirect_to=None, do_redirect=True):
if redirect_to is None:
redirect_to = SAML_LOGOUT_REDIRECT_URL
- url = "%s?%s=%s" % (reverse('local_logout'),
- SAML_REDIRECT_FIELD_NAME,
- redirect_to,
- )
+ url = "%s?%s=%s" % (
+ reverse('local_logout'),
+ SAML_REDIRECT_FIELD_NAME,
+ redirect_to,
+ )
if do_redirect:
return redirect(url)
else:
form = RemoteUserForm(request)
c = {'form': form}
- return render_to_response("saml/login_form.html",
+ return render_to_response(
+ "saml/login_form.html",
c,
context_instance=RequestContext(request))
.. code-block:: guess
- {% load saml %}
+ {% load saml_tags %}
{% if request.user.is_authenticated %}
{% mellon_logout_url %}
--- /dev/null
+[tox]
+envlist = django1.4
+
+[testenv]
+deps =
+ coverage
+ pep8
+
+commands =
+ coverage erase
+ coverage run --source="{envsitepackagesdir}/auf/django/saml/" {envdir}/bin/django-admin.py test saml --settings=auf.django.saml.tests.settings
+ pep8 -r --statistics --count {envsitepackagesdir}/auf/django/saml/
+ coverage report
+ coverage html
+
+[testenv:django1.4]
+deps =
+ {[testenv]deps}
+ django==1.4