From e43d4837c3977a840e3b6824a31d97d9f65654ed Mon Sep 17 00:00:00 2001 From: jedi Date: Wed, 22 Nov 2023 23:55:00 +0100 Subject: [PATCH] temporary fix for websockets --- core/core/asgi.py | 37 ++++++++++++++++++- core/core/settings.py | 2 +- core/notify_sessions/consumers.py | 34 +++++++++++------ core/notify_sessions/routing.py | 2 +- core/requirements.txt | 2 + .../playbooks/templates/c3lf-sys3.service.j2 | 1 + .../ansible/playbooks/templates/nginx.conf.j2 | 2 +- 7 files changed, 63 insertions(+), 17 deletions(-) diff --git a/core/core/asgi.py b/core/core/asgi.py index da744a2..9d7fde2 100644 --- a/core/core/asgi.py +++ b/core/core/asgi.py @@ -19,12 +19,45 @@ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings') django_asgi_app = get_asgi_application() + +class TokenAuthMiddleware: + """ + Token authorization middleware for Django Channels 2 + """ + + def __init__(self, inner): + self.inner = inner + + def __call__(self, scope): + import base64 + headers = dict(scope['headers']) + if b'authorization' in headers: + try: + token_name, token_key = headers[b'authorization'].decode().split() + if token_name == 'Basic': + b64 = base64.b64decode(token_key) + user = b64.decode().split(':')[0] + password = b64.decode().split(':')[1] + print(user, password) + else: + print("Token name is not Basic") + scope['user'] = None + except: + print("Token is not valid") + scope['user'] = None + else: + print("Token is not in headers") + scope['user'] = None + + +TokenAuthMiddlewareStack = lambda inner: TokenAuthMiddleware(AuthMiddlewareStack(inner)) + websocket_asgi_app = AllowedHostsOriginValidator( - #AuthMiddlewareStack( + AuthMiddlewareStack( URLRouter( websocket_urlpatterns ) - #) + ) ) application = ProtocolTypeRouter({ diff --git a/core/core/settings.py b/core/core/settings.py index e752a50..8f3c5b8 100644 --- a/core/core/settings.py +++ b/core/core/settings.py @@ -184,7 +184,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' CHANNEL_LAYERS = { 'default': { - 'BACKEND': 'asgi_redis.RedisChannelLayer', + 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { 'hosts': [('localhost', 6379)], }, diff --git a/core/notify_sessions/consumers.py b/core/notify_sessions/consumers.py index 6284c9e..ebcbc1e 100644 --- a/core/notify_sessions/consumers.py +++ b/core/notify_sessions/consumers.py @@ -1,4 +1,6 @@ -import json +from json.decoder import JSONDecodeError +from json import loads as json_loads +from json import dumps as json_dumps from channels.generic.websocket import AsyncWebsocketConsumer @@ -6,12 +8,12 @@ from channels.generic.websocket import AsyncWebsocketConsumer class NotifyConsumer(AsyncWebsocketConsumer): def __init__(self, *args, **kwargs): super().__init__(args, kwargs) - self.room_group_name = None - self.event_slug = None + self.room_group_name = "general" + # self.event_slug = None async def connect(self): - self.event_slug = self.scope["url_route"]["kwargs"]["event_slug"] - self.room_group_name = f"chat_{self.event_slug}" + # self.event_slug = self.scope["url_route"]["kwargs"]["event_slug"] + # self.room_group_name = f"chat_{self.event_slug}" # Join room group await self.channel_layer.group_add(self.room_group_name, self.channel_name) @@ -24,17 +26,25 @@ class NotifyConsumer(AsyncWebsocketConsumer): # Receive message from WebSocket async def receive(self, text_data): - text_data_json = json.loads(text_data) - message = text_data_json["message"] + try: + text_data_json = json_loads(text_data) + message = text_data_json["message"] - # Send message to room group - await self.channel_layer.group_send( - self.room_group_name, {"type": "chat.message", "message": message} - ) + # Send message to room group + await self.channel_layer.group_send( + self.room_group_name, {"type": "chat.message", "message": message} + ) + except JSONDecodeError: + await self.send(text_data=json_dumps({"message": "error", "error": "malformed json"})) + except KeyError as e: + await self.send(text_data=json_dumps({"message": "error", "error": f"missing key: {str(e)}"})) + except Exception as e: + await self.send(text_data=json_dumps({"message": "error", "error": "unknown error"})) + raise e # Receive message from room group async def chat_message(self, event): message = event["message"] # Send message to WebSocket - await self.send(text_data=json.dumps({"message": message})) \ No newline at end of file + await self.send(text_data=json_dumps({"message": message})) diff --git a/core/notify_sessions/routing.py b/core/notify_sessions/routing.py index fdd4e97..64f561e 100644 --- a/core/notify_sessions/routing.py +++ b/core/notify_sessions/routing.py @@ -3,6 +3,6 @@ from django.urls import path from .consumers import NotifyConsumer websocket_urlpatterns = [ - path('ws/notify//', NotifyConsumer.as_asgi()), + path('ws/notify/', NotifyConsumer.as_asgi()), ] diff --git a/core/requirements.txt b/core/requirements.txt index b969d4b..bf4da2a 100644 --- a/core/requirements.txt +++ b/core/requirements.txt @@ -14,6 +14,7 @@ coreschema==0.0.4 coverage==7.3.2 Django==4.2.7 django-extensions==3.2.3 +django-mysql==4.12.0 django-soft-delete==0.9.21 djangorestframework==3.14.0 drf-yasg==1.21.7 @@ -26,6 +27,7 @@ Jinja2==3.1.2 MarkupSafe==2.1.3 msgpack==1.0.7 msgpack-python==0.5.6 +mysqlclient==2.2.0 openapi-codec==1.3.2 packaging==23.2 Pillow==10.1.0 diff --git a/deploy/ansible/playbooks/templates/c3lf-sys3.service.j2 b/deploy/ansible/playbooks/templates/c3lf-sys3.service.j2 index ee90111..e91e456 100644 --- a/deploy/ansible/playbooks/templates/c3lf-sys3.service.j2 +++ b/deploy/ansible/playbooks/templates/c3lf-sys3.service.j2 @@ -6,6 +6,7 @@ After=network.target Type=notify WorkingDirectory=/var/www/c3lf-sys3 ExecStart=/var/www/c3lf-sys3/venv/bin/python3 /var/www/c3lf-sys3/repo/core/server.py +Environment=DJANGO_SETTINGS_MODULE=core.settings Restart=always RestartSec=5 User=www-data diff --git a/deploy/ansible/playbooks/templates/nginx.conf.j2 b/deploy/ansible/playbooks/templates/nginx.conf.j2 index 652eb84..9834392 100644 --- a/deploy/ansible/playbooks/templates/nginx.conf.j2 +++ b/deploy/ansible/playbooks/templates/nginx.conf.j2 @@ -26,7 +26,7 @@ server { location /ws { proxy_http_version 1.1; - auth_basic off; + #auth_basic off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://c3lf-sys3;