Protect graphene django "auto" queries and mutations
ckristhoff opened this issue · comments
Prerequisites
- Is it a bug?
- Is it a new feature?
- [ ✅] Is it a a question?
- Can you reproduce the problem?
- Are you running the latest version?
- Did you check for similar issues?
- Did you perform a cursory search?
Description
Hi, nice work.
I'm trying to private graphene django auto queries and mutations. "Auto" means queries with DjangoObjectType
and DjangoFilterConnectionField
, and mutations with DjangoModelFormMutation
and DjangoFormMutation
The @login_required decorator in graphql_jwt package does not works if resolve method does not exist.
Although the question is an old one, I went through the same problem and maybe other people will, so here is the solution:
For DjangoObjectType
and DjangoFilterConnectionField
:
class LoginRequiredMixin(object):
@classmethod
@login_required
def get_queryset(cls, queryset, info):
return queryset
class YourType(LoginRequiredMixin, DjangoObjectType):
...
For DjangoFormMutation
:
class LoginRequiredMixin(object):
@classmethod
@login_required
def perform_mutate(cls, form, info):
form.save()
return cls(errors=[], **form.cleaned_data)
class YourMutation(LoginRequiredMixin, DjangoFormMutation):
...
For DjangoModelFormMutation
:
class LoginRequiredMixin(object):
@classmethod
@login_required
def mutate_and_get_payload(cls, root, info, **input):
form = cls.get_form(root, info, **input)
if form.is_valid():
return cls.perform_mutate(form, info)
else:
errors = ErrorType.from_errors(form.errors)
return cls(errors=errors)
class YourMutation(LoginRequiredMixin, DjangoModelFormMutation):
...
And for SerializerMutation
(https://docs.graphene-python.org/projects/django/en/latest/mutations/#django-rest-framework):
from django.shortcuts import get_object_or_404
class LoginRequiredMixin(object):
@classmethod
@login_required
def get_serializer_kwargs(cls, root, info, **input_data):
lookup_field = cls._meta.lookup_field
model_class = cls._meta.model_class
if model_class:
if "update" in cls._meta.model_operations and lookup_field in input_data:
instance = get_object_or_404(
model_class, **{lookup_field: input_data[lookup_field]}
)
partial = True
elif "create" in cls._meta.model_operations:
instance = None
partial = False
else:
raise Exception(
"Invalid update operation. input_data parameter \"{}\" required.".format(
lookup_field
)
)
return {
"instance": instance,
"data": input_data,
"context": {"request": info.context},
"partial": partial,
}
return {"data": input_data, "context": {"request": info.context}}
class YourMutation(LoginRequiredMixin, SerializerMutation):
...
errors = ErrorType.from_errors(form.errors)
Here are the imports:
from graphql_jwt.decorators import login_required
from graphene_django.forms.mutation import DjangoFormMutation
from graphene_django.forms.types import ErrorType
@PedroBern is this LoginRequiredMixin appropriate for a PR, if anybody else comes along and wants to pick it up?