Как потребовать аутентификацию 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)
# ...
<
<