def send_request(destination): ret = yield self.transport_layer.make_membership_event( destination, room_id, user_id, membership, params ) # Note: If not supplied, the room version may be either v1 or v2, # however either way the event format version will be v1. room_version = ret.get("room_version", RoomVersions.V1.identifier) event_format = room_version_to_event_format(room_version) pdu_dict = ret.get("event", None) if not isinstance(pdu_dict, dict): raise InvalidResponseError("Bad 'event' field in response") logger.debug("Got response to make_%s: %s", membership, pdu_dict) pdu_dict["content"].update(content) # The protoevent received over the JSON wire may not have all # the required fields. Lets just gloss over that because # there's some we never care about if "prev_state" not in pdu_dict: pdu_dict["prev_state"] = [] ev = builder.create_local_event_from_event_dict( self._clock, self.hostname, self.signing_key, format_version=event_format, event_dict=pdu_dict, ) return (destination, ev, event_format)
def send_request(destination): ret = yield self.transport_layer.make_membership_event( destination, room_id, user_id, membership, params, ) # Note: If not supplied, the room version may be either v1 or v2, # however either way the event format version will be v1. room_version = ret.get("room_version", RoomVersions.V1.identifier) event_format = room_version_to_event_format(room_version) pdu_dict = ret.get("event", None) if not isinstance(pdu_dict, dict): raise InvalidResponseError("Bad 'event' field in response") logger.debug("Got response to make_%s: %s", membership, pdu_dict) pdu_dict["content"].update(content) # The protoevent received over the JSON wire may not have all # the required fields. Lets just gloss over that because # there's some we never care about if "prev_state" not in pdu_dict: pdu_dict["prev_state"] = [] ev = builder.create_local_event_from_event_dict( self._clock, self.hostname, self.signing_key, format_version=event_format, event_dict=pdu_dict, ) defer.returnValue( (destination, ev, event_format) )
def test_room_state_returned_when_knocking(self): """ Tests that specific, stripped state events from a room are returned after a remote homeserver successfully knocks on a local room. """ user_id = self.register_user("u1", "you the one") user_token = self.login("u1", "you the one") fake_knocking_user_id = "@user:other.example.com" # Create a room with a room version that includes knocking room_id = self.helper.create_room_as( "u1", is_public=False, room_version=RoomVersions.V7.identifier, tok=user_token, ) # Update the join rules and add additional state to the room to check for later expected_room_state = self.send_example_state_events_to_room( self.hs, room_id, user_id) channel = self.make_signed_federation_request( "GET", "/_matrix/federation/v1/make_knock/%s/%s?ver=%s" % ( room_id, fake_knocking_user_id, # Inform the remote that we support the room version of the room we're # knocking on RoomVersions.V7.identifier, ), ) self.assertEqual(200, channel.code, channel.result) # Note: We don't expect the knock membership event to be sent over federation as # part of the stripped room state, as the knocking homeserver already has that # event. It is only done for clients during /sync # Extract the generated knock event json knock_event = channel.json_body["event"] # Check that the event has things we expect in it self.assertEqual(knock_event["room_id"], room_id) self.assertEqual(knock_event["sender"], fake_knocking_user_id) self.assertEqual(knock_event["state_key"], fake_knocking_user_id) self.assertEqual(knock_event["type"], EventTypes.Member) self.assertEqual(knock_event["content"]["membership"], Membership.KNOCK) # Turn the event json dict into a proper event. # We won't sign it properly, but that's OK as we stub out event auth in `prepare` signed_knock_event = builder.create_local_event_from_event_dict( self.clock, self.hs.hostname, self.hs.signing_key, room_version=RoomVersions.V7, event_dict=knock_event, ) # Convert our proper event back to json dict format signed_knock_event_json = signed_knock_event.get_pdu_json( self.clock.time_msec()) # Send the signed knock event into the room channel = self.make_signed_federation_request( "PUT", "/_matrix/federation/v1/send_knock/%s/%s" % (room_id, signed_knock_event.event_id), signed_knock_event_json, ) self.assertEqual(200, channel.code, channel.result) # Check that we got the stripped room state in return room_state_events = channel.json_body["knock_state_events"] # Validate the stripped room state events self.check_knock_room_state_against_room_state(room_state_events, expected_room_state)
async def _locally_reject_invite( self, invite_event: EventBase, txn_id: Optional[str], requester: Requester, content: JsonDict, ) -> Tuple[str, int]: """Generate a local invite rejection This is called after we fail to reject an invite via a remote server. It generates an out-of-band membership event locally. Args: invite_event: the invite to be rejected txn_id: optional transaction ID supplied by the client requester: user making the rejection request, according to the access token content: additional content to include in the rejection event. Normally an empty dict. """ room_id = invite_event.room_id target_user = invite_event.state_key room_version = await self.store.get_room_version(room_id) content["membership"] = Membership.LEAVE # the auth events for the new event are the same as that of the invite, plus # the invite itself. # # the prev_events are just the invite. invite_hash = invite_event.event_id # type: Union[str, Tuple] if room_version.event_format == EventFormatVersions.V1: alg, h = compute_event_reference_hash(invite_event) invite_hash = (invite_event.event_id, {alg: encode_base64(h)}) auth_events = tuple(invite_event.auth_events) + (invite_hash, ) prev_events = (invite_hash, ) # we cap depth of generated events, to ensure that they are not # rejected by other servers (and so that they can be persisted in # the db) depth = min(invite_event.depth + 1, MAX_DEPTH) event_dict = { "depth": depth, "auth_events": auth_events, "prev_events": prev_events, "type": EventTypes.Member, "room_id": room_id, "sender": target_user, "content": content, "state_key": target_user, } event = create_local_event_from_event_dict( clock=self.clock, hostname=self.hs.hostname, signing_key=self.hs.signing_key, room_version=room_version, event_dict=event_dict, ) event.internal_metadata.outlier = True event.internal_metadata.out_of_band_membership = True if txn_id is not None: event.internal_metadata.txn_id = txn_id if requester.access_token_id is not None: event.internal_metadata.token_id = requester.access_token_id EventValidator().validate_new(event, self.config) context = await self.state_handler.compute_event_context(event) context.app_service = requester.app_service stream_id = await self.event_creation_handler.handle_new_client_event( requester, event, context, extra_users=[UserID.from_string(target_user)], ) return event.event_id, stream_id