From 41e8d79e00e90b9a20ad67777236203ddef04a37 Mon Sep 17 00:00:00 2001 From: Karl Stolley Date: Mon, 25 Aug 2025 16:35:10 -0400 Subject: [PATCH] api_docs: Update get-file-temporary-url endpoint and add to sidebar. Co-authored-by: Lauryn Menard --- api_docs/include/rest-endpoints.md | 1 + zerver/openapi/curl_param_value_generators.py | 14 ++++++++++++++ zerver/openapi/zulip.yaml | 15 +++++++++++---- zerver/tests/test_openapi.py | 4 +--- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/api_docs/include/rest-endpoints.md b/api_docs/include/rest-endpoints.md index 21149c4613..b60cae0a45 100644 --- a/api_docs/include/rest-endpoints.md +++ b/api_docs/include/rest-endpoints.md @@ -18,6 +18,7 @@ * [Mark messages in a channel as read](/api/mark-stream-as-read) * [Mark messages in a topic as read](/api/mark-topic-as-read) * [Get a message's read receipts](/api/get-read-receipts) +* [Get temporary URL for an uploaded file](/api/get-file-temporary-url) * [Report a message](/api/report-message) #### Scheduled messages diff --git a/zerver/openapi/curl_param_value_generators.py b/zerver/openapi/curl_param_value_generators.py index 0d47965007..6b39cb0026 100644 --- a/zerver/openapi/curl_param_value_generators.py +++ b/zerver/openapi/curl_param_value_generators.py @@ -5,6 +5,7 @@ # based on Zulip's OpenAPI definitions, as well as test setup and # fetching of appropriate parameter values to use when running the # cURL examples as part of the tools/test-api test suite. +import re from collections.abc import Callable from functools import wraps from typing import Any @@ -413,3 +414,16 @@ def add_channel_folders() -> dict[str, object]: channel_folders = ChannelFolder.objects.filter(realm=realm) return {"order": [folder.id for folder in channel_folders]} + + +@openapi_param_value_generator(["/user_uploads/{realm_id_str}/{filename}:get"]) +def get_temporary_url_for_uploaded_file() -> dict[str, object]: + realm_id = "" + filename = "" + user_profile = helpers.example_user("iago") + url = upload_message_attachment("dummy.txt", "text/plain", b"zulip!", user_profile)[0] + upload_path_parts = re.match(r"/user_uploads/(\d+)/(.*)", url) + if upload_path_parts: + realm_id = upload_path_parts[1] + filename = upload_path_parts[2] + return {"realm_id_str": realm_id, "filename": filename} diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index 0df8bedffe..b0e126ac9b 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -10284,17 +10284,24 @@ paths: /user_uploads/{realm_id_str}/{filename}: get: operationId: get-file-temporary-url - summary: Get public temporary URL + summary: Get public temporary URL for an uploaded file tags: ["messages"] description: | - Get a temporary URL for access to the file that doesn't require authentication. + Get a temporary URL for access to an [uploaded file](/api/upload-file) + that doesn't require authentication. + + The `SIGNED_ACCESS_TOKEN_VALIDITY_IN_SECONDS` server setting controls + the valid length of time for temporary access, which generally is set + to a default of 60 seconds. Consumers of this API are expected to + immediately request the URL that it returns, and should not store it + in any way. **Changes**: New in Zulip 3.0 (feature level 1). parameters: - name: realm_id_str in: path description: | - The realm ID. + The ID of the Zulip organization. schema: type: integer example: 1 @@ -10302,7 +10309,7 @@ paths: - name: filename in: path description: | - Path to the URL. + Path to the [uploaded file](/api/upload-file). schema: type: string example: 4e/m2A3MSqFnWRLUf9SaPzQ0Up_/zulip.txt diff --git a/zerver/tests/test_openapi.py b/zerver/tests/test_openapi.py index 196e4d7dcc..e4f91b7b96 100644 --- a/zerver/tests/test_openapi.py +++ b/zerver/tests/test_openapi.py @@ -210,9 +210,7 @@ class OpenAPIArgumentsTest(ZulipTestCase): # and thus may be complicated to document with our current tooling. # (No /api/v1/ or /json prefix). "/avatar/{email_or_id}", - ## This one is in zulip.yaml, but not the actual docs. - # "/api/v1/user_uploads/{realm_id_str}/{filename}", - ## And this one isn't, and isn't really representable + ## This one isn't really representable # "/user_uploads/{realm_id_str}/{filename}", #### These realm administration settings are valuable to document: # Delete a data export.