Python Authlib: Декоратор ResourceProtecter для представлений на основе классов

Я пытаюсь защитить API на основе Django-DRF с помощью Auth0. Защитник ресурсов Authlib прекрасно работает с представлениями, основанными на функциях, но когда я пытаюсь применить декоратор ResourceProtector из Authlib к представлению, основанному на классах, он продолжает возвращать ошибку 'ViewSet' object has no attribute 'build_absolute_uri'. Похоже, что функция декоратора использует аргумент self вместо аргумента request для получения url, когда она применяется к представлению, основанному на классе, что и вызывает ошибку.

Есть ли другой способ использовать декоратор Authlib resource protector для представления на основе класса?

Views.py

from api.permissions import auth0_validator
from authlib.integrations.django_oauth2 import ResourceProtector
from django.http import JsonResponse

require_oauth = ResourceProtector()
validator = auth0_validator.Auth0JWTBearerTokenValidator(
    os.environ['AUTH0_DOMAIN'],
    os.environ['AUTH0_IDENTIFIER']
)
require_oauth.register_token_validator(validator)

#Resource protector decorator works here
@require_oauth()
def index(request):
    return Response('Access granted')

class Users(ModelViewSet):

    #Resource protector decorator does not work and invokes error below
    @require_oauth()
    def list(self, request):
        return Response('access granted')

трассировка стека

После копания в Authlib выяснилось, что декоратор возвращает эту ошибку, потому что первым параметром в функции декоратора ResourceProtectors будет объект представления, а не запрос, так как он вызывается на методе класса. Чтобы исправить это, я просто расширил класс ResourceProtector и добавил дополнительный параметр 'view', чтобы его можно было применять к методам класса.

class CustomResourceProtectorDecorator(ResourceProtector):

    def __call__(self, scopes=None, optional=False):
        def wrapper(f):
            @functools.wraps(f)
            def decorated(view, request, *args, **kwargs): #Added view as the first argument so it works with class based view methods
                try:
                    token = self.acquire_token(request, scopes)
                    request.oauth_token = token
                except MissingAuthorizationError as error:
                    if optional:
                        request.oauth_token = None
                        return f(request, *args, **kwargs)
                    return return_error_response(error)
                except OAuth2Error as error:
                    return return_error_response(error)
                return f(request, *args, **kwargs)
            return decorated
        return wrapper

Я позже

Вернуться на верх