Ejemplo n.º 1
0
        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)
Ejemplo n.º 2
0
        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)
            )
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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