Skip to content
This repository has been archived by the owner on Jul 8, 2023. It is now read-only.

Cryptic error if permission directive returns non-bool #124

Closed
edomora97 opened this issue Oct 1, 2022 · 1 comment
Closed

Cryptic error if permission directive returns non-bool #124

edomora97 opened this issue Oct 1, 2022 · 1 comment
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers help wanted Extra attention is needed

Comments

@edomora97
Copy link
Contributor

If I have a permission directive (e.g. a class with @gql.schema_directive(locations=[Location.FIELD_DEFINITION])) for which check_condition returns a non-bool value (let's say None) things may break badly.

I'm getting 500 errors with the following stack trace:

Stack trace
Internal Server Error: /graphql/
Traceback (most recent call last):
  File "/home/edomora97/.cache/pypoetry/virtualenvs/olimanager--mAs8BZ3-py3.10/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/edomora97/.cache/pypoetry/virtualenvs/olimanager--mAs8BZ3-py3.10/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/edomora97/.cache/pypoetry/virtualenvs/olimanager--mAs8BZ3-py3.10/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/edomora97/.cache/pypoetry/virtualenvs/olimanager--mAs8BZ3-py3.10/lib/python3.10/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/edomora97/.cache/pypoetry/virtualenvs/olimanager--mAs8BZ3-py3.10/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/edomora97/.cache/pypoetry/virtualenvs/olimanager--mAs8BZ3-py3.10/lib/python3.10/site-packages/strawberry/django/views.py", line 194, in dispatch
    result = self.schema.execute_sync(
  File "/home/edomora97/.cache/pypoetry/virtualenvs/olimanager--mAs8BZ3-py3.10/lib/python3.10/site-packages/strawberry/schema/schema.py", line 241, in execute_sync
    result = execute_sync(
  File "/home/edomora97/.cache/pypoetry/virtualenvs/olimanager--mAs8BZ3-py3.10/lib/python3.10/site-packages/strawberry/schema/execute.py", line 206, in execute_sync
    ensure_future(result).cancel()
  File "/usr/lib/python3.10/asyncio/tasks.py", line 615, in ensure_future
    return _ensure_future(coro_or_future, loop=loop)
  File "/usr/lib/python3.10/asyncio/tasks.py", line 634, in _ensure_future
    loop = events._get_event_loop(stacklevel=4)
  File "/usr/lib/python3.10/asyncio/events.py", line 656, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1 (process_request_thread)'.

The API is not super clear about this:

def check_condition(self, root: Any, info: GraphQLResolveInfo, user: UserType, **kwargs):
raise NotImplementedError

Note how the return type is not documented.

I think the culprit is:

# If this is not bool, assume async. Avoid is_awaitable since it is slow
if not isinstance(auth_ok, bool):
return aio.resolve_async(
auth_ok,
functools.partial(self.resolve_retval, helper, root, info, retval),
)

Here if the value returned is not a boolean it assumes it is a future (which is not the case for None for example).


I'm not saying this is a bug of this library, however the resulting error is very cryptic (and finding the root cause of the problem was quite hard as well). I'm proposing to at least document this behavior, and maybe add an assertion or a proper check for the values returned by check_condition. Is is_awaitable really that slow?

@bellini666
Copy link
Member

Hi @edomora97 ,

Oh I see. Yeah, since that code has a lot of "comes and goes" to handle both sync and async code, it can get messy to debug it properly :(

I agree that the check_condition is missing a better documentation. Maybe just a -> bool could do. Do you want to open a PR for it? I can do it as well, just wondering if you want to make your contribution here :)

And yes, is_awaitable is pretty slow: graphql-python/graphql-core#54 . It is not a major issue when called once or twice, but in this case you can have thousands of resolvers calling it, and things do stack up.

@bellini666 bellini666 added documentation Improvements or additions to documentation good first issue Good for newcomers help wanted Extra attention is needed labels Oct 1, 2022
frleb pushed a commit to frleb/strawberry-django-plus that referenced this issue Feb 28, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants