예제 #1
0
    def test_webhook_result_timing(self, mock_time):
        mock_time.side_effect = [1, 1, 1, 6, 6]

        sms = self.create_msg(contact=self.joe, direction="I", status="H", text="I'm gonna pop some tags")
        self.setupChannel()
        now = timezone.now()

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            self.assertEqual("C", event.status)
            self.assertEqual(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertIn("not JSON", result.message)
            self.assertEqual(200, result.status_code)
            self.assertEqual(result.request_time, 5000)

            self.assertTrue(mock_time.called)
            self.assertTrue(mock.called)
예제 #2
0
파일: tests.py 프로젝트: hectorip/rapidpro
    def test_call_deliveries(self):
        self.setupChannel()
        now = timezone.now()
        call = ChannelEvent.objects.create(
            org=self.org,
            channel=self.channel,
            contact=self.joe,
            contact_urn=self.joe.get_urn(),
            event_type=ChannelEvent.TYPE_CALL_IN_MISSED,
            occurred_on=now)

        self.setupChannel()

        with patch('requests.Session.send') as mock:
            # clear out which events we listen for, we still shouldnt be notified though we have a webhook
            self.channel.org.webhook_events = 0
            self.channel.org.save()

            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event, shouldnn't fire as we don't have a webhook
            WebHookEvent.trigger_call_event(call)
            self.assertFalse(WebHookEvent.objects.all())

        self.setupChannel()

        with patch('requests.Session.send') as mock:
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_call_event(call)
            event = WebHookEvent.objects.get()

            self.assertEqual('C', event.status)
            self.assertEqual(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertIn("not JSON", result.message)
            self.assertEqual(200, result.status_code)
            self.assertEqual("Hello World", result.body)

            self.assertTrue(mock.called)
            args = mock.call_args_list[0][0]
            prepared_request = args[0]
            self.assertEqual(self.channel.org.get_webhook_url(),
                             prepared_request.url)

            data = parse_qs(prepared_request.body)
            self.assertEqual('+250788123123', data['phone'][0])
            self.assertEqual(six.text_type(self.joe.get_urn(TEL_SCHEME)),
                             data['urn'][0])
            self.assertEqual(self.joe.uuid, data['contact'][0])
            self.assertEqual(self.joe.name, data['contact_name'][0])
            self.assertEqual(call.pk, int(data['call'][0]))
            self.assertEqual(call.event_type, data['event'][0])
            self.assertIn('occurred_on', data)
            self.assertEqual(self.channel.pk, int(data['channel'][0]))
예제 #3
0
    def test_alarm_deliveries(self):
        sync_event = SyncEvent.objects.create(
            channel=self.channel,
            power_source="AC",
            power_status="CHARGING",
            power_level=85,
            network_type="WIFI",
            pending_message_count=5,
            retry_message_count=4,
            incoming_command_count=0,
            created_by=self.admin,
            modified_by=self.admin,
        )

        self.setupChannel()

        with patch("requests.Session.send") as mock:
            # clear out which events we listen for, we still shouldnt be notified though we have a webhook
            self.channel.org.webhook_events = 0
            self.channel.org.save()

            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event, shouldnn't fire as we don't have a webhook
            WebHookEvent.trigger_channel_alarm(sync_event)
            self.assertFalse(WebHookEvent.objects.all())

        self.setupChannel()

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(200, "")

            # trigger an event
            WebHookEvent.trigger_channel_alarm(sync_event)
            event = WebHookEvent.objects.get()

            self.assertEqual("C", event.status)
            self.assertEqual(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertEqual(200, result.status_code)
            self.assertEqual("", result.body)

            self.assertTrue(mock.called)
            args = mock.call_args_list[0][0]
            prepared_request = args[0]
            self.assertEqual(self.channel.org.get_webhook_url(),
                             prepared_request.url)

            data = parse_qs(prepared_request.body)
            self.assertEqual(self.channel.pk, int(data["channel"][0]))
            self.assertEqual(85, int(data["power_level"][0]))
            self.assertEqual("AC", data["power_source"][0])
            self.assertEqual("CHARGING", data["power_status"][0])
            self.assertEqual("WIFI", data["network_type"][0])
            self.assertEqual(5, int(data["pending_message_count"][0]))
            self.assertEqual(4, int(data["retry_message_count"][0]))
예제 #4
0
파일: tests.py 프로젝트: amides/rapidpro
    def test_webhook_event_trim_task(self):
        sms = self.create_msg(contact=self.joe,
                              direction='I',
                              status='H',
                              text="I'm gonna pop some tags")
        self.setupChannel()
        now = timezone.now()

        with patch('requests.Session.send') as mock:
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.get()

            five_hours_ago = timezone.now() - timedelta(hours=5)
            event.created_on = five_hours_ago
            event.save()

            with override_settings(SUCCESS_LOGS_TRIM_TIME=0):
                trim_webhook_event_task()
                self.assertTrue(WebHookEvent.objects.all())
                self.assertTrue(WebHookResult.objects.all())

            with override_settings(SUCCESS_LOGS_TRIM_TIME=12):
                trim_webhook_event_task()
                self.assertTrue(WebHookEvent.objects.all())
                self.assertTrue(WebHookResult.objects.all())

            with override_settings(SUCCESS_LOGS_TRIM_TIME=2):
                trim_webhook_event_task()
                self.assertFalse(WebHookEvent.objects.all())
                self.assertFalse(WebHookResult.objects.all())

            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.get()

            five_hours_ago = timezone.now() - timedelta(hours=5)
            event.created_on = five_hours_ago
            event.status = FAILED
            event.save()

            with override_settings(ALL_LOGS_TRIM_TIME=0):
                trim_webhook_event_task()
                self.assertTrue(WebHookEvent.objects.all())
                self.assertTrue(WebHookResult.objects.all())

            with override_settings(ALL_LOGS_TRIM_TIME=12):
                trim_webhook_event_task()
                self.assertTrue(WebHookEvent.objects.all())
                self.assertTrue(WebHookResult.objects.all())

            with override_settings(ALL_LOGS_TRIM_TIME=2):
                trim_webhook_event_task()
                self.assertFalse(WebHookEvent.objects.all())
                self.assertFalse(WebHookResult.objects.all())
예제 #5
0
    def test_alarm_deliveries(self):
        sync_event = SyncEvent.objects.create(
            channel=self.channel,
            power_source="AC",
            power_status="CHARGING",
            power_level=85,
            network_type="WIFI",
            pending_message_count=5,
            retry_message_count=4,
            incoming_command_count=0,
            created_by=self.admin,
            modified_by=self.admin,
        )

        self.setupChannel()

        with patch("requests.Session.send") as mock:
            # clear out which events we listen for, we still shouldnt be notified though we have a webhook
            self.channel.org.webhook_events = 0
            self.channel.org.save()

            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event, shouldnn't fire as we don't have a webhook
            WebHookEvent.trigger_channel_alarm(sync_event)
            self.assertFalse(WebHookEvent.objects.all())

        self.setupChannel()

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(200, "")

            # trigger an event
            WebHookEvent.trigger_channel_alarm(sync_event)
            event = WebHookEvent.objects.get()

            self.assertEqual("C", event.status)
            self.assertEqual(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertEqual(200, result.status_code)
            self.assertEqual("", result.body)

            self.assertTrue(mock.called)
            args = mock.call_args_list[0][0]
            prepared_request = args[0]
            self.assertEqual(self.channel.org.get_webhook_url(), prepared_request.url)

            data = parse_qs(prepared_request.body)
            self.assertEqual(self.channel.pk, int(data["channel"][0]))
            self.assertEqual(85, int(data["power_level"][0]))
            self.assertEqual("AC", data["power_source"][0])
            self.assertEqual("CHARGING", data["power_status"][0])
            self.assertEqual("WIFI", data["network_type"][0])
            self.assertEqual(5, int(data["pending_message_count"][0]))
            self.assertEqual(4, int(data["retry_message_count"][0]))
예제 #6
0
    def test_call_deliveries(self):
        self.setupChannel()
        now = timezone.now()
        call = ChannelEvent.objects.create(
            org=self.org,
            channel=self.channel,
            contact=self.joe,
            contact_urn=self.joe.get_urn(),
            event_type=ChannelEvent.TYPE_CALL_IN_MISSED,
            occurred_on=now,
        )

        self.setupChannel()

        with patch("requests.Session.send") as mock:
            # clear out which events we listen for, we still shouldnt be notified though we have a webhook
            self.channel.org.webhook_events = 0
            self.channel.org.save()

            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event, shouldnn't fire as we don't have a webhook
            WebHookEvent.trigger_call_event(call)
            self.assertFalse(WebHookEvent.objects.all())

        self.setupChannel()

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_call_event(call)
            event = WebHookEvent.objects.get()

            self.assertEqual("C", event.status)
            self.assertEqual(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertIn("not JSON", result.message)
            self.assertEqual(200, result.status_code)
            self.assertEqual("Hello World", result.body)

            self.assertTrue(mock.called)
            args = mock.call_args_list[0][0]
            prepared_request = args[0]
            self.assertEqual(self.channel.org.get_webhook_url(), prepared_request.url)

            data = parse_qs(prepared_request.body)
            self.assertEqual("+250788123123", data["phone"][0])
            self.assertEqual(str(self.joe.get_urn(TEL_SCHEME)), data["urn"][0])
            self.assertEqual(self.joe.uuid, data["contact"][0])
            self.assertEqual(self.joe.name, data["contact_name"][0])
            self.assertEqual(call.pk, int(data["call"][0]))
            self.assertEqual(call.event_type, data["event"][0])
            self.assertIn("occurred_on", data)
            self.assertEqual(self.channel.pk, int(data["channel"][0]))
예제 #7
0
    def test_webhook_event_trim_task(self):
        sms = self.create_msg(contact=self.joe, direction="I", status="H", text="I'm gonna pop some tags")
        self.setupChannel()
        now = timezone.now()

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            five_hours_ago = timezone.now() - timedelta(hours=5)
            event.created_on = five_hours_ago
            event.save()

            with override_settings(SUCCESS_LOGS_TRIM_TIME=0):
                trim_webhook_event_task()
                self.assertTrue(WebHookEvent.objects.all())
                self.assertTrue(WebHookResult.objects.all())

            with override_settings(SUCCESS_LOGS_TRIM_TIME=12):
                trim_webhook_event_task()
                self.assertTrue(WebHookEvent.objects.all())
                self.assertTrue(WebHookResult.objects.all())

            with override_settings(SUCCESS_LOGS_TRIM_TIME=2):
                trim_webhook_event_task()
                self.assertFalse(WebHookEvent.objects.all())
                self.assertFalse(WebHookResult.objects.all())

            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            five_hours_ago = timezone.now() - timedelta(hours=5)
            event.created_on = five_hours_ago
            event.status = FAILED
            event.save()

            with override_settings(ALL_LOGS_TRIM_TIME=0):
                trim_webhook_event_task()
                self.assertTrue(WebHookEvent.objects.all())
                self.assertTrue(WebHookResult.objects.all())

            with override_settings(ALL_LOGS_TRIM_TIME=12):
                trim_webhook_event_task()
                self.assertTrue(WebHookEvent.objects.all())
                self.assertTrue(WebHookResult.objects.all())

            with override_settings(ALL_LOGS_TRIM_TIME=2):
                trim_webhook_event_task()
                self.assertFalse(WebHookEvent.objects.all())
                self.assertFalse(WebHookResult.objects.all())
예제 #8
0
파일: tests.py 프로젝트: amides/rapidpro
    def test_event_deliveries(self):
        sms = self.create_msg(contact=self.joe,
                              direction='I',
                              status='H',
                              text="I'm gonna pop some tags")

        with patch('requests.Session.send') as mock:
            now = timezone.now()
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event, shouldnn't fire as we don't have a webhook
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            self.assertFalse(WebHookEvent.objects.all())

        self.setupChannel()

        with patch('requests.Session.send') as mock:
            # clear out which events we listen for, we still shouldnt be notified though we have a webhook
            self.channel.org.webhook_events = 0
            self.channel.org.save()

            now = timezone.now()
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event, shouldnn't fire as we don't have a webhook
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            self.assertFalse(WebHookEvent.objects.all())

        self.setupChannel()

        with patch('requests.Session.send') as mock:
            # remove all the org users
            self.org.administrators.clear()
            self.org.editors.clear()
            self.org.viewers.clear()

            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.get()

            self.assertEquals('F', event.status)
            self.assertEquals(0, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("No active user", result.message)
            self.assertEquals(0, result.status_code)

            self.assertFalse(mock.called)

            # what if they send weird json back?
            WebHookEvent.objects.all().delete()
            WebHookResult.objects.all().delete()

        # add ad manager back in
        self.org.administrators.add(self.admin)
        self.admin.set_org(self.org)

        with patch('requests.Session.send') as mock:
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.get()

            self.assertEquals('C', event.status)
            self.assertEquals(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertIn("not JSON", result.message)
            self.assertEquals(200, result.status_code)

            self.assertTrue(mock.called)

            WebHookEvent.objects.all().delete()
            WebHookResult.objects.all().delete()

        with patch('requests.Session.send') as mock:
            mock.side_effect = [MockResponse(500, "I am error")]

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.all().first()

            self.assertEquals('E', event.status)
            self.assertEquals(1, event.try_count)
            self.assertTrue(event.next_attempt)

            mock.return_value = MockResponse(200, "Hello World")
            # simulate missing channel
            event.channel = None
            event.save()

            # no exception should raised
            event.deliver()

            self.assertTrue(mock.called)
            self.assertEquals(mock.call_count, 2)

            WebHookEvent.objects.all().delete()
            WebHookResult.objects.all().delete()

        with patch('requests.Session.send') as mock:
            # valid json, but not our format
            bad_json = '{ "thrift_shops": ["Goodwill", "Value Village"] }'
            mock.return_value = MockResponse(200, bad_json)

            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.get()

            self.assertEquals('C', event.status)
            self.assertEquals(1, event.try_count)
            self.assertFalse(event.next_attempt)

            self.assertTrue(mock.called)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertIn("ignoring", result.message)
            self.assertEquals(200, result.status_code)
            self.assertEquals(bad_json, result.body)

            WebHookEvent.objects.all().delete()
            WebHookResult.objects.all().delete()

        with patch('requests.Session.send') as mock:
            mock.return_value = MockResponse(
                200, '{ "phone": "+250788123123", "text": "I am success" }')

            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.get()

            self.assertEquals('C', event.status)
            self.assertEquals(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertEquals(200, result.status_code)

            self.assertTrue(mock.called)

            broadcast = Broadcast.objects.get()
            contact = Contact.get_or_create(self.org,
                                            self.admin,
                                            name=None,
                                            urns=["tel:+250788123123"],
                                            channel=self.channel)
            self.assertTrue(broadcast.text, {'base': "I am success"})
            self.assertTrue(contact, broadcast.contacts.all())

            self.assertTrue(mock.called)
            args = mock.call_args_list[0][0]
            prepared_request = args[0]
            self.assertEquals(self.org.get_webhook_url(), prepared_request.url)

            data = parse_qs(prepared_request.body)
            self.assertEquals(
                self.joe.get_urn(TEL_SCHEME).path, data['phone'][0])
            self.assertEquals(six.text_type(self.joe.get_urn(TEL_SCHEME)),
                              data['urn'][0])
            self.assertEquals(self.joe.uuid, data['contact'][0])
            self.assertEquals(self.joe.name, data['contact_name'][0])
            self.assertEquals(sms.pk, int(data['sms'][0]))
            self.assertEquals(self.channel.pk, int(data['channel'][0]))
            self.assertEquals(WebHookEvent.TYPE_SMS_RECEIVED, data['event'][0])
            self.assertEquals("I'm gonna pop some tags", data['text'][0])
            self.assertTrue('time' in data)

            WebHookEvent.objects.all().delete()
            WebHookResult.objects.all().delete()

        with patch('requests.Session.send') as mock:
            mock.return_value = MockResponse(500, "I am error")

            next_attempt_earliest = timezone.now() + timedelta(minutes=4)
            next_attempt_latest = timezone.now() + timedelta(minutes=6)

            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.get()

            self.assertEquals('E', event.status)
            self.assertEquals(1, event.try_count)
            self.assertTrue(event.next_attempt)
            self.assertTrue(next_attempt_earliest < event.next_attempt
                            and next_attempt_latest > event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Error", result.message)
            self.assertEquals(500, result.status_code)
            self.assertEquals("I am error", result.body)

            # make sure things become failures after three retries
            event.try_count = 2
            event.deliver()
            event.save()

            self.assertTrue(mock.called)

            self.assertEquals('F', event.status)
            self.assertEquals(3, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Error", result.message)
            self.assertEquals(500, result.status_code)
            self.assertEquals("I am error", result.body)
            self.assertEquals("http://fake.com/webhook.php", result.url)
            self.assertTrue(result.data.find("pop+some+tags") > 0)

            # check out our api log
            response = self.client.get(reverse('api.log'))
            self.assertRedirect(response, reverse('users.user_login'))

            response = self.client.get(reverse('api.log_read',
                                               args=[event.pk]))
            self.assertRedirect(response, reverse('users.user_login'))

            WebHookEvent.objects.all().delete()
            WebHookResult.objects.all().delete()

        # add a webhook header to the org
        self.channel.org.webhook = u'{"url": "http://fake.com/webhook.php", "headers": {"X-My-Header": "foobar", "Authorization": "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="}, "method": "POST"}'
        self.channel.org.save()

        # check that our webhook settings have saved
        self.assertEquals('http://fake.com/webhook.php',
                          self.channel.org.get_webhook_url())
        self.assertDictEqual(
            {
                'X-My-Header':
                'foobar',
                'Authorization':
                'Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='
            }, self.channel.org.get_webhook_headers())

        with patch('requests.Session.send') as mock:
            mock.return_value = MockResponse(200, "Boom")
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms,
                                           now)
            event = WebHookEvent.objects.get()

            result = WebHookResult.objects.get()
            # both headers should be in the json-encoded url string
            self.assertIn('X-My-Header: foobar', result.request)
            self.assertIn(
                'Authorization: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==',
                result.request)
예제 #9
0
    def test_event_deliveries(self):
        sms = self.create_msg(contact=self.joe, direction="I", status="H", text="I'm gonna pop some tags")

        with patch("requests.Session.send") as mock:
            now = timezone.now()
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event, shouldnn't fire as we don't have a webhook
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            self.assertFalse(WebHookEvent.objects.all())

        self.setupChannel()

        with patch("requests.Session.send") as mock:
            # clear out which events we listen for, we still shouldnt be notified though we have a webhook
            self.channel.org.webhook_events = 0
            self.channel.org.save()

            now = timezone.now()
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event, shouldnn't fire as we don't have a webhook
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            self.assertFalse(WebHookEvent.objects.all())

        self.setupChannel()

        with patch("requests.Session.send") as mock:
            # remove all the org users
            self.org.administrators.clear()
            self.org.editors.clear()
            self.org.viewers.clear()

            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            self.assertEqual("F", event.status)
            self.assertEqual(0, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("No active user", result.message)
            self.assertEqual(0, result.status_code)

            self.assertFalse(mock.called)

            # what if they send weird json back?
            self.release(WebHookEvent.objects.all())

        # add ad manager back in
        self.org.administrators.add(self.admin)
        self.admin.set_org(self.org)

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(200, "Hello World")

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            self.assertEqual("C", event.status)
            self.assertEqual(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertIn("not JSON", result.message)
            self.assertEqual(200, result.status_code)

            self.assertTrue(mock.called)

            self.release(WebHookEvent.objects.all())

        with patch("requests.Session.send") as mock:
            mock.side_effect = [MockResponse(500, "I am error")]

            # trigger an event
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.all().first()

            self.assertEqual("E", event.status)
            self.assertEqual(1, event.try_count)
            self.assertTrue(event.next_attempt)

            mock.return_value = MockResponse(200, "Hello World")
            # simulate missing channel
            event.channel = None
            event.save()

            # no exception should raised
            event.deliver()

            self.assertTrue(mock.called)
            self.assertEqual(mock.call_count, 2)

            self.release(WebHookEvent.objects.all())

        with patch("requests.Session.send") as mock:
            # valid json, but not our format
            bad_json = '{ "thrift_shops": ["Goodwill", "Value Village"] }'
            mock.return_value = MockResponse(200, bad_json)

            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            self.assertEqual("C", event.status)
            self.assertEqual(1, event.try_count)
            self.assertFalse(event.next_attempt)

            self.assertTrue(mock.called)

            result = WebHookResult.objects.get()
            self.assertIn("Event delivered successfully", result.message)
            self.assertIn("ignoring", result.message)
            self.assertEqual(200, result.status_code)
            self.assertEqual(bad_json, result.body)

            self.release(WebHookEvent.objects.all())

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(200, '{ "phone": "+250788123123", "text": "I am success" }')

            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            self.assertEqual("C", event.status)
            self.assertEqual(1, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertEqual(200, result.status_code)

            self.assertTrue(mock.called)

            broadcast = Broadcast.objects.get()
            contact, urn_obj = Contact.get_or_create(self.org, "tel:+250788123123", self.channel, user=self.admin)
            self.assertTrue(broadcast.text, {"base": "I am success"})
            self.assertTrue(contact, broadcast.contacts.all())

            self.assertTrue(mock.called)
            args = mock.call_args_list[0][0]
            prepared_request = args[0]
            self.assertEqual(self.org.get_webhook_url(), prepared_request.url)

            data = parse_qs(prepared_request.body)
            self.assertEqual(self.joe.get_urn(TEL_SCHEME).path, data["phone"][0])
            self.assertEqual(str(self.joe.get_urn(TEL_SCHEME)), data["urn"][0])
            self.assertEqual(self.joe.uuid, data["contact"][0])
            self.assertEqual(self.joe.name, data["contact_name"][0])
            self.assertEqual(sms.pk, int(data["sms"][0]))
            self.assertEqual(self.channel.pk, int(data["channel"][0]))
            self.assertEqual(WebHookEvent.TYPE_SMS_RECEIVED, data["event"][0])
            self.assertEqual("I'm gonna pop some tags", data["text"][0])
            self.assertIn("time", data)

            self.release(WebHookEvent.objects.all())

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(500, "I am error")

            next_attempt_earliest = timezone.now() + timedelta(minutes=4)
            next_attempt_latest = timezone.now() + timedelta(minutes=6)

            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            self.assertEqual("E", event.status)
            self.assertEqual(1, event.try_count)
            self.assertTrue(event.next_attempt)
            self.assertTrue(next_attempt_earliest < event.next_attempt and next_attempt_latest > event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Error", result.message)
            self.assertEqual(500, result.status_code)
            self.assertEqual("I am error", result.body)

            # make sure things become failures after three retries
            event.try_count = 2
            event.deliver()
            event.save()

            self.assertTrue(mock.called)

            self.assertEqual("F", event.status)
            self.assertEqual(3, event.try_count)
            self.assertFalse(event.next_attempt)

            result = WebHookResult.objects.get()
            self.assertIn("Error", result.message)
            self.assertEqual(500, result.status_code)
            self.assertEqual("I am error", result.body)
            self.assertEqual("http://fake.com/webhook.php", result.url)
            self.assertTrue(result.data.find("pop+some+tags") > 0)

            # check out our api log
            response = self.client.get(reverse("api.log"))
            self.assertRedirect(response, reverse("users.user_login"))

            response = self.client.get(reverse("api.log_read", args=[event.pk]))
            self.assertRedirect(response, reverse("users.user_login"))

            self.release(WebHookEvent.objects.all())

        # add a webhook header to the org
        self.channel.org.webhook = {
            "url": "http://fake.com/webhook.php",
            "headers": {"X-My-Header": "foobar", "Authorization": "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="},
            "method": "POST",
        }
        self.channel.org.save()

        # check that our webhook settings have saved
        self.assertEqual("http://fake.com/webhook.php", self.channel.org.get_webhook_url())
        self.assertDictEqual(
            {"X-My-Header": "foobar", "Authorization": "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="},
            self.channel.org.get_webhook_headers(),
        )

        with patch("requests.Session.send") as mock:
            mock.return_value = MockResponse(200, "Boom")
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, sms, now)
            event = WebHookEvent.objects.get()

            result = WebHookResult.objects.get()
            # both headers should be in the json-encoded url string
            self.assertIn("X-My-Header: foobar", result.request)
            self.assertIn("Authorization: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", result.request)
예제 #10
0
    def post(self, request, *args, **kwargs):
        from temba.triggers.tasks import fire_follow_triggers

        if not settings.MAGE_AUTH_TOKEN:  # pragma: no cover
            return JsonResponse(dict(error="Authentication not configured"),
                                status=401)

        authorization = request.META.get('HTTP_AUTHORIZATION', '').split(' ')

        if len(authorization) != 2 or authorization[
                0] != 'Token' or authorization[1] != settings.MAGE_AUTH_TOKEN:
            return JsonResponse(dict(error="Incorrect authentication token"),
                                status=401)

        action = kwargs['action'].lower()
        new_contact = request.POST.get('new_contact',
                                       '').lower() in ('true', '1')

        if action == 'handle_message':
            try:
                msg_id = int(request.POST.get('message_id', ''))
            except ValueError:
                return JsonResponse(dict(error="Invalid message_id"),
                                    status=400)

            msg = Msg.objects.select_related('org').get(pk=msg_id)

            push_task(
                msg.org, HANDLER_QUEUE, HANDLE_EVENT_TASK,
                dict(type=MSG_EVENT,
                     id=msg.id,
                     from_mage=True,
                     new_contact=new_contact))

            # fire an event off for this message
            WebHookEvent.trigger_sms_event(WebHookEvent.TYPE_SMS_RECEIVED, msg,
                                           msg.created_on)

        elif action == 'follow_notification':
            try:
                channel_id = int(request.POST.get('channel_id', ''))
                contact_urn_id = int(request.POST.get('contact_urn_id', ''))
            except ValueError:  # pragma: needs cover
                return JsonResponse(
                    dict(error="Invalid channel or contact URN id"),
                    status=400)

            on_transaction_commit(lambda: fire_follow_triggers.apply_async(
                args=(channel_id, contact_urn_id, new_contact),
                queue='handler'))

        elif action == 'stop_contact':
            contact = Contact.objects.filter(is_active=True,
                                             id=request.POST.get(
                                                 'contact_id', '-1')).first()
            if not contact:
                return JsonResponse(dict(error="Invalid contact_id"),
                                    status=400)

            contact.stop(contact.modified_by)

        return JsonResponse(dict(error=None))