Only AxesHandler needs to follow a contract

This commit is contained in:
Jorge Galvis 2020-07-12 21:33:52 -05:00 committed by Aleksi Häkli
parent d6c3663025
commit 9bb04a01b8
3 changed files with 117 additions and 110 deletions

View file

@ -14,7 +14,45 @@ from axes.helpers import (
)
class AxesHandler(ABC): # pylint: disable=unused-argument
class AbstractAxesHandler(ABC):
"""
Contract that all handlers need to follow
"""
@abstractmethod
def user_login_failed(self, sender, credentials: dict, request=None, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_login_failed`` authentication signal.
"""
pass
@abstractmethod
def user_logged_in(self, sender, request, user, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_logged_in`` authentication signal.
"""
pass
@abstractmethod
def user_logged_out(self, sender, request, user, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_logged_out`` authentication signal.
"""
pass
@abstractmethod
def get_failures(self, request, credentials: dict = None) -> int:
"""
Checks the number of failures associated to the given request and credentials.
This is a virtual method that needs an implementation in the handler subclass
if the ``settings.AXES_LOCK_OUT_AT_FAILURE`` flag is set to ``True``.
"""
pass
class AxesHandler(AbstractAxesHandler): # pylint: disable=unused-argument
"""
Handler API definition for implementations that are used by the ``AxesProxyHandler``.
@ -26,19 +64,29 @@ class AxesHandler(ABC): # pylint: disable=unused-argument
.. note:: This is a virtual class and **can not be used without specialization**.
"""
@abstractmethod
def reset_attempts(self, *, ip_address: str = None, username: str = None) -> int:
"""
Resets access attempts that match the given IP address or username.
"""
pass
@abstractmethod
:raises NotImplementedError: if the handler does not support resetting attempts.
"""
raise NotImplementedError(
"Reset for access attempts is not supported on this backend"
)
def reset_logs(self, *, age_days: int = None) -> int:
"""
Resets access logs that are older than given number of days.
:raises NotImplementedError: if the handler does not support resetting logs.
"""
pass
raise NotImplementedError(
"Reset for access logs is not supported on this backend"
)
def is_allowed(self, request, credentials: dict = None) -> bool:
@ -70,40 +118,29 @@ class AxesHandler(ABC): # pylint: disable=unused-argument
return True
@abstractmethod
def user_login_failed(self, sender, credentials: dict, request=None, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_login_failed`` authentication signal.
"""
pass
@abstractmethod
def user_logged_in(self, sender, request, user, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_logged_in`` authentication signal.
"""
pass
@abstractmethod
def user_logged_out(self, sender, request, user, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_logged_out`` authentication signal.
"""
pass
@abstractmethod
def post_save_access_attempt(self, instance, **kwargs):
"""
Handles the ``axes.models.AccessAttempt`` object post save signal.
"""
pass
@abstractmethod
:raises NotImplementedError: if the handler does not support post save signal.
"""
raise NotImplementedError(
"Post save signal callback is not supported on this backend"
)
def post_delete_access_attempt(self, instance, **kwargs):
"""
Handles the ``axes.models.AccessAttempt`` object post delete signal.
:raises NotImplementedError: if the handler does not support post delete signal.
"""
pass
raise NotImplementedError(
"Post delete signal callback is not supported on this backend"
)
def is_blacklisted(
self, request, credentials: dict = None
@ -147,16 +184,6 @@ class AxesHandler(ABC): # pylint: disable=unused-argument
return False
@abstractmethod
def get_failures(self, request, credentials: dict = None) -> int:
"""
Checks the number of failures associated to the given request and credentials.
This is a virtual method that needs an implementation in the handler subclass
if the ``settings.AXES_LOCK_OUT_AT_FAILURE`` flag is set to ``True``.
"""
pass
def is_admin_site(self, request) -> bool:
"""
Checks if the request is for admin site.
@ -169,3 +196,51 @@ class AxesHandler(ABC): # pylint: disable=unused-argument
return not re.match("^%s" % admin_url, request.path)
return False
def user_login_failed(self, sender, credentials: dict, request=None, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_login_failed`` authentication signal.
:raises NotImplementedError: if the handler does not support user_login_failed callback.
"""
raise NotImplementedError(
"user_login_failed callback is not supported on this backend"
)
def user_logged_in(self, sender, request, user, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_logged_in`` authentication signal.
:raises NotImplementedError: if the handler does not support user_logged_in callback.
"""
raise NotImplementedError(
"user_logged_in callback is not supported on this backend"
)
def user_logged_out(self, sender, request, user, **kwargs):
"""
Handles the Django ``django.contrib.auth.signals.user_logged_out`` authentication signal.
:raises NotImplementedError: if the handler does not support user_logged_out callback.
"""
raise NotImplementedError(
"user_logged_out callback is not supported on this backend"
)
def get_failures(self, request, credentials: dict = None) -> int:
"""
Checks the number of failures associated to the given request and credentials.
This is a virtual method that needs an implementation in the handler subclass
if the ``settings.AXES_LOCK_OUT_AT_FAILURE`` flag is set to ``True``.
:raises NotImplementedError: if the handler does not support get_failures implementation.
"""
raise NotImplementedError(
"get_failures method is not supported on this backend"
)

View file

@ -25,27 +25,6 @@ class AxesCacheHandler(AxesHandler): # pylint: disable=too-many-locals
self.cache = get_cache()
self.cache_timeout = get_cache_timeout()
def reset_attempts(self, *, ip_address: str = None, username: str = None) -> int:
"""
Resets access attempts that match the given IP address or username.
:raises NotImplementedError: if the handler does not support resetting attempts.
"""
raise NotImplementedError(
"Reset for access attempts is not supported on this backend"
)
def reset_logs(self, *, age_days: int = None) -> int:
"""
Resets access logs that are older than given number of days.
:raises NotImplementedError: if the handler does not support resetting logs.
"""
raise NotImplementedError(
"Reset for access logs is not supported on this backend"
)
def get_failures(self, request, credentials: dict = None) -> int:
cache_key = get_client_cache_key(request, credentials)
@ -150,27 +129,3 @@ class AxesCacheHandler(AxesHandler): # pylint: disable=too-many-locals
)
log.info("AXES: Successful logout by %s.", client_str)
def post_save_access_attempt(self, instance, **kwargs):
"""
Handles the ``axes.models.AccessAttempt`` object post save signal.
:raises NotImplementedError: if the handler does not support post save signal.
"""
raise NotImplementedError(
"Post save signal callback is not supported on this backend"
)
def post_delete_access_attempt(self, instance, **kwargs):
"""
Handles the ``axes.models.AccessAttempt`` object post delete signal.
:raises NotImplementedError: if the handler does not support post delete signal.
"""
raise NotImplementedError(
"Post delete signal callback is not supported on this backend"
)

View file

@ -235,26 +235,3 @@ class AxesDatabaseHandler(AxesHandler): # pylint: disable=too-many-locals
AccessLog.objects.filter(
username=username, logout_time__isnull=True
).update(logout_time=request.axes_attempt_time)
def post_save_access_attempt(self, instance, **kwargs):
"""
Handles the ``axes.models.AccessAttempt`` object post save signal.
:raises NotImplementedError: if the handler does not support post save signal.
"""
raise NotImplementedError(
"Post save signal callback is not supported on AxesDatabaseHandler"
)
def post_delete_access_attempt(self, instance, **kwargs):
"""
Handles the ``axes.models.AccessAttempt`` object post delete signal.
:raises NotImplementedError: if the handler does not support post delete signal.
"""
raise NotImplementedError(
"Post delete signal callback is not supported on AxesDatabaseHandler"
)