From 9c328713e7574882c9726e40b48b411170aad6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksi=20Ha=CC=88kli?= Date: Fri, 1 Feb 2019 17:51:05 +0200 Subject: [PATCH] Use Django checks for cache configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #383 Signed-off-by: Aleksi Häkli --- axes/apps.py | 10 ------- axes/checks.py | 56 +++++++++++++++++++++++++++++++++++++++ axes/tests/test_checks.py | 42 +++++++++++++++++++++++++++++ docs/configuration.rst | 12 +++++++++ 4 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 axes/checks.py create mode 100644 axes/tests/test_checks.py diff --git a/axes/apps.py b/axes/apps.py index f4b641b..8896d07 100644 --- a/axes/apps.py +++ b/axes/apps.py @@ -7,16 +7,6 @@ class AppConfig(apps.AppConfig): name = 'axes' def ready(self): - from django.conf import settings - from django.core.exceptions import ImproperlyConfigured - - if settings.CACHES[getattr(settings, 'AXES_CACHE', 'default')]['BACKEND'] == \ - 'django.core.cache.backends.locmem.LocMemCache': - raise ImproperlyConfigured( - 'django-axes does not work properly with LocMemCache as the default cache backend' - ' please add e.g. a DummyCache backend for axes and configure it with AXES_CACHE' - ) - from django.contrib.auth.views import LoginView from django.utils.decorators import method_decorator diff --git a/axes/checks.py b/axes/checks.py new file mode 100644 index 0000000..1215256 --- /dev/null +++ b/axes/checks.py @@ -0,0 +1,56 @@ +from __future__ import unicode_literals + +from django.core.checks import Error, Tags, register + +from django.conf import settings + + +class Messages: + CACHE_MISSING = 'missing cache configuration for AXES_CACHE' + CACHE_INVALID = 'invalid cache configuration for settings.AXES_CACHE' + + +class Hints: + CACHE_MISSING = ( + 'django-axes needs to have a cache configured with settings.AXES_CACHE' + ) + CACHE_INVALID = ( + 'django-axes does not work properly with LocMemCache as the cache backend' + ' please add e.g. a DummyCache backend and configure it with settings.AXES_CACHE' + ) + + +class Codes: + CACHE_MISSING = 'axes.E001' + CACHE_INVALID = 'axes.E002' + + +@register(Tags.caches) +def axes_cache_backend_check(app_configs, **kwargs): # pylint: disable=unused-argument + errors = [] + + axes_cache_key = getattr(settings, 'AXES_CACHE', 'default') + axes_cache_config = settings.CACHES.get(axes_cache_key, {}) + axes_cache_backend = axes_cache_config.get('BACKEND', '') + + axes_cache_incompatible_backends = [ + 'django.core.cache.backends.locmem.LocMemCache', + ] + + if not axes_cache_config: + errors.append(Error( + msg=Messages.CACHE_MISSING, + hint=Hints.CACHE_MISSING, + obj=settings.CACHES, + id=Codes.CACHE_MISSING, + )) + + if axes_cache_backend in axes_cache_incompatible_backends: + errors.append(Error( + msg=Messages.CACHE_INVALID, + hint=Hints.CACHE_INVALID, + obj=settings.CACHES, + id=Codes.CACHE_INVALID, + )) + + return errors diff --git a/axes/tests/test_checks.py b/axes/tests/test_checks.py new file mode 100644 index 0000000..24a9503 --- /dev/null +++ b/axes/tests/test_checks.py @@ -0,0 +1,42 @@ +from __future__ import unicode_literals + +from django.core.checks import run_checks, Error +from django.conf import settings +from django.test import TestCase, override_settings + +from axes.checks import Messages, Hints, Codes + + +class CacheCheckTestCase(TestCase): + @override_settings( + AXES_CACHE='nonexistent', + ) + def test_cache_missing_produces_check_error(self): + errors = run_checks() + error = Error( + msg=Messages.CACHE_MISSING, + hint=Hints.CACHE_MISSING, + obj=settings.CACHES, + id=Codes.CACHE_MISSING, + ) + + self.assertIn(error, errors) + + @override_settings( + AXES_CACHE='axes', + CACHES={ + 'axes': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + }, + }, + ) + def test_cache_misconfiguration_produces_check_error(self): + errors = run_checks() + error = Error( + msg=Messages.CACHE_INVALID, + hint=Hints.CACHE_INVALID, + obj=settings.CACHES, + id=Codes.CACHE_INVALID, + ) + + self.assertIn(error, errors) diff --git a/docs/configuration.rst b/docs/configuration.rst index 8404142..b36d024 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -27,6 +27,18 @@ Add ``axes.backends.AxesModelBackend`` to the top of ``AUTHENTICATION_BACKENDS`` Run ``python manage.py migrate`` to sync the database. +Running checks +-------------- + +Use the ``python manage.py check`` command to verify the correct configuration in both +development and production environments. It is probably best to use this step as part +of your regular CI workflows to verify that your project is not misconfigured. + +django-axes uses the checks to verify your cache configuration to see that your caches +should be functional with the configuration axes. Many people have different configurations +for their development and production environments. + + Known configuration problems ----------------------------