# Path: axes/helpers.py
# def get_lockout_response(request, credentials: dict = None) -> HttpResponse:
#     if settings.AXES_LOCKOUT_CALLABLE:
#         if callable(settings.AXES_LOCKOUT_CALLABLE):
#             return settings.AXES_LOCKOUT_CALLABLE(  # pylint: disable=not-callable
#                 request, credentials
#             )
#         if isinstance(settings.AXES_LOCKOUT_CALLABLE, str):
#             return import_string(settings.AXES_LOCKOUT_CALLABLE)(request, credentials)
#         raise TypeError(
#             "settings.AXES_LOCKOUT_CALLABLE needs to be a string, callable, or None."
#         )
# 
#     status = settings.AXES_HTTP_RESPONSE_CODE
#     context = {
#         "failure_limit": get_failure_limit(request, credentials),
#         "username": get_client_username(request, credentials) or "",
#     }
# 
#     cool_off = get_cool_off()
#     if cool_off:
#         context.update(
#             {
#                 "cooloff_time": get_cool_off_iso8601(
#                     cool_off
#                 ),  # differing old name is kept for backwards compatibility
#                 "cooloff_timedelta": cool_off,
#             }
#         )
# 
#     if request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest":
#         json_response = JsonResponse(context, status=status)
#         json_response[
#             "Access-Control-Allow-Origin"
#         ] = settings.AXES_ALLOWED_CORS_ORIGINS
#         json_response["Access-Control-Allow-Methods"] = "POST, OPTIONS"
#         json_response[
#             "Access-Control-Allow-Headers"
#         ] = "Origin, Content-Type, Accept, Authorization, x-requested-with"
#         return json_response
# 
#     if settings.AXES_LOCKOUT_TEMPLATE:
#         return render(request, settings.AXES_LOCKOUT_TEMPLATE, context, status=status)
# 
#     if settings.AXES_LOCKOUT_URL:
#         lockout_url = settings.AXES_LOCKOUT_URL
#         query_string = urlencode({"username": context["username"]})
#         url = f"{lockout_url}?{query_string}"
#         return redirect(url)
# 
#     return HttpResponse(get_lockout_message(), status=status)


from typing import Callable
from django.conf import settings
from axes.helpers import get_lockout_response
    and maps lockout signals into readable HTTP 403 Forbidden responses.

    If a project uses ``django rest framework`` then the middleware updates the
    request and checks whether the limit has been exceeded. It's needed only
    for integration with DRF because it uses its own request object.

    This middleware recognizes a logout monitoring flag in the request and
    and uses the ``axes.helpers.get_lockout_response`` handler for returning
    customizable and context aware lockout message to the end user if necessary.

    To customize the lockout handling behaviour further, you can subclass this middleware
    and change the ``__call__`` method to your own liking.

    Please see the following configuration flags before customizing this handler:

    - ``AXES_LOCKOUT_TEMPLATE``,
    - ``AXES_LOCKOUT_URL``,
    - ``AXES_COOLOFF_MESSAGE``, and
    - ``AXES_PERMALOCK_MESSAGE``.
    """

    def __init__(self, get_response: Callable):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)

        if settings.AXES_ENABLED:
            if getattr(request, "axes_locked_out", None):
                credentials = getattr(request, "axes_credentials", None)

# Path: axes/helpers.py
# def get_lockout_response(request, credentials: dict = None) -> HttpResponse:
#     if settings.AXES_LOCKOUT_CALLABLE:
#         if callable(settings.AXES_LOCKOUT_CALLABLE):
#             return settings.AXES_LOCKOUT_CALLABLE(  # pylint: disable=not-callable
#                 request, credentials
#             )
#         if isinstance(settings.AXES_LOCKOUT_CALLABLE, str):
#             return import_string(settings.AXES_LOCKOUT_CALLABLE)(request, credentials)
#         raise TypeError(
#             "settings.AXES_LOCKOUT_CALLABLE needs to be a string, callable, or None."
#         )
# 
#     status = settings.AXES_HTTP_RESPONSE_CODE
#     context = {
#         "failure_limit": get_failure_limit(request, credentials),
#         "username": get_client_username(request, credentials) or "",
#     }
# 
#     cool_off = get_cool_off()
#     if cool_off:
#         context.update(
#             {
#                 "cooloff_time": get_cool_off_iso8601(
#                     cool_off
#                 ),  # differing old name is kept for backwards compatibility
#                 "cooloff_timedelta": cool_off,
#             }
#         )
# 
#     if request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest":
#         json_response = JsonResponse(context, status=status)
#         json_response[
#             "Access-Control-Allow-Origin"
#         ] = settings.AXES_ALLOWED_CORS_ORIGINS
#         json_response["Access-Control-Allow-Methods"] = "POST, OPTIONS"
#         json_response[
#             "Access-Control-Allow-Headers"
#         ] = "Origin, Content-Type, Accept, Authorization, x-requested-with"
#         return json_response
# 
#     if settings.AXES_LOCKOUT_TEMPLATE:
#         return render(request, settings.AXES_LOCKOUT_TEMPLATE, context, status=status)
# 
#     if settings.AXES_LOCKOUT_URL:
#         lockout_url = settings.AXES_LOCKOUT_URL
#         query_string = urlencode({"username": context["username"]})
#         url = f"{lockout_url}?{query_string}"
#         return redirect(url)
# 
#     return HttpResponse(get_lockout_message(), status=status)


# Path: axes/middleware.py
from typing import Callable
from django.conf import settings
from axes.helpers import get_lockout_response

    and maps lockout signals into readable HTTP 403 Forbidden responses.

    If a project uses ``django rest framework`` then the middleware updates the
    request and checks whether the limit has been exceeded. It's needed only
    for integration with DRF because it uses its own request object.

    This middleware recognizes a logout monitoring flag in the request and
    and uses the ``axes.helpers.get_lockout_response`` handler for returning
    customizable and context aware lockout message to the end user if necessary.

    To customize the lockout handling behaviour further, you can subclass this middleware
    and change the ``__call__`` method to your own liking.

    Please see the following configuration flags before customizing this handler:

    - ``AXES_LOCKOUT_TEMPLATE``,
    - ``AXES_LOCKOUT_URL``,
    - ``AXES_COOLOFF_MESSAGE``, and
    - ``AXES_PERMALOCK_MESSAGE``.
    """

    def __init__(self, get_response: Callable):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)

        if settings.AXES_ENABLED:
            if getattr(request, "axes_locked_out", None):
                credentials = getattr(request, "axes_credentials", None)

                response = get_lockout_response(request, credentials)  # type: ignore