Beispiel #1
0
    def get_user_by_req(self, request, allow_guest=False, rights="access"):
        """ Get a registered user's ID.

        Args:
            request - An HTTP request with an access_token query parameter.
        Returns:
            tuple of:
                UserID (str)
                Access token ID (str)
        Raises:
            AuthError if no user by that token exists or the token is invalid.
        """
        # Can optionally look elsewhere in the request (e.g. headers)
        try:
            user_id = yield self._get_appservice_user_id(request.args)
            if user_id:
                request.authenticated_entity = user_id
                defer.returnValue(
                    Requester(UserID.from_string(user_id), "", False))

            access_token = request.args["access_token"][0]
            user_info = yield self.get_user_by_access_token(
                access_token, rights)
            user = user_info["user"]
            token_id = user_info["token_id"]
            is_guest = user_info["is_guest"]

            ip_addr = self.hs.get_ip_from_request(request)
            user_agent = request.requestHeaders.getRawHeaders("User-Agent",
                                                              default=[""])[0]
            if user and access_token and ip_addr:
                preserve_context_over_fn(self.store.insert_client_ip,
                                         user=user,
                                         access_token=access_token,
                                         ip=ip_addr,
                                         user_agent=user_agent)

            if is_guest and not allow_guest:
                raise AuthError(403,
                                "Guest access not allowed",
                                errcode=Codes.GUEST_ACCESS_FORBIDDEN)

            request.authenticated_entity = user.to_string()

            defer.returnValue(Requester(user, token_id, is_guest))
        except KeyError:
            raise AuthError(self.TOKEN_NOT_FOUND_HTTP_STATUS,
                            "Missing access token.",
                            errcode=Codes.MISSING_TOKEN)
Beispiel #2
0
    def test_can_rerun_update(self):
        # First make sure we have completed all updates.
        while not self.get_success(
                self.store.has_completed_background_updates()):
            self.get_success(self.store.do_next_background_update(100), by=0.1)

        # Now let's create a room, which will insert a membership
        user = UserID("alice", "test")
        requester = Requester(user, None, False, None, None)
        self.get_success(self.room_creator.create_room(requester, {}))

        # Register the background update to run again.
        self.get_success(
            self.store._simple_insert(
                table="background_updates",
                values={
                    "update_name": "current_state_events_membership",
                    "progress_json": "{}",
                    "depends_on": None,
                },
            ))

        # ... and tell the DataStore that it hasn't finished all updates yet
        self.store._all_done = False

        # Now let's actually drive the updates to completion
        while not self.get_success(
                self.store.has_completed_background_updates()):
            self.get_success(self.store.do_next_background_update(100), by=0.1)
Beispiel #3
0
    def _handle_request(self, request, room_id, user_id):
        content = parse_json_object_from_request(request)

        remote_room_hosts = content["remote_room_hosts"]

        requester = Requester.deserialize(self.store, content["requester"])

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info("remote_reject_invite: %s out of room: %s", user_id, room_id)

        try:
            event = yield self.federation_handler.do_remotely_reject_invite(
                remote_room_hosts, room_id, user_id
            )
            ret = event.get_pdu_json()
        except Exception as e:
            # if we were unable to reject the exception, just mark
            # it as rejected on our end and plough ahead.
            #
            # The 'except' clause is very broad, but we need to
            # capture everything from DNS failures upwards
            #
            logger.warn("Failed to reject invite: %s", e)

            yield self.store.locally_reject_invite(user_id, room_id)
            ret = {}

        defer.returnValue((200, ret))
Beispiel #4
0
    async def _handle_request(self, request, event_id):
        with Measure(self.clock, "repl_send_event_parse"):
            content = parse_json_object_from_request(request)

            event_dict = content["event"]
            room_ver = KNOWN_ROOM_VERSIONS[content["room_version"]]
            internal_metadata = content["internal_metadata"]
            rejected_reason = content["rejected_reason"]

            event = make_event_from_dict(event_dict, room_ver,
                                         internal_metadata, rejected_reason)

            requester = Requester.deserialize(self.store, content["requester"])
            context = EventContext.deserialize(self.storage,
                                               content["context"])

            ratelimit = content["ratelimit"]
            extra_users = [
                UserID.from_string(u) for u in content["extra_users"]
            ]

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info("Got event to send with ID: %s into room: %s",
                    event.event_id, event.room_id)

        stream_id = await self.event_creation_handler.persist_and_notify_client_event(
            requester,
            event,
            context,
            ratelimit=ratelimit,
            extra_users=extra_users)

        return 200, {"stream_id": stream_id}
Beispiel #5
0
    def on_POST(self, request):
        content = parse_json_object_from_request(request)

        remote_room_hosts = content["remote_room_hosts"]
        room_id = content["room_id"]
        user_id = content["user_id"]
        event_content = content["content"]

        requester = Requester.deserialize(self.store, content["requester"])

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info(
            "remote_join: %s into room: %s",
            user_id,
            room_id,
        )

        yield self.federation_handler.do_invite_join(
            remote_room_hosts,
            room_id,
            user_id,
            event_content,
        )

        defer.returnValue((200, {}))
Beispiel #6
0
    def test_exposed_to_prometheus(self):
        """
        Forward extremity counts are exposed via Prometheus.
        """
        room_creator = self.hs.get_room_creation_handler()

        user = UserID("alice", "test")
        requester = Requester(user, None, False, None, None)

        # Real events, forward extremities
        events = [(3, 2), (6, 2), (4, 6)]

        for event_count, extrems in events:
            info = self.get_success(room_creator.create_room(requester, {}))
            room_id = info["room_id"]

            last_event = None

            # Make a real event chain
            for i in range(event_count):
                ev = self.create_and_send_event(room_id, user, False, last_event)
                last_event = [ev]

            # Sprinkle in some extremities
            for i in range(extrems):
                ev = self.create_and_send_event(room_id, user, False, last_event)

        # Let it run for a while, then pull out the statistics from the
        # Prometheus client registry
        self.reactor.advance(60 * 60 * 1000)
        self.pump(1)

        items = set(
            filter(
                lambda x: b"synapse_forward_extremities_" in x,
                generate_latest(REGISTRY).split(b"\n"),
            )
        )

        expected = set(
            [
                b'synapse_forward_extremities_bucket{le="1.0"} 0.0',
                b'synapse_forward_extremities_bucket{le="2.0"} 2.0',
                b'synapse_forward_extremities_bucket{le="3.0"} 2.0',
                b'synapse_forward_extremities_bucket{le="5.0"} 2.0',
                b'synapse_forward_extremities_bucket{le="7.0"} 3.0',
                b'synapse_forward_extremities_bucket{le="10.0"} 3.0',
                b'synapse_forward_extremities_bucket{le="15.0"} 3.0',
                b'synapse_forward_extremities_bucket{le="20.0"} 3.0',
                b'synapse_forward_extremities_bucket{le="50.0"} 3.0',
                b'synapse_forward_extremities_bucket{le="100.0"} 3.0',
                b'synapse_forward_extremities_bucket{le="200.0"} 3.0',
                b'synapse_forward_extremities_bucket{le="500.0"} 3.0',
                b'synapse_forward_extremities_bucket{le="+Inf"} 3.0',
                b"synapse_forward_extremities_count 3.0",
                b"synapse_forward_extremities_sum 10.0",
            ]
        )

        self.assertEqual(items, expected)
    def _handle_request(self, request, event_id):
        with Measure(self.clock, "repl_send_event_parse"):
            content = parse_json_object_from_request(request)

            event_dict = content["event"]
            internal_metadata = content["internal_metadata"]
            rejected_reason = content["rejected_reason"]
            event = FrozenEvent(event_dict, internal_metadata, rejected_reason)

            requester = Requester.deserialize(self.store, content["requester"])
            context = yield EventContext.deserialize(self.store, content["context"])

            ratelimit = content["ratelimit"]
            extra_users = [UserID.from_string(u) for u in content["extra_users"]]

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info(
            "Got event to send with ID: %s into room: %s",
            event.event_id, event.room_id,
        )

        yield self.event_creation_handler.persist_and_notify_client_event(
            requester, event, context,
            ratelimit=ratelimit,
            extra_users=extra_users,
        )

        defer.returnValue((200, {}))
Beispiel #8
0
    async def _serialize_payload(  # type: ignore[override]
        event_id: str,
        store: "DataStore",
        event: EventBase,
        context: EventContext,
        requester: Requester,
        ratelimit: bool,
        extra_users: List[UserID],
    ) -> JsonDict:
        """
        Args:
            event_id
            store
            requester
            event
            context
            ratelimit
            extra_users: Any extra users to notify about event
        """
        serialized_context = await context.serialize(event, store)

        payload = {
            "event": event.get_pdu_json(),
            "room_version": event.room_version.identifier,
            "event_format_version": event.format_version,
            "internal_metadata": event.internal_metadata.get_dict(),
            "outlier": event.internal_metadata.is_outlier(),
            "rejected_reason": event.rejected_reason,
            "context": serialized_context,
            "requester": requester.serialize(),
            "ratelimit": ratelimit,
            "extra_users": [u.to_string() for u in extra_users],
        }

        return payload
Beispiel #9
0
    def _update_join_states(self, requester):
        user = requester.user
        if not self.hs.is_mine(user):
            return

        self.ratelimit(requester)

        joins = yield self.store.get_rooms_for_user(
            user.to_string(),
        )

        for j in joins:
            handler = self.hs.get_handlers().room_member_handler
            try:
                # Assume the user isn't a guest because we don't let guests set
                # profile or avatar data.
                requester = Requester(user, "", False)
                yield handler.update_membership(
                    requester,
                    user,
                    j.room_id,
                    "join",  # We treat a profile update like a join.
                    ratelimit=False,  # Try to hide that these events aren't atomic.
                )
            except Exception as e:
                logger.warn(
                    "Failed to update join event for room %s - %s",
                    j.room_id, str(e.message)
                )
Beispiel #10
0
    def on_POST(self, request):
        content = parse_json_object_from_request(request)

        remote_room_hosts = content["remote_room_hosts"]
        room_id = content["room_id"]
        user_id = content["user_id"]
        event_content = content["content"]

        requester = Requester.deserialize(self.store, content["requester"])

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info(
            "remote_join: %s into room: %s",
            user_id, room_id,
        )

        yield self.federation_handler.do_invite_join(
            remote_room_hosts,
            room_id,
            user_id,
            event_content,
        )

        defer.returnValue((200, {}))
Beispiel #11
0
    def test_blocking_mau__appservice_requester_disallowed_when_tracking_ips(
            self):
        self.auth_blocking._max_mau_value = 50
        self.auth_blocking._limit_usage_by_mau = True
        self.auth_blocking._track_appservice_user_ips = True

        self.store.get_monthly_active_count = simple_async_mock(100)
        self.store.user_last_seen_monthly_active = simple_async_mock()
        self.store.is_trial_user = simple_async_mock()

        appservice = ApplicationService(
            "abcd",
            self.hs.config.server.server_name,
            id="1234",
            namespaces={
                "users": [{
                    "regex": "@_appservice.*:sender",
                    "exclusive": True
                }]
            },
            sender="@appservice:sender",
        )
        requester = Requester(
            user="******",
            access_token_id=None,
            device_id="FOOBAR",
            is_guest=False,
            shadow_banned=False,
            app_service=appservice,
            authenticated_entity="@appservice:server",
        )
        self.get_failure(self.auth.check_auth_blocking(requester=requester),
                         ResourceLimitError)
Beispiel #12
0
 def test_events(self):
     get = self.get(events="-1", timeout="0")
     yield self.hs.get_handlers().room_creation_handler.create_room(
         Requester(self.user, "", False), {})
     code, body = yield get
     self.assertEquals(code, 200)
     self.assertEquals(body["events"]["field_names"],
                       ["position", "internal", "json"])
Beispiel #13
0
    def prepare(self, reactor, clock, homeserver):
        self.store = homeserver.get_datastore()
        self.room_creator = homeserver.get_room_creation_handler()

        # Create a test user and room
        self.user = UserID("alice", "test")
        self.requester = Requester(self.user, None, False, None, None)
        info, _ = self.get_success(self.room_creator.create_room(self.requester, {}))
        self.room_id = info["room_id"]
Beispiel #14
0
 def test_events_and_state(self):
     get = self.get(events="-1", state="-1", timeout="0")
     yield self.hs.get_handlers().room_creation_handler.create_room(
         Requester(self.user, "", False), {})
     code, body = yield get
     self.assertEquals(code, 200)
     self.assertEquals(body["events"]["field_names"],
                       ["position", "internal", "json", "state_group"])
     self.assertEquals(body["state_groups"]["field_names"],
                       ["position", "room_id", "event_id"])
     self.assertEquals(body["state_group_state"]["field_names"],
                       ["position", "type", "state_key", "event_id"])
Beispiel #15
0
    def get_or_create_user(self, localpart, displayname, duration_seconds):
        """Creates a new user if the user does not exist,
        else revokes all previous access tokens and generates a new one.

        Args:
            localpart : The local part of the user ID to register. If None,
              one will be randomly generated.
        Returns:
            A tuple of (user_id, access_token).
        Raises:
            RegistrationError if there was a problem registering.
        """
        yield run_on_reactor()

        if localpart is None:
            raise SynapseError(400, "Request must include user id")

        need_register = True

        try:
            yield self.check_username(localpart)
        except SynapseError as e:
            if e.errcode == Codes.USER_IN_USE:
                need_register = False
            else:
                raise

        user = UserID(localpart, self.hs.hostname)
        user_id = user.to_string()
        auth_handler = self.hs.get_handlers().auth_handler
        token = auth_handler.generate_short_term_login_token(
            user_id, duration_seconds)

        if need_register:
            yield self.store.register(user_id=user_id,
                                      token=token,
                                      password_hash=None)

            yield registered_user(self.distributor, user)
        else:
            yield self.store.user_delete_access_tokens(user_id=user_id)
            yield self.store.add_access_token_to_user(user_id=user_id,
                                                      token=token)

        if displayname is not None:
            logger.info("setting user display name: %s -> %s", user_id,
                        displayname)
            profile_handler = self.hs.get_handlers().profile_handler
            yield profile_handler.set_displayname(
                user, Requester(user, token, False), displayname)

        defer.returnValue((user_id, token))
Beispiel #16
0
    def prepare(self, reactor, clock, homeserver):
        self.store = homeserver.get_datastore()
        self.room_creator = homeserver.get_room_creation_handler()
        self.event_creator_handler = homeserver.get_event_creation_handler()

        # Create a test user and room
        self.user = UserID.from_string(self.register_user("user1", "password"))
        self.token1 = self.login("user1", "password")
        self.requester = Requester(self.user, None, False, None, None)
        info, _ = self.get_success(self.room_creator.create_room(self.requester, {}))
        self.room_id = info["room_id"]
        self.event_creator = homeserver.get_event_creation_handler()
        homeserver.config.user_consent_version = self.CONSENT_VERSION
Beispiel #17
0
    async def _handle_request(self, request, invite_event_id):
        content = parse_json_object_from_request(request)

        txn_id = content["txn_id"]
        event_content = content["content"]

        requester = Requester.deserialize(self.store, content["requester"])

        request.requester = requester

        # hopefully we're now on the master, so this won't recurse!
        event_id, stream_id = await self.member_handler.remote_reject_invite(
            invite_event_id, txn_id, requester, event_content,
        )

        return 200, {"event_id": event_id, "stream_id": stream_id}
Beispiel #18
0
    async def _handle_request(  # type: ignore
            self, request: SynapseRequest, room_id: str,
            user_id: str) -> Tuple[int, JsonDict]:
        content = parse_json_object_from_request(request)

        remote_room_hosts = content["remote_room_hosts"]
        event_content = content["content"]

        requester = Requester.deserialize(self.store, content["requester"])
        request.requester = requester

        logger.info("remote_join: %s into room: %s", user_id, room_id)

        event_id, stream_id = await self.federation_handler.do_invite_join(
            remote_room_hosts, room_id, user_id, event_content)

        return 200, {"event_id": event_id, "stream_id": stream_id}
Beispiel #19
0
    def create_and_send_event(self,
                              room_id,
                              user,
                              soft_failed=False,
                              prev_event_ids=None):
        """
        Create and send an event.

        Args:
            soft_failed (bool): Whether to create a soft failed event or not
            prev_event_ids (list[str]|None): Explicitly set the prev events,
                or if None just use the default

        Returns:
            str: The new event's ID.
        """
        event_creator = self.hs.get_event_creation_handler()
        secrets = self.hs.get_secrets()
        requester = Requester(user, None, False, None, None)

        prev_events_and_hashes = None
        if prev_event_ids:
            prev_events_and_hashes = [[p, {}, 0] for p in prev_event_ids]

        event, context = self.get_success(
            event_creator.create_event(
                requester,
                {
                    "type": EventTypes.Message,
                    "room_id": room_id,
                    "sender": user.to_string(),
                    "content": {
                        "body": secrets.token_hex(),
                        "msgtype": "m.text"
                    },
                },
                prev_events_and_hashes=prev_events_and_hashes,
            ))

        if soft_failed:
            event.internal_metadata.soft_failed = True

        self.get_success(
            event_creator.send_nonmember_event(requester, event, context))

        return event.event_id
Beispiel #20
0
    async def _handle_request(self, request, room_id, user_id):
        content = parse_json_object_from_request(request)

        remote_room_hosts = content["remote_room_hosts"]
        event_content = content["content"]

        requester = Requester.deserialize(self.store, content["requester"])

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info("remote_join: %s into room: %s", user_id, room_id)

        event_id, stream_id = await self.federation_handler.do_invite_join(
            remote_room_hosts, room_id, user_id, event_content)

        return 200, {"event_id": event_id, "stream_id": stream_id}
Beispiel #21
0
 async def _serialize_payload(  # type: ignore
     knock_event_id: str,
     txn_id: Optional[str],
     requester: Requester,
     content: JsonDict,
 ):
     """
     Args:
         knock_event_id: The ID of the knock to be rescinded.
         txn_id: An optional transaction ID supplied by the client.
         requester: The user making the rescind request, according to the access token.
         content: The content to include in the rescind event.
     """
     return {
         "txn_id": txn_id,
         "requester": requester.serialize(),
         "content": content,
     }
Beispiel #22
0
    def _handle_request(self, request):
        content = parse_json_object_from_request(request)

        medium = content["medium"]
        address = content["address"]
        inviter_user_id = content["inviter_user_id"]

        requester = Requester.deserialize(self.store, content["requester"])

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info("get_or_register_3pid_guest: %r", content)

        ret = yield self.registeration_handler.get_or_register_3pid_guest(
            medium, address, inviter_user_id)

        defer.returnValue((200, ret))
Beispiel #23
0
 async def _serialize_payload(  # type: ignore
     invite_event_id: str,
     txn_id: Optional[str],
     requester: Requester,
     content: JsonDict,
 ):
     """
     Args:
         invite_event_id: ID of 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.
     """
     return {
         "txn_id": txn_id,
         "requester": requester.serialize(),
         "content": content,
     }
Beispiel #24
0
    def _handle_request(self, request):
        content = parse_json_object_from_request(request)

        medium = content["medium"]
        address = content["address"]
        inviter_user_id = content["inviter_user_id"]

        requester = Requester.deserialize(self.store, content["requester"])

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info("get_or_register_3pid_guest: %r", content)

        ret = yield self.registeration_handler.get_or_register_3pid_guest(
            medium, address, inviter_user_id,
        )

        defer.returnValue((200, ret))
Beispiel #25
0
 async def _serialize_payload(  # type: ignore
     requester: Requester,
     room_id: str,
     user_id: str,
     remote_room_hosts: List[str],
     content: JsonDict,
 ):
     """
     Args:
         requester: The user making the request, according to the access token.
         room_id: The ID of the room to knock on.
         user_id: The ID of the knocking user.
         remote_room_hosts: Servers to try and send the knock via.
         content: The event content to use for the knock event.
     """
     return {
         "requester": requester.serialize(),
         "remote_room_hosts": remote_room_hosts,
         "content": content,
     }
Beispiel #26
0
    async def _handle_request(  # type: ignore
        self,
        request: SynapseRequest,
        room_id: str,
        user_id: str,
    ):
        content = parse_json_object_from_request(request)

        remote_room_hosts = content["remote_room_hosts"]
        event_content = content["content"]

        requester = Requester.deserialize(self.store, content["requester"])

        request.requester = requester

        logger.debug("remote_knock: %s on room: %s", user_id, room_id)

        event_id, stream_id = await self.federation_handler.do_knock(
            remote_room_hosts, room_id, user_id, event_content)

        return 200, {"event_id": event_id, "stream_id": stream_id}
Beispiel #27
0
    async def _handle_request(  # type: ignore[override]
            self, request: Request, event_id: str) -> Tuple[int, JsonDict]:
        with Measure(self.clock, "repl_send_event_parse"):
            content = parse_json_object_from_request(request)

            event_dict = content["event"]
            room_ver = KNOWN_ROOM_VERSIONS[content["room_version"]]
            internal_metadata = content["internal_metadata"]
            rejected_reason = content["rejected_reason"]

            event = make_event_from_dict(event_dict, room_ver,
                                         internal_metadata, rejected_reason)
            event.internal_metadata.outlier = content["outlier"]

            requester = Requester.deserialize(self.store, content["requester"])
            context = EventContext.deserialize(self._storage_controllers,
                                               content["context"])

            ratelimit = content["ratelimit"]
            extra_users = [
                UserID.from_string(u) for u in content["extra_users"]
            ]

        logger.info("Got event to send with ID: %s into room: %s",
                    event.event_id, event.room_id)

        event = await self.event_creation_handler.persist_and_notify_client_event(
            requester,
            event,
            context,
            ratelimit=ratelimit,
            extra_users=extra_users)

        return (
            200,
            {
                "stream_id": event.internal_metadata.stream_ordering,
                "event_id": event.event_id,
            },
        )
Beispiel #28
0
    def on_POST(self, request):
        content = parse_json_object_from_request(request)

        remote_room_hosts = content["remote_room_hosts"]
        room_id = content["room_id"]
        user_id = content["user_id"]

        requester = Requester.deserialize(self.store, content["requester"])

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info(
            "remote_reject_invite: %s out of room: %s",
            user_id, room_id,
        )

        try:
            event = yield self.federation_handler.do_remotely_reject_invite(
                remote_room_hosts,
                room_id,
                user_id,
            )
            ret = event.get_pdu_json()
        except Exception as e:
            # if we were unable to reject the exception, just mark
            # it as rejected on our end and plough ahead.
            #
            # The 'except' clause is very broad, but we need to
            # capture everything from DNS failures upwards
            #
            logger.warn("Failed to reject invite: %s", e)

            yield self.store.locally_reject_invite(
                user_id, room_id
            )
            ret = {}

        defer.returnValue((200, ret))
Beispiel #29
0
    async def _serialize_payload(  # type: ignore[override]
        invite_event_id: str,
        txn_id: Optional[str],
        requester: Requester,
        content: JsonDict,
    ) -> JsonDict:
        """
        Args:
            invite_event_id: The ID of 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.

        Returns:
            A dict representing the payload of the request.
        """
        return {
            "txn_id": txn_id,
            "requester": requester.serialize(),
            "content": content,
        }
Beispiel #30
0
    async def _handle_request(  # type: ignore[override]
        self,
        request: SynapseRequest,
        knock_event_id: str,
    ) -> Tuple[int, JsonDict]:
        content = parse_json_object_from_request(request)

        txn_id = content["txn_id"]
        event_content = content["content"]

        requester = Requester.deserialize(self.store, content["requester"])

        request.requester = requester

        # hopefully we're now on the master, so this won't recurse!
        event_id, stream_id = await self.member_handler.remote_rescind_knock(
            knock_event_id,
            txn_id,
            requester,
            event_content,
        )

        return 200, {"event_id": event_id, "stream_id": stream_id}
Beispiel #31
0
    async def _serialize_payload(  # type: ignore
        requester: Requester,
        room_id: str,
        user_id: str,
        remote_room_hosts: List[str],
        content: JsonDict,
    ) -> JsonDict:
        """
        Args:
            requester: The user making the request according to the access token
            room_id: The ID of the room.
            user_id: The ID of the user.
            remote_room_hosts: Servers to try and join via
            content: The event content to use for the join event

        Returns:
            A dict representing the payload of the request.
        """
        return {
            "requester": requester.serialize(),
            "remote_room_hosts": remote_room_hosts,
            "content": content,
        }
Beispiel #32
0
    def kick_guest_users(self, current_state):
        for member_event in current_state:
            try:
                if member_event.type != EventTypes.Member:
                    continue

                target_user = UserID.from_string(member_event.state_key)
                if not self.hs.is_mine(target_user):
                    continue

                if member_event.content["membership"] not in {
                        Membership.JOIN, Membership.INVITE
                }:
                    continue

                if ("kind" not in member_event.content
                        or member_event.content["kind"] != "guest"):
                    continue

                # We make the user choose to leave, rather than have the
                # event-sender kick them. This is partially because we don't
                # need to worry about power levels, and partially because guest
                # users are a concept which doesn't hugely work over federation,
                # and having homeservers have their own users leave keeps more
                # of that decision-making and control local to the guest-having
                # homeserver.
                requester = Requester(target_user, "", True)
                handler = self.hs.get_handlers().room_member_handler
                yield handler.update_membership(
                    requester,
                    target_user,
                    member_event.room_id,
                    "leave",
                    ratelimit=False,
                )
            except Exception as e:
                logger.warn("Error kicking guest user: %s" % (e, ))
Beispiel #33
0
    async def _handle_request(self, request, room_id, user_id):
        content = parse_json_object_from_request(request)

        remote_room_hosts = content["remote_room_hosts"]
        event_content = content["content"]

        requester = Requester.deserialize(self.store, content["requester"])

        if requester.user:
            request.authenticated_entity = requester.user.to_string()

        logger.info("remote_reject_invite: %s out of room: %s", user_id,
                    room_id)

        try:
            event, stream_id = await self.federation_handler.do_remotely_reject_invite(
                remote_room_hosts,
                room_id,
                user_id,
                event_content,
            )
            event_id = event.event_id
        except Exception as e:
            # if we were unable to reject the exception, just mark
            # it as rejected on our end and plough ahead.
            #
            # The 'except' clause is very broad, but we need to
            # capture everything from DNS failures upwards
            #
            logger.warning("Failed to reject invite: %s", e)

            stream_id = await self.member_handler.locally_reject_invite(
                user_id, room_id)
            event_id = None

        return 200, {"event_id": event_id, "stream_id": stream_id}