mirror of https://github.com/zulip/zulip.git
webhooks: Remove repetitive argument to UnsupportedWebhookEventType.
The name of the webhook can be added by the webhook decorator.
This commit is contained in:
parent
e2ab7b9e17
commit
d04db7c5fe
|
@ -619,15 +619,13 @@ webhook bot, notifying them of the missing header.
|
|||
|
||||
### Handling unexpected webhook event types
|
||||
|
||||
Many third-party services have dozens of different event types. In some cases, we
|
||||
may choose to explicitly ignore specific events. In other cases, there may be
|
||||
events that are new or events that we don't know about. In such cases, we
|
||||
recommend raising `UnsupportedWebhookEventType` (found in
|
||||
`zerver/lib/exceptions.py`), like so:
|
||||
Many third-party services have dozens of different event types. In
|
||||
some cases, we may choose to explicitly ignore specific events. In
|
||||
other cases, there may be events that are new or events that we don't
|
||||
know about. In such cases, we recommend raising
|
||||
`UnsupportedWebhookEventType` (found in `zerver/lib/exceptions.py`),
|
||||
with a string describing the unsupported event type, like so:
|
||||
|
||||
```
|
||||
raise UnsupportedWebhookEventType(webhook_name, event_type)
|
||||
raise UnsupportedWebhookEventType(event_type)
|
||||
```
|
||||
|
||||
`webhook_name` is the name of the integration that raises the exception.
|
||||
`event_type` is the name of the unexpected webhook event.
|
||||
|
|
|
@ -348,6 +348,8 @@ def webhook_view(
|
|||
from zerver.lib.webhooks.common import notify_bot_owner_about_invalid_json
|
||||
notify_bot_owner_about_invalid_json(user_profile, webhook_client_name)
|
||||
else:
|
||||
if isinstance(err, UnsupportedWebhookEventType):
|
||||
err.webhook_name = webhook_client_name
|
||||
log_exception_to_webhook_logger(
|
||||
request=request,
|
||||
user_profile=user_profile,
|
||||
|
@ -597,6 +599,8 @@ def authenticated_rest_api_view(
|
|||
return target_view_func(request, profile, *args, **kwargs)
|
||||
except Exception as err:
|
||||
if is_webhook or webhook_client_name is not None:
|
||||
if isinstance(err, UnsupportedWebhookEventType) and webhook_client_name is not None:
|
||||
err.webhook_name = webhook_client_name
|
||||
request_body = request.POST.get('payload')
|
||||
if request_body is not None:
|
||||
log_exception_to_webhook_logger(
|
||||
|
|
|
@ -261,8 +261,8 @@ class UnsupportedWebhookEventType(JsonableError):
|
|||
code = ErrorCode.UNSUPPORTED_WEBHOOK_EVENT_TYPE
|
||||
data_fields = ['webhook_name', 'event_type']
|
||||
|
||||
def __init__(self, webhook_name: str, event_type: Optional[str]) -> None:
|
||||
self.webhook_name = webhook_name
|
||||
def __init__(self, event_type: Optional[str]) -> None:
|
||||
self.webhook_name = "(unknown)"
|
||||
self.event_type = event_type
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -271,7 +271,7 @@ class DecoratorTestCase(ZulipTestCase):
|
|||
@webhook_view('ClientName')
|
||||
def my_webhook_raises_exception_unsupported_event(
|
||||
request: HttpRequest, user_profile: UserProfile) -> None:
|
||||
raise UnsupportedWebhookEventType("helloworld", "test_event")
|
||||
raise UnsupportedWebhookEventType("test_event")
|
||||
|
||||
webhook_bot_email = 'webhook-bot@zulip.com'
|
||||
webhook_bot_realm = get_realm('zulip')
|
||||
|
@ -363,7 +363,7 @@ body:
|
|||
|
||||
# Test when an unsupported webhook event occurs
|
||||
with mock.patch('zerver.decorator.webhook_unsupported_events_logger.exception') as mock_exception:
|
||||
exception_msg = "The 'test_event' event isn't currently supported by the helloworld webhook"
|
||||
exception_msg = "The 'test_event' event isn't currently supported by the ClientName webhook"
|
||||
with self.assertRaisesRegex(UnsupportedWebhookEventType, exception_msg):
|
||||
request.body = "invalidjson"
|
||||
request.content_type = 'application/json'
|
||||
|
@ -543,7 +543,7 @@ body:
|
|||
def test_authenticated_rest_api_view_logging_unsupported_event(self) -> None:
|
||||
@authenticated_rest_api_view(webhook_client_name="ClientName")
|
||||
def my_webhook_raises_exception(request: HttpRequest, user_profile: UserProfile) -> None:
|
||||
raise UnsupportedWebhookEventType("helloworld", "test_event")
|
||||
raise UnsupportedWebhookEventType("test_event")
|
||||
|
||||
webhook_bot_email = 'webhook-bot@zulip.com'
|
||||
webhook_bot_realm = get_realm('zulip')
|
||||
|
@ -558,7 +558,7 @@ body:
|
|||
request.content_type = 'text/plain'
|
||||
|
||||
with mock.patch('zerver.decorator.webhook_unsupported_events_logger.exception') as mock_exception:
|
||||
exception_msg = "The 'test_event' event isn't currently supported by the helloworld webhook"
|
||||
exception_msg = "The 'test_event' event isn't currently supported by the ClientName webhook"
|
||||
with self.assertRaisesRegex(UnsupportedWebhookEventType, exception_msg):
|
||||
my_webhook_raises_exception(request)
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ def api_basecamp_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
event = get_event_type(payload)
|
||||
|
||||
if event not in SUPPORT_EVENTS:
|
||||
raise UnsupportedWebhookEventType('Basecamp', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
||||
subject = get_project_name(payload)
|
||||
if event.startswith('document_'):
|
||||
|
@ -48,7 +48,7 @@ def api_basecamp_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
elif event.startswith('comment_'):
|
||||
body = get_comment_body(event, payload)
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Basecamp', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
||||
check_send_webhook_message(request, user_profile, subject, body)
|
||||
return json_success()
|
||||
|
|
|
@ -161,7 +161,7 @@ def get_type(request: HttpRequest, payload: Dict[str, Any]) -> str:
|
|||
if event_key == 'repo:updated':
|
||||
return event_key
|
||||
|
||||
raise UnsupportedWebhookEventType('BitBucket2', event_key)
|
||||
raise UnsupportedWebhookEventType(event_key)
|
||||
|
||||
def get_body_based_on_type(type: str) -> Any:
|
||||
fn = GET_SINGLE_MESSAGE_BODY_DEPENDING_ON_TYPE_MAPPER.get(type)
|
||||
|
|
|
@ -134,7 +134,7 @@ def repo_push_branch_data(payload: Dict[str, Any], change: Dict[str, Any]) -> Di
|
|||
body = get_remove_branch_event_message(user_name, branch_name)
|
||||
else:
|
||||
message = "{}.{}".format(payload["eventKey"], event_type) # nocoverage
|
||||
raise UnsupportedWebhookEventType("BitBucket Server", message)
|
||||
raise UnsupportedWebhookEventType(message)
|
||||
|
||||
subject = TOPIC_WITH_BRANCH_TEMPLATE.format(repo=repo_name, branch=branch_name)
|
||||
return {"subject": subject, "body": body}
|
||||
|
@ -150,7 +150,7 @@ def repo_push_tag_data(payload: Dict[str, Any], change: Dict[str, Any]) -> Dict[
|
|||
action = "removed"
|
||||
else:
|
||||
message = "{}.{}".format(payload["eventKey"], event_type) # nocoverage
|
||||
raise UnsupportedWebhookEventType("BitBucket Server", message)
|
||||
raise UnsupportedWebhookEventType(message)
|
||||
|
||||
subject = BITBUCKET_TOPIC_TEMPLATE.format(repository_name=repo_name)
|
||||
body = get_push_tag_event_message(get_user_name(payload), tag_name, action=action)
|
||||
|
@ -171,7 +171,7 @@ def repo_push_handler(payload: Dict[str, Any], branches: Optional[str]=None,
|
|||
data.append(repo_push_tag_data(payload, change))
|
||||
else:
|
||||
message = "{}.{}".format(payload["eventKey"], event_target_type) # nocoverage
|
||||
raise UnsupportedWebhookEventType("BitBucket Server", message)
|
||||
raise UnsupportedWebhookEventType(message)
|
||||
return data
|
||||
|
||||
def get_assignees_string(pr: Dict[str, Any]) -> Optional[str]:
|
||||
|
@ -351,7 +351,7 @@ def get_event_handler(eventkey: str) -> Callable[..., List[Dict[str, str]]]:
|
|||
# The main reason for this function existence is because of mypy
|
||||
handler: Any = EVENT_HANDLER_MAP.get(eventkey)
|
||||
if handler is None:
|
||||
raise UnsupportedWebhookEventType("BitBucket Server", eventkey)
|
||||
raise UnsupportedWebhookEventType(eventkey)
|
||||
return handler
|
||||
|
||||
@webhook_view("Bitbucket3")
|
||||
|
|
|
@ -534,7 +534,7 @@ def api_clubhouse_webhook(
|
|||
body_func: Any = EVENT_BODY_FUNCTION_MAPPER.get(event)
|
||||
topic_func = get_topic_function_based_on_type(payload)
|
||||
if body_func is None or topic_func is None:
|
||||
raise UnsupportedWebhookEventType('Clubhouse', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
topic = topic_func(payload)
|
||||
body = body_func(payload)
|
||||
|
||||
|
|
|
@ -620,7 +620,7 @@ def api_github_webhook(
|
|||
"""
|
||||
header_event = validate_extract_webhook_http_header(request, "X_GITHUB_EVENT", "GitHub")
|
||||
if header_event is None:
|
||||
raise UnsupportedWebhookEventType("GitHub", "no header provided")
|
||||
raise UnsupportedWebhookEventType("no header provided")
|
||||
|
||||
event = get_zulip_event_name(header_event, payload, branches)
|
||||
if event is None:
|
||||
|
@ -691,11 +691,11 @@ def get_zulip_event_name(
|
|||
else:
|
||||
# this means GH has actually added new actions since September 2020,
|
||||
# so it's a bit more cause for alarm
|
||||
raise UnsupportedWebhookEventType("GitHub", f"unsupported team action {action}")
|
||||
raise UnsupportedWebhookEventType(f"unsupported team action {action}")
|
||||
elif header_event in list(EVENT_FUNCTION_MAPPER.keys()):
|
||||
return header_event
|
||||
elif header_event in IGNORED_EVENTS:
|
||||
return None
|
||||
|
||||
complete_event = "{}:{}".format(header_event, payload.get("action", "???")) # nocoverage
|
||||
raise UnsupportedWebhookEventType('GitHub', complete_event)
|
||||
raise UnsupportedWebhookEventType(complete_event)
|
||||
|
|
|
@ -452,4 +452,4 @@ def get_event(request: HttpRequest, payload: Dict[str, Any], branches: Optional[
|
|||
if event in list(EVENT_FUNCTION_MAPPER.keys()):
|
||||
return event
|
||||
|
||||
raise UnsupportedWebhookEventType('GitLab', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
|
|
@ -197,7 +197,7 @@ def gogs_webhook_main(integration_name: str, http_header_name: str,
|
|||
)
|
||||
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Gogs', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
||||
check_send_webhook_message(request, user_profile, topic, body)
|
||||
return json_success()
|
||||
|
|
|
@ -55,6 +55,6 @@ def api_gosquared_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
)
|
||||
check_send_webhook_message(request, user_profile, topic, body)
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('GoSquared', 'unknown_event')
|
||||
raise UnsupportedWebhookEventType('unknown_event')
|
||||
|
||||
return json_success()
|
||||
|
|
|
@ -79,7 +79,7 @@ def get_event_handler(event: str) -> Callable[..., str]:
|
|||
# The main reason for this function existence is because of mypy
|
||||
handler: Any = EVENTS_FUNCTION_MAPPER.get(event)
|
||||
if handler is None:
|
||||
raise UnsupportedWebhookEventType("Groove", event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
return handler
|
||||
|
||||
@webhook_view('Groove')
|
||||
|
|
|
@ -107,7 +107,7 @@ def api_harbor_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
content_func = EVENT_FUNCTION_MAPPER.get(event)
|
||||
|
||||
if content_func is None:
|
||||
raise UnsupportedWebhookEventType('Harbor', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
||||
content: str = content_func(payload, user_profile, operator_username)
|
||||
|
||||
|
|
|
@ -279,7 +279,7 @@ EVENT_TO_FUNCTION_MAPPER = {
|
|||
def get_event_handler(event_type: str) -> Callable[..., Tuple[str, str]]:
|
||||
handler: Any = EVENT_TO_FUNCTION_MAPPER.get(event_type)
|
||||
if handler is None:
|
||||
raise UnsupportedWebhookEventType("Intercom", event_type)
|
||||
raise UnsupportedWebhookEventType(event_type)
|
||||
return handler
|
||||
|
||||
@webhook_view('Intercom')
|
||||
|
|
|
@ -328,7 +328,7 @@ def api_jira_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
content_func = get_event_handler(event)
|
||||
|
||||
if content_func is None:
|
||||
raise UnsupportedWebhookEventType('Jira', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
||||
subject = get_issue_subject(payload)
|
||||
content: str = content_func(payload, user_profile)
|
||||
|
|
|
@ -51,4 +51,4 @@ def get_template(request: HttpRequest, payload: Dict[str, Any]) -> str:
|
|||
elif event in EVENTS:
|
||||
return message_template + 'is now {state}.'.format(state=payload['state'])
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Netlify', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
|
|
@ -43,7 +43,7 @@ def api_newrelic_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
subject = "{} deploy".format(deployment['application_name'])
|
||||
content = DEPLOY_TEMPLATE.format(**deployment)
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('New Relic', 'Unknown Event Type')
|
||||
raise UnsupportedWebhookEventType('Unknown Event Type')
|
||||
|
||||
check_send_webhook_message(request, user_profile, subject, content)
|
||||
return json_success()
|
||||
|
|
|
@ -172,7 +172,7 @@ def api_pagerduty_webhook(
|
|||
break
|
||||
|
||||
if message_type not in PAGER_DUTY_EVENT_NAMES:
|
||||
raise UnsupportedWebhookEventType('Pagerduty', message_type)
|
||||
raise UnsupportedWebhookEventType(message_type)
|
||||
|
||||
format_dict = build_pagerduty_formatdict(message)
|
||||
send_formated_pagerduty(request, user_profile, message_type, format_dict)
|
||||
|
@ -186,7 +186,7 @@ def api_pagerduty_webhook(
|
|||
break
|
||||
|
||||
if event not in PAGER_DUTY_EVENT_NAMES_V2:
|
||||
raise UnsupportedWebhookEventType('Pagerduty', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
||||
format_dict = build_pagerduty_formatdict_v2(message)
|
||||
send_formated_pagerduty(request, user_profile, event, format_dict)
|
||||
|
|
|
@ -47,7 +47,7 @@ def api_pingdom_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
subject = get_subject_for_http_request(payload)
|
||||
body = get_body_for_http_request(payload)
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Pingdom', check_type)
|
||||
raise UnsupportedWebhookEventType(check_type)
|
||||
|
||||
check_send_webhook_message(request, user_profile, subject, body)
|
||||
return json_success()
|
||||
|
|
|
@ -152,7 +152,7 @@ def api_pivotal_webhook_v5(request: HttpRequest, user_profile: UserProfile) -> T
|
|||
# Known but unsupported Pivotal event types
|
||||
pass
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Pivotal Tracker', event_type)
|
||||
raise UnsupportedWebhookEventType(event_type)
|
||||
|
||||
return subject, content
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ def api_raygun_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
elif event == 'error_activity':
|
||||
message = compose_activity_message(payload)
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Raygun', event)
|
||||
raise UnsupportedWebhookEventType(event)
|
||||
|
||||
topic = 'test'
|
||||
|
||||
|
@ -220,7 +220,7 @@ def compose_notification_message(payload: Dict[str, Any]) -> str:
|
|||
elif "FollowUp" in event_type:
|
||||
return notification_message_follow_up(payload)
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Raygun', event_type)
|
||||
raise UnsupportedWebhookEventType(event_type)
|
||||
|
||||
|
||||
def activity_message(payload: Dict[str, Any]) -> str:
|
||||
|
@ -276,7 +276,7 @@ def compose_activity_message(payload: Dict[str, Any]) -> str:
|
|||
or event_type == "CommentAdded":
|
||||
return activity_message(payload)
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Raygun', event_type)
|
||||
raise UnsupportedWebhookEventType(event_type)
|
||||
|
||||
|
||||
def parse_time(timestamp: str) -> str:
|
||||
|
|
|
@ -180,6 +180,6 @@ def api_reviewboard_webhook(
|
|||
topic = get_review_request_repo_title(payload)
|
||||
check_send_webhook_message(request, user_profile, topic, body)
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('ReviewBoard', event_type)
|
||||
raise UnsupportedWebhookEventType(event_type)
|
||||
|
||||
return json_success()
|
||||
|
|
|
@ -92,7 +92,7 @@ def handle_event_payload(event: Dict[str, Any]) -> Tuple[str, str]:
|
|||
|
||||
# We shouldn't support the officially deprecated Raven series of SDKs.
|
||||
if int(event["version"]) < 7:
|
||||
raise UnsupportedWebhookEventType("Sentry", "Raven SDK")
|
||||
raise UnsupportedWebhookEventType("Raven SDK")
|
||||
|
||||
platform_name = event["platform"]
|
||||
syntax_highlight_as = syntax_highlight_as_map.get(platform_name, "")
|
||||
|
@ -155,7 +155,7 @@ def handle_event_payload(event: Dict[str, Any]) -> Tuple[str, str]:
|
|||
body = MESSAGE_EVENT_TEMPLATE.format(**context)
|
||||
|
||||
else:
|
||||
raise UnsupportedWebhookEventType("Sentry", "unknown-event type")
|
||||
raise UnsupportedWebhookEventType("unknown-event type")
|
||||
|
||||
return (subject, body)
|
||||
|
||||
|
@ -205,7 +205,7 @@ def handle_issue_payload(action: str, issue: Dict[str, Any], actor: Dict[str, An
|
|||
body = ISSUE_IGNORED_MESSAGE_TEMPLATE.format(**context)
|
||||
|
||||
else:
|
||||
raise UnsupportedWebhookEventType("Sentry", "unknown-issue-action type")
|
||||
raise UnsupportedWebhookEventType("unknown-issue-action type")
|
||||
|
||||
return (subject, body)
|
||||
|
||||
|
@ -233,7 +233,7 @@ def api_sentry_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
elif "issue" in data:
|
||||
subject, body = handle_issue_payload(payload["action"], data["issue"], payload["actor"])
|
||||
else:
|
||||
raise UnsupportedWebhookEventType("Sentry", str(list(data.keys())))
|
||||
raise UnsupportedWebhookEventType(str(list(data.keys())))
|
||||
else:
|
||||
subject, body = handle_deprecated_payload(payload)
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ def topic_and_body(payload: Dict[str, Any]) -> Tuple[str, str]:
|
|||
raise NotImplementedEventType()
|
||||
|
||||
if body is None:
|
||||
raise UnsupportedWebhookEventType('Stripe', event_type)
|
||||
raise UnsupportedWebhookEventType(event_type)
|
||||
return (topic, body)
|
||||
|
||||
def amount_string(amount: int, currency: str) -> str:
|
||||
|
|
|
@ -29,6 +29,6 @@ def api_transifex_webhook(
|
|||
elif reviewed:
|
||||
body = f"Resource {resource} fully reviewed."
|
||||
else:
|
||||
raise UnsupportedWebhookEventType('Transifex', 'Unknown Event Type')
|
||||
raise UnsupportedWebhookEventType('Unknown Event Type')
|
||||
check_send_webhook_message(request, user_profile, subject, body)
|
||||
return json_success()
|
||||
|
|
|
@ -40,4 +40,4 @@ def get_subject_and_body(payload: Mapping[str, Any], action_type: str) -> Option
|
|||
if action_type in SUPPORTED_BOARD_ACTIONS:
|
||||
return process_board_action(payload, action_type)
|
||||
|
||||
raise UnsupportedWebhookEventType("Trello", action_type)
|
||||
raise UnsupportedWebhookEventType(action_type)
|
||||
|
|
|
@ -39,7 +39,7 @@ def get_proper_action(payload: Mapping[str, Any], action_type: Optional[str]) ->
|
|||
return None
|
||||
elif data['old']['name']:
|
||||
return CHANGE_NAME
|
||||
raise UnsupportedWebhookEventType("Trello", action_type)
|
||||
raise UnsupportedWebhookEventType(action_type)
|
||||
return action_type
|
||||
|
||||
def get_subject(payload: Mapping[str, Any]) -> str:
|
||||
|
|
|
@ -115,7 +115,7 @@ def get_proper_action(payload: Mapping[str, Any], action_type: str) -> Optional[
|
|||
for field in ignored_fields:
|
||||
if old_data.get(field):
|
||||
return None
|
||||
raise UnsupportedWebhookEventType("Trello", action_type)
|
||||
raise UnsupportedWebhookEventType(action_type)
|
||||
|
||||
return action_type
|
||||
|
||||
|
|
|
@ -75,4 +75,4 @@ def get_event_type(event: Dict[str, Any]) -> str:
|
|||
event_type = event_type_match.group(1)
|
||||
if event_type in EVENT_TYPE_BODY_MAPPER:
|
||||
return event_type
|
||||
raise UnsupportedWebhookEventType('Updown', event['event'])
|
||||
raise UnsupportedWebhookEventType(event['event'])
|
||||
|
|
Loading…
Reference in New Issue