Hi,
I am trying to implement an easy permission system on retrieving fields. So for each field, I implement such a method:
def resolve_field(self, info, **kwargs):
if not has_permission():
raise PermissionError("Access Denied!")
return self.field
Everything works fine, the user gets a nicely formatted errors filed back to the frontend. But when I look to my server console, I see this:
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Traceback (most recent call last):
...some irrelevant lines...
graphql.error.located_error.GraphQLLocatedError: Access Denied!
[06/Aug/2019 21:19:16] "POST /graphql/ HTTP/1.1" 200 427
No exception is thrown, my exception is perfectly caught in the system. But something somewhere translated the exception into GraphQLLocatedError and prints the traceback, which is super annoying, since I can't manage to find a way to get rid of it. Is that even possible?
Or, is my idea of implementing permissions (with raising an exception) wrong?
Thanks!
I have the same problem in my tests. I've put it on the back burner for now. I was thinking maybe better to handle that validation in the serializer instead.
I'm doing something like this now:
# exceptions.py
from rest_framework.exceptions import ErrorDetail
from graphene_django.types import ErrorType
from django.utils.translation import gettext as _
class MutationError(Exception):
def __init__(self, message, field='non_field_errors'):
self.message = message
self.field = field
def __str__(self):
return self.message
@property
def error_dict(self):
return {self.field: [ErrorDetail(string=self.message)]}
@property
def errors(self):
return [
ErrorType(field=key, messages=value)
for key, value in self.error_dict.items()
]
class PermissionError(MutationError):
pass
class BaseSerializerMutation(SerializerMutation):
class Meta:
abstract = True
@classmethod
def mutate_and_get_payload(cls, root, info, **input):
try:
input = SomeAdvancedPermissionCheckerService().execute()
except PermissionError as e:
return cls(errors=e.errors)
Exceptions raised in your resolvers get caught and wrapped in GraphQLLocatedError, look in the code. If you look at the report_error method, you'll see that the exception together with traceback is logged using the graphql.execution.utils logger. Thus, you should be able to suppress the tracebacks in the log by silencing this logger.
@tlinhart I am not sure if I don't accidentally silence something I don't want to, but it is definitely a good workaround. This one line of code
import logging
logging.getLogger("graphql.execution.utils").setLevel(logging.CRITICAL)
does it. Thanks a lot!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Most helpful comment
@tlinhart I am not sure if I don't accidentally silence something I don't want to, but it is definitely a good workaround. This one line of code
does it. Thanks a lot!