diff --git a/synapse/rest/client/shared_rooms.py b/synapse/rest/client/mutual_rooms.py
index e669fa7890..27bfaf0b29 100644
--- a/synapse/rest/client/shared_rooms.py
+++ b/synapse/rest/client/mutual_rooms.py
@@ -28,13 +28,13 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
-class UserSharedRoomsServlet(RestServlet):
+class UserMutualRoomsServlet(RestServlet):
"""
- GET /uk.half-shot.msc2666/user/shared_rooms/{user_id} HTTP/1.1
+ GET /uk.half-shot.msc2666/user/mutual_rooms/{user_id} HTTP/1.1
"""
PATTERNS = client_patterns(
- "/uk.half-shot.msc2666/user/shared_rooms/(?P<user_id>[^/]*)",
+ "/uk.half-shot.msc2666/user/mutual_rooms/(?P<user_id>[^/]*)",
releases=(), # This is an unstable feature
)
@@ -42,17 +42,19 @@ class UserSharedRoomsServlet(RestServlet):
super().__init__()
self.auth = hs.get_auth()
self.store = hs.get_datastores().main
- self.user_directory_active = hs.config.server.update_user_directory
+ self.user_directory_search_enabled = (
+ hs.config.userdirectory.user_directory_search_enabled
+ )
async def on_GET(
self, request: SynapseRequest, user_id: str
) -> Tuple[int, JsonDict]:
- if not self.user_directory_active:
+ if not self.user_directory_search_enabled:
raise SynapseError(
code=400,
- msg="The user directory is disabled on this server. Cannot determine shared rooms.",
- errcode=Codes.FORBIDDEN,
+ msg="User directory searching is disabled. Cannot determine shared rooms.",
+ errcode=Codes.UNKNOWN,
)
UserID.from_string(user_id)
@@ -64,7 +66,8 @@ class UserSharedRoomsServlet(RestServlet):
msg="You cannot request a list of shared rooms with yourself",
errcode=Codes.FORBIDDEN,
)
- rooms = await self.store.get_shared_rooms_for_users(
+
+ rooms = await self.store.get_mutual_rooms_for_users(
requester.user.to_string(), user_id
)
@@ -72,4 +75,4 @@ class UserSharedRoomsServlet(RestServlet):
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
- UserSharedRoomsServlet(hs).register(http_server)
+ UserMutualRoomsServlet(hs).register(http_server)
diff --git a/synapse/rest/client/notifications.py b/synapse/rest/client/notifications.py
index 20377a9ac6..ff040de6b8 100644
--- a/synapse/rest/client/notifications.py
+++ b/synapse/rest/client/notifications.py
@@ -16,7 +16,10 @@ import logging
from typing import TYPE_CHECKING, Tuple
from synapse.api.constants import ReceiptTypes
-from synapse.events.utils import format_event_for_client_v2_without_room_id
+from synapse.events.utils import (
+ SerializeEventConfig,
+ format_event_for_client_v2_without_room_id,
+)
from synapse.http.server import HttpServer
from synapse.http.servlet import RestServlet, parse_integer, parse_string
from synapse.http.site import SynapseRequest
@@ -75,7 +78,9 @@ class NotificationsServlet(RestServlet):
self._event_serializer.serialize_event(
notif_events[pa.event_id],
self.clock.time_msec(),
- event_format=format_event_for_client_v2_without_room_id,
+ config=SerializeEventConfig(
+ event_format=format_event_for_client_v2_without_room_id
+ ),
)
),
}
diff --git a/synapse/rest/client/relations.py b/synapse/rest/client/relations.py
index 487ea38b55..c16078b187 100644
--- a/synapse/rest/client/relations.py
+++ b/synapse/rest/client/relations.py
@@ -27,50 +27,15 @@ from synapse.http.server import HttpServer
from synapse.http.servlet import RestServlet, parse_integer, parse_string
from synapse.http.site import SynapseRequest
from synapse.rest.client._base import client_patterns
-from synapse.storage.relations import (
- AggregationPaginationToken,
- PaginationChunk,
- RelationPaginationToken,
-)
-from synapse.types import JsonDict, RoomStreamToken, StreamToken
+from synapse.storage.relations import AggregationPaginationToken
+from synapse.types import JsonDict, StreamToken
if TYPE_CHECKING:
from synapse.server import HomeServer
- from synapse.storage.databases.main import DataStore
logger = logging.getLogger(__name__)
-async def _parse_token(
- store: "DataStore", token: Optional[str]
-) -> Optional[StreamToken]:
- """
- For backwards compatibility support RelationPaginationToken, but new pagination
- tokens are generated as full StreamTokens, to be compatible with /sync and /messages.
- """
- if not token:
- return None
- # Luckily the format for StreamToken and RelationPaginationToken differ enough
- # that they can easily be separated. An "_" appears in the serialization of
- # RoomStreamToken (as part of StreamToken), but RelationPaginationToken uses
- # "-" only for separators.
- if "_" in token:
- return await StreamToken.from_string(store, token)
- else:
- relation_token = RelationPaginationToken.from_string(token)
- return StreamToken(
- room_key=RoomStreamToken(relation_token.topological, relation_token.stream),
- presence_key=0,
- typing_key=0,
- receipt_key=0,
- account_data_key=0,
- push_rules_key=0,
- to_device_key=0,
- device_list_key=0,
- groups_key=0,
- )
-
-
class RelationPaginationServlet(RestServlet):
"""API to paginate relations on an event by topological ordering, optionally
filtered by relation type and event type.
@@ -86,9 +51,7 @@ class RelationPaginationServlet(RestServlet):
super().__init__()
self.auth = hs.get_auth()
self.store = hs.get_datastores().main
- self.clock = hs.get_clock()
- self._event_serializer = hs.get_event_client_serializer()
- self.event_handler = hs.get_event_handler()
+ self._relations_handler = hs.get_relations_handler()
async def on_GET(
self,
@@ -100,16 +63,6 @@ class RelationPaginationServlet(RestServlet):
) -> Tuple[int, JsonDict]:
requester = await self.auth.get_user_by_req(request, allow_guest=True)
- await self.auth.check_user_in_room_or_world_readable(
- room_id, requester.user.to_string(), allow_departed_users=True
- )
-
- # This gets the original event and checks that a) the event exists and
- # b) the user is allowed to view it.
- event = await self.event_handler.get_event(requester.user, room_id, parent_id)
- if event is None:
- raise SynapseError(404, "Unknown parent event.")
-
limit = parse_integer(request, "limit", default=5)
direction = parse_string(
request, "org.matrix.msc3715.dir", default="b", allowed_values=["f", "b"]
@@ -117,49 +70,27 @@ class RelationPaginationServlet(RestServlet):
from_token_str = parse_string(request, "from")
to_token_str = parse_string(request, "to")
- if event.internal_metadata.is_redacted():
- # If the event is redacted, return an empty list of relations
- pagination_chunk = PaginationChunk(chunk=[])
- else:
- # Return the relations
- from_token = await _parse_token(self.store, from_token_str)
- to_token = await _parse_token(self.store, to_token_str)
-
- pagination_chunk = await self.store.get_relations_for_event(
- event_id=parent_id,
- room_id=room_id,
- relation_type=relation_type,
- event_type=event_type,
- limit=limit,
- direction=direction,
- from_token=from_token,
- to_token=to_token,
- )
+ # Return the relations
+ from_token = None
+ if from_token_str:
+ from_token = await StreamToken.from_string(self.store, from_token_str)
+ to_token = None
+ if to_token_str:
+ to_token = await StreamToken.from_string(self.store, to_token_str)
- events = await self.store.get_events_as_list(
- [c["event_id"] for c in pagination_chunk.chunk]
- )
-
- now = self.clock.time_msec()
- # Do not bundle aggregations when retrieving the original event because
- # we want the content before relations are applied to it.
- original_event = self._event_serializer.serialize_event(
- event, now, bundle_aggregations=None
- )
- # The relations returned for the requested event do include their
- # bundled aggregations.
- aggregations = await self.store.get_bundled_aggregations(
- events, requester.user.to_string()
- )
- serialized_events = self._event_serializer.serialize_events(
- events, now, bundle_aggregations=aggregations
+ result = await self._relations_handler.get_relations(
+ requester=requester,
+ event_id=parent_id,
+ room_id=room_id,
+ relation_type=relation_type,
+ event_type=event_type,
+ limit=limit,
+ direction=direction,
+ from_token=from_token,
+ to_token=to_token,
)
- return_value = await pagination_chunk.to_dict(self.store)
- return_value["chunk"] = serialized_events
- return_value["original_event"] = original_event
-
- return 200, return_value
+ return 200, result
class RelationAggregationPaginationServlet(RestServlet):
@@ -224,27 +155,23 @@ class RelationAggregationPaginationServlet(RestServlet):
from_token_str = parse_string(request, "from")
to_token_str = parse_string(request, "to")
- if event.internal_metadata.is_redacted():
- # If the event is redacted, return an empty list of relations
- pagination_chunk = PaginationChunk(chunk=[])
- else:
- # Return the relations
- from_token = None
- if from_token_str:
- from_token = AggregationPaginationToken.from_string(from_token_str)
-
- to_token = None
- if to_token_str:
- to_token = AggregationPaginationToken.from_string(to_token_str)
-
- pagination_chunk = await self.store.get_aggregation_groups_for_event(
- event_id=parent_id,
- room_id=room_id,
- event_type=event_type,
- limit=limit,
- from_token=from_token,
- to_token=to_token,
- )
+ # Return the relations
+ from_token = None
+ if from_token_str:
+ from_token = AggregationPaginationToken.from_string(from_token_str)
+
+ to_token = None
+ if to_token_str:
+ to_token = AggregationPaginationToken.from_string(to_token_str)
+
+ pagination_chunk = await self.store.get_aggregation_groups_for_event(
+ event_id=parent_id,
+ room_id=room_id,
+ event_type=event_type,
+ limit=limit,
+ from_token=from_token,
+ to_token=to_token,
+ )
return 200, await pagination_chunk.to_dict(self.store)
@@ -283,9 +210,7 @@ class RelationAggregationGroupPaginationServlet(RestServlet):
super().__init__()
self.auth = hs.get_auth()
self.store = hs.get_datastores().main
- self.clock = hs.get_clock()
- self._event_serializer = hs.get_event_client_serializer()
- self.event_handler = hs.get_event_handler()
+ self._relations_handler = hs.get_relations_handler()
async def on_GET(
self,
@@ -298,18 +223,6 @@ class RelationAggregationGroupPaginationServlet(RestServlet):
) -> Tuple[int, JsonDict]:
requester = await self.auth.get_user_by_req(request, allow_guest=True)
- await self.auth.check_user_in_room_or_world_readable(
- room_id,
- requester.user.to_string(),
- allow_departed_users=True,
- )
-
- # This checks that a) the event exists and b) the user is allowed to
- # view it.
- event = await self.event_handler.get_event(requester.user, room_id, parent_id)
- if event is None:
- raise SynapseError(404, "Unknown parent event.")
-
if relation_type != RelationTypes.ANNOTATION:
raise SynapseError(400, "Relation type must be 'annotation'")
@@ -317,10 +230,15 @@ class RelationAggregationGroupPaginationServlet(RestServlet):
from_token_str = parse_string(request, "from")
to_token_str = parse_string(request, "to")
- from_token = await _parse_token(self.store, from_token_str)
- to_token = await _parse_token(self.store, to_token_str)
+ from_token = None
+ if from_token_str:
+ from_token = await StreamToken.from_string(self.store, from_token_str)
+ to_token = None
+ if to_token_str:
+ to_token = await StreamToken.from_string(self.store, to_token_str)
- result = await self.store.get_relations_for_event(
+ result = await self._relations_handler.get_relations(
+ requester=requester,
event_id=parent_id,
room_id=room_id,
relation_type=relation_type,
@@ -331,17 +249,7 @@ class RelationAggregationGroupPaginationServlet(RestServlet):
to_token=to_token,
)
- events = await self.store.get_events_as_list(
- [c["event_id"] for c in result.chunk]
- )
-
- now = self.clock.time_msec()
- serialized_events = self._event_serializer.serialize_events(events, now)
-
- return_value = await result.to_dict(self.store)
- return_value["chunk"] = serialized_events
-
- return 200, return_value
+ return 200, result
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
diff --git a/synapse/rest/client/room.py b/synapse/rest/client/room.py
index 8a06ab8c5f..47e152c8cc 100644
--- a/synapse/rest/client/room.py
+++ b/synapse/rest/client/room.py
@@ -645,6 +645,7 @@ class RoomEventServlet(RestServlet):
self._store = hs.get_datastores().main
self.event_handler = hs.get_event_handler()
self._event_serializer = hs.get_event_client_serializer()
+ self._relations_handler = hs.get_relations_handler()
self.auth = hs.get_auth()
async def on_GET(
@@ -663,7 +664,7 @@ class RoomEventServlet(RestServlet):
if event:
# Ensure there are bundled aggregations available.
- aggregations = await self._store.get_bundled_aggregations(
+ aggregations = await self._relations_handler.get_bundled_aggregations(
[event], requester.user.to_string()
)
diff --git a/synapse/rest/client/room_batch.py b/synapse/rest/client/room_batch.py
index 0048973e59..0780485322 100644
--- a/synapse/rest/client/room_batch.py
+++ b/synapse/rest/client/room_batch.py
@@ -124,14 +124,14 @@ class RoomBatchSendEventRestServlet(RestServlet):
)
# For the event we are inserting next to (`prev_event_ids_from_query`),
- # find the most recent auth events (derived from state events) that
- # allowed that message to be sent. We will use that as a base
- # to auth our historical messages against.
- auth_event_ids = await self.room_batch_handler.get_most_recent_auth_event_ids_from_event_id_list(
+ # find the most recent state events that allowed that message to be
+ # sent. We will use that as a base to auth our historical messages
+ # against.
+ state_event_ids = await self.room_batch_handler.get_most_recent_full_state_ids_from_event_id_list(
prev_event_ids_from_query
)
- if not auth_event_ids:
+ if not state_event_ids:
raise SynapseError(
HTTPStatus.BAD_REQUEST,
"No auth events found for given prev_event query parameter. The prev_event=%s probably does not exist."
@@ -148,13 +148,13 @@ class RoomBatchSendEventRestServlet(RestServlet):
await self.room_batch_handler.persist_state_events_at_start(
state_events_at_start=body["state_events_at_start"],
room_id=room_id,
- initial_auth_event_ids=auth_event_ids,
+ initial_state_event_ids=state_event_ids,
app_service_requester=requester,
)
)
# Update our ongoing auth event ID list with all of the new state we
# just created
- auth_event_ids.extend(state_event_ids_at_start)
+ state_event_ids.extend(state_event_ids_at_start)
inherited_depth = await self.room_batch_handler.inherit_depth_from_prev_ids(
prev_event_ids_from_query
@@ -196,7 +196,12 @@ class RoomBatchSendEventRestServlet(RestServlet):
),
base_insertion_event_dict,
prev_event_ids=base_insertion_event_dict.get("prev_events"),
- auth_event_ids=auth_event_ids,
+ # Also set the explicit state here because we want to resolve
+ # any `state_events_at_start` here too. It's not strictly
+ # necessary to accomplish anything but if someone asks for the
+ # state at this point, we probably want to show them the
+ # historical state that was part of this batch.
+ state_event_ids=state_event_ids,
historical=True,
depth=inherited_depth,
)
@@ -212,7 +217,7 @@ class RoomBatchSendEventRestServlet(RestServlet):
room_id=room_id,
batch_id_to_connect_to=batch_id_to_connect_to,
inherited_depth=inherited_depth,
- auth_event_ids=auth_event_ids,
+ initial_state_event_ids=state_event_ids,
app_service_requester=requester,
)
diff --git a/synapse/rest/client/sync.py b/synapse/rest/client/sync.py
index f3018ff690..53c385a86c 100644
--- a/synapse/rest/client/sync.py
+++ b/synapse/rest/client/sync.py
@@ -14,24 +14,14 @@
import itertools
import logging
from collections import defaultdict
-from typing import (
- TYPE_CHECKING,
- Any,
- Callable,
- Dict,
- Iterable,
- List,
- Optional,
- Tuple,
- Union,
-)
+from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
from synapse.api.constants import Membership, PresenceState
from synapse.api.errors import Codes, StoreError, SynapseError
from synapse.api.filtering import FilterCollection
from synapse.api.presence import UserPresenceState
-from synapse.events import EventBase
from synapse.events.utils import (
+ SerializeEventConfig,
format_event_for_client_v2_without_room_id,
format_event_raw,
)
@@ -48,7 +38,6 @@ from synapse.http.server import HttpServer
from synapse.http.servlet import RestServlet, parse_boolean, parse_integer, parse_string
from synapse.http.site import SynapseRequest
from synapse.logging.opentracing import trace
-from synapse.storage.databases.main.relations import BundledAggregations
from synapse.types import JsonDict, StreamToken
from synapse.util import json_decoder
@@ -239,28 +228,31 @@ class SyncRestServlet(RestServlet):
else:
raise Exception("Unknown event format %s" % (filter.event_format,))
+ serialize_options = SerializeEventConfig(
+ event_format=event_formatter,
+ token_id=access_token_id,
+ only_event_fields=filter.event_fields,
+ )
+ stripped_serialize_options = SerializeEventConfig(
+ event_format=event_formatter,
+ token_id=access_token_id,
+ include_stripped_room_state=True,
+ )
+
joined = await self.encode_joined(
- sync_result.joined,
- time_now,
- access_token_id,
- filter.event_fields,
- event_formatter,
+ sync_result.joined, time_now, serialize_options
)
invited = await self.encode_invited(
- sync_result.invited, time_now, access_token_id, event_formatter
+ sync_result.invited, time_now, stripped_serialize_options
)
knocked = await self.encode_knocked(
- sync_result.knocked, time_now, access_token_id, event_formatter
+ sync_result.knocked, time_now, stripped_serialize_options
)
archived = await self.encode_archived(
- sync_result.archived,
- time_now,
- access_token_id,
- filter.event_fields,
- event_formatter,
+ sync_result.archived, time_now, serialize_options
)
logger.debug("building sync response dict")
@@ -339,9 +331,7 @@ class SyncRestServlet(RestServlet):
self,
rooms: List[JoinedSyncResult],
time_now: int,
- token_id: Optional[int],
- event_fields: List[str],
- event_formatter: Callable[[JsonDict], JsonDict],
+ serialize_options: SerializeEventConfig,
) -> JsonDict:
"""
Encode the joined rooms in a sync result
@@ -349,24 +339,14 @@ class SyncRestServlet(RestServlet):
Args:
rooms: list of sync results for rooms this user is joined to
time_now: current time - used as a baseline for age calculations
- token_id: ID of the user's auth token - used for namespacing
- of transaction IDs
- event_fields: List of event fields to include. If empty,
- all fields will be returned.
- event_formatter: function to convert from federation format
- to client format
+ serialize_options: Event serializer options
Returns:
The joined rooms list, in our response format
"""
joined = {}
for room in rooms:
joined[room.room_id] = await self.encode_room(
- room,
- time_now,
- token_id,
- joined=True,
- only_fields=event_fields,
- event_formatter=event_formatter,
+ room, time_now, joined=True, serialize_options=serialize_options
)
return joined
@@ -376,8 +356,7 @@ class SyncRestServlet(RestServlet):
self,
rooms: List[InvitedSyncResult],
time_now: int,
- token_id: Optional[int],
- event_formatter: Callable[[JsonDict], JsonDict],
+ serialize_options: SerializeEventConfig,
) -> JsonDict:
"""
Encode the invited rooms in a sync result
@@ -385,10 +364,7 @@ class SyncRestServlet(RestServlet):
Args:
rooms: list of sync results for rooms this user is invited to
time_now: current time - used as a baseline for age calculations
- token_id: ID of the user's auth token - used for namespacing
- of transaction IDs
- event_formatter: function to convert from federation format
- to client format
+ serialize_options: Event serializer options
Returns:
The invited rooms list, in our response format
@@ -396,11 +372,7 @@ class SyncRestServlet(RestServlet):
invited = {}
for room in rooms:
invite = self._event_serializer.serialize_event(
- room.invite,
- time_now,
- token_id=token_id,
- event_format=event_formatter,
- include_stripped_room_state=True,
+ room.invite, time_now, config=serialize_options
)
unsigned = dict(invite.get("unsigned", {}))
invite["unsigned"] = unsigned
@@ -415,8 +387,7 @@ class SyncRestServlet(RestServlet):
self,
rooms: List[KnockedSyncResult],
time_now: int,
- token_id: Optional[int],
- event_formatter: Callable[[Dict], Dict],
+ serialize_options: SerializeEventConfig,
) -> Dict[str, Dict[str, Any]]:
"""
Encode the rooms we've knocked on in a sync result.
@@ -424,8 +395,7 @@ class SyncRestServlet(RestServlet):
Args:
rooms: list of sync results for rooms this user is knocking on
time_now: current time - used as a baseline for age calculations
- token_id: ID of the user's auth token - used for namespacing of transaction IDs
- event_formatter: function to convert from federation format to client format
+ serialize_options: Event serializer options
Returns:
The list of rooms the user has knocked on, in our response format.
@@ -433,11 +403,7 @@ class SyncRestServlet(RestServlet):
knocked = {}
for room in rooms:
knock = self._event_serializer.serialize_event(
- room.knock,
- time_now,
- token_id=token_id,
- event_format=event_formatter,
- include_stripped_room_state=True,
+ room.knock, time_now, config=serialize_options
)
# Extract the `unsigned` key from the knock event.
@@ -470,9 +436,7 @@ class SyncRestServlet(RestServlet):
self,
rooms: List[ArchivedSyncResult],
time_now: int,
- token_id: Optional[int],
- event_fields: List[str],
- event_formatter: Callable[[JsonDict], JsonDict],
+ serialize_options: SerializeEventConfig,
) -> JsonDict:
"""
Encode the archived rooms in a sync result
@@ -480,23 +444,14 @@ class SyncRestServlet(RestServlet):
Args:
rooms: list of sync results for rooms this user is joined to
time_now: current time - used as a baseline for age calculations
- token_id: ID of the user's auth token - used for namespacing
- of transaction IDs
- event_fields: List of event fields to include. If empty,
- all fields will be returned.
- event_formatter: function to convert from federation format to client format
+ serialize_options: Event serializer options
Returns:
The archived rooms list, in our response format
"""
joined = {}
for room in rooms:
joined[room.room_id] = await self.encode_room(
- room,
- time_now,
- token_id,
- joined=False,
- only_fields=event_fields,
- event_formatter=event_formatter,
+ room, time_now, joined=False, serialize_options=serialize_options
)
return joined
@@ -505,10 +460,8 @@ class SyncRestServlet(RestServlet):
self,
room: Union[JoinedSyncResult, ArchivedSyncResult],
time_now: int,
- token_id: Optional[int],
joined: bool,
- only_fields: Optional[List[str]],
- event_formatter: Callable[[JsonDict], JsonDict],
+ serialize_options: SerializeEventConfig,
) -> JsonDict:
"""
Args:
@@ -524,20 +477,6 @@ class SyncRestServlet(RestServlet):
Returns:
The room, encoded in our response format
"""
-
- def serialize(
- events: Iterable[EventBase],
- aggregations: Optional[Dict[str, BundledAggregations]] = None,
- ) -> List[JsonDict]:
- return self._event_serializer.serialize_events(
- events,
- time_now=time_now,
- bundle_aggregations=aggregations,
- token_id=token_id,
- event_format=event_formatter,
- only_event_fields=only_fields,
- )
-
state_dict = room.state
timeline_events = room.timeline.events
@@ -554,9 +493,14 @@ class SyncRestServlet(RestServlet):
event.room_id,
)
- serialized_state = serialize(state_events)
- serialized_timeline = serialize(
- timeline_events, room.timeline.bundled_aggregations
+ serialized_state = self._event_serializer.serialize_events(
+ state_events, time_now, config=serialize_options
+ )
+ serialized_timeline = self._event_serializer.serialize_events(
+ timeline_events,
+ time_now,
+ config=serialize_options,
+ bundle_aggregations=room.timeline.bundled_aggregations,
)
account_data = room.account_data
diff --git a/synapse/rest/client/user_directory.py b/synapse/rest/client/user_directory.py
index a47d9bd01d..116c982ce6 100644
--- a/synapse/rest/client/user_directory.py
+++ b/synapse/rest/client/user_directory.py
@@ -19,7 +19,7 @@ from synapse.api.errors import SynapseError
from synapse.http.server import HttpServer
from synapse.http.servlet import RestServlet, parse_json_object_from_request
from synapse.http.site import SynapseRequest
-from synapse.types import JsonDict
+from synapse.types import JsonMapping
from ._base import client_patterns
@@ -38,7 +38,7 @@ class UserDirectorySearchRestServlet(RestServlet):
self.auth = hs.get_auth()
self.user_directory_handler = hs.get_user_directory_handler()
- async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
+ async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonMapping]:
"""Searches for users in directory
Returns:
diff --git a/synapse/rest/client/versions.py b/synapse/rest/client/versions.py
index 2e5d0e4e22..9a65aa4843 100644
--- a/synapse/rest/client/versions.py
+++ b/synapse/rest/client/versions.py
@@ -101,6 +101,7 @@ class VersionsRestServlet(RestServlet):
"org.matrix.msc3030": self.config.experimental.msc3030_enabled,
# Adds support for thread relations, per MSC3440.
"org.matrix.msc3440": self.config.experimental.msc3440_enabled,
+ "org.matrix.msc3440.stable": True, # TODO: remove when "v1.3" is added above
},
},
)
|