From 2290db1c79266ce9b607e5f0ac57f524f293eade Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 13:31:06 -0600 Subject: [PATCH 01/15] Initial pass at custom error function --- django_auth_adfs/config.py | 5 +++++ django_auth_adfs/views.py | 31 ++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/django_auth_adfs/config.py b/django_auth_adfs/config.py index e6051f9..e8b47d9 100644 --- a/django_auth_adfs/config.py +++ b/django_auth_adfs/config.py @@ -69,6 +69,7 @@ def __init__(self): self.TIMEOUT = 5 self.USERNAME_CLAIM = "winaccountname" self.JWT_LEEWAY = 0 + self.FAILED_RESPONSE_FUNCTION = 'django_auth_adfs.views.render_failed_response' required_settings = [ "AUDIENCE", @@ -151,6 +152,10 @@ def __init__(self): msg = "django_auth_adfs setting '{0}' has not been set".format(setting) raise ImproperlyConfigured(msg) + # Setup dynamic settings + if not callable(_settings.FAILED_RESPONSE_FUNCTION): + _settings.FAILED_RESPONSE_FUNCTION = import_string(_settings.FAILED_RESPONSE_FUNCTION) + # Validate setting conflicts usermodel = get_user_model() if usermodel.USERNAME_FIELD in self.CLAIM_MAPPING.keys(): diff --git a/django_auth_adfs/views.py b/django_auth_adfs/views.py index cddf7b9..9cd536b 100644 --- a/django_auth_adfs/views.py +++ b/django_auth_adfs/views.py @@ -13,6 +13,13 @@ logger = logging.getLogger("django_auth_adfs") +def render_failed_response(request, error_message, status): + # Return an error message + return render(request, 'django_auth_adfs/login_failed.html', { + 'error_message': error_message, + }, status=status) + + class OAuth2CallbackView(View): def get(self, request): """ @@ -25,9 +32,11 @@ def get(self, request): code = request.GET.get("code") if not code: # Return an error message - return render(request, 'django_auth_adfs/login_failed.html', { - 'error_message': "No authorization code was provided.", - }, status=400) + return django_settings.FAILED_RESPONSE_FUNCTION( + request, + error_message="No authorization code was provided.", + status=400 + ) redirect_to = request.GET.get("state") try: @@ -54,14 +63,18 @@ def get(self, request): return redirect(redirect_to) else: # Return a 'disabled account' error message - return render(request, 'django_auth_adfs/login_failed.html', { - 'error_message': "Your account is disabled.", - }, status=403) + return django_settings.FAILED_RESPONSE_FUNCTION( + request, + error_message="Your account is disabled.", + status=403 + ) else: # Return an 'invalid login' error message - return render(request, 'django_auth_adfs/login_failed.html', { - 'error_message': "Login failed.", - }, status=401) + return django_settings.FAILED_RESPONSE_FUNCTION( + request, + error_message="Login failed.", + status=401 + ) class OAuth2LoginView(View): From eb7fa06f7d208b8ac921eec9877bc25c07b5b3e9 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 15:23:52 -0600 Subject: [PATCH 02/15] Initial pass at custom error function --- django_auth_adfs/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_auth_adfs/config.py b/django_auth_adfs/config.py index e8b47d9..10daa15 100644 --- a/django_auth_adfs/config.py +++ b/django_auth_adfs/config.py @@ -153,7 +153,7 @@ def __init__(self): raise ImproperlyConfigured(msg) # Setup dynamic settings - if not callable(_settings.FAILED_RESPONSE_FUNCTION): + if not callable(_settings["FAILED_RESPONSE_FUNCTION"]): _settings.FAILED_RESPONSE_FUNCTION = import_string(_settings.FAILED_RESPONSE_FUNCTION) # Validate setting conflicts From 93d314a59b090449c19ac9c19e9df7f4ef9425e4 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 15:28:05 -0600 Subject: [PATCH 03/15] Initial pass at custom error function --- django_auth_adfs/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_auth_adfs/config.py b/django_auth_adfs/config.py index 10daa15..df7c2e8 100644 --- a/django_auth_adfs/config.py +++ b/django_auth_adfs/config.py @@ -154,7 +154,7 @@ def __init__(self): # Setup dynamic settings if not callable(_settings["FAILED_RESPONSE_FUNCTION"]): - _settings.FAILED_RESPONSE_FUNCTION = import_string(_settings.FAILED_RESPONSE_FUNCTION) + _settings.FAILED_RESPONSE_FUNCTION = import_string(_settings["FAILED_RESPONSE_FUNCTION"]) # Validate setting conflicts usermodel = get_user_model() From a25b6bbfa13b19f634d091818626889eed92ebae Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 15:31:43 -0600 Subject: [PATCH 04/15] Initial pass at custom error function --- django_auth_adfs/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/django_auth_adfs/config.py b/django_auth_adfs/config.py index df7c2e8..79c7e46 100644 --- a/django_auth_adfs/config.py +++ b/django_auth_adfs/config.py @@ -153,8 +153,8 @@ def __init__(self): raise ImproperlyConfigured(msg) # Setup dynamic settings - if not callable(_settings["FAILED_RESPONSE_FUNCTION"]): - _settings.FAILED_RESPONSE_FUNCTION = import_string(_settings["FAILED_RESPONSE_FUNCTION"]) + if "FAILED_RESPONSE_FUNCTION" in _settings and not callable(_settings["FAILED_RESPONSE_FUNCTION"]): + self.FAILED_RESPONSE_FUNCTION = import_string(_settings["FAILED_RESPONSE_FUNCTION"]) # Validate setting conflicts usermodel = get_user_model() From dc395cf28128fcd828afafaa945446962e66a362 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 15:39:13 -0600 Subject: [PATCH 05/15] Initial pass at custom error function --- django_auth_adfs/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/django_auth_adfs/views.py b/django_auth_adfs/views.py index 9cd536b..bcf37ea 100644 --- a/django_auth_adfs/views.py +++ b/django_auth_adfs/views.py @@ -7,7 +7,7 @@ from django.utils.http import is_safe_url from django.views.generic import View -from django_auth_adfs.config import provider_config +from django_auth_adfs.config import provider_config, settings from django_auth_adfs.exceptions import MFARequired logger = logging.getLogger("django_auth_adfs") @@ -32,7 +32,7 @@ def get(self, request): code = request.GET.get("code") if not code: # Return an error message - return django_settings.FAILED_RESPONSE_FUNCTION( + return settings.FAILED_RESPONSE_FUNCTION( request, error_message="No authorization code was provided.", status=400 @@ -63,14 +63,14 @@ def get(self, request): return redirect(redirect_to) else: # Return a 'disabled account' error message - return django_settings.FAILED_RESPONSE_FUNCTION( + return settings.FAILED_RESPONSE_FUNCTION( request, error_message="Your account is disabled.", status=403 ) else: # Return an 'invalid login' error message - return django_settings.FAILED_RESPONSE_FUNCTION( + return settings.FAILED_RESPONSE_FUNCTION( request, error_message="Login failed.", status=401 From a53e7048dc3b41ff77c6acdf5662d1fcfac8a955 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 16:04:25 -0600 Subject: [PATCH 06/15] Added test, added doco --- CHANGELOG.rst | 8 ++++++++ django_auth_adfs/config.py | 7 ++++--- django_auth_adfs/views.py | 2 +- docs/install.rst | 3 +++ docs/settings_ref.rst | 18 ++++++++++++++++++ tests/test_settings.py | 6 ++++++ tests/views.py | 2 ++ 7 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 tests/views.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7c2efcf..9335109 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Changelog ========= +`1.5.1`_ - Not yet released +--------------------- + +**Features** + +* New parameter called `FAILED_RESPONSE_FUNCTION`, allowing you to set a custom django function view to handle login + failures. #? + `1.5.0`_ - 2021-01-18 --------------------- diff --git a/django_auth_adfs/config.py b/django_auth_adfs/config.py index 79c7e46..8c2b142 100644 --- a/django_auth_adfs/config.py +++ b/django_auth_adfs/config.py @@ -21,6 +21,7 @@ except ImportError: # Django < 1.10 from django.core.urlresolvers import reverse + logger = logging.getLogger("django_auth_adfs") AZURE_AD_SERVER = "login.microsoftonline.com" @@ -69,7 +70,7 @@ def __init__(self): self.TIMEOUT = 5 self.USERNAME_CLAIM = "winaccountname" self.JWT_LEEWAY = 0 - self.FAILED_RESPONSE_FUNCTION = 'django_auth_adfs.views.render_failed_response' + self.FAILED_RESPONSE_FUNCTION = 'django_auth_adfs.views.default_failed_response' required_settings = [ "AUDIENCE", @@ -153,8 +154,8 @@ def __init__(self): raise ImproperlyConfigured(msg) # Setup dynamic settings - if "FAILED_RESPONSE_FUNCTION" in _settings and not callable(_settings["FAILED_RESPONSE_FUNCTION"]): - self.FAILED_RESPONSE_FUNCTION = import_string(_settings["FAILED_RESPONSE_FUNCTION"]) + if not callable(self.FAILED_RESPONSE_FUNCTION): + self.FAILED_RESPONSE_FUNCTION = import_string(self.FAILED_RESPONSE_FUNCTION) # Validate setting conflicts usermodel = get_user_model() diff --git a/django_auth_adfs/views.py b/django_auth_adfs/views.py index bcf37ea..14cf241 100644 --- a/django_auth_adfs/views.py +++ b/django_auth_adfs/views.py @@ -13,7 +13,7 @@ logger = logging.getLogger("django_auth_adfs") -def render_failed_response(request, error_message, status): +def default_failed_response(request, error_message, status): # Return an error message return render(request, 'django_auth_adfs/login_failed.html', { 'error_message': error_message, diff --git a/docs/install.rst b/docs/install.rst index 2ccdb1e..c1306ea 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -83,6 +83,9 @@ In your project's ``settings.py`` add these settings. 'django_auth_adfs.middleware.LoginRequiredMiddleware', ) + # You can point login failures to a custom Django function based view for customization of the UI + FAILED_RESPONSE_FUNCTION = 'dot.path.to.custom.views.login_failed' + In your project's ``urls.py`` add these paths: .. code-block:: python diff --git a/docs/settings_ref.rst b/docs/settings_ref.rst index d4913e2..b7b4b33 100644 --- a/docs/settings_ref.rst +++ b/docs/settings_ref.rst @@ -180,6 +180,24 @@ Allows you to set a leeway of the JWT token. See the official `PyJWT `__ docs for more information. +FAILED_RESPONSE_FUNCTION +-------------------------------- +* **Default**: ``django_auth_adfs.views.default_failed_response`` +* **Type**: ``str`` or ``callable`` + +Allows you to set a custom django function view to handle login failures. Can be a dot path to your +Django function based view function or a callable. + +Callable must have the following method signature accepting ``error_message`` and ``status`` arguments: + +.. code-block:: python + + def failed_response(request, error_message, status): + # Return an error message + return render(request, 'myapp/login_failed.html', { + 'error_message': error_message, + }, status=status) + GROUP_CLAIM ----------- diff --git a/tests/test_settings.py b/tests/test_settings.py index a7a07be..252c678 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -41,6 +41,12 @@ def test_required_setting(self): with patch("django_auth_adfs.config.django_settings", settings): self.assertRaises(ImproperlyConfigured, Settings) + def test_dotted_path_failed_response_setting(self): + settings = deepcopy(django_settings) + settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = 'views.test_failed_response' + with patch("django_auth_adfs.config.django_settings", settings): + self.assertTrue(callable(settings.FAILED_RESPONSE_FUNCTION)) + class CustomSettingsTests(SimpleTestCase): def setUp(self): diff --git a/tests/views.py b/tests/views.py new file mode 100644 index 0000000..b16e402 --- /dev/null +++ b/tests/views.py @@ -0,0 +1,2 @@ +def test_failed_response(request, error_message, status): + pass From e3e3550b97c9680b3c4d6b2a88a9cc9f29a1f904 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 16:10:28 -0600 Subject: [PATCH 07/15] Added test, added doco --- django_auth_adfs/config.py | 9 ++++++++- django_auth_adfs/views.py | 9 +-------- docs/settings_ref.rst | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/django_auth_adfs/config.py b/django_auth_adfs/config.py index 8c2b142..3356f29 100644 --- a/django_auth_adfs/config.py +++ b/django_auth_adfs/config.py @@ -14,6 +14,7 @@ from django.contrib.auth import get_user_model from django.core.exceptions import ImproperlyConfigured from django.http import QueryDict +from django.shortcuts import render from django.utils.module_loading import import_string try: @@ -49,6 +50,12 @@ class Settings(object): """ def __init__(self): + def default_failed_response(request, error_message, status): + # Return an error message + return render(request, 'django_auth_adfs/login_failed.html', { + 'error_message': error_message, + }, status=status) + # Set defaults self.AUDIENCE = None # Required self.BOOLEAN_CLAIM_MAPPING = {} @@ -70,7 +77,7 @@ def __init__(self): self.TIMEOUT = 5 self.USERNAME_CLAIM = "winaccountname" self.JWT_LEEWAY = 0 - self.FAILED_RESPONSE_FUNCTION = 'django_auth_adfs.views.default_failed_response' + self.FAILED_RESPONSE_FUNCTION = default_failed_response required_settings = [ "AUDIENCE", diff --git a/django_auth_adfs/views.py b/django_auth_adfs/views.py index 14cf241..388c7be 100644 --- a/django_auth_adfs/views.py +++ b/django_auth_adfs/views.py @@ -3,7 +3,7 @@ from django.conf import settings as django_settings from django.contrib.auth import authenticate, login, logout -from django.shortcuts import redirect, render +from django.shortcuts import redirect from django.utils.http import is_safe_url from django.views.generic import View @@ -13,13 +13,6 @@ logger = logging.getLogger("django_auth_adfs") -def default_failed_response(request, error_message, status): - # Return an error message - return render(request, 'django_auth_adfs/login_failed.html', { - 'error_message': error_message, - }, status=status) - - class OAuth2CallbackView(View): def get(self, request): """ diff --git a/docs/settings_ref.rst b/docs/settings_ref.rst index b7b4b33..ef4c7e0 100644 --- a/docs/settings_ref.rst +++ b/docs/settings_ref.rst @@ -182,7 +182,7 @@ Allows you to set a leeway of the JWT token. See the official FAILED_RESPONSE_FUNCTION -------------------------------- -* **Default**: ``django_auth_adfs.views.default_failed_response`` +* **Default**: ``None`` * **Type**: ``str`` or ``callable`` Allows you to set a custom django function view to handle login failures. Can be a dot path to your From 0a3a177fec8de57e138af3565e7c0a8c38b3b49a Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 16:13:27 -0600 Subject: [PATCH 08/15] More test fixes --- tests/test_settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 252c678..1674fd9 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -43,9 +43,9 @@ def test_required_setting(self): def test_dotted_path_failed_response_setting(self): settings = deepcopy(django_settings) - settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = 'views.test_failed_response' + settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = '.views.test_failed_response' with patch("django_auth_adfs.config.django_settings", settings): - self.assertTrue(callable(settings.FAILED_RESPONSE_FUNCTION)) + self.assertTrue(callable(settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"])) class CustomSettingsTests(SimpleTestCase): From 18d1c20857c21792dfd99cf068422380cff04719 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 16:18:03 -0600 Subject: [PATCH 09/15] More test fixes --- tests/test_settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 1674fd9..befe9eb 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -45,7 +45,8 @@ def test_dotted_path_failed_response_setting(self): settings = deepcopy(django_settings) settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = '.views.test_failed_response' with patch("django_auth_adfs.config.django_settings", settings): - self.assertTrue(callable(settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"])) + with patch("django_auth_adfs.config.settings", Settings()): + self.assertTrue(callable(settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"])) class CustomSettingsTests(SimpleTestCase): From 2a30a2341f079c596f5e57b74fe06ae01ce3e4d4 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 16:19:41 -0600 Subject: [PATCH 10/15] More test fixes (sigh again) --- tests/test_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index befe9eb..919912b 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -43,7 +43,7 @@ def test_required_setting(self): def test_dotted_path_failed_response_setting(self): settings = deepcopy(django_settings) - settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = '.views.test_failed_response' + settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = 'tests.views.test_failed_response' with patch("django_auth_adfs.config.django_settings", settings): with patch("django_auth_adfs.config.settings", Settings()): self.assertTrue(callable(settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"])) From b963d3797c32b1f107f9e469441aebfd55d4cd3e Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 16:22:28 -0600 Subject: [PATCH 11/15] More test fixes (sigh again) --- tests/test_settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 919912b..14bfb98 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -45,8 +45,8 @@ def test_dotted_path_failed_response_setting(self): settings = deepcopy(django_settings) settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = 'tests.views.test_failed_response' with patch("django_auth_adfs.config.django_settings", settings): - with patch("django_auth_adfs.config.settings", Settings()): - self.assertTrue(callable(settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"])) + s = Settings() + self.assertTrue(callable(s.FAILED_RESPONSE_FUNCTION)) class CustomSettingsTests(SimpleTestCase): From febeb2dc5384dd65f6a07f51323e4e8efaf6f988 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Thu, 21 Jan 2021 16:25:13 -0600 Subject: [PATCH 12/15] More test fixes (sigh again) --- tests/test_settings.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_settings.py b/tests/test_settings.py index 14bfb98..f6642c1 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -41,6 +41,12 @@ def test_required_setting(self): with patch("django_auth_adfs.config.django_settings", settings): self.assertRaises(ImproperlyConfigured, Settings) + def test_default_failed_response_setting(self): + settings = deepcopy(django_settings) + with patch("django_auth_adfs.config.django_settings", settings): + s = Settings() + self.assertTrue(callable(s.FAILED_RESPONSE_FUNCTION)) + def test_dotted_path_failed_response_setting(self): settings = deepcopy(django_settings) settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = 'tests.views.test_failed_response' From b51d735ee29cdb7a464b03a2dd199053061beed2 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Mon, 25 Jan 2021 10:43:11 -0600 Subject: [PATCH 13/15] Changes per review --- CHANGELOG.rst | 5 +++-- django_auth_adfs/config.py | 14 +++++--------- django_auth_adfs/views.py | 6 +++--- docs/install.rst | 2 +- docs/settings_ref.rst | 4 ++-- tests/test_settings.py | 6 +++--- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9335109..0bb8274 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,12 +1,12 @@ Changelog ========= -`1.5.1`_ - Not yet released +`1.5.1`_ - 2021-01-25 --------------------- **Features** -* New parameter called `FAILED_RESPONSE_FUNCTION`, allowing you to set a custom django function view to handle login +* New parameter called `CUSTOM_FAILED_RESPONSE_VIEW`, allowing you to set a custom django function view to handle login failures. #? @@ -227,6 +227,7 @@ Changelog * Initial release +.. _1.5.1: https://github.com/snok/django-auth-adfs/compare/1.5.0...1.5.1 .. _1.5.0: https://github.com/jobec/django-auth-adfs/compare/1.4.1...1.5.0 .. _1.4.1: https://github.com/jobec/django-auth-adfs/compare/1.4.0...1.4.1 .. _1.4.0: https://github.com/jobec/django-auth-adfs/compare/1.3.1...1.4.0 diff --git a/django_auth_adfs/config.py b/django_auth_adfs/config.py index 3356f29..af81ac0 100644 --- a/django_auth_adfs/config.py +++ b/django_auth_adfs/config.py @@ -50,12 +50,6 @@ class Settings(object): """ def __init__(self): - def default_failed_response(request, error_message, status): - # Return an error message - return render(request, 'django_auth_adfs/login_failed.html', { - 'error_message': error_message, - }, status=status) - # Set defaults self.AUDIENCE = None # Required self.BOOLEAN_CLAIM_MAPPING = {} @@ -77,7 +71,9 @@ def default_failed_response(request, error_message, status): self.TIMEOUT = 5 self.USERNAME_CLAIM = "winaccountname" self.JWT_LEEWAY = 0 - self.FAILED_RESPONSE_FUNCTION = default_failed_response + self.CUSTOM_FAILED_RESPONSE_VIEW = lambda request, error_message, status: render( + request, 'django_auth_adfs/login_failed.html', {'error_message': error_message}, status=status + ) required_settings = [ "AUDIENCE", @@ -161,8 +157,8 @@ def default_failed_response(request, error_message, status): raise ImproperlyConfigured(msg) # Setup dynamic settings - if not callable(self.FAILED_RESPONSE_FUNCTION): - self.FAILED_RESPONSE_FUNCTION = import_string(self.FAILED_RESPONSE_FUNCTION) + if not callable(self.CUSTOM_FAILED_RESPONSE_VIEW): + self.CUSTOM_FAILED_RESPONSE_VIEW = import_string(self.CUSTOM_FAILED_RESPONSE_VIEW) # Validate setting conflicts usermodel = get_user_model() diff --git a/django_auth_adfs/views.py b/django_auth_adfs/views.py index 388c7be..7f36ae6 100644 --- a/django_auth_adfs/views.py +++ b/django_auth_adfs/views.py @@ -25,7 +25,7 @@ def get(self, request): code = request.GET.get("code") if not code: # Return an error message - return settings.FAILED_RESPONSE_FUNCTION( + return settings.CUSTOM_FAILED_RESPONSE_VIEW( request, error_message="No authorization code was provided.", status=400 @@ -56,14 +56,14 @@ def get(self, request): return redirect(redirect_to) else: # Return a 'disabled account' error message - return settings.FAILED_RESPONSE_FUNCTION( + return settings.CUSTOM_FAILED_RESPONSE_VIEW( request, error_message="Your account is disabled.", status=403 ) else: # Return an 'invalid login' error message - return settings.FAILED_RESPONSE_FUNCTION( + return settings.CUSTOM_FAILED_RESPONSE_VIEW( request, error_message="Login failed.", status=401 diff --git a/docs/install.rst b/docs/install.rst index c1306ea..1026122 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -84,7 +84,7 @@ In your project's ``settings.py`` add these settings. ) # You can point login failures to a custom Django function based view for customization of the UI - FAILED_RESPONSE_FUNCTION = 'dot.path.to.custom.views.login_failed' + CUSTOM_FAILED_RESPONSE_VIEW = 'dot.path.to.custom.views.login_failed' In your project's ``urls.py`` add these paths: diff --git a/docs/settings_ref.rst b/docs/settings_ref.rst index ef4c7e0..ea516af 100644 --- a/docs/settings_ref.rst +++ b/docs/settings_ref.rst @@ -180,9 +180,9 @@ Allows you to set a leeway of the JWT token. See the official `PyJWT `__ docs for more information. -FAILED_RESPONSE_FUNCTION +CUSTOM_FAILED_RESPONSE_VIEW -------------------------------- -* **Default**: ``None`` +* **Default**: ``lambda`` * **Type**: ``str`` or ``callable`` Allows you to set a custom django function view to handle login failures. Can be a dot path to your diff --git a/tests/test_settings.py b/tests/test_settings.py index f6642c1..96726c9 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -45,14 +45,14 @@ def test_default_failed_response_setting(self): settings = deepcopy(django_settings) with patch("django_auth_adfs.config.django_settings", settings): s = Settings() - self.assertTrue(callable(s.FAILED_RESPONSE_FUNCTION)) + self.assertTrue(callable(s.CUSTOM_FAILED_RESPONSE_VIEW)) def test_dotted_path_failed_response_setting(self): settings = deepcopy(django_settings) - settings.AUTH_ADFS["FAILED_RESPONSE_FUNCTION"] = 'tests.views.test_failed_response' + settings.AUTH_ADFS["CUSTOM_FAILED_RESPONSE_VIEW"] = 'tests.views.test_failed_response' with patch("django_auth_adfs.config.django_settings", settings): s = Settings() - self.assertTrue(callable(s.FAILED_RESPONSE_FUNCTION)) + self.assertTrue(callable(s.CUSTOM_FAILED_RESPONSE_VIEW)) class CustomSettingsTests(SimpleTestCase): From ed01c29982630e151a4f619b8d3c22f4eb4e84af Mon Sep 17 00:00:00 2001 From: "Peter J. Farrell" Date: Mon, 25 Jan 2021 11:18:49 -0600 Subject: [PATCH 14/15] Update CHANGELOG.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jonas Krüger Svensson --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0bb8274..fca2ceb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,7 +7,7 @@ Changelog **Features** * New parameter called `CUSTOM_FAILED_RESPONSE_VIEW`, allowing you to set a custom django function view to handle login - failures. #? + failures. #136 `1.5.0`_ - 2021-01-18 From 70e47fe2cfdbdc7696f079c9b3c7a942076cef28 Mon Sep 17 00:00:00 2001 From: pf69348 Date: Mon, 25 Jan 2021 12:48:46 -0600 Subject: [PATCH 15/15] Bump version to 1.6.0 --- CHANGELOG.rst | 4 ++-- django_auth_adfs/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fca2ceb..4f075fe 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Changelog ========= -`1.5.1`_ - 2021-01-25 +`1.6.0`_ - 2021-01-25 --------------------- **Features** @@ -227,7 +227,7 @@ Changelog * Initial release -.. _1.5.1: https://github.com/snok/django-auth-adfs/compare/1.5.0...1.5.1 +.. _1.6.0: https://github.com/snok/django-auth-adfs/compare/1.5.0...1.6.0 .. _1.5.0: https://github.com/jobec/django-auth-adfs/compare/1.4.1...1.5.0 .. _1.4.1: https://github.com/jobec/django-auth-adfs/compare/1.4.0...1.4.1 .. _1.4.0: https://github.com/jobec/django-auth-adfs/compare/1.3.1...1.4.0 diff --git a/django_auth_adfs/__init__.py b/django_auth_adfs/__init__.py index 3c8cc20..c761055 100644 --- a/django_auth_adfs/__init__.py +++ b/django_auth_adfs/__init__.py @@ -4,4 +4,4 @@ Adding imports here will break setup.py """ -__version__ = '1.5.0' +__version__ = '1.6.0' diff --git a/pyproject.toml b/pyproject.toml index de53578..19ca328 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = 'django-auth-adfs' -version = '1.5.0' # Remember to also change __init__.py version +version = '1.6.0' # Remember to also change __init__.py version description = 'A Django authentication backend for Microsoft ADFS and AzureAD' authors = ['Joris Beckers '] maintainers = ['Jonas Krüger Svensson ', 'Sondre Lillebø Gundersen ']