Skip to content

Commit 3a12949

Browse files
authored
Added Django 4.0 compatibility (#317)
* added django 4.0 compat * dropped django 3.0
1 parent cbb7b10 commit 3a12949

File tree

7 files changed

+32
-24
lines changed

7 files changed

+32
-24
lines changed

.github/workflows/python-package.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
matrix:
1818
python-version: [3.8, 3.9]
19-
django-version: ["2.2", "3.0", "3.1", "3.2"]
19+
django-version: ["2.2", "3.1", "3.2", "4.0"]
2020

2121
steps:
2222
- uses: actions/checkout@v2

djangosaml2/signals.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,5 @@
1414

1515
import django.dispatch
1616

17-
pre_user_save = django.dispatch.Signal(
18-
providing_args=['attributes', 'user_modified'])
19-
post_authenticated = django.dispatch.Signal(
20-
providing_args=['session_info', 'request'])
17+
pre_user_save = django.dispatch.Signal()
18+
post_authenticated = django.dispatch.Signal()

djangosaml2/tests/__init__.py

+17-8
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@
2121
from unittest import mock
2222
from urllib.parse import parse_qs, urlparse
2323

24+
from django import http
2425
from django.conf import settings
2526
from django.contrib.auth import SESSION_KEY, get_user_model
2627
from django.contrib.auth.models import AnonymousUser
2728
from django.core.exceptions import ImproperlyConfigured
2829
from django.test import Client, TestCase, override_settings
2930
from django.test.client import RequestFactory
3031
from django.urls import reverse, reverse_lazy
31-
from django.utils.encoding import force_text
3232
from djangosaml2 import views
3333
from djangosaml2.cache import OutstandingQueriesCache
3434
from djangosaml2.conf import get_config
@@ -57,6 +57,15 @@ def dummy_loader(request):
5757
return 'dummy_loader'
5858

5959

60+
def dummy_get_response(request: http.HttpRequest):
61+
"""
62+
Return a basic HttpResponse.
63+
64+
Function needed to instantiate SamlSessionMiddleware.
65+
"""
66+
return http.HttpResponse("Session test")
67+
68+
6069
non_callable = 'just a string'
6170

6271

@@ -433,7 +442,7 @@ def test_assertion_consumer_service(self):
433442

434443
# as the RelayState is empty we have redirect to ACS_DEFAULT_REDIRECT_URL
435444
self.assertRedirects(response, '/dashboard/')
436-
self.assertEqual(force_text(new_user.id), client.session[SESSION_KEY])
445+
self.assertEqual(str(new_user.id), client.session[SESSION_KEY])
437446

438447
@override_settings(ACS_DEFAULT_REDIRECT_URL='testprofiles:dashboard')
439448
def test_assertion_consumer_service_default_relay_state(self):
@@ -458,7 +467,7 @@ def test_assertion_consumer_service_default_relay_state(self):
458467

459468
# The RelayState is missing, redirect to ACS_DEFAULT_REDIRECT_URL
460469
self.assertRedirects(response, '/dashboard/')
461-
self.assertEqual(force_text(new_user.id), self.client.session[SESSION_KEY])
470+
self.assertEqual(str(new_user.id), self.client.session[SESSION_KEY])
462471

463472
def test_assertion_consumer_service_already_logged_in_allowed(self):
464473
self.client.force_login(User.objects.create(
@@ -566,7 +575,7 @@ def test_echo_view_no_saml_session(self):
566575
request.COOKIES = self.client.cookies
567576
request.user = User.objects.last()
568577

569-
middleware = SamlSessionMiddleware()
578+
middleware = SamlSessionMiddleware(dummy_get_response)
570579
middleware.process_request(request)
571580

572581
response = EchoAttributesView.as_view()(request)
@@ -585,7 +594,7 @@ def test_echo_view_success(self):
585594
request = RequestFactory().get('/')
586595
request.user = User.objects.last()
587596

588-
middleware = SamlSessionMiddleware()
597+
middleware = SamlSessionMiddleware(dummy_get_response)
589598
middleware.process_request(request)
590599

591600
saml_session_name = getattr(
@@ -808,7 +817,7 @@ def test_custom_conf_loader_from_view(self):
808817
config_loader_path = 'djangosaml2.tests.test_config_loader_with_real_conf'
809818
request = RequestFactory().get('/login/')
810819
request.user = AnonymousUser()
811-
middleware = SamlSessionMiddleware()
820+
middleware = SamlSessionMiddleware(dummy_get_response)
812821
middleware.process_request(request)
813822

814823
saml_session_name = getattr(
@@ -855,7 +864,7 @@ def test_middleware_cookie_expireatbrowserclose(self):
855864
request = RequestFactory().get('/login/')
856865
request.user = AnonymousUser()
857866
request.session = session
858-
middleware = SamlSessionMiddleware()
867+
middleware = SamlSessionMiddleware(dummy_get_response)
859868
middleware.process_request(request)
860869

861870
saml_session_name = getattr(
@@ -882,7 +891,7 @@ def test_middleware_cookie_with_expiry(self):
882891
request = RequestFactory().get('/login/')
883892
request.user = AnonymousUser()
884893
request.session = session
885-
middleware = SamlSessionMiddleware()
894+
middleware = SamlSessionMiddleware(dummy_get_response)
886895
middleware.process_request(request)
887896

888897
saml_session_name = getattr(

djangosaml2/utils.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@
2222
from django.core.exceptions import ImproperlyConfigured
2323
from django.http import HttpResponse, HttpResponseRedirect
2424
from django.shortcuts import resolve_url
25-
from django.utils.http import is_safe_url
25+
try:
26+
from django.utils.http import url_has_allowed_host_and_scheme
27+
except ImportError: # django 2.2
28+
from django.utils.http import is_safe_url as url_has_allowed_host_and_scheme
2629
from saml2.config import SPConfig
2730
from saml2.s_utils import UnknownSystemEntity
2831

@@ -96,7 +99,7 @@ def validate_referral_url(request, url):
9699
saml_allowed_hosts = set(
97100
getattr(settings, 'SAML_ALLOWED_HOSTS', [request.get_host()]))
98101

99-
if not is_safe_url(url=url, allowed_hosts=saml_allowed_hosts):
102+
if not url_has_allowed_host_and_scheme(url=url, allowed_hosts=saml_allowed_hosts):
100103
return get_fallback_login_redirect_url()
101104
return url
102105

djangosaml2/views.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import base64
1717
import logging
1818
import saml2
19+
from urllib.parse import quote
1920

2021
from django.conf import settings
2122
from django.contrib import auth
@@ -28,7 +29,6 @@
2829
from django.template import TemplateDoesNotExist
2930
from django.urls import reverse
3031
from django.utils.decorators import method_decorator
31-
from django.utils.http import urlquote
3232
from django.views.decorators.csrf import csrf_exempt
3333
from django.views.generic import View
3434
from django.utils.module_loading import import_string
@@ -208,13 +208,11 @@ def get(self, request, *args, **kwargs):
208208
logger.debug(("A discovery process is needed trough a"
209209
"Discovery Service: {}").format(discovery_service))
210210
login_url = request.build_absolute_uri(reverse('saml2_login'))
211-
login_url = '{0}?next={1}'.format(login_url,
212-
urlquote(next_path, safe=''))
211+
login_url = '{0}?next={1}'.format(login_url, quote(next_path, safe=''))
213212
ds_url = '{0}?entityID={1}&return={2}&returnIDParam=idp'
214213
ds_url = ds_url.format(discovery_service,
215-
urlquote(
216-
getattr(conf, 'entityid'), safe=''),
217-
urlquote(login_url, safe=''))
214+
quote(getattr(conf, 'entityid'), safe=''),
215+
quote(login_url, safe=''))
218216
return HttpResponseRedirect(ds_url)
219217

220218
elif len(configured_idps) > 1:

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ def read(*rnames):
3333
"Environment :: Web Environment",
3434
"Framework :: Django",
3535
"Framework :: Django :: 2.2",
36-
"Framework :: Django :: 3.0",
3736
"Framework :: Django :: 3.1",
3837
"Framework :: Django :: 3.2",
38+
"Framework :: Django :: 4.0",
3939
"Intended Audience :: Developers",
4040
"License :: OSI Approved :: Apache Software License",
4141
"Operating System :: OS Independent",

tox.ini

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
[tox]
22
envlist =
3-
py{3.6,3.7,3.8,3.9}-django{2.2,3.0,3.1,3.2}
3+
py{3.6,3.7,3.8,3.9}-django{2.2,3.1,3.2,4.0}
44

55
[testenv]
66
commands =
77
python tests/run_tests.py
88

99
deps =
1010
django2.2: django~=2.2
11-
django3.0: django~=3.0
1211
django3.1: django~=3.1
1312
django3.2: django~=3.2
13+
django4.0: django==4.0rc1
1414
djangomaster: https://github.com/django/django/archive/master.tar.gz
1515
.[test]
1616

0 commit comments

Comments
 (0)