checks.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. from django.core.checks import ( # pylint: disable=redefined-builtin
  2. Tags,
  3. Warning,
  4. register,
  5. )
  6. from django.utils.module_loading import import_string
  7. from axes.backends import AxesBackend
  8. from axes.conf import settings
  9. class Messages:
  10. CACHE_INVALID = (
  11. "You are using the django-axes cache handler for login attempt tracking."
  12. " Your cache configuration is however invalid and will not work correctly with django-axes."
  13. " This can leave security holes in your login systems as attempts are not tracked correctly."
  14. " Reconfigure settings.AXES_CACHE and settings.CACHES per django-axes configuration documentation."
  15. )
  16. MIDDLEWARE_INVALID = (
  17. "You do not have 'axes.middleware.AxesMiddleware' in your settings.MIDDLEWARE."
  18. )
  19. BACKEND_INVALID = "You do not have 'axes.backends.AxesBackend' or a subclass in your settings.AUTHENTICATION_BACKENDS."
  20. SETTING_DEPRECATED = "You have a deprecated setting {deprecated_setting} configured in your project settings"
  21. class Hints:
  22. CACHE_INVALID = None
  23. MIDDLEWARE_INVALID = None
  24. BACKEND_INVALID = (
  25. "AxesModelBackend was renamed to AxesBackend in django-axes version 5.0."
  26. )
  27. SETTING_DEPRECATED = None
  28. class Codes:
  29. CACHE_INVALID = "axes.W001"
  30. MIDDLEWARE_INVALID = "axes.W002"
  31. BACKEND_INVALID = "axes.W003"
  32. SETTING_DEPRECATED = "axes.W004"
  33. @register(Tags.security, Tags.caches, Tags.compatibility)
  34. def axes_cache_check(app_configs, **kwargs): # pylint: disable=unused-argument
  35. axes_handler = getattr(settings, "AXES_HANDLER", "")
  36. axes_cache_key = getattr(settings, "AXES_CACHE", "default")
  37. axes_cache_config = settings.CACHES.get(axes_cache_key, {})
  38. axes_cache_backend = axes_cache_config.get("BACKEND", "")
  39. axes_cache_backend_incompatible = [
  40. "django.core.cache.backends.dummy.DummyCache",
  41. "django.core.cache.backends.locmem.LocMemCache",
  42. "django.core.cache.backends.filebased.FileBasedCache",
  43. ]
  44. warnings = []
  45. if axes_handler == "axes.handlers.cache.AxesCacheHandler":
  46. if axes_cache_backend in axes_cache_backend_incompatible:
  47. warnings.append(
  48. Warning(
  49. msg=Messages.CACHE_INVALID,
  50. hint=Hints.CACHE_INVALID,
  51. id=Codes.CACHE_INVALID,
  52. )
  53. )
  54. return warnings
  55. @register(Tags.security, Tags.compatibility)
  56. def axes_middleware_check(app_configs, **kwargs): # pylint: disable=unused-argument
  57. warnings = []
  58. if "axes.middleware.AxesMiddleware" not in settings.MIDDLEWARE:
  59. warnings.append(
  60. Warning(
  61. msg=Messages.MIDDLEWARE_INVALID,
  62. hint=Hints.MIDDLEWARE_INVALID,
  63. id=Codes.MIDDLEWARE_INVALID,
  64. )
  65. )
  66. return warnings
  67. @register(Tags.security, Tags.compatibility)
  68. def axes_backend_check(app_configs, **kwargs): # pylint: disable=unused-argument
  69. warnings = []
  70. found = False
  71. for name in settings.AUTHENTICATION_BACKENDS:
  72. try:
  73. backend = import_string(name)
  74. except ModuleNotFoundError as e:
  75. raise ModuleNotFoundError(
  76. "Can not find module path defined in settings.AUTHENTICATION_BACKENDS"
  77. ) from e
  78. except ImportError as e:
  79. raise ImportError(
  80. "Can not import backend class defined in settings.AUTHENTICATION_BACKENDS"
  81. ) from e
  82. if issubclass(backend, AxesBackend):
  83. found = True
  84. break
  85. if not found:
  86. warnings.append(
  87. Warning(
  88. msg=Messages.BACKEND_INVALID,
  89. hint=Hints.BACKEND_INVALID,
  90. id=Codes.BACKEND_INVALID,
  91. )
  92. )
  93. return warnings
  94. @register(Tags.compatibility)
  95. def axes_deprecation_check(app_configs, **kwargs): # pylint: disable=unused-argument
  96. warnings = []
  97. deprecated_settings = [
  98. "AXES_DISABLE_SUCCESS_ACCESS_LOG",
  99. "AXES_LOGGER",
  100. ]
  101. for deprecated_setting in deprecated_settings:
  102. try:
  103. getattr(settings, deprecated_setting)
  104. warnings.append(
  105. Warning(
  106. msg=Messages.SETTING_DEPRECATED.format(
  107. deprecated_setting=deprecated_setting
  108. ),
  109. hint=None,
  110. id=Codes.SETTING_DEPRECATED,
  111. )
  112. )
  113. except AttributeError:
  114. pass
  115. return warnings