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
Я позже