Skip to content

Commit 379652f

Browse files
Add compatibility with Django master
Some import path changed in Django 2.0, the code has been updated to first attempt to import the newer path and import the older on ImportError. A is_safe_url_compat helper has been introduced to deal with Django's change of is_safe_url, where a dictionary of allowed hosts is expected instead of a single host. Finally, the MIDDLEWARE_CLASSES setting has been renamed to MIDDLEWARE classes with the new middleware style. Django's middleware have been updated and djangosaml2 does not define middlewares, it should safe to rename MIDDLEWARE_CLASSES to MIDDLEWARE.
1 parent 0639a45 commit 379652f

File tree

5 files changed

+37
-10
lines changed

5 files changed

+37
-10
lines changed

djangosaml2/tests/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,17 @@
2424
from django.contrib.auth import SESSION_KEY, get_user_model
2525
from django.contrib.auth.models import AnonymousUser
2626
from django.contrib.sessions.middleware import SessionMiddleware
27-
from django.core.urlresolvers import reverse
27+
try:
28+
from django.urls import reverse
29+
except ImportError:
30+
from django.core.urlresolvers import reverse
2831
from django.template import Template, Context
2932
from django.test import TestCase
3033
from django.test.client import RequestFactory
31-
from django.utils.text import force_text
34+
try:
35+
from django.utils.encoding import force_text
36+
except ImportError:
37+
from django.utils.text import force_text
3238
from django.utils.six.moves.urllib.parse import urlparse, parse_qs
3339

3440
from saml2.config import SPConfig

djangosaml2/utils.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import django
1516
from django.conf import settings
1617
from django.core.exceptions import ImproperlyConfigured
18+
from django.utils.http import is_safe_url
1719
from django.utils.module_loading import import_string
1820
from saml2.s_utils import UnknownSystemEntity
1921

@@ -78,3 +80,11 @@ def fail_acs_response(request, *args, **kwargs):
7880
failure_function = import_string(get_custom_setting('SAML_ACS_FAILURE_RESPONSE_FUNCTION',
7981
'djangosaml2.acs_failures.template_failure'))
8082
return failure_function(request, *args, **kwargs)
83+
84+
85+
def is_safe_url_compat(url, allowed_hosts=None, require_https=False):
86+
if django.VERSION >= (1, 11):
87+
return is_safe_url(url, allowed_hosts=allowed_hosts, require_https=require_https)
88+
assert len(allowed_hosts) == 1
89+
host = allowed_hosts.pop()
90+
return is_safe_url(url, host=host)

djangosaml2/views.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
from django.conf import settings
2525
from django.contrib import auth
2626
from django.contrib.auth.decorators import login_required
27-
from django.contrib.auth.views import logout as django_logout
27+
try:
28+
from django.contrib.auth.views import LogoutView
29+
django_logout = LogoutView.as_view()
30+
except ImportError:
31+
from django.contrib.auth.views import logout as django_logout
2832
from django.core.exceptions import PermissionDenied, SuspiciousOperation
2933
from django.http import Http404, HttpResponse
3034
from django.http import HttpResponseRedirect # 30x
@@ -33,7 +37,6 @@
3337
from django.views.decorators.http import require_POST
3438
from django.shortcuts import render
3539
from django.template import TemplateDoesNotExist
36-
from django.utils.http import is_safe_url
3740
from django.utils.six import text_type, binary_type
3841
from django.views.decorators.csrf import csrf_exempt
3942

@@ -51,7 +54,10 @@
5154
from djangosaml2.conf import get_config
5255
from djangosaml2.overrides import Saml2Client
5356
from djangosaml2.signals import post_authenticated
54-
from djangosaml2.utils import fail_acs_response, get_custom_setting, available_idps, get_location, get_idp_sso_supported_bindings
57+
from djangosaml2.utils import (
58+
available_idps, fail_acs_response, get_custom_setting,
59+
get_idp_sso_supported_bindings, get_location, is_safe_url_compat,
60+
)
5561

5662

5763
logger = logging.getLogger('djangosaml2')
@@ -106,7 +112,7 @@ def login(request,
106112
came_from = settings.LOGIN_REDIRECT_URL
107113

108114
# Ensure the user-originating redirection url is safe.
109-
if not is_safe_url(url=came_from, host=request.get_host()):
115+
if not is_safe_url_compat(url=came_from, allowed_hosts={request.get_host()}):
110116
came_from = settings.LOGIN_REDIRECT_URL
111117

112118
# if the user is already authenticated that maybe because of two reasons:
@@ -315,7 +321,7 @@ def assertion_consumer_service(request,
315321
if not relay_state:
316322
logger.warning('The RelayState parameter exists but is empty')
317323
relay_state = default_relay_state
318-
if not is_safe_url(url=relay_state, host=request.get_host()):
324+
if not is_safe_url_compat(url=relay_state, allowed_hosts={request.get_host()}):
319325
relay_state = settings.LOGIN_REDIRECT_URL
320326
logger.debug('Redirecting to the RelayState: %s', relay_state)
321327
return HttpResponseRedirect(relay_state)
@@ -451,7 +457,7 @@ def finish_logout(request, response, next_page=None):
451457
if response and response.status_ok():
452458
if next_page is None and hasattr(settings, 'LOGOUT_REDIRECT_URL'):
453459
next_page = settings.LOGOUT_REDIRECT_URL
454-
logger.debug('Performing django_logout with a next_page of %s',
460+
logger.debug('Performing django logout with a next_page of %s',
455461
next_page)
456462
return django_logout(request, next_page=next_page)
457463
else:

tests/settings.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
import os
1414

15+
import django
16+
1517
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
1618
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
1719

@@ -34,7 +36,7 @@
3436
'testprofiles',
3537
)
3638

37-
MIDDLEWARE_CLASSES = (
39+
MIDDLEWARE = (
3840
'django.middleware.security.SecurityMiddleware',
3941
'django.contrib.sessions.middleware.SessionMiddleware',
4042
'django.middleware.common.CommonMiddleware',
@@ -44,6 +46,9 @@
4446
'django.middleware.clickjacking.XFrameOptionsMiddleware',
4547
)
4648

49+
if django.VERSION < (1, 10):
50+
MIDDLEWARE_CLASSES = MIDDLEWARE
51+
4752
ROOT_URLCONF = 'testprofiles.urls'
4853

4954
TEMPLATES = [

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tox]
2-
envlist = py{27,35}-django{18,19,110,111,master}
2+
envlist = py27-django{18,19,110,111}, py36-django{18,19,110,111,master}
33

44
[testenv]
55
commands =

0 commit comments

Comments
 (0)