slack_incoming: Add ok=false to JSON in case of error.

Previously, errors were returned using Zulip's default format,
which did not match Slack's expected response structure.

This change ensures that errors in the Slack incoming webhook handler
return JSON responses in Slack's expected format: {ok: false, error:
"error string"}.

Fixes: #31878.
This commit is contained in:
Aditya Kumar Kasaudhan 2024-10-18 17:11:48 +05:30 committed by Tim Abbott
parent 46a0c6507c
commit d448b75176
2 changed files with 28 additions and 2 deletions

View File

@ -66,7 +66,8 @@ Hello, world.
def test_message_without_payload(self) -> None:
self.url = self.build_webhook_url()
result = self.client_post(self.url)
self.assert_json_error(result, "Missing 'payload' argument")
self.assertEqual(result.json()["error"], "Missing 'payload' argument")
self.assertEqual(result.json()["ok"], False)
def test_message_with_actions(self) -> None:
expected_topic_name = "C1H9RESGL"

View File

@ -1,10 +1,13 @@
# Webhooks for external integrations.
import re
from collections.abc import Callable
from functools import wraps
from itertools import zip_longest
from typing import Literal, TypedDict, cast
from django.http import HttpRequest, HttpResponse
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.utils.translation import gettext as _
from typing_extensions import ParamSpec
from zerver.decorator import webhook_view
from zerver.lib.exceptions import JsonableError
@ -25,9 +28,31 @@ from zerver.lib.validator import (
from zerver.lib.webhooks.common import OptionalUserSpecifiedTopicStr, check_send_webhook_message
from zerver.models import UserProfile
ParamT = ParamSpec("ParamT")
def slack_error_handler(view_func: Callable[..., HttpResponse]) -> Callable[..., HttpResponse]:
"""
A decorator that catches JsonableError exceptions and returns a
Slack-compatible error response in the format:
{ok: false, error: "error message"}.
"""
@wraps(view_func)
def wrapped_view(
request: HttpRequest, *args: ParamT.args, **kwargs: ParamT.kwargs
) -> HttpResponse:
try:
return view_func(request, *args, **kwargs)
except JsonableError as error:
return JsonResponse({"ok": False, "error": error.msg}, status=error.http_status_code)
return wrapped_view
@webhook_view("SlackIncoming")
@typed_endpoint
@slack_error_handler
def api_slack_incoming_webhook(
request: HttpRequest,
user_profile: UserProfile,