Как потребовать аутентификацию django на strawberry-graphql

Я хочу потребовать аутентификацию пользователя django, чтобы получить доступ к представлению graphql.

Моей первой попыткой было украсить представление с помощью login_required:

from django.contrib.auth.decorators import login_required
from django.urls import path

urlpatterns = [
    path("graphql/sync", login_required(GraphQLView.as_view(schema=schema))),
    path("graphql", login_required(AsyncGraphQLView.as_view(schema=schema))),
]

Это работает для синхронного представления, но не для асинхронного, поскольку login_required не знает об асинхронности.

На данный момент я заканчиваю писать свой собственный вид, который копирует поведение login_required:


from urllib.parse import urlparse

from asgiref.sync import sync_to_async
from strawberry.django.views import AsyncGraphQLView

from django.conf import settings
from django.contrib.auth.views import redirect_to_login
from django.shortcuts import resolve_url
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt

class LoginRequiredAsyncGraphQLView(AsyncGraphQLView):
    @method_decorator(csrf_exempt)
    async def dispatch(self, request, *args, **kwargs):
        is_authenticated = await sync_to_async(lambda: request.user.is_authenticated)()
        if not is_authenticated:
            path = request.build_absolute_uri()
            resolved_login_url = resolve_url(settings.LOGIN_URL)
            # If the login url is the same scheme and net location then just
            # use the path as the "next" url.
            login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
            current_scheme, current_netloc = urlparse(path)[:2]
            if (not login_scheme or login_scheme == current_scheme) and (
                not login_netloc or login_netloc == current_netloc
            ):
                path = request.get_full_path()

            return redirect_to_login(path, resolved_login_url)
            
        return await super().dispatch(request, *args, **kwargs)


# urls.py
urlpatterns = [

    path("graphql", LoginRequiredAsyncGraphQLView.as_view(schema=schema)),
]

Но это кажется не очень хорошим решением, и я уверен, что есть что-то более чистое.

Есть ли лучшее решение, чтобы иметь login_required декоратор, совместимый с async view?

<
import strawberry
import strawberry.django
from django.http.request import HttpRequest
from django.core.exceptions import PermissionDenied
from strawberry_django.fields.field import StrawberryDjangoField


class AuthStrawberryDjangoField(StrawberryDjangoField):
    def resolver(self, info, source, **kwargs):
        request: HttpRequest = info.context.request
        if not request.user.is_authenticated:
            raise PermissionDenied()
        return super().resolver(info, source, **kwargs)


@strawberry.type
class Query:
    foo: List[Foo] = AuthStrawberryDjangoField()

Для мутации можно использовать

async def graphql_check_authenticated(info: Info):
    auth = await sync_to_async(lambda: info.context.request.user.is_authenticated)()
    if auth is False:
        raise PermissionDenied()

@strawberry.type
class Mutation:
    @strawberry.mutation
    async def add_foo(self, info: Info, new_foo: FooInput) -> None:
        await graphql_check_authenticated(info)
        # ...
< <
Вернуться на верх