Repository: jazzband/django-axes

Issue:
Middleware still runs with AXES_ENABLED turned off
I'm integrating django-axes into a project where I'd like to disable it in the tests, except where I specifically turn it on.

Unfortunately, if I follow the instructions in the docs, and set `AXES_ENABLED=False` in my test settings, the logic for the middleware still runs during my tests that hit endpoints, many of which don't expect any database access, so they break.

I can conditionally include the middleware based on whether `AXES_ENABLED` is set, but it gets pretty ugly (and I also need to silence the relevant system check, to avoid a spurious warning when I've not included the middleware).

Apologies if I've misunderstood the documentation, but looking at the middleware code, it appears that it doesn't use `toggleable` nor does it check the enabled flag directly.

I'll put up a PR that I think should help.


Discussion:

Resolving patch:
diff --git a/axes/middleware.py b/axes/middleware.py
--- a/axes/middleware.py
+++ b/axes/middleware.py
@@ -42,19 +42,22 @@ def __init__(self, get_response: Callable):
     def __call__(self, request):
         response = self.get_response(request)
 
-        if "rest_framework" in settings.INSTALLED_APPS:
-            AxesProxyHandler.update_request(request)
-            username = get_client_username(request)
-            credentials = get_credentials(username)
-            failures_since_start = AxesProxyHandler.get_failures(request, credentials)
-            if (
-                settings.AXES_LOCK_OUT_AT_FAILURE
-                and failures_since_start >= get_failure_limit(request, credentials)
-            ):
-
-                request.axes_locked_out = True
-
-        if getattr(request, "axes_locked_out", None):
-            response = get_lockout_response(request)  # type: ignore
+        if settings.AXES_ENABLED:
+            if "rest_framework" in settings.INSTALLED_APPS:
+                AxesProxyHandler.update_request(request)
+                username = get_client_username(request)
+                credentials = get_credentials(username)
+                failures_since_start = AxesProxyHandler.get_failures(
+                    request, credentials
+                )
+                if (
+                    settings.AXES_LOCK_OUT_AT_FAILURE
+                    and failures_since_start >= get_failure_limit(request, credentials)
+                ):
+
+                    request.axes_locked_out = True
+
+            if getattr(request, "axes_locked_out", None):
+                response = get_lockout_response(request)  # type: ignore
 
         return response


Test patch:
diff --git a/axes/tests/test_middleware.py b/axes/tests/test_middleware.py
--- a/axes/tests/test_middleware.py
+++ b/axes/tests/test_middleware.py
@@ -31,6 +31,15 @@ def get_response(request):
         response = AxesMiddleware(get_response)(self.request)
         self.assertEqual(response.status_code, self.STATUS_LOCKOUT)
 
+    @override_settings(AXES_ENABLED=False)
+    def test_respects_enabled_switch(self):
+        def get_response(request):
+            request.axes_locked_out = True
+            return HttpResponse()
+
+        response = AxesMiddleware(get_response)(self.request)
+        self.assertEqual(response.status_code, self.STATUS_SUCCESS)
+
     @mock.patch("django.conf.settings.INSTALLED_APPS", ["rest_framework"])
     def test_response_contains_required_attrs_with_drf_integration(self):
         def get_response(request):