def test_fail_request(self) -> None:
        bot_user = self.example_user('outgoing_webhook_bot')
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        response = ResponseMock(400)
        expect_400 = mock.patch("requests.request", return_value=response)
        expect_fail = mock.patch(
            "zerver.lib.outgoing_webhook.fail_with_message")
        expect_warnings = mock.patch("logging.warning")

        with expect_400, expect_fail as mock_fail, expect_warnings:
            do_rest_call('', None, mock_event, service_handler)

        self.assertTrue(mock_fail.called)

        bot_owner_notification = self.get_last_message()
        self.assertEqual(
            bot_owner_notification.content,
            '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) triggered an outgoing webhook.
The webhook got a response with status code *400*.''')

        assert bot_user.bot_owner is not None
        self.assertEqual(bot_owner_notification.recipient_id,
                         bot_user.bot_owner.id)
Beispiel #2
0
 def test_successful_request(self, mock_succeed_with_message):
     # type: (mock.Mock) -> None
     response = ResponseMock(200)
     with mock.patch('requests.request', return_value=response):
         do_rest_call(self.rest_operation, None, self.mock_event,
                      service_handler, None)
         self.assertTrue(mock_succeed_with_message.called)
Beispiel #3
0
    def test_jsonable_exception(self) -> None:
        bot_user = self.example_user("outgoing_webhook_bot")
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        # The "widget_content" key is required to be a string which is
        # itself JSON-encoded; passing arbitrary text data in it will
        # cause the hook to fail.
        response = {"content": "whatever", "widget_content": "test"}
        expect_logging_info = self.assertLogs(level="INFO")
        expect_fail = mock.patch(
            "zerver.lib.outgoing_webhook.fail_with_message")

        with responses.RequestsMock(
                assert_all_requests_are_fired=True) as requests_mock:
            requests_mock.add(requests_mock.POST,
                              "https://example.zulip.com",
                              status=200,
                              json=response)
            with expect_logging_info, expect_fail as mock_fail:
                do_rest_call("https://example.zulip.com", mock_event,
                             service_handler)
            self.assertTrue(mock_fail.called)
            bot_owner_notification = self.get_last_message()
            self.assertEqual(
                bot_owner_notification.content,
                """[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) to your bot @_**Outgoing Webhook** triggered an outgoing webhook.
The outgoing webhook server attempted to send a message in Zulip, but that request resulted in the following error:
> Widgets: API programmer sent invalid JSON content\nThe response contains the following payload:\n```\n'{"content": "whatever", "widget_content": "test"}'\n```""",
            )
        assert bot_user.bot_owner is not None
        self.assertEqual(bot_owner_notification.recipient_id,
                         bot_user.bot_owner.recipient_id)
    def test_request_exception(self) -> None:
        bot_user = self.example_user('outgoing_webhook_bot')
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        expect_request_exception = mock.patch(
            "requests.request", side_effect=request_exception_error)
        expect_logging_exception = mock.patch("logging.exception")
        expect_fail = mock.patch(
            "zerver.lib.outgoing_webhook.fail_with_message")

        with expect_request_exception, expect_logging_exception, expect_fail as mock_fail:
            do_rest_call('', None, mock_event, service_handler)

        self.assertTrue(mock_fail.called)

        bot_owner_notification = self.get_last_message()
        self.assertEqual(
            bot_owner_notification.content,
            '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) triggered an outgoing webhook.
When trying to send a request to the webhook service, an exception of type RequestException occurred:
```
I'm a generic exception :(
```''')
        assert bot_user.bot_owner is not None
        self.assertEqual(bot_owner_notification.recipient_id,
                         bot_user.bot_owner.id)
Beispiel #5
0
    def test_successful_request(self) -> None:
        bot_user = self.example_user("outgoing_webhook_bot")
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        expect_send_response = mock.patch(
            "zerver.lib.outgoing_webhook.send_response_message")
        with mock.patch.object(
                service_handler,
                "session") as session, expect_send_response as mock_send:
            session.post.return_value = ResponseMock(
                200, orjson.dumps(dict(content="whatever")))
            with self.assertLogs(level="INFO") as logs:
                do_rest_call("", mock_event, service_handler)
            self.assert_length(logs.output, 1)
            self.assertIn(
                f"Outgoing webhook request from {bot_user.id}@zulip took ",
                logs.output[0])

        self.assertTrue(mock_send.called)

        for service_class in [
                GenericOutgoingWebhookService, SlackOutgoingWebhookService
        ]:
            handler = service_class("token", bot_user, "service")
            with mock.patch.object(handler, "session") as session:
                session.post.return_value = ResponseMock(200, b"{}")
                with self.assertLogs(level="INFO") as logs:
                    do_rest_call("", mock_event, handler)
                self.assert_length(logs.output, 1)
                self.assertIn(
                    f"Outgoing webhook request from {bot_user.id}@zulip took ",
                    logs.output[0])
                session.post.assert_called_once()
        def _helper(content: Optional[str]) -> None:
            expect_send_response = mock.patch(
                "zerver.lib.outgoing_webhook.send_response_message")
            with mock.patch.object(
                    service_handler,
                    "session") as session, expect_send_response as mock_send:
                session.post.return_value = ResponseMock(
                    200, orjson.dumps(dict(content=content)))
                with self.assertLogs(level="INFO") as logs:
                    do_rest_call("", mock_event, service_handler)
                self.assert_length(logs.output, 1)
                self.assertIn(
                    f"Outgoing webhook request from {bot_user.id}@zulip took ",
                    logs.output[0])

            if content == "":
                self.assertFalse(mock_send.called)
            else:
                self.assertTrue(mock_send.called)

            for service_class in [
                    GenericOutgoingWebhookService, SlackOutgoingWebhookService
            ]:
                handler = service_class("token", bot_user, "service")
                with mock.patch.object(handler, "session") as session:
                    session.post.return_value = ResponseMock(200, b"{}")
                    with self.assertLogs(level="INFO") as logs:
                        do_rest_call("", mock_event, handler)
                    self.assert_length(logs.output, 1)
                    self.assertIn(
                        f"Outgoing webhook request from {bot_user.id}@zulip took ",
                        logs.output[0])
                    session.post.assert_called_once()
Beispiel #7
0
    def test_request_exception(self) -> None:
        bot_user = self.example_user('outgoing_webhook_bot')
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        expect_request_exception = mock.patch(
            "requests.request", side_effect=request_exception_error)
        expect_logging_exception = self.assertLogs(level="ERROR")
        expect_fail = mock.patch(
            "zerver.lib.outgoing_webhook.fail_with_message")

        # Don't think that we should catch and assert whole log output(which is actually a very big error traceback).
        # We are already asserting bot_owner_notification.content which verifies exception did occur.
        with expect_request_exception, expect_logging_exception, expect_fail as mock_fail:
            do_rest_call('', None, mock_event, service_handler)

        self.assertTrue(mock_fail.called)

        bot_owner_notification = self.get_last_message()
        self.assertEqual(
            bot_owner_notification.content,
            '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) triggered an outgoing webhook.
When trying to send a request to the webhook service, an exception of type RequestException occurred:
```
I'm a generic exception :(
```''')
        assert bot_user.bot_owner is not None
        self.assertEqual(bot_owner_notification.recipient_id,
                         bot_user.bot_owner.id)
Beispiel #8
0
    def test_invalid_json_in_response(self) -> None:
        bot_user = self.example_user("outgoing_webhook_bot")
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        expect_logging_info = self.assertLogs(level="INFO")
        expect_fail = mock.patch(
            "zerver.lib.outgoing_webhook.fail_with_message")

        with responses.RequestsMock(
                assert_all_requests_are_fired=True) as requests_mock:
            # We mock the endpoint to return response with a body which isn't valid json.
            requests_mock.add(
                requests_mock.POST,
                "https://example.zulip.com",
                status=200,
                body="this isn't valid json",
            )
            with expect_logging_info, expect_fail as mock_fail:
                do_rest_call("https://example.zulip.com", mock_event,
                             service_handler)
            self.assertTrue(mock_fail.called)
            bot_owner_notification = self.get_last_message()
            self.assertEqual(
                bot_owner_notification.content,
                """[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) to your bot @_**Outgoing Webhook** triggered an outgoing webhook.
The outgoing webhook server attempted to send a message in Zulip, but that request resulted in the following error:
> Invalid JSON in response\nThe response contains the following payload:\n```\n"this isn't valid json"\n```""",
            )
        assert bot_user.bot_owner is not None
        self.assertEqual(bot_owner_notification.recipient_id,
                         bot_user.bot_owner.recipient_id)
 def helper(side_effect: Any, error_text: str) -> None:
     with mock.patch('logging.info'):
         with mock.patch('requests.request', side_effect=side_effect):
             do_rest_call('', None, self.mock_event, service_handler)
             bot_owner_notification = self.get_last_message()
             self.assertIn(error_text, bot_owner_notification.content)
             self.assertIn('triggered', bot_owner_notification.content)
             self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
Beispiel #10
0
    def consume(self, event: Dict[str, Any]) -> None:
        message = event["message"]
        event["command"] = message["content"]

        services = get_bot_services(event["user_profile_id"])
        for service in services:
            event["service_name"] = str(service.name)
            service_handler = get_outgoing_webhook_service_handler(service)
            do_rest_call(service.base_url, event, service_handler)
 def helper(side_effect: Any, error_text: str) -> None:
     with mock.patch('logging.info'):
         with mock.patch('requests.request', side_effect=side_effect):
             do_rest_call('', None, self.mock_event, service_handler)
             bot_owner_notification = self.get_last_message()
             self.assertIn(error_text, bot_owner_notification.content)
             self.assertIn('triggered', bot_owner_notification.content)
             self.assertEqual(bot_owner_notification.recipient_id,
                              self.bot_user.bot_owner.id)
Beispiel #12
0
    def test_timeout_request(self, mock_requests_request: mock.Mock, mock_logger: mock.Mock) -> None:
        do_rest_call(self.rest_operation, None, self.mock_event, service_handler, None)
        bot_owner_notification = self.get_last_message()
        self.assertEqual(bot_owner_notification.content,
                         '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/subject/Foo/near/) triggered an outgoing webhook.
When trying to send a request to the webhook service, an exception of type Timeout occurred:
```
Time is up!
```''')
        self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
    def test_timeout_request(self, mock_requests_request: mock.Mock, mock_logger: mock.Mock) -> None:
        do_rest_call(self.rest_operation, None, self.mock_event, service_handler, None)
        bot_owner_notification = self.get_last_message()
        self.assertEqual(bot_owner_notification.content,
                         '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/subject/Foo/near/) triggered an outgoing webhook.
When trying to send a request to the webhook service, an exception of type Timeout occurred:
```
Time is up!
```''')
        self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
Beispiel #14
0
    def test_fail_request(self, mock_fail_with_message: mock.Mock) -> None:
        response = ResponseMock(400)
        with mock.patch('requests.request', return_value=response):
            do_rest_call(self.rest_operation, None, self.mock_event, service_handler, None)
            bot_owner_notification = self.get_last_message()
            self.assertTrue(mock_fail_with_message.called)
            self.assertEqual(bot_owner_notification.content,
                             '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/subject/Foo/near/) triggered an outgoing webhook.
The webhook got a response with status code *400*.''')
            self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
    def test_fail_request(self, mock_fail_with_message: mock.Mock) -> None:
        response = ResponseMock(400)
        with mock.patch('requests.request', return_value=response):
            do_rest_call(self.rest_operation, None, self.mock_event, service_handler, None)
            bot_owner_notification = self.get_last_message()
            self.assertTrue(mock_fail_with_message.called)
            self.assertEqual(bot_owner_notification.content,
                             '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/subject/Foo/near/) triggered an outgoing webhook.
The webhook got a response with status code *400*.''')
            self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
Beispiel #16
0
        def helper(side_effect: Any, error_text: str) -> None:
            with mock.patch.object(service_handler, "session") as session:
                session.post.side_effect = side_effect
                do_rest_call("", mock_event, service_handler)

            bot_owner_notification = self.get_last_message()
            self.assertIn(error_text, bot_owner_notification.content)
            self.assertIn("triggered", bot_owner_notification.content)
            assert bot_user.bot_owner is not None
            self.assertEqual(bot_owner_notification.recipient_id, bot_user.bot_owner.recipient_id)
Beispiel #17
0
    def consume(self, event: Mapping[str, Any]) -> None:
        message = event['message']
        dup_event = cast(Dict[str, Any], event)
        dup_event['command'] = message['content']

        services = get_bot_services(event['user_profile_id'])
        for service in services:
            dup_event['service_name'] = str(service.name)
            service_handler = get_outgoing_webhook_service_handler(service)
            rest_operation, request_data = service_handler.process_event(dup_event)
            do_rest_call(rest_operation, request_data, dup_event, service_handler)
    def test_successful_request(self, mock_send: mock.Mock) -> None:
        response = ResponseMock(200, dict(content='whatever'))
        with mock.patch('requests.request', return_value=response):
            do_rest_call('', None, self.mock_event, service_handler)
            self.assertTrue(mock_send.called)

        for service_class in [GenericOutgoingWebhookService, SlackOutgoingWebhookService]:
            handler = service_class(None, None, None)
            with mock.patch('requests.request', return_value=response):
                do_rest_call('', None, self.mock_event, handler)
                self.assertTrue(mock_send.called)
Beispiel #19
0
    def consume(self, event: Mapping[str, Any]) -> None:
        message = event['message']
        dup_event = cast(Dict[str, Any], event)
        dup_event['command'] = message['content']

        services = get_bot_services(event['user_profile_id'])
        for service in services:
            dup_event['service_name'] = str(service.name)
            service_handler = get_outgoing_webhook_service_handler(service)
            rest_operation, request_data = service_handler.process_event(dup_event)
            do_rest_call(rest_operation, request_data, dup_event, service_handler)
    def test_request_exception(self, mock_fail_with_message, mock_requests_request, mock_logger):
        # type: (mock.Mock, mock.Mock, mock.Mock) -> None
        do_rest_call(self.rest_operation, None, self.mock_event, service_handler, None)
        bot_owner_notification = self.get_last_message()
        self.assertTrue(mock_fail_with_message.called)
        self.assertEqual(bot_owner_notification.content,
                         '''[A message](http://zulip.testserver/#narrow/stream/Verona/subject/Foo/near/) triggered an outgoing webhook.
When trying to send a request to the webhook service, an exception of type RequestException occured:
```
I'm a generic exception :(
```''')
        self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
    def test_headers(self) -> None:
        with mock.patch('requests.request') as mock_request:
            do_rest_call('', 'payload-stub', self.mock_event, service_handler)
            kwargs = mock_request.call_args[1]
            self.assertEqual(kwargs['data'], 'payload-stub')

            user_agent = 'ZulipOutgoingWebhook/' + ZULIP_VERSION
            headers = {
                'content-type': 'application/json',
                'User-Agent': user_agent,
            }
            self.assertEqual(kwargs['headers'], headers)
    def test_headers(self) -> None:
        with mock.patch('requests.request') as mock_request:
            do_rest_call('', 'payload-stub', self.mock_event, service_handler)
            kwargs = mock_request.call_args[1]
            self.assertEqual(kwargs['data'], 'payload-stub')

            user_agent = 'ZulipOutgoingWebhook/' + ZULIP_VERSION
            headers = {
                'content-type': 'application/json',
                'User-Agent': user_agent,
            }
            self.assertEqual(kwargs['headers'], headers)
    def test_retry_request(self: mock.Mock) -> None:
        response = ResponseMock(500)

        self.mock_event['failed_tries'] = 3
        with mock.patch('requests.request', return_value=response):
            do_rest_call('',  None, self.mock_event, service_handler)
            bot_owner_notification = self.get_last_message()
            self.assertEqual(bot_owner_notification.content,
                             '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) triggered an outgoing webhook.
The webhook got a response with status code *500*.''')
            self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
        self.mock_event['failed_tries'] = 0
Beispiel #24
0
    def consume(self, event: Dict[str, Any]) -> None:
        message = event['message']
        event['command'] = message['content']

        services = get_bot_services(event['user_profile_id'])
        for service in services:
            event['service_name'] = str(service.name)
            service_handler = get_outgoing_webhook_service_handler(service)
            request_data = service_handler.build_bot_request(event)
            if request_data:
                do_rest_call(service.base_url, request_data, event,
                             service_handler)
    def test_request_exception(self, mock_fail_with_message: mock.Mock,
                               mock_requests_request: mock.Mock, mock_logger: mock.Mock) -> None:
        do_rest_call('', None, self.mock_event, service_handler)
        bot_owner_notification = self.get_last_message()
        self.assertTrue(mock_fail_with_message.called)
        self.assertEqual(bot_owner_notification.content,
                         '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) triggered an outgoing webhook.
When trying to send a request to the webhook service, an exception of type RequestException occurred:
```
I'm a generic exception :(
```''')
        self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
    def test_successful_request(self, mock_send: mock.Mock) -> None:
        response = ResponseMock(200, dict(content='whatever'))
        with mock.patch('requests.request', return_value=response):
            do_rest_call('', None, self.mock_event, service_handler)
            self.assertTrue(mock_send.called)

        for service_class in [
                GenericOutgoingWebhookService, SlackOutgoingWebhookService
        ]:
            handler = service_class(None, None, None)
            with mock.patch('requests.request', return_value=response):
                do_rest_call('', None, self.mock_event, handler)
                self.assertTrue(mock_send.called)
    def test_retry_request(self):
        # type: (mock.Mock) -> None
        response = ResponseMock(500, {"message": "testing"}, '')

        self.mock_event['failed_tries'] = 3
        with mock.patch('requests.request', return_value=response):
            do_rest_call(self.rest_operation, None, self.mock_event, service_handler, None)
            bot_owner_notification = self.get_last_message()
            self.assertEqual(bot_owner_notification.content,
                             '''[A message](http://zulip.testserver/#narrow/stream/Verona/subject/Foo/near/) triggered an outgoing webhook.
The webhook got a response with status code *500*.''')
            self.assertEqual(bot_owner_notification.recipient_id, self.bot_user.bot_owner.id)
        self.mock_event['failed_tries'] = 0
Beispiel #28
0
        def helper(side_effect: Any, error_text: str) -> None:
            bot_user = self.example_user('outgoing_webhook_bot')
            mock_event = self.mock_event(bot_user)
            service_handler = GenericOutgoingWebhookService("token", bot_user, "service")

            with mock.patch('logging.warning'), mock.patch('logging.info'):
                with mock.patch('requests.request', side_effect=side_effect):
                    do_rest_call('', None, mock_event, service_handler)

            bot_owner_notification = self.get_last_message()
            self.assertIn(error_text, bot_owner_notification.content)
            self.assertIn('triggered', bot_owner_notification.content)
            assert bot_user.bot_owner is not None
            self.assertEqual(bot_owner_notification.recipient_id, bot_user.bot_owner.id)
    def test_bad_msg_type(self) -> None:
        bot_user = self.example_user("outgoing_webhook_bot")
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        mock_event["message"]["type"] = "unknown"
        with mock.patch.object(
                service_handler, "session") as session, self.assertRaises(
                    JsonableError), self.assertLogs(level="INFO"):
            session.post.return_value = ResponseMock(200)
            url = "http://somewhere.com/api/call"
            with mock.patch("zerver.lib.outgoing_webhook.get_message_url",
                            return_value=url):
                do_rest_call("", mock_event, service_handler)
    def test_retry_request(self: mock.Mock) -> None:
        response = ResponseMock(500)

        self.mock_event['failed_tries'] = 3
        with mock.patch('requests.request',
                        return_value=response), mock.patch('logging.warning'):
            do_rest_call('', None, self.mock_event, self.service_handler)
            bot_owner_notification = self.get_last_message()
            self.assertEqual(
                bot_owner_notification.content,
                '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) triggered an outgoing webhook.
The webhook got a response with status code *500*.''')
            self.assertEqual(bot_owner_notification.recipient_id,
                             self.bot_user.bot_owner.id)
        self.mock_event['failed_tries'] = 0
    def test_headers(self) -> None:
        bot_user = self.example_user("outgoing_webhook_bot")
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService("token", bot_user, "service")

        with mock.patch("requests.request") as mock_request, self.assertLogs(level="WARNING") as m:
            final_response = do_rest_call("", "payload-stub", mock_event, service_handler)
            assert final_response is not None

            self.assertEqual(
                m.output,
                [
                    f'WARNING:root:Message http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/ triggered an outgoing webhook, returning status code {final_response.status_code}.\n Content of response (in quotes): "{final_response.text}"'
                ],
            )

        kwargs = mock_request.call_args[1]
        self.assertEqual(kwargs["data"], "payload-stub")

        user_agent = "ZulipOutgoingWebhook/" + ZULIP_VERSION
        headers = {
            "content-type": "application/json",
            "User-Agent": user_agent,
        }
        self.assertEqual(kwargs["headers"], headers)
Beispiel #32
0
    def test_retry_request(self) -> None:
        bot_user = self.example_user('outgoing_webhook_bot')
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        response = ResponseMock(500)
        with mock.patch(
                'requests.request',
                return_value=response), self.assertLogs(level="WARNING") as m:
            final_response = do_rest_call('', None, mock_event,
                                          service_handler)
            assert final_response is not None

            self.assertEqual(m.output, [
                f"WARNING:root:Message http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/ triggered an outgoing webhook, returning status code 500.\n Content of response (in quotes): \"{final_response.content.decode()}\""
            ])
        bot_owner_notification = self.get_last_message()
        self.assertEqual(
            bot_owner_notification.content,
            '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) triggered an outgoing webhook.
The webhook got a response with status code *500*.''')

        assert bot_user.bot_owner is not None
        self.assertEqual(bot_owner_notification.recipient_id,
                         bot_user.bot_owner.id)
Beispiel #33
0
    def test_headers(self) -> None:
        bot_user = self.example_user('outgoing_webhook_bot')
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        with mock.patch('requests.request') as mock_request, self.assertLogs(
                level="WARNING") as m:
            final_response = do_rest_call('', 'payload-stub', mock_event,
                                          service_handler)
            assert final_response is not None

            self.assertEqual(m.output, [
                f"WARNING:root:Message http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/ triggered an outgoing webhook, returning status code {final_response.status_code}.\n Content of response (in quotes): \"{final_response.content.decode()}\""
            ])

        kwargs = mock_request.call_args[1]
        self.assertEqual(kwargs['data'], 'payload-stub')

        user_agent = 'ZulipOutgoingWebhook/' + ZULIP_VERSION
        headers = {
            'content-type': 'application/json',
            'User-Agent': user_agent,
        }
        self.assertEqual(kwargs['headers'], headers)
Beispiel #34
0
    def consume(self, event):
        # type: (Mapping[str, Any]) -> None
        message = event['message']
        services = get_bot_services(event['user_profile_id'])
        rest_operation = {'method': 'POST',
                          'relative_url_path': '',
                          'request_kwargs': {},
                          'base_url': ''}

        dup_event = cast(Dict[str, Any], event)
        dup_event['command'] = message['content']

        for service in services:
            rest_operation['base_url'] = str(service.base_url)
            dup_event['service_name'] = str(service.name)
            do_rest_call(rest_operation, dup_event)
Beispiel #35
0
    def test_headers(self) -> None:
        bot_user = self.example_user("outgoing_webhook_bot")
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        session = service_handler.session
        with mock.patch.object(session, "send") as mock_send:
            mock_send.return_value = ResponseMock(200, b"{}")
            with self.assertLogs(level="INFO") as logs:
                final_response = do_rest_call("https://example.com/",
                                              mock_event, service_handler)
            assert final_response is not None

            self.assert_length(logs.output, 1)
            self.assertIn(
                f"Outgoing webhook request from {bot_user.id}@zulip took ",
                logs.output[0])

            mock_send.assert_called_once()
            prepared_request = mock_send.call_args[0][0]
            user_agent = "ZulipOutgoingWebhook/" + ZULIP_VERSION
            headers = {
                "Content-Type": "application/json",
                "User-Agent": user_agent,
            }
            self.assertLessEqual(headers.items(),
                                 prepared_request.headers.items())
Beispiel #36
0
    def test_retry_request(self) -> None:
        bot_user = self.example_user("outgoing_webhook_bot")
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService(
            "token", bot_user, "service")

        with mock.patch.object(
                service_handler,
                "session") as session, self.assertLogs(level="WARNING") as m:
            session.post.return_value = ResponseMock(500)
            final_response = do_rest_call("", mock_event, service_handler)
            assert final_response is not None

            self.assertEqual(
                m.output,
                [
                    f'WARNING:root:Message http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/ triggered an outgoing webhook, returning status code 500.\n Content of response (in quotes): "{final_response.text}"'
                ],
            )
        bot_owner_notification = self.get_last_message()
        self.assertEqual(
            bot_owner_notification.content,
            """[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) to your bot @_**Outgoing Webhook** triggered an outgoing webhook.
The webhook got a response with status code *500*.""",
        )

        assert bot_user.bot_owner is not None
        self.assertEqual(bot_owner_notification.recipient_id,
                         bot_user.bot_owner.recipient_id)
Beispiel #37
0
    def test_headers(self) -> None:
        bot_user = self.example_user('outgoing_webhook_bot')
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService("token", bot_user, "service")

        with mock.patch('requests.request') as mock_request, mock.patch('logging.warning'):
            do_rest_call('', 'payload-stub', mock_event, service_handler)

        kwargs = mock_request.call_args[1]
        self.assertEqual(kwargs['data'], 'payload-stub')

        user_agent = 'ZulipOutgoingWebhook/' + ZULIP_VERSION
        headers = {
            'content-type': 'application/json',
            'User-Agent': user_agent,
        }
        self.assertEqual(kwargs['headers'], headers)
Beispiel #38
0
    def test_retry_request(self) -> None:
        bot_user = self.example_user('outgoing_webhook_bot')
        mock_event = self.mock_event(bot_user)
        service_handler = GenericOutgoingWebhookService("token", bot_user, "service")

        response = ResponseMock(500)

        with mock.patch('requests.request', return_value=response), mock.patch('logging.warning'):
            do_rest_call('',  None, mock_event, service_handler)

        bot_owner_notification = self.get_last_message()
        self.assertEqual(bot_owner_notification.content,
                         '''[A message](http://zulip.testserver/#narrow/stream/999-Verona/topic/Foo/near/) triggered an outgoing webhook.
The webhook got a response with status code *500*.''')

        assert bot_user.bot_owner is not None
        self.assertEqual(bot_owner_notification.recipient_id, bot_user.bot_owner.id)
 def test_successful_request(self, mock_succeed_with_message: mock.Mock) -> None:
     response = ResponseMock(200)
     with mock.patch('requests.request', return_value=response):
         do_rest_call(self.rest_operation, None, self.mock_event, service_handler, None)
         self.assertTrue(mock_succeed_with_message.called)