From c67aaa66f2b2f0335fb0b43555bb010490ae4b38 Mon Sep 17 00:00:00 2001 From: Daniel Osaetin Date: Sat, 13 Mar 2021 19:21:12 +0100 Subject: [PATCH] Completed part 7 --- chat/channels.py | 2 +- chat/views.py | 33 ++++---- chatire-frontend/package-lock.json | 103 ++++++++++++++++------- chatire-frontend/src/components/Chat.vue | 4 +- chatire/asgi.py | 17 ++++ chatire/settings.py | 27 ++++-- chatire/urls.py | 4 +- requirements.txt | 16 ++-- websocket.py | 4 +- 9 files changed, 141 insertions(+), 69 deletions(-) create mode 100644 chatire/asgi.py diff --git a/chat/channels.py b/chat/channels.py index 416bd9a..1f21a52 100644 --- a/chat/channels.py +++ b/chat/channels.py @@ -8,7 +8,7 @@ class BroadCastWebSocketChannel(BaseNotificationChannel): - """Fanout notification for RabbitMQ.""" + """Fanout notification channel with RabbitMQ.""" def _connect(self): """Connect to the RabbitMQ server.""" diff --git a/chat/views.py b/chat/views.py index 75bbd90..e6ad62c 100644 --- a/chat/views.py +++ b/chat/views.py @@ -3,14 +3,14 @@ from django.http import Http404 from django.contrib.auth import get_user_model -from .models import ( - ChatSession, ChatSessionMember, ChatSessionMessage, deserialize_user -) - from rest_framework import permissions from rest_framework.views import APIView from rest_framework.response import Response -from notifications.signals import notify + +from notifications.utils import notify +from notifications import default_settings as notifs_settings + +from .models import ChatSession, ChatSessionMessage, deserialize_user class ChatSessionView(APIView): @@ -47,17 +47,17 @@ def patch(self, request, *args, **kwargs): owner = deserialize_user(owner) members = [ - deserialize_user(chat_session.user) + deserialize_user(chat_session.user) for chat_session in chat_session.members.all() ] members.insert(0, owner) # Make the owner the first member - return Response ({ + return Response({ 'status': 'SUCCESS', 'members': members, - 'message': '%s joined that chat' % user.username, + 'message': '%s joined the chat' % user.username, 'user': deserialize_user(user) }) - + class ChatSessionMessageView(APIView): """Create/Get Chat session messages.""" @@ -69,8 +69,8 @@ def get(self, request, *args, **kwargs): uri = kwargs['uri'] chat_session = ChatSession.objects.get(uri=uri) - messages = [chat_session_message.to_json() - for chat_session_message in chat_session.messages.all()] + messages = [chat_session_message.to_json() + for chat_session_message in chat_session.messages.all()] return Response({ 'id': chat_session.id, 'uri': chat_session.uri, @@ -96,15 +96,14 @@ def post(self, request, *args, **kwargs): 'obj': chat_session_message.id, 'short_description': 'You a new message', 'silent': True, 'extra_data': { - 'uri': chat_session.uri, + notifs_settings.NOTIFICATIONS_WEBSOCKET_URL_PARAM: + chat_session.uri, 'message': chat_session_message.to_json() } } - notify.send( - sender=self.__class__,**notif_args, channels=['websocket'] - ) + notify(**notif_args, channels=['websocket']) - return Response ({ + return Response({ 'status': 'SUCCESS', 'uri': chat_session.uri, 'message': message, 'user': deserialize_user(user) }) @@ -112,4 +111,4 @@ def post(self, request, *args, **kwargs): def raise_404(request): """Raise a 404 Error.""" - raise Http404 \ No newline at end of file + raise Http404 diff --git a/chatire-frontend/package-lock.json b/chatire-frontend/package-lock.json index 9874a89..a339a69 100644 --- a/chatire-frontend/package-lock.json +++ b/chatire-frontend/package-lock.json @@ -2666,12 +2666,6 @@ "cssom": "0.3.x" } }, - "cuint": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", - "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", - "dev": true - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -4290,7 +4284,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.1.1", @@ -4341,7 +4336,8 @@ "balanced-match": { "version": "0.4.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "bcrypt-pbkdf": { "version": "1.0.1", @@ -4356,6 +4352,7 @@ "version": "0.0.9", "bundled": true, "dev": true, + "optional": true, "requires": { "inherits": "~2.0.0" } @@ -4364,6 +4361,7 @@ "version": "2.10.1", "bundled": true, "dev": true, + "optional": true, "requires": { "hoek": "2.x.x" } @@ -4372,6 +4370,7 @@ "version": "1.1.7", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^0.4.1", "concat-map": "0.0.1" @@ -4380,7 +4379,8 @@ "buffer-shims": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "caseless": { "version": "0.12.0", @@ -4397,12 +4397,14 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "combined-stream": { "version": "1.0.5", "bundled": true, "dev": true, + "optional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -4410,22 +4412,26 @@ "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "cryptiles": { "version": "2.0.5", "bundled": true, "dev": true, + "optional": true, "requires": { "boom": "2.x.x" } @@ -4465,7 +4471,8 @@ "delayed-stream": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "delegates": { "version": "1.0.0", @@ -4497,7 +4504,8 @@ "extsprintf": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "forever-agent": { "version": "0.6.1", @@ -4519,12 +4527,14 @@ "fs.realpath": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "fstream": { "version": "1.0.11", "bundled": true, "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -4580,6 +4590,7 @@ "version": "7.1.2", "bundled": true, "dev": true, + "optional": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4592,7 +4603,8 @@ "graceful-fs": { "version": "4.1.11", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "har-schema": { "version": "1.0.5", @@ -4620,6 +4632,7 @@ "version": "3.1.3", "bundled": true, "dev": true, + "optional": true, "requires": { "boom": "2.x.x", "cryptiles": "2.x.x", @@ -4630,7 +4643,8 @@ "hoek": { "version": "2.16.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "http-signature": { "version": "1.1.1", @@ -4647,6 +4661,7 @@ "version": "1.0.6", "bundled": true, "dev": true, + "optional": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -4655,7 +4670,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.4", @@ -4667,6 +4683,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "1.0.1" } @@ -4680,7 +4697,8 @@ "isarray": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "isstream": { "version": "0.1.2", @@ -4753,12 +4771,14 @@ "mime-db": { "version": "1.27.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "mime-types": { "version": "2.1.15", "bundled": true, "dev": true, + "optional": true, "requires": { "mime-db": "1.27.0" } @@ -4767,6 +4787,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "1.1.7" } @@ -4774,12 +4795,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "mkdirp": { "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4834,7 +4857,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "oauth-sign": { "version": "0.8.2", @@ -4852,6 +4876,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4881,7 +4906,8 @@ "path-is-absolute": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "performance-now": { "version": "0.2.0", @@ -4892,7 +4918,8 @@ "process-nextick-args": { "version": "1.0.7", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "punycode": { "version": "1.4.1", @@ -4930,6 +4957,7 @@ "version": "2.2.9", "bundled": true, "dev": true, + "optional": true, "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -4974,6 +5002,7 @@ "version": "2.6.1", "bundled": true, "dev": true, + "optional": true, "requires": { "glob": "^7.0.5" } @@ -4981,7 +5010,8 @@ "safe-buffer": { "version": "5.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "semver": { "version": "5.3.0", @@ -5005,6 +5035,7 @@ "version": "1.0.9", "bundled": true, "dev": true, + "optional": true, "requires": { "hoek": "2.x.x" } @@ -5038,6 +5069,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5048,6 +5080,7 @@ "version": "1.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -5062,6 +5095,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5076,6 +5110,7 @@ "version": "2.2.1", "bundled": true, "dev": true, + "optional": true, "requires": { "block-stream": "*", "fstream": "^1.0.2", @@ -5131,7 +5166,8 @@ "util-deprecate": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "uuid": { "version": "3.0.1", @@ -5160,7 +5196,8 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -12983,7 +13020,15 @@ "integrity": "sha1-m76b6JYUKXbfo0wGGy0GjEPTDeA=", "dev": true, "requires": { - "cuint": "latest" + "cuint": "^0.2.2" + }, + "dependencies": { + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", + "dev": true + } } }, "y18n": { diff --git a/chatire-frontend/src/components/Chat.vue b/chatire-frontend/src/components/Chat.vue index e49d840..cfd0c9f 100644 --- a/chatire-frontend/src/components/Chat.vue +++ b/chatire-frontend/src/components/Chat.vue @@ -91,8 +91,8 @@ export default { // Setup headers for all requests $.ajaxSetup({ - headers: { - 'Authorization': `JWT ${sessionStorage.getItem('authToken')}` + beforeSend: function (xhr) { + xhr.setRequestHeader('Authorization', `JWT ${sessionStorage.getItem('authToken')}`) } }) diff --git a/chatire/asgi.py b/chatire/asgi.py new file mode 100644 index 0000000..3c5b73a --- /dev/null +++ b/chatire/asgi.py @@ -0,0 +1,17 @@ +import os + +import django + +from channels.http import AsgiHandler +from channels.routing import ProtocolTypeRouter, URLRouter + +from notifications import routing as notifications_routing + + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chatire.settings') +django.setup() + +application = ProtocolTypeRouter({ + 'http': AsgiHandler(), + 'websocket': URLRouter(notifications_routing.websocket_urlpatterns) +}) diff --git a/chatire/settings.py b/chatire/settings.py index c79a91e..2c4d9bc 100644 --- a/chatire/settings.py +++ b/chatire/settings.py @@ -44,6 +44,8 @@ 'rest_framework.authtoken', 'corsheaders', 'djoser', + 'channels', + 'django_jsonfield_backport', # backport of django 3.1's JSONField # Our apps 'chat', @@ -82,7 +84,7 @@ ] WSGI_APPLICATION = 'chatire.wsgi.application' - +ASGI_APPLICATION = 'chatire.asgi.application' # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases @@ -143,17 +145,26 @@ # django-cors-header Configuration - CORS_ORIGIN_ALLOW_ALL = True -# Celery settings -CELERY_TASK_ALWAYS_EAGER = True - # notifications settings NOTIFICATIONS_CHANNELS = { - 'websocket': 'chat.channels.BroadCastWebSocketChannel' + 'websocket': 'notifications.channels.WebSocketChannel' } # djangorestframework-jwt settings -JWT_ALLOW_REFRESH = True -JWT_EXPIRATION_DELTA = timedelta(minutes=30) +JWT_AUTH = { + 'JWT_ALLOW_REFRESH': True, + 'JWT_EXPIRATION_DELTA': timedelta(minutes=30) +} + +# django-channels +ASGI_APPLICATION = 'chatire.asgi.application' +CHANNEL_LAYERS = { + 'default': { + 'BACKEND': 'channels_redis.core.RedisChannelLayer', + 'CONFIG': { + 'hosts': [('127.0.0.1', 6379)], + }, + } +} diff --git a/chatire/urls.py b/chatire/urls.py index 78c3403..e0f6e73 100644 --- a/chatire/urls.py +++ b/chatire/urls.py @@ -16,7 +16,7 @@ from django.contrib import admin from django.urls import path, include -from rest_framework_jwt.views import verify_jwt_token +from rest_framework_jwt.views import refresh_jwt_token from chat.views import raise_404 @@ -30,7 +30,7 @@ path('auth/jwt/refresh/', raise_404), # Register the new URL under an ambigous name - path('this/is/hard/to/find/', verify_jwt_token), + path('this/is/hard/to/find/', refresh_jwt_token), path('auth/', include('djoser.urls.jwt')), path('api/', include('chat.urls')) diff --git a/requirements.txt b/requirements.txt index 4e59e95..eecb4d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -amqp==2.2.2 -billiard==3.5.0.3 -celery==4.1.0 +amqp==2.6.1 +billiard==3.6.3.0 +celery==4.4.7 Django==2.0.1 django-cors-headers==2.1.0 django-notifs==2.6.0 @@ -8,13 +8,13 @@ django-templated-mail==1.0.0 djangorestframework==3.7.7 djangorestframework-jwt==1.11.0 djoser==1.1.5 -gevent==1.2.2 -greenlet==0.4.12 -kombu==4.1.0 +gevent==21.1.2 +greenlet==1.0.0 +kombu==4.6.11 pika==0.11.2 PyJWT==1.6.1 pytz==2017.3 simplejson==3.13.2 six==1.11.0 -uWSGI==2.0.15 -vine==1.1.4 +uWSGI==2.0.19.1 +vine==1.3.0 diff --git a/websocket.py b/websocket.py index 2dd7284..ec61f71 100644 --- a/websocket.py +++ b/websocket.py @@ -9,7 +9,7 @@ def application(env, start_response): """Setup the Websocket Server and read messages off the queue.""" connection = pika.BlockingConnection( - pika.ConnectionParameters(host='localhost') + pika.ConnectionParameters(host='localhost') ) channel = connection.channel() @@ -20,7 +20,7 @@ def application(env, start_response): ) # exclusive means the queue should be deleted once the connection is closed - result = channel.queue_declare(exclusive=True) + result = channel.queue_declare(queue='', exclusive=True) queue_name = result.method.queue # random queue name generated by RabbitMQ channel.queue_bind(exchange=exchange, queue=queue_name)