From 0740c94517b45f4523d297a1932da9ab7daa5886 Mon Sep 17 00:00:00 2001 From: PIG208 <359101898@qq.com> Date: Wed, 30 Jun 2021 20:15:27 +0800 Subject: [PATCH] webhooks: Support configuring destination stream by id. --- zerver/lib/actions.py | 14 ++++++++++ zerver/lib/webhooks/common.py | 10 ++++++-- zerver/tests/test_webhooks_common.py | 38 ++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index 386a6dbd88..366159574b 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -2680,6 +2680,20 @@ def check_send_stream_message( return do_send_messages([message])[0] +def check_send_stream_message_by_id( + sender: UserProfile, + client: Client, + stream_id: int, + topic: str, + body: str, + realm: Optional[Realm] = None, +) -> int: + addressee = Addressee.for_stream_id(stream_id, topic) + message = check_message(sender, client, addressee, body, realm) + + return do_send_messages([message])[0] + + def check_send_private_message( sender: UserProfile, client: Client, receiving_user: UserProfile, body: str ) -> int: diff --git a/zerver/lib/webhooks/common.py b/zerver/lib/webhooks/common.py index a962f69856..36b0030020 100644 --- a/zerver/lib/webhooks/common.py +++ b/zerver/lib/webhooks/common.py @@ -10,6 +10,7 @@ from django.utils.translation import gettext as _ from zerver.lib.actions import ( check_send_private_message, check_send_stream_message, + check_send_stream_message_by_id, send_rate_limited_pm_notification_to_bot_owner, ) from zerver.lib.exceptions import ErrorCode, JsonableError, StreamDoesNotExistError @@ -114,7 +115,7 @@ def check_send_webhook_message( # double escape their URLs in a manner that escaped space characters # (%20) are never properly decoded. We work around that by making sure # that the URL parameters are decoded on our end. - if unquote_url_parameters: + if stream is not None and unquote_url_parameters: stream = unquote(stream) if user_specified_topic is not None: @@ -123,7 +124,12 @@ def check_send_webhook_message( topic = unquote(topic) try: - check_send_stream_message(user_profile, request.client, stream, topic, body) + if stream.isdecimal(): + check_send_stream_message_by_id( + user_profile, request.client, int(stream), topic, body + ) + else: + check_send_stream_message(user_profile, request.client, stream, topic, body) except StreamDoesNotExistError: # A PM will be sent to the bot_owner by check_message, notifying # that the webhook bot just tried to send a message to a non-existent diff --git a/zerver/tests/test_webhooks_common.py b/zerver/tests/test_webhooks_common.py index 358107cd45..307f33e0c6 100644 --- a/zerver/tests/test_webhooks_common.py +++ b/zerver/tests/test_webhooks_common.py @@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch from django.http import HttpRequest from zerver.decorator import webhook_view +from zerver.lib.actions import do_rename_stream from zerver.lib.exceptions import InvalidJSONError, JsonableError from zerver.lib.send_email import FromAddress from zerver.lib.test_classes import WebhookTestCase, ZulipTestCase @@ -134,6 +135,43 @@ class WebhooksCommonTestCase(ZulipTestCase): self.assertEqual(djangoified_headers, expected_djangoified_headers) +class WebhookURLConfigurationTestCase(WebhookTestCase): + STREAM_NAME = "helloworld" + WEBHOOK_DIR_NAME = "helloworld" + URL_TEMPLATE = "/api/v1/external/helloworld?stream={stream}&api_key={api_key}" + + def setUp(self) -> None: + super().setUp() + stream = self.subscribe(self.test_user, self.STREAM_NAME) + + # In actual webhook tests, we will not need to use stream id. + # We assign stream id to STREAM_NAME for testing URL configuration only. + self.STREAM_NAME = str(stream.id) + do_rename_stream(stream, "helloworld_renamed", self.test_user) + + self.url = self.build_webhook_url() + + def test_trigger_stream_message_by_id(self) -> None: + # check_webhook cannot be used here as it + # subscribes the test user to self.STREAM_NAME + payload = self.get_body("hello") + + self.send_webhook_payload( + self.test_user, self.url, payload, content_type="application/json" + ) + + expected_topic = "Hello World" + expected_message = "Hello! I am happy to be here! :smile:\nThe Wikipedia featured article for today is **[Marilyn Monroe](https://en.wikipedia.org/wiki/Marilyn_Monroe)**" + + msg = self.get_last_message() + self.assert_stream_message( + message=msg, + stream_name="helloworld_renamed", + topic_name=expected_topic, + content=expected_message, + ) + + class MissingEventHeaderTestCase(WebhookTestCase): STREAM_NAME = "groove" URL_TEMPLATE = "/api/v1/external/groove?stream={stream}&api_key={api_key}"