Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def unsubscribe_sync(cls, *, group=None):
"""Unsubscribe, synchronous version."""
# Send the message to the Channels group.
group = cls._group_name(group)
group_send = asgiref.sync.async_to_sync(cls._channel_layer().group_send)
group_send(group=group, message={"type": "unsubscribe", "group": group})
def broadcast_sync(cls, *, group=None, payload=None):
"""Broadcast, synchronous version."""
# Manually serialize the `payload` to allow transfer of Django
# models inside the `payload`.
serialized_payload = Serializer.serialize(payload)
# Send the message to the Channels group.
group = cls._group_name(group)
group_send = asgiref.sync.async_to_sync(cls._channel_layer().group_send)
group_send(
group=group,
message={
"type": "broadcast",
"group": group,
"payload": serialized_payload,
},
# confirmation message is sent before any subscription
# notifications.
if self.confirm_subscriptions:
await self._send_gql_data(
operation_id,
data=self.subscription_confirmation_message["data"],
errors=self.subscription_confirmation_message["errors"],
)
# Subscribe to the observable.
# NOTE: The function `on_next` is called from a
# threadpool which processes all GraphQL requests. So we
# wrap `_send_gql_data` into `async_to_sync` here, so
# eventually `_send_gql_data` will be invoked from the
# current eventloop.
send_gql_data = asgiref.sync.async_to_sync(self._send_gql_data)
result.subscribe(
lambda r: send_gql_data(operation_id, r.data, r.errors)
)
else:
# Respond to a query or mutation immediately.
# If Graphene complains that the request is invalid
# (e.g. query contains syntax error), then the `data`
# argument is `None` and the 'errors' argument contains
# all errors that occurred before or during execution.
# The `result` is an instance of the `ExecutionResult`.
await self._send_gql_data(operation_id, result.data, result.errors)
# Tell the client that the request processing is over.
await self._send_gql_complete(operation_id)
async def _get_user(self):
user = None
try:
if self.scope['jwt']:
user = await sync.sync_to_async(passive_credentials_auth)(self.scope['jwt'])
except (APIException, InvalidTokenError):
# Can ignore JWT auth failures, scope['user'] will not be set.
pass
return user
query = payload["query"]
op_name = payload.get("operationName")
variables = payload.get("variables", {})
# Create object-like context (like in `Query` or `Mutation`)
# from the dict-like one provided by the Channels.
context = ScopeAsContext(self.scope)
# The `register` will be called from the worker thread
# (spawned for a GraphQL processing) when a client
# subscribes. So we "synchronize" it with `async_to_sync`.
# NOTE: It is important to invoke `async_to_sync` in the
# thread with the eventloop which serves this consumer. This
# assures that IO operations is performed within a single
# eventloop.
register_subscription = asgiref.sync.async_to_sync(
functools.partial(self._register_subscription, operation_id)
)
def register_middleware(next_middleware, root, info, *args, **kwds):
"""Transfers registration function to the `_subscribe`.
Check that `next_middleware` is precisely a subscription
handler `Subscription._subscribe` and hack it's `root`
to deliver the subscription registration function.
"""
from .subscription import Subscription
# We do not expose `Subscription._subscribe` because
# `Subscription` is a public interface class. So it OK
# to get `Subscription._subscribe` here - we are tightly
# coupled anyway.
def mutate(self, info, username, password):
"""Login request."""
# Ask Django to authenticate user.
user = django.contrib.auth.authenticate(username=username, password=password)
if user is None:
return Login(ok=False)
# Use Channels to login, in other words to put proper data to
# the session stored in the scope. The `info.context` is
# practically just a wrapper around Channel `self.scope`, but
# the `login` method requires dict, so use `_asdict`.
asgiref.sync.async_to_sync(channels.auth.login)(info.context._asdict(), user)
# Save the session, `channels.auth.login` does not do this.
info.context.session.save()
return Login(ok=True)