Django Update Middleware для замены декоратора

У меня есть следующий декоратор, который отлично работает, когда применяется к различным представлениям с: @otp_required(login_url='login') на моем сайте:

Декоратор

from django.contrib.auth.decorators import user_passes_test

from django_otp import user_has_device
from django_otp.conf import settings


def otp_required(view=None, redirect_field_name='next', login_url=None, if_configured=False):
    """
    Similar to :func:`~django.contrib.auth.decorators.login_required`, but
    requires the user to be :term:`verified`. By default, this redirects users
    to :setting:`OTP_LOGIN_URL`.

    :param if_configured: If ``True``, an authenticated user with no confirmed
        OTP devices will be allowed. Default is ``False``.
    :type if_configured: bool
    """
    if login_url is None:
        login_url = settings.OTP_LOGIN_URL

    def test(user):
        return user.is_verified() or (if_configured and user.is_authenticated and not user_has_device(user))

    decorator = user_passes_test(test, login_url=login_url, redirect_field_name=redirect_field_name)

    return decorator if (view is None) else decorator(view)

Однако я хотел бы преобразовать это в Middleware, так как хочу избежать необходимости применять декоратор к каждому представлению на моем сайте, но не смог добиться желаемого результата. Я попытался изменить следующее Middleware, которое у меня сейчас есть, и которое предназначено только для авторизованных пользователей, и оно работает, но в соответствии с вышеуказанным декоратором я хочу, чтобы это Middleware было расширено, чтобы также требовалось OTP:

Middleware

from django.utils.deprecation import MiddlewareMixin
from django.urls import resolve, reverse
from django.http import HttpResponseRedirect
from wfi_workflow import settings

class LoginRequiredMiddleware(MiddlewareMixin):
    """
    Middleware that requires a user to be authenticated to view any page other
    than LOGIN_URL. Exemptions to this requirement can optionally be specified
    in settings by setting a tuple of routes to ignore
    """
    def process_request(self, request):
        assert hasattr(request, 'user'), """
        The Login Required middleware needs to be after AuthenticationMiddleware.
        Also make sure to include the template context_processor:
        'django.contrib.account.context_processors.account'."""

        if not request.user.is_authenticated and not request.path.startswith('/admin/') and not request.path.startswith('/account/' ):

            current_route_name = resolve(request.path_info).url_name

            if not current_route_name in settings.AUTH_EXEMPT_ROUTES:
                return HttpResponseRedirect(reverse(settings.LOGIN_URL))

Помощь будет очень признательна.

Тот факт, что вы возвращаете HttpResponseRedirect, не сработает: Django MiddlewareMixin просто вызовет функцию, чтобы (по желанию) изменить запрос, но он никогда не примет во внимание возврат.

Что вы можете сделать, так это определить промежуточное ПО в структуре, подобной декоратору, и вернуть HttpResponseRedirect в случае, если пользователь должен быть аутентифицирован с помощью:

from django.urls import resolve, reverse
from django.http import HttpResponseRedirect
from wfi_workflow import settings

def LoginRequiredMiddleware(get_response):
    """
    Middleware that requires a user to be authenticated to view any page other
    than LOGIN_URL. Exemptions to this requirement can optionally be specified
    in settings by setting a tuple of routes to ignore
    """
    def middleware(request):
        assert hasattr(request, 'user'), """
        The Login Required middleware needs to be after AuthenticationMiddleware.
        Also make sure to include the template context_processor:
        'django.contrib.account.context_processors.account'."""

        if not request.user.is_authenticated and not request.path.startswith('/admin/') and not request.path.startswith('/account/' ):

            current_route_name = resolve(request.path_info).url_name

            if not current_route_name in settings.AUTH_EXEMPT_ROUTES:
                return HttpResponseRedirect(settings.LOGIN_URL)
        return get_response(request)
Вернуться на верх