diff --git a/templates/zerver/help/include/rest-endpoints.md b/templates/zerver/help/include/rest-endpoints.md index f6cde3b639..8f9943a2e5 100644 --- a/templates/zerver/help/include/rest-endpoints.md +++ b/templates/zerver/help/include/rest-endpoints.md @@ -29,6 +29,7 @@ * [Archive a stream](/api/archive-stream) * [Get topics in a stream](/api/get-stream-topics) * [Topic muting](/api/mute-topic) +* [Delete a topic](/api/delete-topic) #### Users diff --git a/zerver/openapi/python_examples.py b/zerver/openapi/python_examples.py index 7e01549bc4..0d1d41e33d 100644 --- a/zerver/openapi/python_examples.py +++ b/zerver/openapi/python_examples.py @@ -499,6 +499,23 @@ def archive_stream(client: Client, stream_id: int) -> None: assert result["result"] == "success" +@openapi_test_function("/streams/{stream_id}/delete_topic:post") +def delete_topic(client: Client, stream_id: int, topic: str) -> None: + + # {code_example|start} + # Delete a topic given its stream_id + request = { + "topic_name": topic, + } + result = client.call_endpoint( + url=f"/streams/{stream_id}/delete_topic", method="POST", request=request + ) + # {code_example|end} + validate_against_openapi_schema(result, "/streams/{stream_id}/delete_topic", "post", "200") + + assert result["result"] == "success" + + @openapi_test_function("/streams:get") def get_streams(client: Client) -> None: @@ -1505,6 +1522,7 @@ def test_streams(client: Client, nonadmin_client: Client) -> None: toggle_mute_topic(client) update_subscription_settings(client) get_stream_topics(client, 1) + delete_topic(client, 1, "test") archive_stream(client, stream_id) test_user_not_authorized_error(nonadmin_client) diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index 82a918dcec..a9e58dc0ec 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -10755,6 +10755,54 @@ paths: "result": "error", } description: An example JSON response for when the supplied stream does not exist + /streams/{stream_id}/delete_topic: + post: + operationId: delete-topic + summary: Delete a topic + tags: ["streams"] + description: | + Delete all messages in a topic. + + `POST {{ api_url }}/v1/streams/{stream_id}/delete_topic` + + Topics are a field on messages (not an independent + data structure), so deleting all the messages in the topic + deletes the topic from Zulip. + parameters: + - $ref: "#/components/parameters/StreamIdInPath" + - name: topic_name + in: query + description: | + The name of the topic to delete. + schema: + type: string + example: new coffee machine + required: true + responses: + "200": + description: Success. + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/JsonSuccess" + - $ref: "#/components/schemas/SuccessDescription" + "400": + description: Error. + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/JsonError" + - example: + { + "result": "error", + "msg": "Must be an organization administrator", + "code": "UNAUTHORIZED_PRINCIPAL", + } + description: | + Error when the user does not have permission + to delete topics in this organization. /typing: post: operationId: set-typing-status diff --git a/zerver/tests/test_openapi.py b/zerver/tests/test_openapi.py index c06d2c2061..254b06b8f4 100644 --- a/zerver/tests/test_openapi.py +++ b/zerver/tests/test_openapi.py @@ -208,7 +208,6 @@ class OpenAPIArgumentsTest(ZulipTestCase): #### TODO: These endpoints are a priority to document: "/realm/presence", "/streams/{stream_id}/members", - "/streams/{stream_id}/delete_topic", "/users/me/presence", "/users/me/alert_words", "/users/me/status", diff --git a/zerver/views/streams.py b/zerver/views/streams.py index db38b1d4c7..fcfe9abdf6 100644 --- a/zerver/views/streams.py +++ b/zerver/views/streams.py @@ -751,7 +751,7 @@ def get_topics_backend( def delete_in_topic( request: HttpRequest, user_profile: UserProfile, - stream_id: int = REQ(converter=to_non_negative_int), + stream_id: int = REQ(converter=to_non_negative_int, path_only=True), topic_name: str = REQ("topic_name"), ) -> HttpResponse: (stream, sub) = access_stream_by_id(user_profile, stream_id)