snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
This commit is contained in:
571
zerver/openapi/curl_param_value_generators.py
Normal file
571
zerver/openapi/curl_param_value_generators.py
Normal file
@@ -0,0 +1,571 @@
|
||||
# Zulip's OpenAPI-based API documentation system is documented at
|
||||
# https://zulip.readthedocs.io/en/latest/documentation/api.html
|
||||
#
|
||||
# This file contains helper functions for generating cURL examples
|
||||
# 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, cast
|
||||
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
from zerver.actions.channel_folders import check_add_channel_folder
|
||||
from zerver.actions.create_user import do_create_user
|
||||
from zerver.actions.custom_profile_fields import try_add_realm_custom_profile_field
|
||||
from zerver.actions.presence import update_user_presence
|
||||
from zerver.actions.reactions import do_add_reaction
|
||||
from zerver.actions.realm_domains import do_add_realm_domain
|
||||
from zerver.actions.realm_linkifiers import do_add_linkifier
|
||||
from zerver.actions.realm_playgrounds import check_add_realm_playground
|
||||
from zerver.lib.bot_storage import set_bot_storage
|
||||
from zerver.lib.events import do_events_register
|
||||
from zerver.lib.initial_password import initial_password
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.test_helpers import read_test_image_file
|
||||
from zerver.lib.types import ProfileFieldData
|
||||
from zerver.lib.upload import upload_message_attachment
|
||||
from zerver.models import Client, CustomProfileField, Message, NamedUserGroup, UserPresence
|
||||
from zerver.models.channel_folders import ChannelFolder
|
||||
from zerver.models.realms import RealmExport, get_realm
|
||||
from zerver.models.users import UserProfile, get_user
|
||||
from zerver.openapi.openapi import Parameter
|
||||
|
||||
GENERATOR_FUNCTIONS: dict[str, Callable[[], dict[str, object]]] = {}
|
||||
REGISTERED_GENERATOR_FUNCTIONS: set[str] = set()
|
||||
CALLED_GENERATOR_FUNCTIONS: set[str] = set()
|
||||
# This is a List rather than just a string in order to make it easier
|
||||
# to write to it from another module.
|
||||
AUTHENTICATION_LINE: list[str] = [""]
|
||||
|
||||
helpers = ZulipTestCase()
|
||||
|
||||
|
||||
def openapi_param_value_generator(
|
||||
endpoints: list[str],
|
||||
) -> Callable[[Callable[[], dict[str, object]]], Callable[[], dict[str, object]]]:
|
||||
"""This decorator is used to register OpenAPI param value generator functions
|
||||
with endpoints. Example usage:
|
||||
|
||||
@openapi_param_value_generator(["/messages/render:post"])
|
||||
def ...
|
||||
"""
|
||||
|
||||
def wrapper(generator_func: Callable[[], dict[str, object]]) -> Callable[[], dict[str, object]]:
|
||||
@wraps(generator_func)
|
||||
def _record_calls_wrapper() -> dict[str, object]:
|
||||
CALLED_GENERATOR_FUNCTIONS.add(generator_func.__name__)
|
||||
return generator_func()
|
||||
|
||||
REGISTERED_GENERATOR_FUNCTIONS.add(generator_func.__name__)
|
||||
for endpoint in endpoints:
|
||||
GENERATOR_FUNCTIONS[endpoint] = _record_calls_wrapper
|
||||
|
||||
return _record_calls_wrapper
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def assert_all_helper_functions_called() -> None:
|
||||
"""Throws an exception if any registered helpers were not called by tests"""
|
||||
if REGISTERED_GENERATOR_FUNCTIONS == CALLED_GENERATOR_FUNCTIONS:
|
||||
return
|
||||
|
||||
uncalled_functions = str(REGISTERED_GENERATOR_FUNCTIONS - CALLED_GENERATOR_FUNCTIONS)
|
||||
|
||||
raise Exception(f"Registered curl API generators were not called: {uncalled_functions}")
|
||||
|
||||
|
||||
def patch_openapi_example_values(
|
||||
entry: str,
|
||||
parameters: list[Parameter],
|
||||
request_body: dict[str, Any] | None = None,
|
||||
) -> tuple[list[Parameter], dict[str, object] | None]:
|
||||
if entry not in GENERATOR_FUNCTIONS:
|
||||
return parameters, request_body
|
||||
func = GENERATOR_FUNCTIONS[entry]
|
||||
realm_example_values: dict[str, object] = func()
|
||||
|
||||
for parameter in parameters:
|
||||
if parameter.name in realm_example_values:
|
||||
parameter.example = realm_example_values[parameter.name]
|
||||
|
||||
if request_body is not None and "multipart/form-data" in (content := request_body["content"]):
|
||||
properties = content["multipart/form-data"]["schema"]["properties"]
|
||||
for key, property in properties.items():
|
||||
if key in realm_example_values:
|
||||
property["example"] = realm_example_values[key]
|
||||
return parameters, request_body
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/fetch_api_key:post"])
|
||||
def fetch_api_key() -> dict[str, object]:
|
||||
email = helpers.example_email("iago")
|
||||
password = initial_password(email)
|
||||
|
||||
return {
|
||||
"username": email,
|
||||
"password": password,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(
|
||||
[
|
||||
"/messages/{message_id}:get",
|
||||
"/messages/{message_id}/history:get",
|
||||
"/messages/{message_id}:patch",
|
||||
"/messages/{message_id}:delete",
|
||||
"/messages/{message_id}/reactions:post",
|
||||
]
|
||||
)
|
||||
def iago_message_id() -> dict[str, object]:
|
||||
iago = helpers.example_user("iago")
|
||||
helpers.subscribe(iago, "Denmark")
|
||||
return {
|
||||
"message_id": helpers.send_stream_message(iago, "Denmark"),
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/messages/{message_id}/reactions:delete"])
|
||||
def add_emoji_to_message() -> dict[str, object]:
|
||||
user_profile = helpers.example_user("iago")
|
||||
|
||||
# Get a message ID by calling the message generator
|
||||
message_id = cast(int, iago_message_id()["message_id"])
|
||||
|
||||
emoji_name = "octopus"
|
||||
emoji_code = "1f419"
|
||||
reaction_type = "unicode_emoji"
|
||||
|
||||
message = Message.objects.select_related(*Message.DEFAULT_SELECT_RELATED).get(id=message_id)
|
||||
do_add_reaction(user_profile, message, emoji_name, emoji_code, reaction_type)
|
||||
|
||||
return {
|
||||
"message_id": message_id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/messages/flags:post"])
|
||||
def update_flags_message_ids() -> dict[str, object]:
|
||||
stream_name = "Venice"
|
||||
helpers.subscribe(helpers.example_user("iago"), stream_name)
|
||||
|
||||
messages = [
|
||||
helpers.send_stream_message(helpers.example_user("iago"), stream_name) for _ in range(3)
|
||||
]
|
||||
return {
|
||||
"messages": messages,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/mark_stream_as_read:post", "/users/me/{stream_id}/topics:get"])
|
||||
def get_venice_stream_id() -> dict[str, object]:
|
||||
return {
|
||||
"stream_id": helpers.get_stream_id("Venice"),
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/streams/{stream_id}:patch"])
|
||||
def update_stream() -> dict[str, object]:
|
||||
stream = helpers.subscribe(helpers.example_user("iago"), "temp_stream 1")
|
||||
return {
|
||||
"stream_id": stream.id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/streams/{stream_id}:delete"])
|
||||
def create_temp_stream_and_get_id() -> dict[str, object]:
|
||||
stream = helpers.subscribe(helpers.example_user("iago"), "temp_stream 2")
|
||||
return {
|
||||
"stream_id": stream.id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/mark_topic_as_read:post"])
|
||||
def get_denmark_stream_id_and_topic() -> dict[str, object]:
|
||||
stream_name = "Denmark"
|
||||
topic_name = "Tivoli Gardens"
|
||||
|
||||
helpers.subscribe(helpers.example_user("iago"), stream_name)
|
||||
helpers.send_stream_message(helpers.example_user("hamlet"), stream_name, topic_name=topic_name)
|
||||
|
||||
return {
|
||||
"stream_id": helpers.get_stream_id(stream_name),
|
||||
"topic_name": topic_name,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/users/me/subscriptions/properties:post"])
|
||||
def update_subscription_data() -> dict[str, object]:
|
||||
profile = helpers.example_user("iago")
|
||||
helpers.subscribe(profile, "Verona")
|
||||
helpers.subscribe(profile, "social")
|
||||
return {
|
||||
"subscription_data": [
|
||||
{"stream_id": helpers.get_stream_id("Verona"), "property": "pin_to_top", "value": True},
|
||||
{"stream_id": helpers.get_stream_id("social"), "property": "color", "value": "#f00f00"},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/users/me/subscriptions:delete"])
|
||||
def delete_subscription_data() -> dict[str, object]:
|
||||
iago = helpers.example_user("iago")
|
||||
zoe = helpers.example_user("ZOE")
|
||||
helpers.subscribe(iago, "Verona")
|
||||
helpers.subscribe(iago, "social")
|
||||
helpers.subscribe(zoe, "Verona")
|
||||
helpers.subscribe(zoe, "social")
|
||||
return {}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/events:get"])
|
||||
def get_events() -> dict[str, object]:
|
||||
profile = helpers.example_user("iago")
|
||||
helpers.subscribe(profile, "Verona")
|
||||
client = Client.objects.create(name="curl-test-client-1")
|
||||
response = do_events_register(
|
||||
profile, profile.realm, client, event_types=["message", "realm_emoji"]
|
||||
)
|
||||
helpers.send_stream_message(helpers.example_user("hamlet"), "Verona")
|
||||
return {
|
||||
"queue_id": response["queue_id"],
|
||||
"last_event_id": response["last_event_id"],
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/events:delete"])
|
||||
def delete_event_queue() -> dict[str, object]:
|
||||
profile = helpers.example_user("iago")
|
||||
client = Client.objects.create(name="curl-test-client-2")
|
||||
response = do_events_register(profile, profile.realm, client, event_types=["message"])
|
||||
return {
|
||||
"queue_id": response["queue_id"],
|
||||
"last_event_id": response["last_event_id"],
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/users/{user_id_or_email}/presence:get"])
|
||||
def get_user_presence() -> dict[str, object]:
|
||||
iago = helpers.example_user("iago")
|
||||
client = Client.objects.create(name="curl-test-client-3")
|
||||
update_user_presence(iago, client, timezone_now(), UserPresence.LEGACY_STATUS_ACTIVE_INT, False)
|
||||
return {}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/users:post"])
|
||||
def create_user() -> dict[str, object]:
|
||||
return {
|
||||
"email": helpers.nonreg_email("test"),
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/users/{email]:patch", "/users/{user_id}:patch"])
|
||||
def new_email_value() -> dict[str, object]:
|
||||
count = 0
|
||||
exists = True
|
||||
while exists:
|
||||
email = f"new{count}@zulip.com"
|
||||
exists = UserProfile.objects.filter(delivery_email=email).exists()
|
||||
count += 1
|
||||
return {
|
||||
"new_email": email,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/user_groups/create:post"])
|
||||
def create_user_group_data() -> dict[str, object]:
|
||||
return {
|
||||
"members": [helpers.example_user("hamlet").id, helpers.example_user("othello").id],
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/user_groups/{user_group_id}:patch"])
|
||||
def get_temp_user_group_id() -> dict[str, object]:
|
||||
user_group, _ = NamedUserGroup.objects.get_or_create(
|
||||
name="temp",
|
||||
realm=get_realm("zulip"),
|
||||
can_add_members_group_id=11,
|
||||
can_join_group_id=11,
|
||||
can_leave_group_id=15,
|
||||
can_manage_group_id=11,
|
||||
can_mention_group_id=11,
|
||||
can_remove_members_group_id=11,
|
||||
realm_for_sharding=get_realm("zulip"),
|
||||
)
|
||||
return {
|
||||
"user_group_id": user_group.id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/user_groups/{user_group_id}/deactivate:post"])
|
||||
def get_temp_user_group_id_for_deactivation() -> dict[str, object]:
|
||||
user_group, _ = NamedUserGroup.objects.get_or_create(
|
||||
name="temp-deactivation",
|
||||
realm=get_realm("zulip"),
|
||||
can_add_members_group_id=11,
|
||||
can_join_group_id=11,
|
||||
can_leave_group_id=15,
|
||||
can_manage_group_id=11,
|
||||
can_mention_group_id=11,
|
||||
can_remove_members_group_id=11,
|
||||
realm_for_sharding=get_realm("zulip"),
|
||||
)
|
||||
return {
|
||||
"user_group_id": user_group.id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/filters/{filter_id}:delete"])
|
||||
def remove_realm_filters() -> dict[str, object]:
|
||||
filter_id = do_add_linkifier(
|
||||
get_realm("zulip"),
|
||||
"#(?P<id>[0-9]{2,8})",
|
||||
"https://github.com/zulip/zulip/pull/{id}",
|
||||
acting_user=None,
|
||||
)
|
||||
return {
|
||||
"filter_id": filter_id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/emoji/{emoji_name}:post", "/user_uploads:post"])
|
||||
def upload_custom_emoji() -> dict[str, object]:
|
||||
return {
|
||||
"filename": "zerver/tests/images/animated_img.gif",
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/playgrounds:post"])
|
||||
def add_realm_playground() -> dict[str, object]:
|
||||
return {
|
||||
"name": "Python2 playground",
|
||||
"pygments_language": "Python2",
|
||||
"url_template": "https://python2.example.com?code={code}",
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/playgrounds/{playground_id}:delete"])
|
||||
def remove_realm_playground() -> dict[str, object]:
|
||||
playground_id = check_add_realm_playground(
|
||||
get_realm("zulip"),
|
||||
acting_user=None,
|
||||
name="Python playground",
|
||||
pygments_language="Python",
|
||||
url_template="https://python.example.com?code={code}",
|
||||
)
|
||||
return {
|
||||
"playground_id": playground_id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/profile_fields/{field_id}:patch"])
|
||||
def update_custom_profile_field() -> dict[str, object]:
|
||||
# A dropdown field, so that the documented field_data example validates.
|
||||
field_data: ProfileFieldData = {
|
||||
"0": {"text": "Vim", "order": "1"},
|
||||
"1": {"text": "Emacs", "order": "2"},
|
||||
}
|
||||
field = try_add_realm_custom_profile_field(
|
||||
get_realm("zulip"),
|
||||
"Favorite IDE",
|
||||
CustomProfileField.DROPDOWN,
|
||||
field_data=field_data,
|
||||
)
|
||||
return {
|
||||
"field_id": field.id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/profile_fields/{field_id}:delete"])
|
||||
def delete_custom_profile_field() -> dict[str, object]:
|
||||
field = try_add_realm_custom_profile_field(
|
||||
get_realm("zulip"),
|
||||
"Field to delete",
|
||||
CustomProfileField.SHORT_TEXT,
|
||||
)
|
||||
return {
|
||||
"field_id": field.id,
|
||||
}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/users/{user_id}:delete"])
|
||||
def deactivate_user() -> dict[str, object]:
|
||||
user_profile = do_create_user(
|
||||
email="testuser@zulip.com",
|
||||
password=None,
|
||||
full_name="test_user",
|
||||
realm=get_realm("zulip"),
|
||||
acting_user=None,
|
||||
)
|
||||
return {"user_id": user_profile.id}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/users/me:delete"])
|
||||
def deactivate_own_user() -> dict[str, object]:
|
||||
test_user_email = "delete-test@zulip.com"
|
||||
deactivate_test_user = do_create_user(
|
||||
test_user_email,
|
||||
"secret",
|
||||
get_realm("zulip"),
|
||||
"Mr. Delete",
|
||||
role=200,
|
||||
acting_user=None,
|
||||
)
|
||||
realm = get_realm("zulip")
|
||||
test_user = get_user(test_user_email, realm)
|
||||
test_user_api_key = test_user.api_key
|
||||
# change authentication line to allow test_client to delete itself.
|
||||
AUTHENTICATION_LINE[0] = f"{deactivate_test_user.email}:{test_user_api_key}"
|
||||
return {}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/attachments/{attachment_id}:delete"])
|
||||
def remove_attachment() -> dict[str, object]:
|
||||
user_profile = helpers.example_user("iago")
|
||||
url = upload_message_attachment("dummy.txt", "text/plain", b"zulip!", user_profile)[0]
|
||||
attachment_id = url.replace("/user_uploads/", "").split("/")[0]
|
||||
|
||||
return {"attachment_id": attachment_id}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/channel_folders:patch"])
|
||||
def add_channel_folders() -> dict[str, object]:
|
||||
user_profile = helpers.example_user("iago")
|
||||
realm = user_profile.realm
|
||||
check_add_channel_folder(
|
||||
realm,
|
||||
"General",
|
||||
"Channel for general discussions",
|
||||
acting_user=user_profile,
|
||||
)
|
||||
check_add_channel_folder(
|
||||
realm,
|
||||
"Documentation",
|
||||
"Channels for **documentation** discussions",
|
||||
acting_user=user_profile,
|
||||
)
|
||||
check_add_channel_folder(realm, "Memes", "Channels for sharing memes", acting_user=user_profile)
|
||||
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}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/users/me/api_key/regenerate:post"])
|
||||
def regenerate_api_key_test_user() -> dict[str, object]:
|
||||
test_user_email = "regenerate-api-key-test@zulip.com"
|
||||
test_user = do_create_user(
|
||||
test_user_email,
|
||||
"secret",
|
||||
get_realm("zulip"),
|
||||
"Mr. Regenerate",
|
||||
role=200,
|
||||
acting_user=None,
|
||||
)
|
||||
realm = get_realm("zulip")
|
||||
test_user_api_key = get_user(test_user_email, realm).api_key
|
||||
# Change authentication line to allow test_client to regenerate its own key.
|
||||
AUTHENTICATION_LINE[0] = f"{test_user.email}:{test_user_api_key}"
|
||||
return {}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/bots/{bot_id}/api_key/regenerate:post"])
|
||||
def regenerate_bot_api_key_test() -> dict[str, object]:
|
||||
bot = UserProfile.objects.filter(is_bot=True, realm=get_realm("zulip")).first()
|
||||
assert bot is not None
|
||||
return {"bot_id": bot.id}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/thumbnail/status/{realm_id_str}/{filename}:get"])
|
||||
def check_thumbnail_status_for_uploaded_file() -> dict[str, object]:
|
||||
realm_id = ""
|
||||
filename = ""
|
||||
user_profile = helpers.example_user("iago")
|
||||
url = upload_message_attachment(
|
||||
"img.png", "image/png", read_test_image_file("img.png"), 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}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/domains:post"])
|
||||
def add_realm_domain_owner_auth() -> dict[str, object]:
|
||||
# This endpoint requires organization owner permissions.
|
||||
owner = helpers.example_user("desdemona")
|
||||
AUTHENTICATION_LINE[0] = f"{owner.email}:{owner.api_key}"
|
||||
return {}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/domains/{domain}:patch"])
|
||||
def patch_realm_domain_owner_auth() -> dict[str, object]:
|
||||
# This endpoint requires organization owner permissions.
|
||||
owner = helpers.example_user("desdemona")
|
||||
AUTHENTICATION_LINE[0] = f"{owner.email}:{owner.api_key}"
|
||||
|
||||
do_add_realm_domain(owner.realm, "patch-domain-example.com", False, acting_user=None)
|
||||
return {"domain": "patch-domain-example.com"}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/realm/domains/{domain}:delete"])
|
||||
def delete_realm_domain_owner_auth() -> dict[str, object]:
|
||||
# This endpoint requires organization owner permissions.
|
||||
owner = helpers.example_user("desdemona")
|
||||
AUTHENTICATION_LINE[0] = f"{owner.email}:{owner.api_key}"
|
||||
|
||||
do_add_realm_domain(owner.realm, "delete-domain-example.com", False, acting_user=None)
|
||||
return {"domain": "delete-domain-example.com"}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/bot_storage:put"])
|
||||
def update_bot_storage_bot_auth() -> dict[str, object]:
|
||||
bot = helpers.example_user("default_bot")
|
||||
AUTHENTICATION_LINE[0] = f"{bot.email}:{bot.api_key}"
|
||||
return {}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/bot_storage:get"])
|
||||
def get_bot_storage_bot_auth() -> dict[str, object]:
|
||||
bot = helpers.example_user("default_bot")
|
||||
set_bot_storage(bot, [("foo", "bar")])
|
||||
AUTHENTICATION_LINE[0] = f"{bot.email}:{bot.api_key}"
|
||||
return {}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/bot_storage:delete"])
|
||||
def remove_bot_storage_bot_auth() -> dict[str, object]:
|
||||
bot = helpers.example_user("default_bot")
|
||||
set_bot_storage(bot, [("foo", "bar")])
|
||||
AUTHENTICATION_LINE[0] = f"{bot.email}:{bot.api_key}"
|
||||
return {}
|
||||
|
||||
|
||||
@openapi_param_value_generator(["/export/realm/{export_id}:delete"])
|
||||
def delete_realm_export() -> dict[str, object]:
|
||||
export = RealmExport.objects.create(
|
||||
realm=get_realm("zulip"),
|
||||
type=RealmExport.EXPORT_PUBLIC,
|
||||
status=RealmExport.SUCCEEDED,
|
||||
date_requested=timezone_now(),
|
||||
date_started=timezone_now(),
|
||||
date_succeeded=timezone_now(),
|
||||
export_path="/dummy",
|
||||
)
|
||||
return {"export_id": export.id}
|
||||
Reference in New Issue
Block a user