From 676456a98c73000d859d6aec2a38379eee82a0e1 Mon Sep 17 00:00:00 2001
From: Brandon Rodriguez <brodriguez8774@gmail.com>
Date: Tue, 28 Jan 2025 23:05:50 -0500
Subject: [PATCH] Add additional whitelist logic, to hopefully account for
 things like DjangoDebugBar

---
 adminlte2_pdq/constants/__init__.py           |   2 +
 .../constants/route_and_policy_constants.py   |  19 +
 adminlte2_pdq/middleware.py                   |  14 +-
 .../testing/test_urls_2.py                    |  21 +
 tests/django_adminlte2_pdq/testing/urls.py    |   1 +
 .../tests/test_app_wide_whitelists.py         | 437 ++++++++++++++++++
 6 files changed, 492 insertions(+), 2 deletions(-)
 create mode 100644 tests/django_adminlte2_pdq/testing/test_urls_2.py
 create mode 100644 tests/django_adminlte2_pdq/tests/test_app_wide_whitelists.py

diff --git a/adminlte2_pdq/constants/__init__.py b/adminlte2_pdq/constants/__init__.py
index c1213b9..ccc62a3 100644
--- a/adminlte2_pdq/constants/__init__.py
+++ b/adminlte2_pdq/constants/__init__.py
@@ -46,6 +46,8 @@ from .route_and_policy_constants import (
 from .route_and_policy_constants import (
     LOGIN_EXEMPT_WHITELIST,
     STRICT_POLICY_WHITELIST,
+    APP_WIDE_LOGIN_EXEMPT_WHITELIST,
+    APP_WIDE_STRICT_POLICY_WHITELIST,
     LOGIN_REQUIRED,
     STRICT_POLICY,
 )
diff --git a/adminlte2_pdq/constants/route_and_policy_constants.py b/adminlte2_pdq/constants/route_and_policy_constants.py
index e12789e..c04d86c 100644
--- a/adminlte2_pdq/constants/route_and_policy_constants.py
+++ b/adminlte2_pdq/constants/route_and_policy_constants.py
@@ -48,6 +48,25 @@ LOGIN_EXEMPT_WHITELIST += getattr(settings, "ADMINLTE2_LOGIN_EXEMPT_WHITELIST",
 STRICT_POLICY_WHITELIST += getattr(settings, "ADMINLTE2_STRICT_POLICY_WHITELIST", [])
 
 
+# App-wide whitelists.
+# These take a url base, and whitelist any urls that stem from said base.
+# For example, this is required to make the Django Debug Toolbar function.
+APP_WIDE_LOGIN_EXEMPT_WHITELIST = tuple(
+    getattr(
+        settings,
+        "ADMINLTE2_APP_WIDE_LOGIN_EXEMPT_WHITELIST",
+        [],
+    )
+)
+APP_WIDE_STRICT_POLICY_WHITELIST = tuple(
+    getattr(
+        settings,
+        "ADMINLTE2_APP_WIDE_STRICT_POLICY_WHITELIST",
+        [],
+    )
+)
+
+
 # Get whether or not we are using LoginRequired and PermissionRequired.
 # NOTE: By nature of what STRICT_POLICY is, it implicitly means login is required.
 STRICT_POLICY = getattr(settings, "ADMINLTE2_USE_STRICT_POLICY", False)
diff --git a/adminlte2_pdq/middleware.py b/adminlte2_pdq/middleware.py
index fbea0a5..8485858 100644
--- a/adminlte2_pdq/middleware.py
+++ b/adminlte2_pdq/middleware.py
@@ -17,12 +17,14 @@ from django.views.generic.base import RedirectView
 from .constants import (
     LOGIN_REQUIRED,
     LOGIN_EXEMPT_WHITELIST,
+    APP_WIDE_LOGIN_EXEMPT_WHITELIST,
     RESPONSE_403_DEBUG_MESSAGE,
     RESPONSE_403_PRODUCTION_MESSAGE,
     RESPONSE_404_DEBUG_MESSAGE,
     RESPONSE_404_PRODUCTION_MESSAGE,
     STRICT_POLICY,
     STRICT_POLICY_WHITELIST,
+    APP_WIDE_STRICT_POLICY_WHITELIST,
     LOGIN_URL,
     HOME_ROUTE,
     MEDIA_ROUTE,
@@ -681,9 +683,13 @@ class AuthMiddleware:
 
     def is_login_whitelisted(self, view_data):
         """Determines if view is login-whitelisted. Used for login_required mode or strict mode."""
+
         try:
             return bool(
-                view_data["current_url_name"] in LOGIN_EXEMPT_WHITELIST
+                # In "app-wide" exemption list.
+                view_data["path"].startswith(APP_WIDE_LOGIN_EXEMPT_WHITELIST)
+                # In "standard" exemption list.
+                or view_data["current_url_name"] in LOGIN_EXEMPT_WHITELIST
                 or view_data["fully_qualified_url_name"] in LOGIN_EXEMPT_WHITELIST
             )
         except KeyError:
@@ -691,9 +697,13 @@ class AuthMiddleware:
 
     def is_permission_whitelisted(self, view_data):
         """Determines if view is permission-whitelisted. Used for strict mode."""
+
         try:
             return bool(
-                view_data["current_url_name"] in STRICT_POLICY_WHITELIST
+                # In "app-wide" exemption list.
+                view_data["path"].startswith(APP_WIDE_STRICT_POLICY_WHITELIST)
+                # In "standard" exemption list.
+                or view_data["current_url_name"] in STRICT_POLICY_WHITELIST
                 or view_data["fully_qualified_url_name"] in STRICT_POLICY_WHITELIST
             )
         except KeyError:
diff --git a/tests/django_adminlte2_pdq/testing/test_urls_2.py b/tests/django_adminlte2_pdq/testing/test_urls_2.py
new file mode 100644
index 0000000..023eed7
--- /dev/null
+++ b/tests/django_adminlte2_pdq/testing/test_urls_2.py
@@ -0,0 +1,21 @@
+"""
+Project testing views.
+These urls exist to reliably test the two settings:
+ * ADMINLTE2_APP_WIDE_LOGIN_EXEMPT_WHITELIST
+ * ADMINLTE2_APP_WIDE_STRICT_POLICY_WHITELIST
+without having potential side-effects on other existing tests.
+"""
+
+# Third-Party Imports.
+from django.urls import include, path
+
+# Internal Imports.
+from . import views
+
+
+app_name = "adminlte2_pdq_tests_2"
+urlpatterns = [
+    path("standard-1/", views.standard_view, name="standard-1"),
+    path("standard-2/", views.standard_view, name="standard-2"),
+    path("standard-3/", views.standard_view, name="standard-3"),
+]
diff --git a/tests/django_adminlte2_pdq/testing/urls.py b/tests/django_adminlte2_pdq/testing/urls.py
index a74a2b3..f3e3893 100644
--- a/tests/django_adminlte2_pdq/testing/urls.py
+++ b/tests/django_adminlte2_pdq/testing/urls.py
@@ -27,6 +27,7 @@ urlpatterns = [
     path("admin/", admin.site.urls),
     # Testing views.
     path("tests/", include("tests.django_adminlte2_pdq.testing.test_urls")),
+    path("tests-2/", include("tests.django_adminlte2_pdq.testing.test_urls_2")),
     # Adminlte2 views.
     path("accounts/", include("django.contrib.auth.urls")),
     path("", include("adminlte2_pdq.urls")),
diff --git a/tests/django_adminlte2_pdq/tests/test_app_wide_whitelists.py b/tests/django_adminlte2_pdq/tests/test_app_wide_whitelists.py
new file mode 100644
index 0000000..b10e5ed
--- /dev/null
+++ b/tests/django_adminlte2_pdq/tests/test_app_wide_whitelists.py
@@ -0,0 +1,437 @@
+"""
+Tests for the "app-wide" whitelist settings. Aka:
+ * ADMINLTE2_APP_WIDE_LOGIN_EXEMPT_WHITELIST
+ * ADMINLTE2_APP_WIDE_STRICT_POLICY_WHITELIST
+"""
+
+# System Imports.
+from unittest.mock import patch
+from pytest import warns
+
+# Third-Party Imports.
+from django.contrib.auth import get_user_model
+from django.contrib.auth.models import AnonymousUser
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+from django.test import override_settings
+from django_expanded_test_cases import IntegrationTestCase
+
+
+# Module Variables.
+UserModel = get_user_model()
+
+
+@override_settings(ADMINLTE2_USE_LOGIN_REQUIRED=True)
+@override_settings(LOGIN_REQUIRED=True)
+@patch("adminlte2_pdq.constants.LOGIN_REQUIRED", True)
+@patch("adminlte2_pdq.middleware.LOGIN_REQUIRED", True)
+class Test_LoginRequiredMode_AppWideWhitelistSettings(IntegrationTestCase):
+    """Test for project "app-wide" whitelist settings.
+
+    For these tests, we only use the Anonymous user and the default user, without any modifications.
+    All the work should be done by the whitelists.
+    """
+
+    APP_WIDE_LOGIN_WHITELIST_VIEWS = ("/tests-2/",)
+    APP_WIDE_PERM_WHITELIST_VIEWS = ("/tests-2/",)
+
+    def test__ensure_views_cannot_be_accessed_without_settings(self):
+        """Sanity check tests, to ensure these specific views cannot be accessed by default."""
+
+        # Should fail and redirect to login for anyone unauthenticated.
+        with self.subTest("As Anonymous User"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=AnonymousUser(),
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=True,
+                # Expected content on page.
+                expected_title="Login |",
+                expected_content=[
+                    "Sign in to start your session",
+                    "Remember Me",
+                    "I forgot my password",
+                ],
+            )
+
+        # Should succeed and load as expected.
+        with self.subTest("As default standard user"):
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=self.test_user,
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
+
+    @override_settings(ADMINLTE2_APP_WIDE_LOGIN_EXEMPT_WHITELIST=APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @override_settings(APP_WIDE_LOGIN_EXEMPT_WHITELIST=APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.constants.APP_WIDE_LOGIN_EXEMPT_WHITELIST", APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.middleware.APP_WIDE_LOGIN_EXEMPT_WHITELIST", APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    def test__verify_login_whitelist(self):
+        """Tests to verify handling of "app-wide" login whitelist."""
+
+        # Should succeed and load as expected.
+        with self.subTest("As Anonymous User"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=AnonymousUser(),
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
+
+        # Should succeed and load as expected.
+        with self.subTest("As default standard user"):
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=self.test_user,
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
+
+    @override_settings(ADMINLTE2_APP_WIDE_STRICT_POLICY_WHITELIST=APP_WIDE_PERM_WHITELIST_VIEWS)
+    @override_settings(APP_WIDE_STRICT_POLICY_WHITELIST=APP_WIDE_PERM_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.constants.APP_WIDE_STRICT_POLICY_WHITELIST", APP_WIDE_PERM_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.middleware.APP_WIDE_STRICT_POLICY_WHITELIST", APP_WIDE_PERM_WHITELIST_VIEWS)
+    def test__verify_perm_whitelist(self):
+        """Tests to verify handling of "app-wide" perm whitelist.
+        In this case, should handle identical to no settings provided.
+        """
+
+        # Should fail and redirect to login for anyone unauthenticated.
+        with self.subTest("As Anonymous User"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=AnonymousUser(),
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=True,
+                # Expected content on page.
+                expected_title="Login |",
+                expected_content=[
+                    "Sign in to start your session",
+                    "Remember Me",
+                    "I forgot my password",
+                ],
+            )
+
+        # Should succeed and load as expected.
+        with self.subTest("As default standard user"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=self.test_user,
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
+
+    @override_settings(ADMINLTE2_APP_WIDE_LOGIN_EXEMPT_WHITELIST=APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @override_settings(LOGIN_APP_WIDE_EXEMPT_WHITELIST=APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @override_settings(ADMINLTE2_APP_WIDE_STRICT_POLICY_WHITELIST=APP_WIDE_PERM_WHITELIST_VIEWS)
+    @override_settings(APP_WIDE_STRICT_POLICY_WHITELIST=APP_WIDE_PERM_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.constants.APP_WIDE_LOGIN_EXEMPT_WHITELIST", APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.middleware.APP_WIDE_LOGIN_EXEMPT_WHITELIST", APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.constants.APP_WIDE_STRICT_POLICY_WHITELIST", APP_WIDE_PERM_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.middleware.APP_WIDE_STRICT_POLICY_WHITELIST", APP_WIDE_PERM_WHITELIST_VIEWS)
+    def test__verify_both_whitelists(self):
+        """Tests to verify handling of combined "app-wide" login and permission whitelists."""
+
+        # Should succeed and load as expected.
+        with self.subTest("As Anonymous User"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=AnonymousUser(),
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
+
+        # Should succeed and load as expected.
+        with self.subTest("As default standard user"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=self.test_user,
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
+
+
+@override_settings(ADMINLTE2_USE_LOGIN_REQUIRED=True)
+@override_settings(LOGIN_REQUIRED=True)
+@override_settings(ADMINLTE2_USE_STRICT_POLICY=True)
+@override_settings(STRICT_POLICY=True)
+@patch("adminlte2_pdq.constants.LOGIN_REQUIRED", True)
+@patch("adminlte2_pdq.middleware.LOGIN_REQUIRED", True)
+@patch("adminlte2_pdq.constants.STRICT_POLICY", True)
+@patch("adminlte2_pdq.middleware.STRICT_POLICY", True)
+class Test_StrictMode_AppWideWhitelistSettings(IntegrationTestCase):
+    """Test for project "app-wide" whitelist settings.
+
+    For these tests, we only use the Anonymous user and the default user, without any modifications.
+    All the work should be done by the whitelists.
+    """
+
+    APP_WIDE_LOGIN_WHITELIST_VIEWS = ("/tests-2/",)
+    APP_WIDE_PERM_WHITELIST_VIEWS = ("/tests-2/",)
+
+    def test__ensure_views_cannot_be_accessed_without_settings(self):
+        """Sanity check tests, to ensure these specific views cannot be accessed by default."""
+
+        # Should fail and redirect to login for anyone unauthenticated.
+        with self.subTest("As Anonymous User"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=AnonymousUser(),
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=True,
+                # Expected content on page.
+                expected_title="Login |",
+                expected_content=[
+                    "Sign in to start your session",
+                    "Remember Me",
+                    "I forgot my password",
+                ],
+            )
+
+        # Should fail and redirect to home.
+        with self.subTest("As default standard user"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=self.test_user,
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=True,
+                # Expected content on page.
+                expected_title="Dashboard",
+                expected_header="Dashboard <small>Version 2.0</small>",
+                expected_content=[
+                    "Monthly Recap Report",
+                    "Visitors Report",
+                    "Inventory",
+                    "Downloads",
+                ],
+            )
+
+    @override_settings(ADMINLTE2_APP_WIDE_LOGIN_EXEMPT_WHITELIST=APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @override_settings(APP_WIDE_LOGIN_EXEMPT_WHITELIST=APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.constants.APP_WIDE_LOGIN_EXEMPT_WHITELIST", APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.middleware.APP_WIDE_LOGIN_EXEMPT_WHITELIST", APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    def test__verify_login_whitelist(self):
+        """Tests to verify handling of "app-wide" login whitelist."""
+
+        # Should fail and redirect to home.
+        with self.subTest("As Anonymous User"):
+            with warns(Warning) as warning_info:
+
+                # Should fail and redirect to home. But then home requires login so it still redirects to login.
+                self.assertGetResponse(
+                    # View setup.
+                    "adminlte2_pdq_tests_2:standard-1",
+                    user=AnonymousUser(),
+                    # Expected view return data.
+                    expected_status=200,
+                    view_should_redirect=True,
+                    # Expected content on page.
+                    expected_title="Login |",
+                    expected_content=[
+                        "Sign in to start your session",
+                        "Remember Me",
+                        "I forgot my password",
+                    ],
+                )
+
+        # Should fail and redirect to home.
+        with self.subTest("As default standard user"):
+            with warns(Warning) as warning_info:
+
+                # Verify we get the expected page.
+                self.assertGetResponse(
+                    # View setup.
+                    "adminlte2_pdq_tests_2:standard-1",
+                    user=self.test_user,
+                    # Expected view return data.
+                    expected_status=200,
+                    view_should_redirect=True,
+                    # Expected content on page.
+                    expected_title="Dashboard",
+                    expected_header="Dashboard <small>Version 2.0</small>",
+                    expected_content=[
+                        "Monthly Recap Report",
+                        "Visitors Report",
+                        "Inventory",
+                        "Downloads",
+                    ],
+                )
+
+    @override_settings(ADMINLTE2_APP_WIDE_STRICT_POLICY_WHITELIST=APP_WIDE_PERM_WHITELIST_VIEWS)
+    @override_settings(APP_WIDE_STRICT_POLICY_WHITELIST=APP_WIDE_PERM_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.constants.APP_WIDE_STRICT_POLICY_WHITELIST", APP_WIDE_PERM_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.middleware.APP_WIDE_STRICT_POLICY_WHITELIST", APP_WIDE_PERM_WHITELIST_VIEWS)
+    def test__verify_perm_whitelist(self):
+        """Tests to verify handling of "app-wide" perm whitelist."""
+
+        # Should fail and redirect to login for anyone unauthenticated.
+        with self.subTest("As Anonymous User"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=AnonymousUser(),
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=True,
+                # Expected content on page.
+                expected_title="Login |",
+                expected_content=[
+                    "Sign in to start your session",
+                    "Remember Me",
+                    "I forgot my password",
+                ],
+            )
+
+        # Should succeed and load as expected.
+        with self.subTest("As default standard user"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=self.test_user,
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
+
+    @override_settings(ADMINLTE2_APP_WIDE_LOGIN_EXEMPT_WHITELIST=APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @override_settings(LOGIN_APP_WIDE_EXEMPT_WHITELIST=APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @override_settings(ADMINLTE2_APP_WIDE_STRICT_POLICY_WHITELIST=APP_WIDE_PERM_WHITELIST_VIEWS)
+    @override_settings(APP_WIDE_STRICT_POLICY_WHITELIST=APP_WIDE_PERM_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.constants.APP_WIDE_LOGIN_EXEMPT_WHITELIST", APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.middleware.APP_WIDE_LOGIN_EXEMPT_WHITELIST", APP_WIDE_LOGIN_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.constants.APP_WIDE_STRICT_POLICY_WHITELIST", APP_WIDE_PERM_WHITELIST_VIEWS)
+    @patch("adminlte2_pdq.middleware.APP_WIDE_STRICT_POLICY_WHITELIST", APP_WIDE_PERM_WHITELIST_VIEWS)
+    def test__verify_both_whitelists(self):
+        """Tests to verify handling of combined "app-wide" login and permission whitelists."""
+
+        # Should succeed and load as expected.
+        with self.subTest("As Anonymous User"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=AnonymousUser(),
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
+
+        # Should succeed and load as expected.
+        with self.subTest("As default standard user"):
+
+            # Verify we get the expected page.
+            self.assertGetResponse(
+                # View setup.
+                "adminlte2_pdq_tests_2:standard-1",
+                user=self.test_user,
+                # Expected view return data.
+                expected_status=200,
+                view_should_redirect=False,
+                # Expected content on page.
+                expected_title="Standard View | Django AdminLtePdq Testing",
+                expected_header="Django AdminLtePdq | Standard View Header",
+                expected_content=[
+                    "Django AdminLtePdq | Standard View Subheader",
+                    "Django AdminLtePdq | Standard View Content",
+                ],
+            )
-- 
GitLab