authentik.root.ws.storage

Channels Messages storage

 1"""Channels Messages storage"""
 2
 3from asgiref.sync import async_to_sync
 4from channels.layers import get_channel_layer
 5from django.contrib.messages.storage.base import Message
 6from django.contrib.messages.storage.session import SessionStorage
 7from django.core.cache import cache
 8from django.http.request import HttpRequest
 9
10SESSION_KEY = "_messages"
11CACHE_PREFIX = "goauthentik.io/root/messages_"
12
13
14class ChannelsStorage(SessionStorage):
15    """Send contrib.messages over websocket"""
16
17    def __init__(self, request: HttpRequest) -> None:
18        super().__init__(request)
19        self.channel = get_channel_layer()
20
21    def _store(self, messages: list[Message], response, *args, **kwargs):
22        prefix = f"{CACHE_PREFIX}{self.request.session.session_key}_messages_"
23        keys = cache.keys(f"{prefix}*")
24        # if no active connections are open, fallback to storing messages in the
25        # session, so they can always be retrieved
26        if len(keys) < 1:
27            return super()._store(messages, response, *args, **kwargs)
28        for key in keys:
29            uid = key.replace(prefix, "")
30            for message in messages:
31                async_to_sync(self.channel.send)(
32                    uid,
33                    {
34                        "type": "event.message",
35                        "message_type": "message",
36                        "level": message.level_tag,
37                        "tags": message.tags,
38                        "message": message.message,
39                    },
40                )
41        return []
SESSION_KEY = '_messages'
CACHE_PREFIX = 'goauthentik.io/root/messages_'
class ChannelsStorage(django.contrib.messages.storage.session.SessionStorage):
15class ChannelsStorage(SessionStorage):
16    """Send contrib.messages over websocket"""
17
18    def __init__(self, request: HttpRequest) -> None:
19        super().__init__(request)
20        self.channel = get_channel_layer()
21
22    def _store(self, messages: list[Message], response, *args, **kwargs):
23        prefix = f"{CACHE_PREFIX}{self.request.session.session_key}_messages_"
24        keys = cache.keys(f"{prefix}*")
25        # if no active connections are open, fallback to storing messages in the
26        # session, so they can always be retrieved
27        if len(keys) < 1:
28            return super()._store(messages, response, *args, **kwargs)
29        for key in keys:
30            uid = key.replace(prefix, "")
31            for message in messages:
32                async_to_sync(self.channel.send)(
33                    uid,
34                    {
35                        "type": "event.message",
36                        "message_type": "message",
37                        "level": message.level_tag,
38                        "tags": message.tags,
39                        "message": message.message,
40                    },
41                )
42        return []

Send contrib.messages over websocket

ChannelsStorage(request: django.http.request.HttpRequest)
18    def __init__(self, request: HttpRequest) -> None:
19        super().__init__(request)
20        self.channel = get_channel_layer()
channel