Beispiel #1
0
    def account_data(self, writer, current_token, limit):
        current_position = current_token.account_data

        user_account_data = parse_integer(writer.request, "user_account_data")
        room_account_data = parse_integer(writer.request, "room_account_data")
        tag_account_data = parse_integer(writer.request, "tag_account_data")

        if user_account_data is not None or room_account_data is not None:
            if user_account_data is None:
                user_account_data = current_position
            if room_account_data is None:
                room_account_data = current_position
            user_rows, room_rows = yield self.store.get_all_updated_account_data(
                user_account_data, room_account_data, current_position, limit
            )
            writer.write_header_and_rows("user_account_data", user_rows, (
                "position", "user_id", "type", "content"
            ))
            writer.write_header_and_rows("room_account_data", room_rows, (
                "position", "user_id", "room_id", "type", "content"
            ))

        if tag_account_data is not None:
            tag_rows = yield self.store.get_all_updated_tags(
                tag_account_data, current_position, limit
            )
            writer.write_header_and_rows("tag_account_data", tag_rows, (
                "position", "user_id", "room_id", "tags"
            ))
Beispiel #2
0
    def on_GET(self, request, target_user_id):
        """Get request to get specific number of users from Synapse.
        This needs user to have administrator access in Synapse.
        """
        target_user = UserID.from_string(target_user_id)
        requester = yield self.auth.get_user_by_req(request)
        is_admin = yield self.auth.is_server_admin(requester.user)

        if not is_admin:
            raise AuthError(403, "You are not a server admin")

        # To allow all users to get the users list
        # if not is_admin and target_user != auth_user:
        #     raise AuthError(403, "You are not a server admin")

        if not self.hs.is_mine(target_user):
            raise SynapseError(400, "Can only users a local user")

        order = "name"  # order by name in user table
        start = parse_integer(request, "start", required=True)
        limit = parse_integer(request, "limit", required=True)

        logger.info("limit: %s, start: %s", limit, start)

        ret = yield self.handlers.admin_handler.get_users_paginate(
            order, start, limit
        )
        defer.returnValue((200, ret))
Beispiel #3
0
    def _async_render_GET(self, request):
        limit = parse_integer(request, "limit", 100)
        timeout = parse_integer(request, "timeout", 10 * 1000)

        request.setHeader(b"Content-Type", b"application/json")

        request_streams = {
            name: parse_integer(request, name)
            for names in STREAM_NAMES for name in names
        }
        request_streams["streams"] = parse_string(request, "streams")

        def replicate():
            return self.replicate(request_streams, limit)

        result = yield self.notifier.wait_for_replication(replicate, timeout)

        for stream_name, stream_content in result.items():
            logger.info(
                "Replicating %d rows of %s from %s -> %s",
                len(stream_content["rows"]),
                stream_name,
                request_streams.get(stream_name),
                stream_content["position"],
            )

        request.write(json.dumps(result, ensure_ascii=False))
        finish_request(request)
Beispiel #4
0
    def _async_render_GET(self, request):
        server_name, media_id, _ = parse_media_id(request)
        width = parse_integer(request, "width")
        height = parse_integer(request, "height")
        method = parse_string(request, "method", "scale")
        m_type = parse_string(request, "type", "image/png")

        if server_name == self.server_name:
            if self.dynamic_thumbnails:
                yield self._select_or_generate_local_thumbnail(
                    request, media_id, width, height, method, m_type
                )
            else:
                yield self._respond_local_thumbnail(
                    request, media_id, width, height, method, m_type
                )
        else:
            if self.dynamic_thumbnails:
                yield self._select_or_generate_remote_thumbnail(
                    request, server_name, media_id,
                    width, height, method, m_type
                )
            else:
                yield self._respond_remote_thumbnail(
                    request, server_name, media_id,
                    width, height, method, m_type
                )
Beispiel #5
0
    def _async_render_GET(self, request):
        limit = parse_integer(request, "limit", 100)
        timeout = parse_integer(request, "timeout", 10 * 1000)

        request.setHeader(b"Content-Type", b"application/json")
        writer = _Writer(request)

        @defer.inlineCallbacks
        def replicate():
            current_token = yield self.current_replication_token()
            logger.info("Replicating up to %r", current_token)

            yield self.account_data(writer, current_token, limit)
            yield self.events(writer, current_token, limit)
            yield self.presence(writer, current_token)  # TODO: implement limit
            yield self.typing(writer, current_token)  # TODO: implement limit
            yield self.receipts(writer, current_token, limit)
            yield self.push_rules(writer, current_token, limit)
            yield self.pushers(writer, current_token, limit)
            self.streams(writer, current_token)

            logger.info("Replicated %d rows", writer.total)
            defer.returnValue(writer.total)

        yield self.notifier.wait_for_replication(replicate, timeout)

        writer.finish()
Beispiel #6
0
    def events(self, writer, current_token, limit):
        request_events = parse_integer(writer.request, "events")
        request_backfill = parse_integer(writer.request, "backfill")

        if request_events is not None or request_backfill is not None:
            if request_events is None:
                request_events = current_token.events
            if request_backfill is None:
                request_backfill = current_token.backfill
            events_rows, backfill_rows = yield self.store.get_all_new_events(
                request_backfill, request_events, current_token.backfill, current_token.events, limit
            )
            writer.write_header_and_rows("events", events_rows, ("position", "internal", "json"))
            writer.write_header_and_rows("backfill", backfill_rows, ("position", "internal", "json"))
Beispiel #7
0
    def on_GET(self, request):
        user, client = yield self.auth.get_user_by_req(request)

        timeout = parse_integer(request, "timeout", default=0)
        limit = parse_integer(request, "limit", required=True)
        gap = parse_boolean(request, "gap", default=True)
        sort = parse_string(request, "sort", default="timeline,asc", allowed_values=self.ALLOWED_SORT)
        since = parse_string(request, "since")
        set_presence = parse_string(request, "set_presence", default="online", allowed_values=self.ALLOWED_PRESENCE)
        backfill = parse_boolean(request, "backfill", default=False)
        filter_id = parse_string(request, "filter", default=None)

        logger.info(
            "/sync: user=%r, timeout=%r, limit=%r, gap=%r, sort=%r, since=%r,"
            " set_presence=%r, backfill=%r, filter_id=%r"
            % (user, timeout, limit, gap, sort, since, set_presence, backfill, filter_id)
        )

        # TODO(mjark): Load filter and apply overrides.
        try:
            filter = yield self.filtering.get_user_filter(user.localpart, filter_id)
        except:
            filter = Filter({})
        # filter = filter.apply_overrides(http_request)
        # if filter.matches(event):
        #   # stuff

        sync_config = SyncConfig(
            user=user, client_info=client, gap=gap, limit=limit, sort=sort, backfill=backfill, filter=filter
        )

        if since is not None:
            since_token = StreamToken.from_string(since)
        else:
            since_token = None

        sync_result = yield self.sync_handler.wait_for_sync_for_user(
            sync_config, since_token=since_token, timeout=timeout
        )

        time_now = self.clock.time_msec()

        response_content = {
            "public_user_data": self.encode_user_data(sync_result.public_user_data, filter, time_now),
            "private_user_data": self.encode_user_data(sync_result.private_user_data, filter, time_now),
            "rooms": self.encode_rooms(sync_result.rooms, filter, time_now, client.token_id),
            "next_batch": sync_result.next_batch.to_string(),
        }

        defer.returnValue((200, response_content))
Beispiel #8
0
    def pushers(self, writer, current_token, limit):
        current_position = current_token.pushers

        pushers = parse_integer(writer.request, "pushers")
        if pushers is not None:
            updated, deleted = yield self.store.get_all_updated_pushers(pushers, current_position, limit)
            writer.write_header_and_rows(
                "pushers",
                updated,
                (
                    "position",
                    "user_id",
                    "access_token",
                    "profile_tag",
                    "kind",
                    "app_id",
                    "app_display_name",
                    "device_display_name",
                    "pushkey",
                    "ts",
                    "lang",
                    "data",
                ),
            )
            writer.write_header_and_rows("deleted", deleted, ("position", "user_id", "app_id", "pushkey"))
Beispiel #9
0
    def on_GET(self, request):
        server = parse_string(request, "server", default=None)

        try:
            yield self.auth.get_user_by_req(request, allow_guest=True)
        except AuthError as e:
            # We allow people to not be authed if they're just looking at our
            # room list, but require auth when we proxy the request.
            # In both cases we call the auth function, as that has the side
            # effect of logging who issued this request if an access token was
            # provided.
            if server:
                raise e
            else:
                pass

        limit = parse_integer(request, "limit", 0)
        since_token = parse_string(request, "since", None)

        handler = self.hs.get_room_list_handler()
        if server:
            data = yield handler.get_remote_public_room_list(
                server,
                limit=limit,
                since_token=since_token,
            )
        else:
            data = yield handler.get_local_public_room_list(
                limit=limit,
                since_token=since_token,
            )

        defer.returnValue((200, data))
Beispiel #10
0
    def from_request(cls, request, raise_invalid_params=True,
                     default_limit=None):
        direction = parse_string(request, "dir", default='f', allowed_values=['f', 'b'])

        from_tok = parse_string(request, "from")
        to_tok = parse_string(request, "to")

        try:
            if from_tok == "END":
                from_tok = None  # For backwards compat.
            elif from_tok:
                from_tok = StreamToken.from_string(from_tok)
        except Exception:
            raise SynapseError(400, "'from' paramater is invalid")

        try:
            if to_tok:
                to_tok = StreamToken.from_string(to_tok)
        except Exception:
            raise SynapseError(400, "'to' paramater is invalid")

        limit = parse_integer(request, "limit", default=default_limit)

        if limit and limit < 0:
            raise SynapseError(400, "Limit must be 0 or above")

        try:
            return PaginationConfig(from_tok, to_tok, direction, limit)
        except Exception:
            logger.exception("Failed to create pagination config")
            raise SynapseError(400, "Invalid request.")
Beispiel #11
0
    def on_GET(self, request, room_id, parent_id, relation_type=None, event_type=None):
        requester = yield self.auth.get_user_by_req(request, allow_guest=True)

        yield self.auth.check_in_room_or_world_readable(
            room_id, requester.user.to_string()
        )

        # This checks that a) the event exists and b) the user is allowed to
        # view it.
        yield self.event_handler.get_event(requester.user, room_id, parent_id)

        if relation_type not in (RelationTypes.ANNOTATION, None):
            raise SynapseError(400, "Relation type must be 'annotation'")

        limit = parse_integer(request, "limit", default=5)
        from_token = parse_string(request, "from")
        to_token = parse_string(request, "to")

        if from_token:
            from_token = AggregationPaginationToken.from_string(from_token)

        if to_token:
            to_token = AggregationPaginationToken.from_string(to_token)

        res = yield self.store.get_aggregation_groups_for_event(
            event_id=parent_id,
            event_type=event_type,
            limit=limit,
            from_token=from_token,
            to_token=to_token,
        )

        defer.returnValue((200, res.to_dict()))
Beispiel #12
0
    def typing(self, writer, current_token):
        current_position = current_token.presence

        request_typing = parse_integer(writer.request, "typing")

        if request_typing is not None:
            typing_rows = yield self.typing_handler.get_all_typing_updates(request_typing, current_position)
            writer.write_header_and_rows("typing", typing_rows, ("position", "room_id", "typing"))
Beispiel #13
0
 def on_GET(self, request, user_id, device_id, algorithm):
     yield self.auth.get_user_by_req(request)
     timeout = parse_integer(request, "timeout", 10 * 1000)
     result = yield self.e2e_keys_handler.claim_one_time_keys(
         {"one_time_keys": {user_id: {device_id: algorithm}}},
         timeout,
     )
     defer.returnValue((200, result))
Beispiel #14
0
 def on_POST(self, request, user_id, device_id, algorithm):
     yield self.auth.get_user_by_req(request)
     timeout = parse_integer(request, "timeout", 10 * 1000)
     body = parse_json_object_from_request(request)
     result = yield self.e2e_keys_handler.claim_one_time_keys(
         body,
         timeout,
     )
     defer.returnValue((200, result))
Beispiel #15
0
    def on_POST(self, request):
        yield assert_requester_is_admin(self.auth, request)

        before_ts = parse_integer(request, "before_ts", required=True)
        logger.info("before_ts: %r", before_ts)

        ret = yield self.media_repository.delete_old_remote_media(before_ts)

        defer.returnValue((200, ret))
Beispiel #16
0
    def on_GET(self, request):
        requester = yield self.auth.get_user_by_req(request)
        user_id = requester.user.to_string()

        from_token = parse_string(request, "from", required=False)
        limit = parse_integer(request, "limit", default=50)

        limit = min(limit, 500)

        push_actions = yield self.store.get_push_actions_for_user(
            user_id, from_token, limit)

        receipts_by_room = yield self.store.get_receipts_for_user_with_orderings(
            user_id, 'm.read')

        notif_event_ids = [pa["event_id"] for pa in push_actions]
        notif_events = yield self.store.get_events(notif_event_ids)

        returned_push_actions = []

        next_token = None

        for pa in push_actions:
            returned_pa = {
                "room_id":
                pa["room_id"],
                "profile_tag":
                pa["profile_tag"],
                "actions":
                pa["actions"],
                "ts":
                pa["received_ts"],
                "event":
                serialize_event(
                    notif_events[pa["event_id"]],
                    self.clock.time_msec(),
                    event_format=format_event_for_client_v2_without_room_id,
                ),
            }

            if pa["room_id"] not in receipts_by_room:
                returned_pa["read"] = False
            else:
                receipt = receipts_by_room[pa["room_id"]]

                returned_pa["read"] = (receipt["topological_ordering"],
                                       receipt["stream_ordering"]) >= (
                                           pa["topological_ordering"],
                                           pa["stream_ordering"])
            returned_push_actions.append(returned_pa)
            next_token = pa["stream_ordering"]

        defer.returnValue((200, {
            "notifications": returned_push_actions,
            "next_token": next_token,
        }))
Beispiel #17
0
    async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
        requester = await self.auth.get_user_by_req(request)
        user_id = requester.user.to_string()

        from_token = parse_string(request, "from", required=False)
        limit = parse_integer(request, "limit", default=50)
        only = parse_string(request, "only", required=False)

        limit = min(limit, 500)

        push_actions = await self.store.get_push_actions_for_user(
            user_id, from_token, limit, only_highlight=(only == "highlight"))

        receipts_by_room = await self.store.get_receipts_for_user_with_orderings(
            user_id, ReceiptTypes.READ)

        notif_event_ids = [pa.event_id for pa in push_actions]
        notif_events = await self.store.get_events(notif_event_ids)

        returned_push_actions = []

        next_token = None

        for pa in push_actions:
            returned_pa = {
                "room_id":
                pa.room_id,
                "profile_tag":
                pa.profile_tag,
                "actions":
                pa.actions,
                "ts":
                pa.received_ts,
                "event": (self._event_serializer.serialize_event(
                    notif_events[pa.event_id],
                    self.clock.time_msec(),
                    event_format=format_event_for_client_v2_without_room_id,
                )),
            }

            if pa.room_id not in receipts_by_room:
                returned_pa["read"] = False
            else:
                receipt = receipts_by_room[pa.room_id]

                returned_pa["read"] = (
                    receipt["topological_ordering"],
                    receipt["stream_ordering"],
                ) >= (pa.topological_ordering, pa.stream_ordering)
            returned_push_actions.append(returned_pa)
            next_token = str(pa.stream_ordering)

        return 200, {
            "notifications": returned_push_actions,
            "next_token": next_token
        }
Beispiel #18
0
    async def _handle_request(self, request, stream_name):
        stream = self.streams.get(stream_name)
        if stream is None:
            raise SynapseError(400, "Unknown stream")

        from_token = parse_integer(request, "from_token", required=True)
        upto_token = parse_integer(request, "upto_token", required=True)

        updates, upto_token, limited = await stream.get_updates_since(
            self._instance_name, from_token, upto_token)

        return (
            200,
            {
                "updates": updates,
                "upto_token": upto_token,
                "limited": limited
            },
        )
Beispiel #19
0
    def typing(self, writer, current_token):
        current_position = current_token.presence

        request_typing = parse_integer(writer.request, "typing")

        if request_typing is not None:
            typing_rows = yield self.typing_handler.get_all_typing_updates(
                request_typing, current_position)
            writer.write_header_and_rows("typing", typing_rows,
                                         ("position", "room_id", "typing"))
Beispiel #20
0
    def receipts(self, writer, current_token, limit):
        current_position = current_token.receipts

        request_receipts = parse_integer(writer.request, "receipts")

        if request_receipts is not None:
            receipts_rows = yield self.store.get_all_updated_receipts(request_receipts, current_position, limit)
            writer.write_header_and_rows(
                "receipts", receipts_rows, ("position", "room_id", "receipt_type", "user_id", "event_id", "data")
            )
Beispiel #21
0
    def on_GET(self, request, target_user_id):
        """Get request to get specific number of users from Synapse.
        This needs user to have administrator access in Synapse.
        """
        yield assert_requester_is_admin(self.auth, request)

        target_user = UserID.from_string(target_user_id)

        if not self.hs.is_mine(target_user):
            raise SynapseError(400, "Can only users a local user")

        order = "name"  # order by name in user table
        start = parse_integer(request, "start", required=True)
        limit = parse_integer(request, "limit", required=True)

        logger.info("limit: %s, start: %s", limit, start)

        ret = yield self.handlers.admin_handler.get_users_paginate(order, start, limit)
        return (200, ret)
Beispiel #22
0
    async def on_GET(
        self,
        request: SynapseRequest,
        room_id: str,
        parent_id: str,
        relation_type: Optional[str] = None,
        event_type: Optional[str] = None,
    ) -> 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 not in (RelationTypes.ANNOTATION, None):
            raise SynapseError(
                400, f"Relation type must be '{RelationTypes.ANNOTATION}'")

        limit = parse_integer(request, "limit", default=5)
        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 200, pagination_chunk.to_dict()
Beispiel #23
0
    def on_GET(self, request):
        requester = yield self.auth.get_user_by_req(request)
        user_id = requester.user.to_string()

        from_token = parse_string(request, "from", required=False)
        limit = parse_integer(request, "limit", default=50)
        only = parse_string(request, "only", required=False)

        limit = min(limit, 500)

        push_actions = yield self.store.get_push_actions_for_user(
            user_id, from_token, limit, only_highlight=(only == "highlight")
        )

        receipts_by_room = yield self.store.get_receipts_for_user_with_orderings(
            user_id, 'm.read'
        )

        notif_event_ids = [pa["event_id"] for pa in push_actions]
        notif_events = yield self.store.get_events(notif_event_ids)

        returned_push_actions = []

        next_token = None

        for pa in push_actions:
            returned_pa = {
                "room_id": pa["room_id"],
                "profile_tag": pa["profile_tag"],
                "actions": pa["actions"],
                "ts": pa["received_ts"],
                "event": serialize_event(
                    notif_events[pa["event_id"]],
                    self.clock.time_msec(),
                    event_format=format_event_for_client_v2_without_room_id,
                ),
            }

            if pa["room_id"] not in receipts_by_room:
                returned_pa["read"] = False
            else:
                receipt = receipts_by_room[pa["room_id"]]

                returned_pa["read"] = (
                    receipt["topological_ordering"], receipt["stream_ordering"]
                ) >= (
                    pa["topological_ordering"], pa["stream_ordering"]
                )
            returned_push_actions.append(returned_pa)
            next_token = str(pa["stream_ordering"])

        defer.returnValue((200, {
            "notifications": returned_push_actions,
            "next_token": next_token,
        }))
Beispiel #24
0
 def on_GET(self, request, user_id, device_id):
     requester = yield self.auth.get_user_by_req(request)
     timeout = parse_integer(request, "timeout", 10 * 1000)
     auth_user_id = requester.user.to_string()
     user_id = user_id if user_id else auth_user_id
     device_ids = [device_id] if device_id else []
     result = yield self.e2e_keys_handler.query_devices(
         {"device_keys": {user_id: device_ids}},
         timeout,
     )
     defer.returnValue((200, result))
Beispiel #25
0
    async def on_GET(
        self, request: SynapseRequest, room_id: str
    ) -> Tuple[int, JsonDict]:
        requester = await self._auth.get_user_by_req(request, allow_guest=True)

        return 200, await self._space_summary_handler.get_space_summary(
            requester.user.to_string(),
            room_id,
            suggested_only=parse_boolean(request, "suggested_only", default=False),
            max_rooms_per_space=parse_integer(request, "max_rooms_per_space"),
        )
Beispiel #26
0
    async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
        await assert_requester_is_admin(self._auth, request)

        start = parse_integer(request, "from", default=0)
        limit = parse_integer(request, "limit", default=100)

        if start < 0:
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "Query parameter from must be a string representing a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        if limit < 0:
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "Query parameter limit must be a string representing a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        destination = parse_string(request, "destination")

        order_by = parse_string(
            request,
            "order_by",
            default=DestinationSortOrder.DESTINATION.value,
            allowed_values=[dest.value for dest in DestinationSortOrder],
        )

        direction = parse_string(request,
                                 "dir",
                                 default="f",
                                 allowed_values=("f", "b"))

        destinations, total = await self._store.get_destinations_paginate(
            start, limit, destination, order_by, direction)
        response = {"destinations": destinations, "total": total}
        if (start + limit) < total:
            response["next_token"] = str(start + len(destinations))

        return HTTPStatus.OK, response
Beispiel #27
0
    def receipts(self, writer, current_token, limit):
        current_position = current_token.receipts

        request_receipts = parse_integer(writer.request, "receipts")

        if request_receipts is not None:
            receipts_rows = yield self.store.get_all_updated_receipts(
                request_receipts, current_position, limit)
            writer.write_header_and_rows(
                "receipts", receipts_rows,
                ("position", "room_id", "receipt_type", "user_id", "event_id",
                 "data"))
Beispiel #28
0
    def push_rules(self, writer, current_token, limit):
        current_position = current_token.push_rules

        push_rules = parse_integer(writer.request, "push_rules")

        if push_rules is not None:
            rows = yield self.store.get_all_push_rule_updates(
                push_rules, current_position, limit)
            writer.write_header_and_rows(
                "push_rules", rows,
                ("position", "event_stream_ordering", "user_id", "rule_id",
                 "op", "priority_class", "priority", "conditions", "actions"))
Beispiel #29
0
    async def on_GET(self, request: SynapseRequest, room_id: str,
                     event_id: str) -> Tuple[int, JsonDict]:
        requester = await self.auth.get_user_by_req(request, allow_guest=True)

        limit = parse_integer(request, "limit", default=10)

        # picking the API shape for symmetry with /messages
        filter_str = parse_string(request, "filter", encoding="utf-8")
        if filter_str:
            filter_json = urlparse.unquote(filter_str)
            event_filter: Optional[Filter] = Filter(
                self._hs, json_decoder.decode(filter_json))
        else:
            event_filter = None

        event_context = await self.room_context_handler.get_event_context(
            requester, room_id, event_id, limit, event_filter)

        if not event_context:
            raise SynapseError(404,
                               "Event not found.",
                               errcode=Codes.NOT_FOUND)

        time_now = self.clock.time_msec()
        results = {
            "events_before":
            self._event_serializer.serialize_events(
                event_context.events_before,
                time_now,
                bundle_aggregations=event_context.aggregations,
            ),
            "event":
            self._event_serializer.serialize_event(
                event_context.event,
                time_now,
                bundle_aggregations=event_context.aggregations,
            ),
            "events_after":
            self._event_serializer.serialize_events(
                event_context.events_after,
                time_now,
                bundle_aggregations=event_context.aggregations,
            ),
            "state":
            self._event_serializer.serialize_events(event_context.state,
                                                    time_now),
            "start":
            event_context.start,
            "end":
            event_context.end,
        }

        return 200, results
Beispiel #30
0
    def on_GET(self, request, target_user_id):
        """Get request to get specific number of users from Synapse.
        This needs user to have administrator access in Synapse.
        """
        yield assert_requester_is_admin(self.auth, request)

        target_user = UserID.from_string(target_user_id)

        if not self.hs.is_mine(target_user):
            raise SynapseError(400, "Can only users a local user")

        order = "name"  # order by name in user table
        start = parse_integer(request, "start", required=True)
        limit = parse_integer(request, "limit", required=True)

        logger.info("limit: %s, start: %s", limit, start)

        ret = yield self.handlers.admin_handler.get_users_paginate(
            order, start, limit
        )
        defer.returnValue((200, ret))
Beispiel #31
0
    async def on_POST(self, request: SynapseRequest,
                      server_name: str) -> Tuple[int, JsonDict]:
        await assert_requester_is_admin(self.auth, request)

        before_ts = parse_integer(request, "before_ts", required=True)
        size_gt = parse_integer(request, "size_gt", default=0)
        keep_profiles = parse_boolean(request, "keep_profiles", default=True)

        if before_ts < 0:
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "Query parameter before_ts must be a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )
        elif before_ts < 30000000000:  # Dec 1970 in milliseconds, Aug 2920 in seconds
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "Query parameter before_ts you provided is from the year 1970. "
                +
                "Double check that you are providing a timestamp in milliseconds.",
                errcode=Codes.INVALID_PARAM,
            )
        if size_gt < 0:
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "Query parameter size_gt must be a string representing a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        if self.server_name != server_name:
            raise SynapseError(HTTPStatus.BAD_REQUEST,
                               "Can only delete local media")

        logging.info(
            "Deleting local media by timestamp: %s, size larger than: %s, keep profile media: %s"
            % (before_ts, size_gt, keep_profiles))

        deleted_media, total = await self.media_repository.delete_old_local_media(
            before_ts, size_gt, keep_profiles)
        return HTTPStatus.OK, {"deleted_media": deleted_media, "total": total}
Beispiel #32
0
    def push_rules(self, writer, current_token, limit):
        current_position = current_token.push_rules

        push_rules = parse_integer(writer.request, "push_rules")

        if push_rules is not None:
            rows = yield self.store.get_all_push_rule_updates(
                push_rules, current_position, limit
            )
            writer.write_header_and_rows("push_rules", rows, (
                "position", "event_stream_ordering", "user_id", "rule_id", "op",
                "priority_class", "priority", "conditions", "actions"
            ))
Beispiel #33
0
    def on_POST(self, request):
        requester = yield self.auth.get_user_by_req(request)
        is_admin = yield self.auth.is_server_admin(requester.user)

        if not is_admin:
            raise AuthError(403, "You are not a server admin")

        before_ts = parse_integer(request, "before_ts", required=True)
        logger.info("before_ts: %r", before_ts)

        ret = yield self.media_repository.delete_old_remote_media(before_ts)

        defer.returnValue((200, ret))
Beispiel #34
0
    def on_POST(self, request):
        requester = yield self.auth.get_user_by_req(request)
        is_admin = yield self.auth.is_server_admin(requester.user)

        if not is_admin:
            raise AuthError(403, "You are not a server admin")

        before_ts = parse_integer(request, "before_ts", required=True)
        logger.info("before_ts: %r", before_ts)

        ret = yield self.media_repository.delete_old_remote_media(before_ts)

        defer.returnValue((200, ret))
Beispiel #35
0
    async def on_GET(self, request):
        server = parse_string(request, "server", default=None)

        try:
            await self.auth.get_user_by_req(request, allow_guest=True)
        except InvalidClientCredentialsError as e:
            # Option to allow servers to require auth when accessing
            # /publicRooms via CS API. This is especially helpful in private
            # federations.
            if not self.hs.config.allow_public_rooms_without_auth:
                raise

            # We allow people to not be authed if they're just looking at our
            # room list, but require auth when we proxy the request.
            # In both cases we call the auth function, as that has the side
            # effect of logging who issued this request if an access token was
            # provided.
            if server:
                raise e

        limit = parse_integer(request, "limit", 0)
        since_token = parse_string(request, "since", None)

        if limit == 0:
            # zero is a special value which corresponds to no limit.
            limit = None

        handler = self.hs.get_room_list_handler()
        if server and server != self.hs.config.server_name:
            # Ensure the server is valid.
            try:
                parse_and_validate_server_name(server)
            except ValueError:
                raise SynapseError(
                    400,
                    "Invalid server name: %s" % (server,),
                    Codes.INVALID_PARAM,
                )

            try:
                data = await handler.get_remote_public_room_list(
                    server, limit=limit, since_token=since_token
                )
            except HttpResponseException as e:
                raise e.to_synapse_error()
        else:
            data = await handler.get_local_public_room_list(
                limit=limit, since_token=since_token
            )

        return 200, data
Beispiel #36
0
    async def on_GET(
        self, request: SynapseRequest, user_id: str
    ) -> Tuple[int, JsonDict]:
        await assert_requester_is_admin(self.auth, request)

        if not self.is_mine(UserID.from_string(user_id)):
            raise SynapseError(400, "Can only lookup local users")

        user = await self.store.get_user_by_id(user_id)
        if user is None:
            raise NotFoundError("Unknown user")

        start = parse_integer(request, "from", default=0)
        limit = parse_integer(request, "limit", default=100)

        if start < 0:
            raise SynapseError(
                400,
                "Query parameter from must be a string representing a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        if limit < 0:
            raise SynapseError(
                400,
                "Query parameter limit must be a string representing a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        media, total = await self.store.get_local_media_by_user_paginate(
            start, limit, user_id
        )

        ret = {"media": media, "total": total}
        if (start + limit) < total:
            ret["next_token"] = start + len(media)

        return 200, ret
Beispiel #37
0
    async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
        await assert_requester_is_admin(self.auth, request)

        start = parse_integer(request, "from", default=0)
        limit = parse_integer(request, "limit", default=100)
        direction = parse_string(request, "dir", default="b")
        user_id = parse_string(request, "user_id")
        room_id = parse_string(request, "room_id")

        if start < 0:
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "The start parameter must be a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        if limit < 0:
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "The limit parameter must be a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        if direction not in ("f", "b"):
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "Unknown direction: %s" % (direction,),
                errcode=Codes.INVALID_PARAM,
            )

        event_reports, total = await self.store.get_event_reports_paginate(
            start, limit, direction, user_id, room_id
        )
        ret = {"event_reports": event_reports, "total": total}
        if (start + limit) < total:
            ret["next_token"] = start + len(event_reports)

        return HTTPStatus.OK, ret
Beispiel #38
0
    def presence(self, writer, current_token):
        current_position = current_token.presence

        request_presence = parse_integer(writer.request, "presence")

        if request_presence is not None:
            presence_rows = yield self.presence_handler.get_all_presence_updates(
                request_presence, current_position
            )
            writer.write_header_and_rows("presence", presence_rows, (
                "position", "user_id", "state", "last_active_ts",
                "last_federation_update_ts", "last_user_sync_ts",
                "status_msg", "currently_active",
            ))
Beispiel #39
0
    def _async_render_GET(self, request):
        server_name, media_id, _ = parse_media_id(request)
        width = parse_integer(request, "width")
        height = parse_integer(request, "height")
        method = parse_string(request, "method", "scale")
        m_type = parse_string(request, "type", "image/png")

        if server_name == self.server_name:
            if self.dynamic_thumbnails:
                yield self._select_or_generate_local_thumbnail(
                    request, media_id, width, height, method, m_type)
            else:
                yield self._respond_local_thumbnail(request, media_id, width,
                                                    height, method, m_type)
        else:
            if self.dynamic_thumbnails:
                yield self._select_or_generate_remote_thumbnail(
                    request, server_name, media_id, width, height, method,
                    m_type)
            else:
                yield self._respond_remote_thumbnail(request, server_name,
                                                     media_id, width, height,
                                                     method, m_type)
Beispiel #40
0
    async def on_GET(self, request, room_id, parent_id, relation_type,
                     event_type, key):
        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.
        await self.event_handler.get_event(requester.user, room_id, parent_id)

        if relation_type != RelationTypes.ANNOTATION:
            raise SynapseError(400, "Relation type must be 'annotation'")

        limit = parse_integer(request, "limit", default=5)
        from_token_str = parse_string(request, "from")
        to_token_str = parse_string(request, "to")

        from_token = None
        if from_token_str:
            from_token = RelationPaginationToken.from_string(from_token_str)

        to_token = None
        if to_token_str:
            to_token = RelationPaginationToken.from_string(to_token_str)

        result = await self.store.get_relations_for_event(
            event_id=parent_id,
            relation_type=relation_type,
            event_type=event_type,
            aggregation_key=key,
            limit=limit,
            from_token=from_token,
            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()
        events = await self._event_serializer.serialize_events(events, now)

        return_value = result.to_dict()
        return_value["chunk"] = events

        return 200, return_value
Beispiel #41
0
    async def _async_render_GET(self, request):
        if len(request.postpath) == 1:
            (server,) = request.postpath
            query = {server.decode("ascii"): {}}
        elif len(request.postpath) == 2:
            server, key_id = request.postpath
            minimum_valid_until_ts = parse_integer(request, "minimum_valid_until_ts")
            arguments = {}
            if minimum_valid_until_ts is not None:
                arguments["minimum_valid_until_ts"] = minimum_valid_until_ts
            query = {server.decode("ascii"): {key_id.decode("ascii"): arguments}}
        else:
            raise SynapseError(404, "Not found %r" % request.postpath, Codes.NOT_FOUND)

        await self.query_keys(request, query, query_remote_on_cache_miss=True)
Beispiel #42
0
    def pushers(self, writer, current_token, limit):
        current_position = current_token.pushers

        pushers = parse_integer(writer.request, "pushers")
        if pushers is not None:
            updated, deleted = yield self.store.get_all_updated_pushers(
                pushers, current_position, limit)
            writer.write_header_and_rows(
                "pushers", updated,
                ("position", "user_id", "access_token", "profile_tag", "kind",
                 "app_id", "app_display_name", "device_display_name",
                 "pushkey", "ts", "lang", "data"))
            writer.write_header_and_rows(
                "deleted", deleted,
                ("position", "user_id", "app_id", "pushkey"))
Beispiel #43
0
    async def on_GET(self, request: SynapseRequest,
                     destination: str) -> Tuple[int, JsonDict]:
        await assert_requester_is_admin(self._auth, request)

        if not await self._store.is_destination_known(destination):
            raise NotFoundError("Unknown destination")

        start = parse_integer(request, "from", default=0)
        limit = parse_integer(request, "limit", default=100)

        if start < 0:
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "Query parameter from must be a string representing a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        if limit < 0:
            raise SynapseError(
                HTTPStatus.BAD_REQUEST,
                "Query parameter limit must be a string representing a positive integer.",
                errcode=Codes.INVALID_PARAM,
            )

        direction = parse_string(request,
                                 "dir",
                                 default="f",
                                 allowed_values=("f", "b"))

        rooms, total = await self._store.get_destination_rooms_paginate(
            destination, start, limit, direction)
        response = {"rooms": rooms, "total": total}
        if (start + limit) < total:
            response["next_token"] = str(start + len(rooms))

        return HTTPStatus.OK, response
Beispiel #44
0
    async def on_GET(
        self, request: SynapseRequest, room_id: str, event_id: str
    ) -> Tuple[int, JsonDict]:
        requester = await self.auth.get_user_by_req(request, allow_guest=False)
        await assert_user_is_admin(self.auth, requester.user)

        limit = parse_integer(request, "limit", default=10)

        # picking the API shape for symmetry with /messages
        filter_str = parse_string(request, b"filter", encoding="utf-8")
        if filter_str:
            filter_json = urlparse.unquote(filter_str)
            event_filter = Filter(
                json_decoder.decode(filter_json)
            )  # type: Optional[Filter]
        else:
            event_filter = None

        results = await self.room_context_handler.get_event_context(
            requester,
            room_id,
            event_id,
            limit,
            event_filter,
            use_admin_priviledge=True,
        )

        if not results:
            raise SynapseError(404, "Event not found.", errcode=Codes.NOT_FOUND)

        time_now = self.clock.time_msec()
        results["events_before"] = await self._event_serializer.serialize_events(
            results["events_before"], time_now
        )
        results["event"] = await self._event_serializer.serialize_event(
            results["event"], time_now
        )
        results["events_after"] = await self._event_serializer.serialize_events(
            results["events_after"], time_now
        )
        results["state"] = await self._event_serializer.serialize_events(
            results["state"],
            time_now,
            # No need to bundle aggregations for state events
            bundle_aggregations=False,
        )

        return 200, results
Beispiel #45
0
    def on_GET(self, request, room_id, event_id):
        requester = yield self.auth.get_user_by_req(request, allow_guest=True)

        limit = parse_integer(request, "limit", default=10)

        # picking the API shape for symmetry with /messages
        filter_bytes = parse_string(request, "filter")
        if filter_bytes:
            filter_json = urlparse.unquote(filter_bytes)
            event_filter = Filter(json.loads(filter_json))
        else:
            event_filter = None

        results = yield self.room_context_handler.get_event_context(
            requester.user,
            room_id,
            event_id,
            limit,
            event_filter,
        )

        if not results:
            raise SynapseError(404,
                               "Event not found.",
                               errcode=Codes.NOT_FOUND)

        time_now = self.clock.time_msec()
        results[
            "events_before"] = yield self._event_serializer.serialize_events(
                results["events_before"],
                time_now,
            )
        results["event"] = yield self._event_serializer.serialize_event(
            results["event"],
            time_now,
        )
        results[
            "events_after"] = yield self._event_serializer.serialize_events(
                results["events_after"],
                time_now,
            )
        results["state"] = yield self._event_serializer.serialize_events(
            results["state"],
            time_now,
        )

        defer.returnValue((200, results))
Beispiel #46
0
    async def on_GET(
        self,
        request: SynapseRequest,
        room_id: str,
        parent_id: str,
        relation_type: Optional[str] = None,
        event_type: Optional[str] = None,
    ) -> Tuple[int, JsonDict]:
        requester = await self.auth.get_user_by_req(request, allow_guest=True)

        limit = parse_integer(request, "limit", default=5)
        if self._msc3715_enabled:
            direction = parse_string(
                request,
                "org.matrix.msc3715.dir",
                default="b",
                allowed_values=["f", "b"],
            )
        else:
            direction = "b"
        from_token_str = parse_string(request, "from")
        to_token_str = parse_string(request, "to")

        # 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)

        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 200, result
Beispiel #47
0
    def on_GET(self, request, room_id, parent_id, relation_type, event_type, key):
        requester = yield self.auth.get_user_by_req(request, allow_guest=True)

        yield self.auth.check_in_room_or_world_readable(
            room_id, requester.user.to_string()
        )

        # This checks that a) the event exists and b) the user is allowed to
        # view it.
        yield self.event_handler.get_event(requester.user, room_id, parent_id)

        if relation_type != RelationTypes.ANNOTATION:
            raise SynapseError(400, "Relation type must be 'annotation'")

        limit = parse_integer(request, "limit", default=5)
        from_token = parse_string(request, "from")
        to_token = parse_string(request, "to")

        if from_token:
            from_token = RelationPaginationToken.from_string(from_token)

        if to_token:
            to_token = RelationPaginationToken.from_string(to_token)

        result = yield self.store.get_relations_for_event(
            event_id=parent_id,
            relation_type=relation_type,
            event_type=event_type,
            aggregation_key=key,
            limit=limit,
            from_token=from_token,
            to_token=to_token,
        )

        events = yield self.store.get_events_as_list(
            [c["event_id"] for c in result.chunk]
        )

        now = self.clock.time_msec()
        events = yield self._event_serializer.serialize_events(events, now)

        return_value = result.to_dict()
        return_value["chunk"] = events

        defer.returnValue((200, return_value))
Beispiel #48
0
    def on_POST(self, request, room_id, event_type, txn_id=None):
        requester = yield self.auth.get_user_by_req(request, allow_guest=True)
        content = parse_json_object_from_request(request)

        event_dict = {
            "type": event_type,
            "content": content,
            "room_id": room_id,
            "sender": requester.user.to_string(),
        }

        if b"ts" in request.args and requester.app_service:
            event_dict["origin_server_ts"] = parse_integer(request, "ts", 0)

        event = yield self.event_creation_handler.create_and_send_nonmember_event(
            requester, event_dict, txn_id=txn_id)

        return (200, {"event_id": event.event_id})
Beispiel #49
0
 def async_render_GET(self, request):
     if len(request.postpath) == 1:
         server, = request.postpath
         query = {server: {}}
     elif len(request.postpath) == 2:
         server, key_id = request.postpath
         minimum_valid_until_ts = parse_integer(
             request, "minimum_valid_until_ts"
         )
         arguments = {}
         if minimum_valid_until_ts is not None:
             arguments["minimum_valid_until_ts"] = minimum_valid_until_ts
         query = {server: {key_id: arguments}}
     else:
         raise SynapseError(
             404, "Not found %r" % request.postpath, Codes.NOT_FOUND
         )
     yield self.query_keys(request, query, query_remote_on_cache_miss=True)
Beispiel #50
0
    def presence(self, writer, current_token):
        current_position = current_token.presence

        request_presence = parse_integer(writer.request, "presence")

        if request_presence is not None:
            presence_rows = yield self.presence_handler.get_all_presence_updates(
                request_presence, current_position)
            writer.write_header_and_rows("presence", presence_rows, (
                "position",
                "user_id",
                "state",
                "last_active_ts",
                "last_federation_update_ts",
                "last_user_sync_ts",
                "status_msg",
                "currently_active",
            ))
Beispiel #51
0
    def on_GET(self,
               request,
               room_id,
               parent_id,
               relation_type=None,
               event_type=None):
        requester = yield self.auth.get_user_by_req(request, allow_guest=True)

        yield self.auth.check_in_room_or_world_readable(
            room_id, requester.user.to_string())

        # This checks that a) the event exists and b) the user is allowed to
        # view it.
        yield self.event_handler.get_event(requester.user, room_id, parent_id)

        limit = parse_integer(request, "limit", default=5)
        from_token = parse_string(request, "from")
        to_token = parse_string(request, "to")

        if from_token:
            from_token = RelationPaginationToken.from_string(from_token)

        if to_token:
            to_token = RelationPaginationToken.from_string(to_token)

        result = yield self.store.get_relations_for_event(
            event_id=parent_id,
            relation_type=relation_type,
            event_type=event_type,
            limit=limit,
            from_token=from_token,
            to_token=to_token,
        )

        events = yield self.store.get_events_as_list(
            [c["event_id"] for c in result.chunk])

        now = self.clock.time_msec()
        events = yield self._event_serializer.serialize_events(events, now)

        return_value = result.to_dict()
        return_value["chunk"] = events

        defer.returnValue((200, return_value))
Beispiel #52
0
    async def from_request(
        cls,
        store: "DataStore",
        request: SynapseRequest,
        raise_invalid_params: bool = True,
        default_limit: Optional[int] = None,
    ) -> "PaginationConfig":
        direction = parse_string(request,
                                 "dir",
                                 default="f",
                                 allowed_values=["f", "b"])

        from_tok_str = parse_string(request, "from")
        to_tok_str = parse_string(request, "to")

        try:
            from_tok = None
            if from_tok_str == "END":
                from_tok = None  # For backwards compat.
            elif from_tok_str:
                from_tok = await StreamToken.from_string(store, from_tok_str)
        except Exception:
            raise SynapseError(400, "'from' parameter is invalid")

        try:
            to_tok = None
            if to_tok_str:
                to_tok = await StreamToken.from_string(store, to_tok_str)
        except Exception:
            raise SynapseError(400, "'to' parameter is invalid")

        limit = parse_integer(request, "limit", default=default_limit)

        if limit:
            if limit < 0:
                raise SynapseError(400, "Limit must be 0 or above")

            limit = min(int(limit), MAX_LIMIT)

        try:
            return PaginationConfig(from_tok, to_tok, direction, limit)
        except Exception:
            logger.exception("Failed to create pagination config")
            raise SynapseError(400, "Invalid request.")
Beispiel #53
0
    async def on_GET(
        self, request: SynapseRequest, room_id: str
    ) -> Tuple[int, JsonDict]:
        requester = await self._auth.get_user_by_req(request, allow_guest=True)

        max_rooms_per_space = parse_integer(request, "max_rooms_per_space")
        if max_rooms_per_space is not None and max_rooms_per_space < 0:
            raise SynapseError(
                400,
                "Value for 'max_rooms_per_space' must be a non-negative integer",
                Codes.BAD_JSON,
            )

        return 200, await self._room_summary_handler.get_space_summary(
            requester.user.to_string(),
            room_id,
            suggested_only=parse_boolean(request, "suggested_only", default=False),
            max_rooms_per_space=max_rooms_per_space,
        )
Beispiel #54
0
    def on_GET(self, request, room_id, event_id):
        requester = yield self.auth.get_user_by_req(request, allow_guest=True)

        limit = parse_integer(request, "limit", default=10)

        # picking the API shape for symmetry with /messages
        filter_bytes = parse_string(request, "filter")
        if filter_bytes:
            filter_json = urlparse.unquote(filter_bytes)
            event_filter = Filter(json.loads(filter_json))
        else:
            event_filter = None

        results = yield self.room_context_handler.get_event_context(
            requester.user,
            room_id,
            event_id,
            limit,
            event_filter,
        )

        if not results:
            raise SynapseError(
                404, "Event not found.", errcode=Codes.NOT_FOUND
            )

        time_now = self.clock.time_msec()
        results["events_before"] = yield self._event_serializer.serialize_events(
            results["events_before"], time_now,
        )
        results["event"] = yield self._event_serializer.serialize_event(
            results["event"], time_now,
        )
        results["events_after"] = yield self._event_serializer.serialize_events(
            results["events_after"], time_now,
        )
        results["state"] = yield self._event_serializer.serialize_events(
            results["state"], time_now,
        )

        defer.returnValue((200, results))
Beispiel #55
0
    def on_POST(self, request, room_id, event_type, txn_id=None):
        requester = yield self.auth.get_user_by_req(request, allow_guest=True)
        content = parse_json_object_from_request(request)

        event_dict = {
            "type": event_type,
            "content": content,
            "room_id": room_id,
            "sender": requester.user.to_string(),
        }

        if b'ts' in request.args and requester.app_service:
            event_dict['origin_server_ts'] = parse_integer(request, "ts", 0)

        event = yield self.event_creation_hander.create_and_send_nonmember_event(
            requester,
            event_dict,
            txn_id=txn_id,
        )

        defer.returnValue((200, {"event_id": event.event_id}))
Beispiel #56
0
    def on_GET(self, request):
        if "from" in request.args:
            # /events used to use 'from', but /sync uses 'since'.
            # Lets be helpful and whine if we see a 'from'.
            raise SynapseError(
                400, "'from' is not a valid query parameter. Did you mean 'since'?"
            )

        requester = yield self.auth.get_user_by_req(
            request, allow_guest=True
        )
        user = requester.user
        device_id = requester.device_id

        timeout = parse_integer(request, "timeout", default=0)
        since = parse_string(request, "since")
        set_presence = parse_string(
            request, "set_presence", default="online",
            allowed_values=self.ALLOWED_PRESENCE
        )
        filter_id = parse_string(request, "filter", default=None)
        full_state = parse_boolean(request, "full_state", default=False)

        logger.debug(
            "/sync: user=%r, timeout=%r, since=%r,"
            " set_presence=%r, filter_id=%r, device_id=%r" % (
                user, timeout, since, set_presence, filter_id, device_id
            )
        )

        request_key = (user, timeout, since, filter_id, full_state, device_id)

        if filter_id:
            if filter_id.startswith('{'):
                try:
                    filter_object = json.loads(filter_id)
                    set_timeline_upper_limit(filter_object,
                                             self.hs.config.filter_timeline_limit)
                except Exception:
                    raise SynapseError(400, "Invalid filter JSON")
                self.filtering.check_valid_filter(filter_object)
                filter = FilterCollection(filter_object)
            else:
                filter = yield self.filtering.get_user_filter(
                    user.localpart, filter_id
                )
        else:
            filter = DEFAULT_FILTER_COLLECTION

        sync_config = SyncConfig(
            user=user,
            filter_collection=filter,
            is_guest=requester.is_guest,
            request_key=request_key,
            device_id=device_id,
        )

        if since is not None:
            since_token = StreamToken.from_string(since)
        else:
            since_token = None

        affect_presence = set_presence != PresenceState.OFFLINE

        if affect_presence:
            yield self.presence_handler.set_state(user, {"presence": set_presence}, True)

        context = yield self.presence_handler.user_syncing(
            user.to_string(), affect_presence=affect_presence,
        )
        with context:
            sync_result = yield self.sync_handler.wait_for_sync_for_user(
                sync_config, since_token=since_token, timeout=timeout,
                full_state=full_state
            )

        time_now = self.clock.time_msec()
        response_content = self.encode_response(
            time_now, sync_result, requester.access_token_id, filter
        )

        defer.returnValue((200, response_content))
Beispiel #57
0
    def on_GET(self, request):
        user, token_id, _ = yield self.auth.get_user_by_req(request)

        timeout = parse_integer(request, "timeout", default=0)
        since = parse_string(request, "since")
        set_presence = parse_string(
            request, "set_presence", default="online",
            allowed_values=self.ALLOWED_PRESENCE
        )
        filter_id = parse_string(request, "filter", default=None)
        full_state = parse_boolean(request, "full_state", default=False)

        logger.info(
            "/sync: user=%r, timeout=%r, since=%r,"
            " set_presence=%r, filter_id=%r" % (
                user, timeout, since, set_presence, filter_id
            )
        )

        try:
            filter = yield self.filtering.get_user_filter(
                user.localpart, filter_id
            )
        except:
            filter = FilterCollection({})

        sync_config = SyncConfig(
            user=user,
            filter=filter,
        )

        if since is not None:
            since_token = StreamToken.from_string(since)
        else:
            since_token = None

        if set_presence == "online":
            yield self.event_stream_handler.started_stream(user)

        try:
            sync_result = yield self.sync_handler.wait_for_sync_for_user(
                sync_config, since_token=since_token, timeout=timeout,
                full_state=full_state
            )
        finally:
            if set_presence == "online":
                self.event_stream_handler.stopped_stream(user)

        time_now = self.clock.time_msec()

        joined = self.encode_joined(
            sync_result.joined, filter, time_now, token_id
        )

        invited = self.encode_invited(
            sync_result.invited, filter, time_now, token_id
        )

        archived = self.encode_archived(
            sync_result.archived, filter, time_now, token_id
        )

        response_content = {
            "presence": self.encode_presence(
                sync_result.presence, filter, time_now
            ),
            "rooms": {
                "join": joined,
                "invite": invited,
                "leave": archived,
            },
            "next_batch": sync_result.next_batch.to_string(),
        }

        defer.returnValue((200, response_content))
Beispiel #58
0
 def on_POST(self, request):
     yield self.auth.get_user_by_req(request, allow_guest=True)
     timeout = parse_integer(request, "timeout", 10 * 1000)
     body = parse_json_object_from_request(request)
     result = yield self.e2e_keys_handler.query_devices(body, timeout)
     defer.returnValue((200, result))
    def _async_render_GET(self, request):

        # XXX: if get_user_by_req fails, what should we do in an async render?
        requester = yield self.auth.get_user_by_req(request)
        url = parse_string(request, "url")
        if b"ts" in request.args:
            ts = parse_integer(request, "ts")
        else:
            ts = self.clock.time_msec()

        # XXX: we could move this into _do_preview if we wanted.
        url_tuple = urlparse.urlsplit(url)
        for entry in self.url_preview_url_blacklist:
            match = True
            for attrib in entry:
                pattern = entry[attrib]
                value = getattr(url_tuple, attrib)
                logger.debug((
                    "Matching attrib '%s' with value '%s' against"
                    " pattern '%s'"
                ) % (attrib, value, pattern))

                if value is None:
                    match = False
                    continue

                if pattern.startswith('^'):
                    if not re.match(pattern, getattr(url_tuple, attrib)):
                        match = False
                        continue
                else:
                    if not fnmatch.fnmatch(getattr(url_tuple, attrib), pattern):
                        match = False
                        continue
            if match:
                logger.warn(
                    "URL %s blocked by url_blacklist entry %s", url, entry
                )
                raise SynapseError(
                    403, "URL blocked by url pattern blacklist entry",
                    Codes.UNKNOWN
                )

        # the in-memory cache:
        # * ensures that only one request is active at a time
        # * takes load off the DB for the thundering herds
        # * also caches any failures (unlike the DB) so we don't keep
        #    requesting the same endpoint

        observable = self._cache.get(url)

        if not observable:
            download = run_in_background(
                self._do_preview,
                url, requester.user, ts,
            )
            observable = ObservableDeferred(
                download,
                consumeErrors=True
            )
            self._cache[url] = observable
        else:
            logger.info("Returning cached response")

        og = yield make_deferred_yieldable(observable.observe())
        respond_with_json_bytes(request, 200, og, send_cors=True)