def publish_message_to_centrifugo(sender, instance, created, **kwargs): """ Publishes each saved message to Centrifugo. """ if created is True: client = Client( "{0}api/".format(getattr(settings, "CENTRIFUGE_ADDRESS")), getattr(settings, "CENTRIFUGE_SECRET")) # we ensure the client is still in the thread (he may have left or have been removed) active_participants = [ participation.participant.id for participation in Participation.objects.filter( thread=instance.thread, date_left__isnull=True).select_related( 'participant') ] client.publish( build_channel(settings.CENTRIFUGO_MESSAGE_NAMESPACE, instance.thread.id, active_participants), { "id": instance.id, "body": instance.body, "sender": instance.sender.id, "thread": instance.thread.id, "sent_at": str(instance.sent_at), "is_notification": True, # ATTENTION: check against sender too to be sure to not notify him his message })
def publish_participation_to_thread(sender, instance, created, **kwargs): """ Warns users everytime a thread including them is published. This is done via channel subscription. """ if kwargs.get('created_and_add_participants') is True: request_participant_id = kwargs.get('request_participant_id') if request_participant_id is not None: client = Client( "{0}api/".format(getattr(settings, "CENTRIFUGE_ADDRESS")), getattr(settings, "CENTRIFUGE_SECRET")) active_participants = [ participation.participant for participation in Participation.objects.filter( thread=instance, date_left__isnull=True).select_related( 'participant') ] for participant in active_participants: client.publish( build_channel(settings.CENTRIFUGO_THREAD_NAMESPACE, participant.id, [participant.id]), { "message_channel_to_connect_to": build_channel(settings.CENTRIFUGO_MESSAGE_NAMESPACE, instance.id, [p.id for p in active_participants]) })
def test_integration(self): # we hit whatever view just to set the cookie self.selenium.get(self.live_server_url + reverse('dummy')) self.selenium.add_cookie(self.cookie) self.selenium.refresh() # we create threads which call signals telling centrifugo to connect self.thread1 = Thread.managers.get_or_create_thread(self.request, "The #1 Thread", self.participant1.id, self.participant2.id) self.thread2 = Thread.managers.get_or_create_thread(self.request, "The #2 Thread", self.participant1.id, self.participant3.id) # the following conversation does not include the current user, we do not want it on the screen! self.thread_unrelated = Thread.objects.create(name="The unrelated Thread") # the conversation does not involve the current user, we do not want it on the screen! self.participationU1 = Participation.objects.create(participant=self.participant2, thread=self.thread_unrelated) self.participationU2 = Participation.objects.create(participant=self.participant3, thread=self.thread_unrelated) # we load the index page which contains the logic (in javascript) self.selenium.get(self.live_server_url + reverse('index')) # we wait a little bit time.sleep(4) # we create a message # this will trigger a publishing signal in django-rest-messaging-centrifugo body11 = "hi #11" body12 = "hi #12" body21 = "hi #21" body22 = "hi #22" bodyU1 = "We do not want to see this! #1" bodyU2 = "We do not want to see this! #2" m11 = Message.objects.create(sender=self.participant1, thread=self.thread1, body=body11) m12 = Message.objects.create(sender=self.participant2, thread=self.thread1, body=body12) m21 = Message.objects.create(sender=self.participant3, thread=self.thread2, body=body21) m22 = Message.objects.create(sender=self.participant1, thread=self.thread2, body=body22) mU1 = Message.objects.create(sender=self.participant2, thread=self.thread_unrelated, body=bodyU1) mU2 = Message.objects.create(sender=self.participant3, thread=self.thread_unrelated, body=bodyU2) # the channels are private # this means that Centrifugo will check the users ids to know if the user may connect # if we query a private channel the user does not belong to, we never see the message client = Client("{0}api/".format(getattr(settings, "CENTRIFUGE_ADDRESS")), getattr(settings, "CENTRIFUGE_SECRET")) forbidden_message = "Message forbidden" client.publish( build_channel(namespace=settings.CENTRIFUGO_MESSAGE_NAMESPACE, name=self.thread_unrelated.id, user_ids=[p.id for p in self.thread_unrelated.participants.all()]), forbidden_message ) # we wait a little bit time.sleep(4) # now the messages should be displayed m11 = self.selenium.find_element_by_id('message__{0}'.format(m11.id)) m12 = self.selenium.find_element_by_id('message__{0}'.format(m12.id)) m21 = self.selenium.find_element_by_id('message__{0}'.format(m21.id)) m22 = self.selenium.find_element_by_id('message__{0}'.format(m22.id)) self.assertTrue(body11 in m11.text) self.assertTrue(body12 in m12.text) self.assertTrue(body21 in m21.text) self.assertTrue(body22 in m22.text) # the following ensures we get the new threads created during the connection self.thread4 = Thread.managers.get_or_create_thread(self.request, "The #4 Thread", self.participant4.id, self.participant1.id) time.sleep(4) message_channel_to_connect_to = 'messages:4#4,1'.format(self.thread4.id, self.thread4.participants.all()[0].id, self.thread4.participants.all()[1].id) thread_messages = self.selenium.find_element_by_id('thread__{0}'.format(message_channel_to_connect_to)) self.assertTrue(message_channel_to_connect_to in thread_messages.text) # we should not find the unrelated messages self.assertRaises(Exception, self.selenium.find_element_by_id, 'message__{0}'.format(mU1.id)) self.assertRaises(Exception, self.selenium.find_element_by_id, 'message__{0}'.format(mU2.id)) self.assertRaises(Exception, self.selenium.find_element_by_id, 'message__{0}'.format(mU2.id)) self.assertEqual([], self.selenium.find_elements_by_xpath("//*[contains(text(), '{0}')]".format(forbidden_message)))
def get_client_token(user, timestamp): """ Create token to validate information provided by new connection. """ sign = hmac.new(CENT['SECRET']) sign.update(CENT['PROJECT_ID']) sign.update(user) sign.update(timestamp) token = sign.hexdigest() print 'TOKEN = ' + token return token client = Client("http://localhost:8000/api", CENT['PROJECT_ID'], CENT['SECRET']) def select_player(request): return render_to_response('index.html') def page_x(request): timestamp = str(int(time())) return render_to_response( 'game.html', dict({ 'me': 'x', 'enemy': 'o', 'timestamp': timestamp, 'token': get_client_token('x', timestamp)
from cent.core import Client from cent.core import generate_channel_sign import six import time import hmac from hashlib import sha256 centrifuge_host = "http://127.0.0.1:8001" web_secret = "strong_secret" secret = "very-long-secret-key" client = Client(centrifuge_host, secret) def generate_token(secret, user, timestamp, info=""): sign = hmac.new(six.b(secret), digestmod=sha256) sign.update(six.b(user)) sign.update(six.b(timestamp)) sign.update(six.b(info)) return sign.hexdigest() def generate_channel_token(secret, user, info=""): channel_name = "$versionmonitor" + user print(channel_name) auth = hmac.new(six.b(str(secret)), digestmod=sha256) auth.update(six.b(str(client)))
def getConnectin(self): return Client(SETTINGS["URL"], SETTINGS["SECRET"])
def connect(self, url, secret): """ This method is used to connect to centrifuge server """ self.client = Client(url, secret)