diff --git a/sapl/base/consumers.py b/sapl/base/consumers.py index 3498a4ce9..7b0b64c4b 100644 --- a/sapl/base/consumers.py +++ b/sapl/base/consumers.py @@ -2,6 +2,53 @@ import json from asgiref.sync import async_to_sync from channels.generic.websocket import AsyncWebsocketConsumer, WebsocketConsumer +from channels.layers import get_channel_layer +from django.db.models.signals import post_save, post_delete, pre_delete +from django.dispatch.dispatcher import receiver + + +class TimeRefreshConsumer(AsyncWebsocketConsumer): + + async def connect(self): + self.room_name = 'time_refresh_channel' + self.room_group_name = 'group_%s' % self.room_name + + # Join room group + await self.channel_layer.group_add( + self.room_group_name, + self.channel_name + ) + + await self.accept() + + async def disconnect(self, close_code): + await self.channel_layer.group_discard( + self.room_group_name, + self.channel_name + ) + + # Receive message from WebSocket + async def receive(self, text_data): + 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': 'time_refresh_message', + 'message': message + } + ) + + # Receive message from room group + async def time_refresh_message(self, event): + message = event['message'] + + # Send message to WebSocket + await self.send(text_data=json.dumps({ + 'message': message + })) class ChatConsumer(AsyncWebsocketConsumer): diff --git a/sapl/base/routing.py b/sapl/base/routing.py index d16571f00..ce0091b33 100644 --- a/sapl/base/routing.py +++ b/sapl/base/routing.py @@ -4,4 +4,6 @@ from . import consumers websocket_urlpatterns = [ url(r'^ws/chat/(?P[^/]+)/$', consumers.ChatConsumer), -] \ No newline at end of file + + url(r'^ws/time-refresh/$', consumers.TimeRefreshConsumer), +] diff --git a/sapl/base/urls.py b/sapl/base/urls.py index 2ee2788c3..a66ecd864 100644 --- a/sapl/base/urls.py +++ b/sapl/base/urls.py @@ -84,6 +84,15 @@ recuperar_senha = [ name='recuperar_senha_completo'), ] +channels_url = [ + + url(r'^sapl/channel$', base.views.chanel_index, name='channel_index'), + url(r'^sapl/channel/(?P[^/]+)/$', + base.views.chanel_room, name='channel_room'), + url(r'^sapl/time-refresh/$', + base.views.time_refresh_log_test, name='time_refresh_log_test_index'), +] + urlpatterns = [ url(r'^sistema/autor/tipo/', include(TipoAutorCrud.get_urls())), @@ -186,8 +195,4 @@ urlpatterns = [ LogotipoView.as_view(), name='logotipo'), - url(r'^channel$', base.views.chanel_index, name='channel_index'), - url(r'^channel/(?P[^/]+)/$', - base.views.chanel_room, name='channel_room'), - -] + recuperar_senha + alterar_senha + admin_user +] + recuperar_senha + alterar_senha + admin_user + channels_url diff --git a/sapl/base/views.py b/sapl/base/views.py index 66c3d093d..d647237fe 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -74,6 +74,10 @@ def chanel_room(request, room_name): }) +def time_refresh_log_test(request): + return render(request, 'base/time_refresh_log_test.html', {}) + + def filtra_url_materias_em_tramitacao(qr, qs, campo_url, local_ou_status): id_materias = [] filtro_url = qr[campo_url] diff --git a/sapl/rules/apps.py b/sapl/rules/apps.py index c0dc19fd8..677383084 100644 --- a/sapl/rules/apps.py +++ b/sapl/rules/apps.py @@ -1,13 +1,17 @@ from builtins import LookupError import logging +from asgiref.sync import async_to_sync +from channels.layers import get_channel_layer import django from django.apps import apps from django.contrib.auth import get_user_model from django.contrib.auth.management import _get_all_permissions from django.core import exceptions from django.db import models, router +from django.db.models.signals import post_save from django.db.utils import DEFAULT_DB_ALIAS +from django.dispatch.dispatcher import receiver from django.utils.translation import string_concat from django.utils.translation import ugettext_lazy as _ import reversion @@ -253,16 +257,52 @@ def cria_usuarios_padrao(): rules.cria_usuarios_padrao() +def send_signal_for_websocket_time_refresh(inst, action): + + if hasattr(inst, '_meta') and inst._meta.app_config.name[:4] == 'sapl': + + # um mensagem não deve ser enviada se é post_save mas originou se de + # revision_pre_delete_signal + + funcs = [] + + if action == 'post_save': + import inspect + funcs = list(filter(lambda x: x == 'revision_pre_delete_signal', + map(lambda x: x[3], inspect.stack()))) + + if not funcs: + channel_layer = get_channel_layer() + + async_to_sync(channel_layer.group_send)( + "group_time_refresh_channel", { + "type": "time_refresh.message", + 'message': { + 'action': action, + 'id': inst.id, + 'app': inst._meta.app_label, + 'model': inst._meta.model_name + } + } + ) + + def revision_pre_delete_signal(sender, **kwargs): + send_signal_for_websocket_time_refresh(kwargs['instance'], 'pre_delete') with reversion.create_revision(): kwargs['instance'].save() reversion.set_comment("Deletado pelo sinal.") +@receiver(post_save, dispatch_uid='sapl_post_save_signal') +def sapl_post_save_signal(sender, instance, using, **kwargs): + + send_signal_for_websocket_time_refresh(instance, 'post_save') + + models.signals.post_migrate.connect( receiver=update_groups) - models.signals.post_migrate.connect( receiver=create_proxy_permissions, dispatch_uid="django.contrib.auth.management.create_permissions") diff --git a/sapl/templates/base/time_refresh_log_test.html b/sapl/templates/base/time_refresh_log_test.html new file mode 100644 index 000000000..ed3adb7d5 --- /dev/null +++ b/sapl/templates/base/time_refresh_log_test.html @@ -0,0 +1,34 @@ + + + + + + Chat Room + + +
+ + + + \ No newline at end of file