webhooks/teamcity: Ignore third-party specific payload formats.

The TeamCity webhook plugin supports multiple payload formats that
are customized to be used by different services such as Slack,
Flowdock, etc. We don't support such payloads, so we should ignore
them and stick to parsing only the generic ones. We should also
notify that bot owner about the error.
This commit is contained in:
Eeshan Garg 2018-08-01 16:33:30 -02:30 committed by Tim Abbott
parent 97995b4779
commit 404439e98c
3 changed files with 81 additions and 3 deletions

View File

@ -0,0 +1,42 @@
{
"username":"TeamCity",
"icon_url":"https://raw.githubusercontent.com/tcplugins/tcWebHooks/master/docs/icons/teamcity-logo-48x48.png",
"attachments":[
{
"title":"Failed (broken) : ${buildName} <${buildStatusUrl}|build #${buildNumber}>",
"fallback":"Failed (broken) : ${buildName} build #${buildNumber}",
"color":"danger",
"fields":[
{
"title":"Status",
"value":"${buildStatus}"
},
{
"title":"Project Name",
"value":"<${rootUrl}/project.html?projectId=${projectExternalId}|${projectName}>",
"short":true
},
{
"title":"Build Name",
"value":"<${rootUrl}/viewType.html?buildTypeId=${buildExternalTypeId}|${buildName}>",
"short":true
},
{
"title":"Commit",
"value":"<${buildStatusUrl}&tab=buildChangesDiv|${substr(build.vcs.number,0,7,32)}>",
"short":true
},
{
"title":"Triggered By",
"value":"${triggeredBy}",
"short":true
},
{
"title":"Agent",
"value":"${agentName}",
"short":true
}
]
}
]
}

View File

@ -2,7 +2,9 @@
import ujson
from zerver.lib.test_classes import WebhookTestCase
from zerver.models import Recipient
from zerver.lib.send_email import FromAddress
from zerver.models import Recipient, get_user, get_realm
from zerver.webhooks.teamcity.view import MISCONFIGURED_PAYLOAD_TYPE_ERROR_MESSAGE
class TeamcityHookTests(WebhookTestCase):
STREAM_NAME = 'teamcity'
@ -39,3 +41,15 @@ class TeamcityHookTests(WebhookTestCase):
self.assertEqual(msg.content, expected_message)
self.assertEqual(msg.recipient.type, Recipient.PERSONAL)
def test_non_generic_payload_ignore_pm_notification(self) -> None:
expected_message = MISCONFIGURED_PAYLOAD_TYPE_ERROR_MESSAGE.format(
bot_name=get_user('webhook-bot@zulip.com', get_realm('zulip')).full_name,
support_email=FromAddress.SUPPORT
).strip()
payload = self.get_body('slack_non_generic_payload')
self.client_post(self.url, payload, content_type="application/json")
msg = self.get_last_message()
self.assertEqual(msg.content, expected_message)
self.assertEqual(msg.recipient.type, Recipient.PERSONAL)

View File

@ -8,12 +8,23 @@ from django.db.models import Q
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_private_message
from zerver.lib.actions import check_send_private_message, \
send_rate_limited_pm_notification_to_bot_owner
from zerver.lib.send_email import FromAddress
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import Realm, UserProfile
MISCONFIGURED_PAYLOAD_TYPE_ERROR_MESSAGE = """
Hi there! Your bot {bot_name} just received a TeamCity payload in a
format that Zulip doesn't recognize. This usually indicates a
configuration issue in your TeamCity webhook settings. Please make sure
that you set the **Payload Format** option to **Legacy Webhook (JSON)**
in your TeamCity webhook configuration. Contact {support_email} if you
need further help!
"""
def guess_zulip_user_from_teamcity(teamcity_username: str, realm: Realm) -> Optional[UserProfile]:
try:
# Try to find a matching user in Zulip
@ -39,7 +50,18 @@ def get_teamcity_property_value(property_list: List[Dict[str, str]], name: str)
@has_request_variables
def api_teamcity_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
message = payload['build']
message = payload.get('build')
if message is None:
# Ignore third-party specific (e.g. Slack/HipChat) payload formats
# and notify the bot owner
message = MISCONFIGURED_PAYLOAD_TYPE_ERROR_MESSAGE.format(
bot_name=user_profile.full_name,
support_email=FromAddress.SUPPORT,
).strip()
send_rate_limited_pm_notification_to_bot_owner(
user_profile, user_profile.realm, message)
return json_success()
build_name = message['buildFullName']
build_url = message['buildStatusUrl']