From df134be23501cb24f5abd548ddcdd5bc0db7d074 Mon Sep 17 00:00:00 2001 From: Puneeth Chaganti Date: Tue, 3 Sep 2019 20:45:31 +0530 Subject: [PATCH] webhooks/papertrail: Requests from Papertrail are not JSON requests. Papertrail sends requests with the content type `application/x-www-form-urlencoded`, with the payload parameter holding the JSON body. This commit fixes the papertrail integration to use the payload parameter in the request's POST data instead of trying to parse the request's entire body as JSON. Papertrail documentation here: https://help.papertrailapp.com/kb/how-it-works/web-hooks#encoding --- .../papertrail/fixtures/incorrect_post.json | 11 +++++++++++ zerver/webhooks/papertrail/tests.py | 15 ++++++++++++++- zerver/webhooks/papertrail/view.py | 12 ++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 zerver/webhooks/papertrail/fixtures/incorrect_post.json diff --git a/zerver/webhooks/papertrail/fixtures/incorrect_post.json b/zerver/webhooks/papertrail/fixtures/incorrect_post.json new file mode 100644 index 0000000000..2b93cb92fc --- /dev/null +++ b/zerver/webhooks/papertrail/fixtures/incorrect_post.json @@ -0,0 +1,11 @@ +{ + "saved_search": { + "id": 42, + "name": "Important stuff", + "query": "cron OR server1", + "html_edit_url": "https://papertrailapp.com/searches/42/edit", + "html_search_url": "https://papertrailapp.com/searches/42" + }, + "max_id": 7711582041804800, + "min_id": 7711561783320576 +} diff --git a/zerver/webhooks/papertrail/tests.py b/zerver/webhooks/papertrail/tests.py index 0c90655505..e3b6e1f3c8 100644 --- a/zerver/webhooks/papertrail/tests.py +++ b/zerver/webhooks/papertrail/tests.py @@ -1,3 +1,5 @@ +from urllib.parse import urlencode + from zerver.lib.test_classes import WebhookTestCase class PapertrailHookTests(WebhookTestCase): @@ -50,5 +52,16 @@ message body 4 self.send_and_test_stream_message('long_post', expected_topic, expected_message, content_type="application/x-www-form-urlencoded") + def test_incorrect_message(self) -> None: + with self.assertRaises(AssertionError) as e: + self.send_and_test_stream_message('incorrect_post', '', '', + content_type="application/x-www-form-urlencoded") + + self.assertIn("Missing expected keys", e.exception.args[0]) + def get_body(self, fixture_name: str) -> str: - return self.webhook_fixture_data("papertrail", fixture_name, file_type="json") + # Papertrail webhook sends a POST request with payload parameter + # containing the JSON body. Documented here: + # https://help.papertrailapp.com/kb/how-it-works/web-hooks#encoding + body = self.webhook_fixture_data("papertrail", fixture_name, file_type="json") + return urlencode({'payload': body}) diff --git a/zerver/webhooks/papertrail/view.py b/zerver/webhooks/papertrail/view.py index b50f8374cd..9a71e8cd05 100644 --- a/zerver/webhooks/papertrail/view.py +++ b/zerver/webhooks/papertrail/view.py @@ -1,6 +1,7 @@ -from typing import Any, Dict +from typing import Any, Dict, Optional from django.http import HttpRequest, HttpResponse +from django.utils.translation import ugettext as _ from zerver.decorator import api_key_only_webhook_view from zerver.lib.request import REQ, has_request_variables @@ -16,10 +17,17 @@ SEARCH_TEMPLATE = """ ``` """.strip() +def ensure_keys(name: str, data: Any) -> Optional[str]: + if 'events' in data and 'saved_search' in data: + saved_search = data['saved_search'] + if 'name' in saved_search and 'html_search_url' in saved_search: + return None + return _("Missing expected keys") + @api_key_only_webhook_view('Papertrail') @has_request_variables def api_papertrail_webhook(request: HttpRequest, user_profile: UserProfile, - payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse: + payload: Dict[str, Any]=REQ(validator=ensure_keys)) -> HttpResponse: matches = MATCHES_TEMPLATE.format( name=payload["saved_search"]["name"],