mirror of
https://github.com/zulip/zulip.git
synced 2025-11-01 20:44:04 +00:00
events: Migrate to typed_endpoint.
Migrate `event_register.py` and `tornado` to typed_endpoint. Modified the tests to work with the migrated endpoints.
This commit is contained in:
committed by
Tim Abbott
parent
4e63daf2ce
commit
97f15d8811
@@ -1,29 +1,21 @@
|
||||
import time
|
||||
from collections.abc import Callable, Mapping, Sequence
|
||||
from typing import Any, TypeVar
|
||||
from collections.abc import Callable
|
||||
from typing import Annotated, Any, TypeVar
|
||||
|
||||
from asgiref.sync import async_to_sync
|
||||
from django.conf import settings
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import gettext as _
|
||||
from pydantic import Json
|
||||
from pydantic import BaseModel, Json, NonNegativeInt, StringConstraints, model_validator
|
||||
from typing_extensions import ParamSpec
|
||||
|
||||
from zerver.decorator import internal_api_view, process_client
|
||||
from zerver.lib.exceptions import JsonableError
|
||||
from zerver.lib.queue import get_queue_client
|
||||
from zerver.lib.request import REQ, RequestNotes, has_request_variables
|
||||
from zerver.lib.request import RequestNotes
|
||||
from zerver.lib.response import AsynchronousResponse, json_success
|
||||
from zerver.lib.typed_endpoint import typed_endpoint
|
||||
from zerver.lib.validator import (
|
||||
check_bool,
|
||||
check_dict,
|
||||
check_int,
|
||||
check_list,
|
||||
check_string,
|
||||
to_non_negative_int,
|
||||
)
|
||||
from zerver.models import Client, UserProfile
|
||||
from zerver.lib.typed_endpoint import ApiParamConfig, DocumentationStatus, typed_endpoint
|
||||
from zerver.models import UserProfile
|
||||
from zerver.models.clients import get_client
|
||||
from zerver.models.users import get_user_profile_by_id
|
||||
from zerver.tornado.descriptors import is_current_port
|
||||
@@ -47,10 +39,8 @@ def in_tornado_thread(f: Callable[P, T]) -> Callable[P, T]:
|
||||
|
||||
|
||||
@internal_api_view(True)
|
||||
@has_request_variables
|
||||
def notify(
|
||||
request: HttpRequest, data: Mapping[str, Any] = REQ(json_validator=check_dict([]))
|
||||
) -> HttpResponse:
|
||||
@typed_endpoint
|
||||
def notify(request: HttpRequest, *, data: Json[dict[str, Any]]) -> HttpResponse:
|
||||
# Only the puppeteer full-stack tests use this endpoint; it
|
||||
# injects an event, as if read from RabbitMQ.
|
||||
in_tornado_thread(process_notification)(data)
|
||||
@@ -77,9 +67,9 @@ def web_reload_clients(
|
||||
)
|
||||
|
||||
|
||||
@has_request_variables
|
||||
@typed_endpoint
|
||||
def cleanup_event_queue(
|
||||
request: HttpRequest, user_profile: UserProfile, queue_id: str = REQ()
|
||||
request: HttpRequest, user_profile: UserProfile, *, queue_id: str
|
||||
) -> HttpResponse:
|
||||
log_data = RequestNotes.get_notes(request).log_data
|
||||
assert log_data is not None
|
||||
@@ -108,10 +98,8 @@ def cleanup_event_queue(
|
||||
|
||||
|
||||
@internal_api_view(True)
|
||||
@has_request_variables
|
||||
def get_events_internal(
|
||||
request: HttpRequest, user_profile_id: int = REQ(json_validator=check_int)
|
||||
) -> HttpResponse:
|
||||
@typed_endpoint
|
||||
def get_events_internal(request: HttpRequest, *, user_profile_id: Json[int]) -> HttpResponse:
|
||||
user_profile = get_user_profile_by_id(user_profile_id)
|
||||
RequestNotes.get_notes(request).requester_for_logs = user_profile.format_requester_for_logs()
|
||||
assert is_current_port(get_user_tornado_port(user_profile))
|
||||
@@ -137,64 +125,90 @@ def get_events(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
|
||||
return get_events_backend(request, user_profile)
|
||||
|
||||
|
||||
@has_request_variables
|
||||
class UserClient(BaseModel):
|
||||
id: int
|
||||
name: Annotated[str, StringConstraints(max_length=30)]
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def convert_term(cls, elem: str) -> dict[str, Any]:
|
||||
client = get_client(elem)
|
||||
return {"id": client.id, "name": client.name}
|
||||
|
||||
|
||||
@typed_endpoint
|
||||
def get_events_backend(
|
||||
request: HttpRequest,
|
||||
user_profile: UserProfile,
|
||||
*,
|
||||
# user_client is intended only for internal Django=>Tornado requests
|
||||
# and thus shouldn't be documented for external use.
|
||||
user_client: Client | None = REQ(
|
||||
converter=lambda var_name, s: get_client(s), default=None, intentionally_undocumented=True
|
||||
),
|
||||
last_event_id: int | None = REQ(json_validator=check_int, default=None),
|
||||
queue_id: str | None = REQ(default=None),
|
||||
user_client: Annotated[
|
||||
UserClient | None,
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = None,
|
||||
last_event_id: Json[int] | None = None,
|
||||
queue_id: str | None = None,
|
||||
# apply_markdown, client_gravatar, all_public_streams, and various
|
||||
# other parameters are only used when registering a new queue via this
|
||||
# endpoint. This is a feature used primarily by get_events_internal
|
||||
# and not expected to be used by third-party clients.
|
||||
apply_markdown: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
client_gravatar: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
slim_presence: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
all_public_streams: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
event_types: Sequence[str] | None = REQ(
|
||||
default=None, json_validator=check_list(check_string), intentionally_undocumented=True
|
||||
),
|
||||
dont_block: bool = REQ(default=False, json_validator=check_bool),
|
||||
narrow: Sequence[Sequence[str]] = REQ(
|
||||
default=[],
|
||||
json_validator=check_list(check_list(check_string)),
|
||||
intentionally_undocumented=True,
|
||||
),
|
||||
lifespan_secs: int = REQ(
|
||||
default=0, converter=to_non_negative_int, intentionally_undocumented=True
|
||||
),
|
||||
bulk_message_deletion: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
stream_typing_notifications: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
user_settings_object: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
pronouns_field_type_supported: bool = REQ(
|
||||
default=True, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
linkifier_url_template: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
user_list_incomplete: bool = REQ(
|
||||
default=False, json_validator=check_bool, intentionally_undocumented=True
|
||||
),
|
||||
apply_markdown: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
client_gravatar: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
slim_presence: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
all_public_streams: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
event_types: Annotated[
|
||||
Json[list[str]] | None,
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = None,
|
||||
dont_block: Json[bool] = False,
|
||||
narrow: Annotated[
|
||||
Json[list[list[str]]] | None,
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = None,
|
||||
lifespan_secs: Annotated[
|
||||
Json[NonNegativeInt],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = 0,
|
||||
bulk_message_deletion: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
stream_typing_notifications: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
user_settings_object: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
pronouns_field_type_supported: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = True,
|
||||
linkifier_url_template: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
user_list_incomplete: Annotated[
|
||||
Json[bool],
|
||||
ApiParamConfig(documentation_status=DocumentationStatus.INTENTIONALLY_UNDOCUMENTED),
|
||||
] = False,
|
||||
) -> HttpResponse:
|
||||
if narrow is None:
|
||||
narrow = []
|
||||
if all_public_streams and not user_profile.can_access_public_streams():
|
||||
raise JsonableError(_("User not authorized for this query"))
|
||||
|
||||
@@ -205,8 +219,9 @@ def get_events_backend(
|
||||
if user_client is None:
|
||||
valid_user_client = RequestNotes.get_notes(request).client
|
||||
assert valid_user_client is not None
|
||||
valid_user_client_name = valid_user_client.name
|
||||
else:
|
||||
valid_user_client = user_client
|
||||
valid_user_client_name = user_client.name
|
||||
|
||||
new_queue_data = None
|
||||
if queue_id is None:
|
||||
@@ -214,7 +229,7 @@ def get_events_backend(
|
||||
user_profile_id=user_profile.id,
|
||||
realm_id=user_profile.realm_id,
|
||||
event_types=event_types,
|
||||
client_type_name=valid_user_client.name,
|
||||
client_type_name=valid_user_client_name,
|
||||
apply_markdown=apply_markdown,
|
||||
client_gravatar=client_gravatar,
|
||||
slim_presence=slim_presence,
|
||||
@@ -234,7 +249,7 @@ def get_events_backend(
|
||||
user_profile_id=user_profile.id,
|
||||
queue_id=queue_id,
|
||||
last_event_id=last_event_id,
|
||||
client_type_name=valid_user_client.name,
|
||||
client_type_name=valid_user_client_name,
|
||||
dont_block=dont_block,
|
||||
handler_id=handler_id,
|
||||
new_queue_data=new_queue_data,
|
||||
|
||||
Reference in New Issue
Block a user