Use PDUs for stripped state over federation
As per MSC4311 updates.
This commit is contained in:
@@ -870,7 +870,7 @@ def maybe_upsert_event_field(
|
||||
return upsert_okay
|
||||
|
||||
|
||||
def strip_event(event: EventBase) -> JsonDict:
|
||||
def strip_event(event: EventBase, for_federation: Optional[bool] = False) -> JsonDict:
|
||||
"""
|
||||
Used for "stripped state" events which provide a simplified view of the state of a
|
||||
room intended to help a potential joiner identify the room (relevant when the user
|
||||
@@ -879,13 +879,10 @@ def strip_event(event: EventBase) -> JsonDict:
|
||||
Stripped state events can only have the `sender`, `type`, `state_key` and `content`
|
||||
properties present.
|
||||
"""
|
||||
# MSC4311: Ensure the create event is available on invites and knocks.
|
||||
# TODO: Implement the rest of MSC4311
|
||||
if (
|
||||
event.room_version.msc4291_room_ids_as_hashes
|
||||
and event.type == EventTypes.Create
|
||||
and event.get_state_key() == ""
|
||||
):
|
||||
# MSC4311 makes all stripped state events fully-formed PDUs over federation,
|
||||
# especially the `m.room.create` event.
|
||||
# TODO: Implement the validation component of MSC4311
|
||||
if for_federation:
|
||||
return event.get_pdu_json()
|
||||
|
||||
return {
|
||||
|
||||
@@ -1336,10 +1336,16 @@ class FederationClient(FederationBase):
|
||||
room_id: str,
|
||||
event_id: str,
|
||||
pdu: EventBase,
|
||||
stripped_state: List[JsonDict],
|
||||
) -> EventBase:
|
||||
room_version = await self.store.get_room_version(room_id)
|
||||
|
||||
content = await self._do_send_invite(destination, pdu, room_version)
|
||||
content = await self._do_send_invite(
|
||||
destination,
|
||||
pdu,
|
||||
room_version,
|
||||
stripped_state,
|
||||
)
|
||||
|
||||
pdu_dict = content["event"]
|
||||
|
||||
@@ -1360,7 +1366,11 @@ class FederationClient(FederationBase):
|
||||
return pdu
|
||||
|
||||
async def _do_send_invite(
|
||||
self, destination: str, pdu: EventBase, room_version: RoomVersion
|
||||
self,
|
||||
destination: str,
|
||||
pdu: EventBase,
|
||||
room_version: RoomVersion,
|
||||
stripped_state: List[JsonDict],
|
||||
) -> JsonDict:
|
||||
"""Actually sends the invite, first trying v2 API and falling back to
|
||||
v1 API if necessary.
|
||||
@@ -1383,7 +1393,7 @@ class FederationClient(FederationBase):
|
||||
content={
|
||||
"event": pdu.get_pdu_json(time_now),
|
||||
"room_version": room_version.identifier,
|
||||
"invite_room_state": pdu.unsigned.get("invite_room_state", []),
|
||||
"invite_room_state": stripped_state,
|
||||
},
|
||||
)
|
||||
except HttpResponseException as e:
|
||||
|
||||
@@ -907,7 +907,7 @@ class FederationServer(FederationBase):
|
||||
# related to the room while the knock request is pending.
|
||||
stripped_room_state = (
|
||||
await self.store.get_stripped_room_state_from_event_context(
|
||||
context, self._room_prejoin_state_types
|
||||
context, self._room_prejoin_state_types, for_federation=True,
|
||||
)
|
||||
)
|
||||
return {"knock_room_state": stripped_room_state}
|
||||
|
||||
@@ -547,7 +547,7 @@ class FederationHandler:
|
||||
|
||||
return False
|
||||
|
||||
async def send_invite(self, target_host: str, event: EventBase) -> EventBase:
|
||||
async def send_invite(self, target_host: str, event: EventBase, stripped_state: List[JsonDict]) -> EventBase:
|
||||
"""Sends the invite to the remote server for signing.
|
||||
|
||||
Invites must be signed by the invitee's server before distribution.
|
||||
@@ -558,6 +558,7 @@ class FederationHandler:
|
||||
room_id=event.room_id,
|
||||
event_id=event.event_id,
|
||||
pdu=event,
|
||||
stripped_state=stripped_state,
|
||||
)
|
||||
except RequestSendFailed:
|
||||
raise SynapseError(502, f"Can't connect to server {target_host}")
|
||||
|
||||
@@ -1973,8 +1973,17 @@ class EventCreationHandler:
|
||||
# way? If we have been invited by a remote server, we need
|
||||
# to get them to sign the event.
|
||||
|
||||
# As of MSC4311, "stripped" state events are formatted differently
|
||||
# over federation.
|
||||
stripped_state_fed = await self.store.get_stripped_room_state_from_event_context(
|
||||
context,
|
||||
self.room_prejoin_state_types,
|
||||
membership_user_id=event.sender,
|
||||
for_federation=True,
|
||||
)
|
||||
|
||||
returned_invite = await federation_handler.send_invite(
|
||||
invitee.domain, event
|
||||
invitee.domain, event, stripped_state_fed,
|
||||
)
|
||||
event.unsigned.pop("room_state", None)
|
||||
|
||||
|
||||
@@ -1094,6 +1094,7 @@ class EventsWorkerStore(SQLBaseStore):
|
||||
context: EventContext,
|
||||
state_keys_to_include: StateFilter,
|
||||
membership_user_id: Optional[str] = None,
|
||||
for_federation: Optional[bool] = False,
|
||||
) -> List[JsonDict]:
|
||||
"""
|
||||
Retrieve the stripped state from a room, given an event context to retrieve state
|
||||
@@ -1110,6 +1111,8 @@ class EventsWorkerStore(SQLBaseStore):
|
||||
events of. This is useful when generating the stripped state of a room for
|
||||
invites. We want to send membership events of the inviter, so that the
|
||||
invitee can display the inviter's profile information if the room lacks any.
|
||||
for_federation: When True, the stripped state events will be returned as PDUs
|
||||
as per MSC4311. When False, the stripped client format is used.
|
||||
|
||||
Returns:
|
||||
A list of dictionaries, each representing a stripped state event from the room.
|
||||
@@ -1134,7 +1137,7 @@ class EventsWorkerStore(SQLBaseStore):
|
||||
|
||||
state_to_include = await self.get_events(selected_state_ids.values())
|
||||
|
||||
return [strip_event(e) for e in state_to_include.values()]
|
||||
return [strip_event(e, for_federation) for e in state_to_include.values()]
|
||||
|
||||
def _maybe_start_fetch_thread(self) -> None:
|
||||
"""Starts an event fetch thread if we are not yet at the maximum number."""
|
||||
|
||||
Reference in New Issue
Block a user