diff --git a/axes/handlers/cache.py b/axes/handlers/cache.py index 97b36f2..f5de9b6 100644 --- a/axes/handlers/cache.py +++ b/axes/handlers/cache.py @@ -6,7 +6,7 @@ from axes.handlers.base import AxesBaseHandler, AbstractAxesHandler from axes.helpers import ( get_cache, get_cache_timeout, - get_client_cache_key, + get_client_cache_keys, get_client_str, get_client_username, get_credentials, @@ -110,7 +110,18 @@ class AxesCacheHandler(AbstractAxesHandler, AxesBaseHandler): log.info("AXES: Login failed from whitelisted client %s.", client_str) return - failures_since_start = 1 + self.get_failures(request, credentials) + cache_keys = get_client_cache_keys(request, credentials) + cache_timeout = get_cache_timeout() + failures = [] + for cache_key in cache_keys: + added = self.cache.add(key=cache_key, value=1, timeout=cache_timeout) + if added: + failures.append(1) + else: + failures.append(self.cache.incr(key=cache_key, delta=1)) + self.cache.touch(key=cache_key, timeout=cache_timeout) + + failures_since_start = max(failures) request.axes_failures_since_start = failures_since_start if failures_since_start > 1: @@ -126,11 +137,6 @@ class AxesCacheHandler(AbstractAxesHandler, AxesBaseHandler): client_str, ) - cache_keys = get_client_cache_keys(request, credentials) - for cache_key in cache_keys: - failures = self.cache.get(cache_key, default=0) - self.cache.set(cache_key, failures + 1, get_cache_timeout()) - if ( settings.AXES_LOCK_OUT_AT_FAILURE and failures_since_start >= get_failure_limit(request, credentials) diff --git a/tests/test_handlers.py b/tests/test_handlers.py index 5ae36b0..d32af60 100644 --- a/tests/test_handlers.py +++ b/tests/test_handlers.py @@ -496,12 +496,12 @@ class AxesCacheHandlerTestCase(AxesHandlerBaseTestCase): "AXES: Username is None and AXES_ONLY_USER_FAILURES is enabled, new record will NOT be created." ) - @patch.object(cache, "set") - def test_user_login_failed_with_none_username(self, cache_set): + @patch.object(cache, "add") + def test_user_login_failed_with_none_username(self, cache_add): credentials = {"username": None, "password": "test"} sender = MagicMock() AxesProxyHandler.user_login_failed(sender, credentials, self.request) - self.assertTrue(cache_set.called) + self.assertTrue(cache_add.called) @override_settings(AXES_HANDLER="axes.handlers.dummy.AxesDummyHandler")