Exemplo n.º 1
0
    def update_group_summary_room(self, group_id, requester_user_id,
                                  room_id, category_id, content):
        """Add/update a room to the group summary
        """
        yield self.check_group_is_ours(
            group_id,
            requester_user_id,
            and_exists=True,
            and_is_admin=requester_user_id,
        )

        RoomID.from_string(room_id)  # Ensure valid room id

        order = content.get("order", None)

        is_public = _parse_visibility_from_contents(content)

        yield self.store.add_room_to_summary(
            group_id=group_id,
            room_id=room_id,
            category_id=category_id,
            order=order,
            is_public=is_public,
        )

        defer.returnValue({})
Exemplo n.º 2
0
    def add_room_to_group(self, group_id, requester_user_id, room_id, content):
        """Add room to group
        """
        RoomID.from_string(room_id)  # Ensure valid room id

        yield self.check_group_is_ours(
            group_id, requester_user_id, and_exists=True, and_is_admin=requester_user_id
        )

        is_public = _parse_visibility_from_contents(content)

        yield self.store.add_room_to_group(group_id, room_id, is_public=is_public)

        defer.returnValue({})
Exemplo n.º 3
0
    def setUp(self):
        hs = yield setup_test_homeserver(resource_for_federation=Mock(), http_client=None)

        self.store = hs.get_datastore()
        self.event_builder_factory = hs.get_event_builder_factory()
        self.handlers = hs.get_handlers()
        self.message_handler = self.handlers.message_handler

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        self.room1 = RoomID.from_string("!abc123:test")
        self.room2 = RoomID.from_string("!xyx987:test")

        self.depth = 1
Exemplo n.º 4
0
    def setUp(self):
        hs = yield setup_test_homeserver()

        self.store = DirectoryStore(hs)

        self.room = RoomID.from_string("!abcde:test")
        self.alias = RoomAlias.from_string("#my-room:test")
Exemplo n.º 5
0
    def lookup_room_alias(self, room_alias):
        """
        Get the room ID associated with a room alias.

        Args:
            room_alias (RoomAlias): The alias to look up.
        Returns:
            A tuple of:
                The room ID as a RoomID object.
                Hosts likely to be participating in the room ([str]).
        Raises:
            SynapseError if room alias could not be found.
        """
        directory_handler = self.directory_handler
        mapping = yield directory_handler.get_association(room_alias)

        if not mapping:
            raise SynapseError(404, "No such room alias")

        room_id = mapping["room_id"]
        servers = mapping["servers"]

        # put the server which owns the alias at the front of the server list.
        if room_alias.domain in servers:
            servers.remove(room_alias.domain)
        servers.insert(0, room_alias.domain)

        defer.returnValue((RoomID.from_string(room_id), servers))
Exemplo n.º 6
0
    def setUp(self):
        hs = yield setup_test_homeserver(self.addCleanup)

        self.store = hs.get_datastore()

        self.room = RoomID.from_string("!abcde:test")
        self.alias = RoomAlias.from_string("#my-room:test")
Exemplo n.º 7
0
    def _check_definition(self, definition):
        """Check if the provided definition is valid.

        This inspects not only the types but also the values to make sure they
        make sense.

        Args:
            definition(dict): The filter definition
        Raises:
            SynapseError: If there was a problem with this definition.
        """
        # NB: Filters are the complete json blobs. "Definitions" are an
        # individual top-level key e.g. public_user_data. Filters are made of
        # many definitions.
        if type(definition) != dict:
            raise SynapseError(
                400, "Expected JSON object, not %s" % (definition,)
            )

        # check rooms are valid room IDs
        room_id_keys = ["rooms", "not_rooms"]
        for key in room_id_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for room_id in definition[key]:
                    RoomID.from_string(room_id)

        # check senders are valid user IDs
        user_id_keys = ["senders", "not_senders"]
        for key in user_id_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for user_id in definition[key]:
                    UserID.from_string(user_id)

        # TODO: We don't limit event type values but we probably should...
        # check types are valid event types
        event_keys = ["types", "not_types"]
        for key in event_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for event_type in definition[key]:
                    if not isinstance(event_type, basestring):
                        raise SynapseError(400, "Event type should be a string")
Exemplo n.º 8
0
    def _check_definition_room_lists(self, definition):
        """Check that "rooms" and "not_rooms" are lists of room ids if they
        are present

        Args:
            definition(dict): The filter definition
        Raises:
            SynapseError: If there was a problem with this definition.
        """
        # check rooms are valid room IDs
        room_id_keys = ["rooms", "not_rooms"]
        for key in room_id_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for room_id in definition[key]:
                    RoomID.from_string(room_id)
Exemplo n.º 9
0
    def validate_builder(self, event):
        """Validates that the builder/event has roughly the right format. Only
        checks values that we expect a proto event to have, rather than all the
        fields an event would have

        Args:
            event (EventBuilder|FrozenEvent)
        """

        strings = [
            "room_id",
            "sender",
            "type",
        ]

        if hasattr(event, "state_key"):
            strings.append("state_key")

        for s in strings:
            if not isinstance(getattr(event, s), string_types):
                raise SynapseError(400, "Not '%s' a string type" % (s,))

        RoomID.from_string(event.room_id)
        UserID.from_string(event.sender)

        if event.type == EventTypes.Message:
            strings = [
                "body",
                "msgtype",
            ]

            self._ensure_strings(event.content, strings)

        elif event.type == EventTypes.Topic:
            self._ensure_strings(event.content, ["topic"])

        elif event.type == EventTypes.Name:
            self._ensure_strings(event.content, ["name"])

        elif event.type == EventTypes.Member:
            if "membership" not in event.content:
                raise SynapseError(400, "Content has not membership key")

            if event.content["membership"] not in Membership.LIST:
                raise SynapseError(400, "Invalid membership key")
Exemplo n.º 10
0
    def test_count_daily_messages(self):
        self.db_pool.runQuery("DELETE FROM stats_reporting")

        self.hs.clock.now = 100

        # Never reported before, and nothing which could be reported
        count = yield self.store.count_daily_messages()
        self.assertIsNone(count)
        count = yield self.db_pool.runQuery("SELECT COUNT(*) FROM stats_reporting")
        self.assertEqual([(0,)], count)

        # Create something to report
        room = RoomID.from_string("!abc123:test")
        user = UserID.from_string("@raccoonlover:test")
        yield self.event_injector.create_room(room)

        self.base_event = yield self._get_last_stream_token()

        yield self.event_injector.inject_message(room, user, "Raccoons are really cute")

        # Never reported before, something could be reported, but isn't because
        # it isn't old enough.
        count = yield self.store.count_daily_messages()
        self.assertIsNone(count)
        self._assert_stats_reporting(1, self.hs.clock.now)

        # Already reported yesterday, two new events from today.
        yield self.event_injector.inject_message(room, user, "Yeah they are!")
        yield self.event_injector.inject_message(room, user, "Incredibly!")
        self.hs.clock.now += 60 * 60 * 24
        count = yield self.store.count_daily_messages()
        self.assertEqual(2, count)  # 2 since yesterday
        self._assert_stats_reporting(3, self.hs.clock.now)  # 3 ever

        # Last reported too recently.
        yield self.event_injector.inject_message(room, user, "Who could disagree?")
        self.hs.clock.now += 60 * 60 * 22
        count = yield self.store.count_daily_messages()
        self.assertIsNone(count)
        self._assert_stats_reporting(4, self.hs.clock.now)

        # Last reported too long ago
        yield self.event_injector.inject_message(room, user, "No one.")
        self.hs.clock.now += 60 * 60 * 26
        count = yield self.store.count_daily_messages()
        self.assertIsNone(count)
        self._assert_stats_reporting(5, self.hs.clock.now)

        # And now let's actually report something
        yield self.event_injector.inject_message(room, user, "Indeed.")
        yield self.event_injector.inject_message(room, user, "Indeed.")
        yield self.event_injector.inject_message(room, user, "Indeed.")
        # A little over 24 hours is fine :)
        self.hs.clock.now += (60 * 60 * 24) + 50
        count = yield self.store.count_daily_messages()
        self.assertEqual(3, count)
        self._assert_stats_reporting(8, self.hs.clock.now)
Exemplo n.º 11
0
    def update_room_in_group(self, group_id, requester_user_id, room_id, config_key,
                             content):
        """Update room in group
        """
        RoomID.from_string(room_id)  # Ensure valid room id

        yield self.check_group_is_ours(
            group_id, requester_user_id, and_exists=True, and_is_admin=requester_user_id
        )

        if config_key == "m.visibility":
            is_public = _parse_visibility_dict(content)

            yield self.store.update_room_in_group_visibility(
                group_id, room_id,
                is_public=is_public,
            )
        else:
            raise SynapseError(400, "Uknown config option")

        defer.returnValue({})
Exemplo n.º 12
0
    def setUp(self):
        hs = setup_test_homeserver()

        # Room events need the full datastore, for persist_event() and
        # get_room_state()
        self.store = hs.get_datastore()
        self.event_factory = hs.get_event_factory()

        self.room = RoomID.from_string("!abcde:test")

        yield self.store.store_room(self.room.to_string(),
                                    room_creator_user_id="@creator:text",
                                    is_public=True)
Exemplo n.º 13
0
    def setUp(self):
        hs = setup_test_homeserver(self.addCleanup)

        # Room events need the full datastore, for persist_event() and
        # get_room_state()
        self.store = hs.get_datastore()
        self.event_factory = hs.get_event_factory()

        self.room = RoomID.from_string("!abcde:test")

        yield self.store.store_room(
            self.room.to_string(), room_creator_user_id="@creator:text", is_public=True
        )
Exemplo n.º 14
0
    def validate(self, event):
        EventID.from_string(event.event_id)
        RoomID.from_string(event.room_id)

        required = [
            # "auth_events",
            "content",
            # "hashes",
            "origin",
            # "prev_events",
            "sender",
            "type",
        ]

        for k in required:
            if not hasattr(event, k):
                raise SynapseError(400, "Event does not have key %s" % (k, ))

        # Check that the following keys have string values
        strings = [
            "origin",
            "sender",
            "type",
        ]

        if hasattr(event, "state_key"):
            strings.append("state_key")

        for s in strings:
            if not isinstance(getattr(event, s), string_types):
                raise SynapseError(400, "Not '%s' a string type" % (s, ))

        if event.type == EventTypes.Member:
            if "membership" not in event.content:
                raise SynapseError(400, "Content has not membership key")

            if event.content["membership"] not in Membership.LIST:
                raise SynapseError(400, "Invalid membership key")
Exemplo n.º 15
0
    def validate(self, event):
        EventID.from_string(event.event_id)
        RoomID.from_string(event.room_id)

        required = [
            # "auth_events",
            "content",
            # "hashes",
            "origin",
            # "prev_events",
            "sender",
            "type",
        ]

        for k in required:
            if not hasattr(event, k):
                raise SynapseError(400, "Event does not have key %s" % (k,))

        # Check that the following keys have string values
        strings = [
            "origin",
            "sender",
            "type",
        ]

        if hasattr(event, "state_key"):
            strings.append("state_key")

        for s in strings:
            if not isinstance(getattr(event, s), basestring):
                raise SynapseError(400, "Not '%s' a string type" % (s,))

        if event.type == EventTypes.Member:
            if "membership" not in event.content:
                raise SynapseError(400, "Content has not membership key")

            if event.content["membership"] not in Membership.LIST:
                raise SynapseError(400, "Invalid membership key")
Exemplo n.º 16
0
    def validate_builder(self, event):
        """Validates that the builder/event has roughly the right format. Only
        checks values that we expect a proto event to have, rather than all the
        fields an event would have

        Args:
            event (EventBuilder|FrozenEvent)
        """

        strings = ["room_id", "sender", "type"]

        if hasattr(event, "state_key"):
            strings.append("state_key")

        for s in strings:
            if not isinstance(getattr(event, s), string_types):
                raise SynapseError(400, "Not '%s' a string type" % (s, ))

        RoomID.from_string(event.room_id)
        UserID.from_string(event.sender)

        if event.type == EventTypes.Message:
            strings = ["body", "msgtype"]

            self._ensure_strings(event.content, strings)

        elif event.type == EventTypes.Topic:
            self._ensure_strings(event.content, ["topic"])

        elif event.type == EventTypes.Name:
            self._ensure_strings(event.content, ["name"])

        elif event.type == EventTypes.Member:
            if "membership" not in event.content:
                raise SynapseError(400, "Content has not membership key")

            if event.content["membership"] not in Membership.LIST:
                raise SynapseError(400, "Invalid membership key")
Exemplo n.º 17
0
    def update_group_summary_room(self, group_id, user_id, room_id,
                                  category_id, content):
        """Add/update a room to the group summary
        """
        yield self.check_group_is_ours(group_id,
                                       and_exists=True,
                                       and_is_admin=user_id)

        RoomID.from_string(room_id)  # Ensure valid room id

        order = content.get("order", None)

        is_public = _parse_visibility_from_contents(content)

        yield self.store.add_room_to_summary(
            group_id=group_id,
            room_id=room_id,
            category_id=category_id,
            order=order,
            is_public=is_public,
        )

        defer.returnValue({})
    def update_room_in_group(self, group_id, requester_user_id, room_id,
                             config_key, content):
        """Update room in group
        """
        RoomID.from_string(room_id)  # Ensure valid room id

        yield self.check_group_is_ours(group_id,
                                       requester_user_id,
                                       and_exists=True,
                                       and_is_admin=requester_user_id)

        if config_key == "m.visibility":
            is_public = _parse_visibility_dict(content)

            yield self.store.update_room_in_group_visibility(
                group_id,
                room_id,
                is_public=is_public,
            )
        else:
            raise SynapseError(400, "Uknown config option")

        defer.returnValue({})
Exemplo n.º 19
0
    def prepare(self, reactor, clock, hs):
        self.store = hs.get_datastore()
        self.event_builder_factory = hs.get_event_builder_factory()
        self.event_creation_handler = hs.get_event_creation_handler()

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        self.room1 = RoomID.from_string("!abc123:test")

        self.get_success(
            create_room(hs, self.room1.to_string(), self.u_alice.to_string()))

        self.depth = 1
Exemplo n.º 20
0
    def setUp(self):
        hs = yield setup_test_homeserver()

        # We can't test RoomStore on its own without the DirectoryStore, for
        # management of the 'room_aliases' table
        self.store = hs.get_datastore()

        self.room = RoomID.from_string("!abcde:test")
        self.alias = RoomAlias.from_string("#a-room-name:test")
        self.u_creator = UserID.from_string("@creator:test")

        yield self.store.store_room(self.room.to_string(),
            room_creator_user_id=self.u_creator.to_string(),
            is_public=True
        )
Exemplo n.º 21
0
    def setUp(self):
        hs = yield setup_test_homeserver()

        # We can't test RoomStore on its own without the DirectoryStore, for
        # management of the 'room_aliases' table
        self.store = hs.get_datastore()

        self.room = RoomID.from_string("!abcde:test")
        self.alias = RoomAlias.from_string("#a-room-name:test")
        self.u_creator = UserID.from_string("@creator:test")

        yield self.store.store_room(
            self.room.to_string(),
            room_creator_user_id=self.u_creator.to_string(),
            is_public=True)
Exemplo n.º 22
0
    def setUp(self):
        hs = yield tests.utils.setup_test_homeserver(self.addCleanup)

        self.store = hs.get_datastore()
        self.event_builder_factory = hs.get_event_builder_factory()
        self.event_creation_handler = hs.get_event_creation_handler()

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        self.room = RoomID.from_string("!abc123:test")

        yield self.store.store_room(
            self.room.to_string(), room_creator_user_id="@creator:text", is_public=True
        )
Exemplo n.º 23
0
    def setUp(self):
        hs = yield tests.utils.setup_test_homeserver(self.addCleanup)

        self.store = hs.get_datastore()
        self.event_builder_factory = hs.get_event_builder_factory()
        self.event_creation_handler = hs.get_event_creation_handler()

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        self.room = RoomID.from_string("!abc123:test")

        yield self.store.store_room(self.room.to_string(),
                                    room_creator_user_id="@creator:text",
                                    is_public=True)
Exemplo n.º 24
0
    def setUp(self):
        hs = yield setup_test_homeserver(self.addCleanup,
                                         resource_for_federation=Mock(),
                                         http_client=None)

        self.store = hs.get_datastore()
        self.event_builder_factory = hs.get_event_builder_factory()
        self.event_creation_handler = hs.get_event_creation_handler()

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        self.room1 = RoomID.from_string("!abc123:test")

        self.depth = 1
Exemplo n.º 25
0
    def prepare(self, reactor, clock, hs):
        # We can't test RoomStore on its own without the DirectoryStore, for
        # management of the 'room_aliases' table
        self.store = hs.get_datastore()

        self.room = RoomID.from_string("!abcde:test")
        self.alias = RoomAlias.from_string("#a-room-name:test")
        self.u_creator = UserID.from_string("@creator:test")

        self.get_success(
            self.store.store_room(
                self.room.to_string(),
                room_creator_user_id=self.u_creator.to_string(),
                is_public=True,
                room_version=RoomVersions.V1,
            ))
Exemplo n.º 26
0
    def prepare(self, reactor, clock, hs):
        # Room events need the full datastore, for persist_event() and
        # get_room_state()
        self.store = hs.get_datastore()
        self.storage = hs.get_storage()
        self.event_factory = hs.get_event_factory()

        self.room = RoomID.from_string("!abcde:test")

        self.get_success(
            self.store.store_room(
                self.room.to_string(),
                room_creator_user_id="@creator:text",
                is_public=True,
                room_version=RoomVersions.V1,
            ))
Exemplo n.º 27
0
    def setUp(self):
        hs = yield setup_test_homeserver(self.addCleanup,
                                         resource_for_federation=Mock(),
                                         http_client=None)
        # We can't test the RoomMemberStore on its own without the other event
        # storage logic
        self.store = hs.get_datastore()
        self.event_builder_factory = hs.get_event_builder_factory()
        self.event_creation_handler = hs.get_event_creation_handler()

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        # User elsewhere on another host
        self.u_charlie = UserID.from_string("@charlie:elsewhere")

        self.room = RoomID.from_string("!abc123:test")
Exemplo n.º 28
0
    def on_POST(self, request, room_identifier, txn_id=None):
        requester = yield self.auth.get_user_by_req(
            request,
            allow_guest=True,
        )

        # the identifier could be a room alias or a room id. Try one then the
        # other if it fails to parse, without swallowing other valid
        # SynapseErrors.

        identifier = None
        is_room_alias = False
        try:
            identifier = RoomAlias.from_string(room_identifier)
            is_room_alias = True
        except SynapseError:
            identifier = RoomID.from_string(room_identifier)

        # TODO: Support for specifying the home server to join with?

        if is_room_alias:
            handler = self.handlers.room_member_handler
            ret_dict = yield handler.join_room_alias(
                requester.user,
                identifier,
            )
            defer.returnValue((200, ret_dict))
        else:  # room id
            msg_handler = self.handlers.message_handler
            content = {"membership": Membership.JOIN}
            if requester.is_guest:
                content["kind"] = "guest"
            yield msg_handler.create_and_send_event(
                {
                    "type": EventTypes.Member,
                    "content": content,
                    "room_id": identifier.to_string(),
                    "sender": requester.user.to_string(),
                    "state_key": requester.user.to_string(),
                },
                token_id=requester.access_token_id,
                txn_id=txn_id,
                is_guest=requester.is_guest,
            )

            defer.returnValue((200, {"room_id": identifier.to_string()}))
Exemplo n.º 29
0
    def setUp(self):
        hs = yield setup_test_homeserver(
            self.addCleanup, resource_for_federation=Mock(), http_client=None
        )

        self.store = hs.get_datastore()
        self.event_builder_factory = hs.get_event_builder_factory()
        self.event_creation_handler = hs.get_event_creation_handler()

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        self.room1 = RoomID.from_string("!abc123:test")

        yield create_room(hs, self.room1.to_string(), self.u_alice.to_string())

        self.depth = 1
Exemplo n.º 30
0
    def setUp(self):
        hs = setup_test_homeserver(self.addCleanup)

        # Room events need the full datastore, for persist_event() and
        # get_room_state()
        self.store = hs.get_datastore()
        self.storage = hs.get_storage()
        self.event_factory = hs.get_event_factory()

        self.room = RoomID.from_string("!abcde:test")

        yield defer.ensureDeferred(
            self.store.store_room(
                self.room.to_string(),
                room_creator_user_id="@creator:text",
                is_public=True,
                room_version=RoomVersions.V1,
            ))
Exemplo n.º 31
0
    def on_PUT(self, request, room_id):
        requester = yield self.auth.get_user_by_req(request)
        room = RoomID.from_string(room_id)
        is_admin = yield self.auth.is_server_admin(requester.user)
        content = parse_json_object_from_request(request)

        new_avatar_url = content["group_avatar_url"]

        try:
            new_name = content["room_icon_url"]
        except Exception:
            defer.returnValue((400, "Unable to parse name"))

        yield self.profile_handler.set_room_avatar_url(room, requester,
                                                       new_avatar_url,
                                                       is_admin)

        defer.returnValue((200, {}))
Exemplo n.º 32
0
    def setUp(self):
        hs = yield setup_test_homeserver(
            resource_for_federation=Mock(),
            http_client=None,
        )
        # We can't test the RoomMemberStore on its own without the other event
        # storage logic
        self.store = hs.get_datastore()
        self.event_builder_factory = hs.get_event_builder_factory()
        self.event_creation_handler = hs.get_event_creation_handler()

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        # User elsewhere on another host
        self.u_charlie = UserID.from_string("@charlie:elsewhere")

        self.room = RoomID.from_string("!abc123:test")
Exemplo n.º 33
0
    def prepare(self, reactor, clock, hs):
        self.store = hs.get_datastores().main
        self.storage = hs.get_storage_controllers()
        self.state_datastore = self.storage.state.stores.state
        self.event_builder_factory = hs.get_event_builder_factory()
        self.event_creation_handler = hs.get_event_creation_handler()

        self.u_alice = UserID.from_string("@alice:test")
        self.u_bob = UserID.from_string("@bob:test")

        self.room = RoomID.from_string("!abc123:test")

        self.get_success(
            self.store.store_room(
                self.room.to_string(),
                room_creator_user_id="@creator:text",
                is_public=True,
                room_version=RoomVersions.V1,
            ))
Exemplo n.º 34
0
    def on_POST(self, request, room_identifier, txn_id=None):
        user, token_id, is_guest = yield self.auth.get_user_by_req(
            request, allow_guest=True)

        # the identifier could be a room alias or a room id. Try one then the
        # other if it fails to parse, without swallowing other valid
        # SynapseErrors.

        identifier = None
        is_room_alias = False
        try:
            identifier = RoomAlias.from_string(room_identifier)
            is_room_alias = True
        except SynapseError:
            identifier = RoomID.from_string(room_identifier)

        # TODO: Support for specifying the home server to join with?

        if is_room_alias:
            handler = self.handlers.room_member_handler
            ret_dict = yield handler.join_room_alias(user, identifier)
            defer.returnValue((200, ret_dict))
        else:  # room id
            msg_handler = self.handlers.message_handler
            content = {"membership": Membership.JOIN}
            if is_guest:
                content["kind"] = "guest"
            yield msg_handler.create_and_send_event(
                {
                    "type": EventTypes.Member,
                    "content": content,
                    "room_id": identifier.to_string(),
                    "sender": user.to_string(),
                    "state_key": user.to_string(),
                },
                token_id=token_id,
                txn_id=txn_id,
                is_guest=is_guest,
            )

            defer.returnValue((200, {"room_id": identifier.to_string()}))
Exemplo n.º 35
0
    def lookup_room_alias(self, room_alias):
        """
        Get the room ID associated with a room alias.

        Args:
            room_alias (RoomAlias): The alias to look up.
        Returns:
            A tuple of:
                The room ID as a RoomID object.
                Hosts likely to be participating in the room ([str]).
        Raises:
            SynapseError if room alias could not be found.
        """
        directory_handler = self.hs.get_handlers().directory_handler
        mapping = yield directory_handler.get_association(room_alias)

        if not mapping:
            raise SynapseError(404, "No such room alias")

        room_id = mapping["room_id"]
        servers = mapping["servers"]

        defer.returnValue((RoomID.from_string(room_id), servers))
Exemplo n.º 36
0
    def check(self, event, auth_events):
        """ Checks if this event is correctly authed.

        Args:
            event: the event being checked.
            auth_events (dict: event-key -> event): the existing room state.


        Returns:
            True if the auth checks pass.
        """
        self.check_size_limits(event)

        try:
            if not hasattr(event, "room_id"):
                raise AuthError(500, "Event has no room_id: %s" % event)
            if auth_events is None:
                # Oh, we don't know what the state of the room was, so we
                # are trusting that this is allowed (at least for now)
                logger.warn("Trusting event: %s", event.event_id)
                return True

            if event.type == EventTypes.Create:
                # FIXME
                return True

            creation_event = auth_events.get((EventTypes.Create, ""), None)

            if not creation_event:
                raise SynapseError(
                    403, "Room %r does not exist" % (event.room_id, ))

            creating_domain = RoomID.from_string(event.room_id).domain
            originating_domain = UserID.from_string(event.sender).domain
            if creating_domain != originating_domain:
                if not self.can_federate(event, auth_events):
                    raise AuthError(
                        403, "This room has been marked as unfederatable.")

            # FIXME: Temp hack
            if event.type == EventTypes.Aliases:
                return True

            logger.debug("Auth events: %s",
                         [a.event_id for a in auth_events.values()])

            if event.type == EventTypes.Member:
                allowed = self.is_membership_change_allowed(event, auth_events)
                if allowed:
                    logger.debug("Allowing! %s", event)
                else:
                    logger.debug("Denying! %s", event)
                return allowed

            self.check_event_sender_in_room(event, auth_events)
            self._can_send_event(event, auth_events)

            if event.type == EventTypes.PowerLevels:
                self._check_power_levels(event, auth_events)

            if event.type == EventTypes.Redaction:
                self.check_redaction(event, auth_events)

            logger.debug("Allowing! %s", event)
        except AuthError as e:
            logger.info("Event auth check failed on event %s with msg: %s",
                        event, e.msg)
            logger.info("Denying! %s", event)
            raise
Exemplo n.º 37
0
    def prepare(self, reactor, clock, hs):
        self.store = hs.get_datastore()

        self.room = RoomID.from_string("!abcde:test")
        self.alias = RoomAlias.from_string("#my-room:test")
Exemplo n.º 38
0
    def _check_definition(self, definition):
        """Check if the provided definition is valid.

        This inspects not only the types but also the values to make sure they
        make sense.

        Args:
            definition(dict): The filter definition
        Raises:
            SynapseError: If there was a problem with this definition.
        """
        # NB: Filters are the complete json blobs. "Definitions" are an
        # individual top-level key e.g. public_user_data. Filters are made of
        # many definitions.
        if type(definition) != dict:
            raise SynapseError(
                400, "Expected JSON object, not %s" % (definition,)
            )

        # check rooms are valid room IDs
        room_id_keys = ["rooms", "not_rooms"]
        for key in room_id_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for room_id in definition[key]:
                    RoomID.from_string(room_id)

        # check senders are valid user IDs
        user_id_keys = ["senders", "not_senders"]
        for key in user_id_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for user_id in definition[key]:
                    UserID.from_string(user_id)

        # TODO: We don't limit event type values but we probably should...
        # check types are valid event types
        event_keys = ["types", "not_types"]
        for key in event_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for event_type in definition[key]:
                    if not isinstance(event_type, basestring):
                        raise SynapseError(400, "Event type should be a string")

        if "format" in definition:
            event_format = definition["format"]
            if event_format not in ["federation", "events"]:
                raise SynapseError(400, "Invalid format: %s" % (event_format,))

        if "select" in definition:
            event_select_list = definition["select"]
            for select_key in event_select_list:
                if select_key not in ["event_id", "origin_server_ts",
                                      "thread_id", "content", "content.body"]:
                    raise SynapseError(400, "Bad select: %s" % (select_key,))

        if ("bundle_updates" in definition and
                type(definition["bundle_updates"]) != bool):
            raise SynapseError(400, "Bad bundle_updates: expected bool.")
Exemplo n.º 39
0
    def create_room(self, user_id, room_id, config):
        """ Creates a new room.

        Args:
            user_id (str): The ID of the user creating the new room.
            room_id (str): The proposed ID for the new room. Can be None, in
            which case one will be created for you.
            config (dict) : A dict of configuration options.
        Returns:
            The new room ID.
        Raises:
            SynapseError if the room ID was taken, couldn't be stored, or
            something went horribly wrong.
        """
        self.ratelimit(user_id)

        if "room_alias_name" in config:
            for wchar in string.whitespace:
                if wchar in config["room_alias_name"]:
                    raise SynapseError(400, "Invalid characters in room alias")

            room_alias = RoomAlias.create(
                config["room_alias_name"],
                self.hs.hostname,
            )
            mapping = yield self.store.get_association_from_room_alias(
                room_alias
            )

            if mapping:
                raise SynapseError(400, "Room alias already taken")
        else:
            room_alias = None

        invite_list = config.get("invite", [])
        for i in invite_list:
            try:
                UserID.from_string(i)
            except:
                raise SynapseError(400, "Invalid user_id: %s" % (i,))

        is_public = config.get("visibility", None) == "public"

        if room_id:
            # Ensure room_id is the correct type
            room_id_obj = RoomID.from_string(room_id)
            if not self.hs.is_mine(room_id_obj):
                raise SynapseError(400, "Room id must be local")

            yield self.store.store_room(
                room_id=room_id,
                room_creator_user_id=user_id,
                is_public=is_public
            )
        else:
            # autogen room IDs and try to create it. We may clash, so just
            # try a few times till one goes through, giving up eventually.
            attempts = 0
            room_id = None
            while attempts < 5:
                try:
                    random_string = stringutils.random_string(18)
                    gen_room_id = RoomID.create(
                        random_string,
                        self.hs.hostname,
                    )
                    yield self.store.store_room(
                        room_id=gen_room_id.to_string(),
                        room_creator_user_id=user_id,
                        is_public=is_public
                    )
                    room_id = gen_room_id.to_string()
                    break
                except StoreError:
                    attempts += 1
            if not room_id:
                raise StoreError(500, "Couldn't generate a room ID.")

        if room_alias:
            directory_handler = self.hs.get_handlers().directory_handler
            yield directory_handler.create_association(
                user_id=user_id,
                room_id=room_id,
                room_alias=room_alias,
                servers=[self.hs.hostname],
            )

        preset_config = config.get(
            "preset",
            RoomCreationPreset.PUBLIC_CHAT
            if is_public
            else RoomCreationPreset.PRIVATE_CHAT
        )

        raw_initial_state = config.get("initial_state", [])

        initial_state = OrderedDict()
        for val in raw_initial_state:
            initial_state[(val["type"], val.get("state_key", ""))] = val["content"]

        creation_content = config.get("creation_content", {})

        user = UserID.from_string(user_id)
        creation_events = self._create_events_for_new_room(
            user, room_id,
            preset_config=preset_config,
            invite_list=invite_list,
            initial_state=initial_state,
            creation_content=creation_content,
            room_alias=room_alias,
        )

        msg_handler = self.hs.get_handlers().message_handler

        for event in creation_events:
            yield msg_handler.create_and_send_event(event, ratelimit=False)

        if "name" in config:
            name = config["name"]
            yield msg_handler.create_and_send_event({
                "type": EventTypes.Name,
                "room_id": room_id,
                "sender": user_id,
                "state_key": "",
                "content": {"name": name},
            }, ratelimit=False)

        if "topic" in config:
            topic = config["topic"]
            yield msg_handler.create_and_send_event({
                "type": EventTypes.Topic,
                "room_id": room_id,
                "sender": user_id,
                "state_key": "",
                "content": {"topic": topic},
            }, ratelimit=False)

        for invitee in invite_list:
            yield msg_handler.create_and_send_event({
                "type": EventTypes.Member,
                "state_key": invitee,
                "room_id": room_id,
                "sender": user_id,
                "content": {"membership": Membership.INVITE},
            }, ratelimit=False)

        result = {"room_id": room_id}

        if room_alias:
            result["room_alias"] = room_alias.to_string()
            yield directory_handler.send_room_alias_update_event(
                user_id, room_id
            )

        defer.returnValue(result)
Exemplo n.º 40
0
 async def lookup_room_alias(*args, **kwargs):
     return RoomID.from_string(self.room_id), ["remotetest"]
Exemplo n.º 41
0
    def create_room(self, user_id, room_id, config):
        """ Creates a new room.

        Args:
            user_id (str): The ID of the user creating the new room.
            room_id (str): The proposed ID for the new room. Can be None, in
            which case one will be created for you.
            config (dict) : A dict of configuration options.
        Returns:
            The new room ID.
        Raises:
            SynapseError if the room ID was taken, couldn't be stored, or
            something went horribly wrong.
        """
        self.ratelimit(user_id)

        if "room_alias_name" in config:
            room_alias = RoomAlias.create_local(
                config["room_alias_name"],
                self.hs
            )
            mapping = yield self.store.get_association_from_room_alias(
                room_alias
            )

            if mapping:
                raise SynapseError(400, "Room alias already taken")
        else:
            room_alias = None

        invite_list = config.get("invite", [])
        for i in invite_list:
            try:
                self.hs.parse_userid(i)
            except:
                raise SynapseError(400, "Invalid user_id: %s" % (i,))

        is_public = config.get("visibility", None) == "public"

        if room_id:
            # Ensure room_id is the correct type
            room_id_obj = RoomID.from_string(room_id, self.hs)
            if not room_id_obj.is_mine:
                raise SynapseError(400, "Room id must be local")

            yield self.store.store_room(
                room_id=room_id,
                room_creator_user_id=user_id,
                is_public=is_public
            )
        else:
            # autogen room IDs and try to create it. We may clash, so just
            # try a few times till one goes through, giving up eventually.
            attempts = 0
            room_id = None
            while attempts < 5:
                try:
                    random_string = stringutils.random_string(18)
                    gen_room_id = RoomID.create_local(random_string, self.hs)
                    yield self.store.store_room(
                        room_id=gen_room_id.to_string(),
                        room_creator_user_id=user_id,
                        is_public=is_public
                    )
                    room_id = gen_room_id.to_string()
                    break
                except StoreError:
                    attempts += 1
            if not room_id:
                raise StoreError(500, "Couldn't generate a room ID.")

        user = self.hs.parse_userid(user_id)
        creation_events = self._create_events_for_new_room(
            user, room_id, is_public=is_public
        )

        if room_alias:
            directory_handler = self.hs.get_handlers().directory_handler
            yield directory_handler.create_association(
                user_id=user_id,
                room_id=room_id,
                room_alias=room_alias,
                servers=[self.hs.hostname],
            )

        @defer.inlineCallbacks
        def handle_event(event):
            snapshot = yield self.store.snapshot_room(
                room_id=room_id,
                user_id=user_id,
            )

            logger.debug("Event: %s", event)

            yield self.state_handler.handle_new_event(event, snapshot)
            yield self._on_new_room_event(event, snapshot, extra_users=[user])

        for event in creation_events:
            yield handle_event(event)

        if "name" in config:
            name = config["name"]
            name_event = self.event_factory.create_event(
                etype=RoomNameEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                required_power_level=50,
                content={"name": name},
            )

            yield handle_event(name_event)
        elif room_alias:
            name = room_alias.to_string()
            name_event = self.event_factory.create_event(
                etype=RoomNameEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                required_power_level=50,
                content={"name": name},
            )

            yield handle_event(name_event)

        if "topic" in config:
            topic = config["topic"]
            topic_event = self.event_factory.create_event(
                etype=RoomTopicEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                required_power_level=50,
                content={"topic": topic},
            )

            yield handle_event(topic_event)

        content = {"membership": Membership.JOIN}
        join_event = self.event_factory.create_event(
            etype=RoomMemberEvent.TYPE,
            state_key=user_id,
            room_id=room_id,
            user_id=user_id,
            membership=Membership.JOIN,
            content=content
        )

        yield self.hs.get_handlers().room_member_handler.change_membership(
            join_event,
            do_auth=False
        )

        content = {"membership": Membership.INVITE}
        for invitee in invite_list:
            invite_event = self.event_factory.create_event(
                etype=RoomMemberEvent.TYPE,
                state_key=invitee,
                room_id=room_id,
                user_id=user_id,
                content=content
            )

            yield self.hs.get_handlers().room_member_handler.change_membership(
                invite_event,
                do_auth=False
            )

        yield self.hs.get_handlers().room_member_handler.change_membership(
            join_event,
            do_auth=False
        )
        result = {"room_id": room_id}
        if room_alias:
            result["room_alias"] = room_alias.to_string()

        defer.returnValue(result)
Exemplo n.º 42
0
    def _check_definition(self, definition):
        """Check if the provided definition is valid.

        This inspects not only the types but also the values to make sure they
        make sense.

        Args:
            definition(dict): The filter definition
        Raises:
            SynapseError: If there was a problem with this definition.
        """
        # NB: Filters are the complete json blobs. "Definitions" are an
        # individual top-level key e.g. public_user_data. Filters are made of
        # many definitions.
        if type(definition) != dict:
            raise SynapseError(400,
                               "Expected JSON object, not %s" % (definition, ))

        # check rooms are valid room IDs
        room_id_keys = ["rooms", "not_rooms"]
        for key in room_id_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for room_id in definition[key]:
                    RoomID.from_string(room_id)

        # check senders are valid user IDs
        user_id_keys = ["senders", "not_senders"]
        for key in user_id_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for user_id in definition[key]:
                    UserID.from_string(user_id)

        # TODO: We don't limit event type values but we probably should...
        # check types are valid event types
        event_keys = ["types", "not_types"]
        for key in event_keys:
            if key in definition:
                if type(definition[key]) != list:
                    raise SynapseError(400, "Expected %s to be a list." % key)
                for event_type in definition[key]:
                    if not isinstance(event_type, basestring):
                        raise SynapseError(400,
                                           "Event type should be a string")

        if "format" in definition:
            event_format = definition["format"]
            if event_format not in ["federation", "events"]:
                raise SynapseError(400,
                                   "Invalid format: %s" % (event_format, ))

        if "select" in definition:
            event_select_list = definition["select"]
            for select_key in event_select_list:
                if select_key not in [
                        "event_id", "origin_server_ts", "thread_id", "content",
                        "content.body"
                ]:
                    raise SynapseError(400, "Bad select: %s" % (select_key, ))

        if ("bundle_updates" in definition
                and type(definition["bundle_updates"]) != bool):
            raise SynapseError(400, "Bad bundle_updates: expected bool.")
Exemplo n.º 43
0
    def check(self, event, auth_events):
        """ Checks if this event is correctly authed.

        Args:
            event: the event being checked.
            auth_events (dict: event-key -> event): the existing room state.


        Returns:
            True if the auth checks pass.
        """
        self.check_size_limits(event)

        try:
            if not hasattr(event, "room_id"):
                raise AuthError(500, "Event has no room_id: %s" % event)
            if auth_events is None:
                # Oh, we don't know what the state of the room was, so we
                # are trusting that this is allowed (at least for now)
                logger.warn("Trusting event: %s", event.event_id)
                return True

            if event.type == EventTypes.Create:
                # FIXME
                return True

            creation_event = auth_events.get((EventTypes.Create, ""), None)

            if not creation_event:
                raise SynapseError(
                    403,
                    "Room %r does not exist" % (event.room_id,)
                )

            creating_domain = RoomID.from_string(event.room_id).domain
            originating_domain = UserID.from_string(event.sender).domain
            if creating_domain != originating_domain:
                if not self.can_federate(event, auth_events):
                    raise AuthError(
                        403,
                        "This room has been marked as unfederatable."
                    )

            # FIXME: Temp hack
            if event.type == EventTypes.Aliases:
                return True

            logger.debug(
                "Auth events: %s",
                [a.event_id for a in auth_events.values()]
            )

            if event.type == EventTypes.Member:
                allowed = self.is_membership_change_allowed(
                    event, auth_events
                )
                if allowed:
                    logger.debug("Allowing! %s", event)
                else:
                    logger.debug("Denying! %s", event)
                return allowed

            self.check_event_sender_in_room(event, auth_events)
            self._can_send_event(event, auth_events)

            if event.type == EventTypes.PowerLevels:
                self._check_power_levels(event, auth_events)

            if event.type == EventTypes.Redaction:
                self.check_redaction(event, auth_events)

            logger.debug("Allowing! %s", event)
        except AuthError as e:
            logger.info(
                "Event auth check failed on event %s with msg: %s",
                event, e.msg
            )
            logger.info("Denying! %s", event)
            raise
Exemplo n.º 44
0
    def create_room(self, user_id, room_id, config):
        """ Creates a new room.

        Args:
            user_id (str): The ID of the user creating the new room.
            room_id (str): The proposed ID for the new room. Can be None, in
            which case one will be created for you.
            config (dict) : A dict of configuration options.
        Returns:
            The new room ID.
        Raises:
            SynapseError if the room ID was taken, couldn't be stored, or
            something went horribly wrong.
        """
        self.ratelimit(user_id)

        if "room_alias_name" in config:
            room_alias = RoomAlias.create(
                config["room_alias_name"],
                self.hs.hostname,
            )
            mapping = yield self.store.get_association_from_room_alias(
                room_alias)

            if mapping:
                raise SynapseError(400, "Room alias already taken")
        else:
            room_alias = None

        invite_list = config.get("invite", [])
        for i in invite_list:
            try:
                self.hs.parse_userid(i)
            except:
                raise SynapseError(400, "Invalid user_id: %s" % (i, ))

        is_public = config.get("visibility", None) == "public"

        if room_id:
            # Ensure room_id is the correct type
            room_id_obj = RoomID.from_string(room_id)
            if not self.hs.is_mine(room_id_obj):
                raise SynapseError(400, "Room id must be local")

            yield self.store.store_room(room_id=room_id,
                                        room_creator_user_id=user_id,
                                        is_public=is_public)
        else:
            # autogen room IDs and try to create it. We may clash, so just
            # try a few times till one goes through, giving up eventually.
            attempts = 0
            room_id = None
            while attempts < 5:
                try:
                    random_string = stringutils.random_string(18)
                    gen_room_id = RoomID.create(
                        random_string,
                        self.hs.hostname,
                    )
                    yield self.store.store_room(
                        room_id=gen_room_id.to_string(),
                        room_creator_user_id=user_id,
                        is_public=is_public)
                    room_id = gen_room_id.to_string()
                    break
                except StoreError:
                    attempts += 1
            if not room_id:
                raise StoreError(500, "Couldn't generate a room ID.")

        if room_alias:
            directory_handler = self.hs.get_handlers().directory_handler
            yield directory_handler.create_association(
                user_id=user_id,
                room_id=room_id,
                room_alias=room_alias,
                servers=[self.hs.hostname],
            )

        user = self.hs.parse_userid(user_id)
        creation_events = self._create_events_for_new_room(user,
                                                           room_id,
                                                           is_public=is_public)

        msg_handler = self.hs.get_handlers().message_handler

        for event in creation_events:
            yield msg_handler.create_and_send_event(event)

        if "name" in config:
            name = config["name"]
            yield msg_handler.create_and_send_event({
                "type": EventTypes.Name,
                "room_id": room_id,
                "sender": user_id,
                "state_key": "",
                "content": {
                    "name": name
                },
            })

        if "topic" in config:
            topic = config["topic"]
            yield msg_handler.create_and_send_event({
                "type": EventTypes.Topic,
                "room_id": room_id,
                "sender": user_id,
                "state_key": "",
                "content": {
                    "topic": topic
                },
            })

        for invitee in invite_list:
            yield msg_handler.create_and_send_event({
                "type": EventTypes.Member,
                "state_key": invitee,
                "room_id": room_id,
                "sender": user_id,
                "content": {
                    "membership": Membership.INVITE
                },
            })

        result = {"room_id": room_id}

        if room_alias:
            result["room_alias"] = room_alias.to_string()
            yield directory_handler.send_room_alias_update_event(
                user_id, room_id)

        defer.returnValue(result)
Exemplo n.º 45
0
def matrix_room_id_validator(room_id_str):
    return RoomID.from_string(room_id_str)
Exemplo n.º 46
0
def matrix_room_id_validator(room_id_str):
    return RoomID.from_string(room_id_str)
Exemplo n.º 47
0
    def is_membership_change_allowed(self, event, auth_events):
        membership = event.content["membership"]

        # Check if this is the room creator joining:
        if len(event.prev_events) == 1 and Membership.JOIN == membership:
            # Get room creation event:
            key = (
                EventTypes.Create,
                "",
            )
            create = auth_events.get(key)
            if create and event.prev_events[0][0] == create.event_id:
                if create.content["creator"] == event.state_key:
                    return True

        target_user_id = event.state_key

        creating_domain = RoomID.from_string(event.room_id).domain
        target_domain = UserID.from_string(target_user_id).domain
        if creating_domain != target_domain:
            if not self.can_federate(event, auth_events):
                raise AuthError(403,
                                "This room has been marked as unfederatable.")

        # get info about the caller
        key = (
            EventTypes.Member,
            event.user_id,
        )
        caller = auth_events.get(key)

        caller_in_room = caller and caller.membership == Membership.JOIN
        caller_invited = caller and caller.membership == Membership.INVITE

        # get info about the target
        key = (
            EventTypes.Member,
            target_user_id,
        )
        target = auth_events.get(key)

        target_in_room = target and target.membership == Membership.JOIN
        target_banned = target and target.membership == Membership.BAN

        key = (
            EventTypes.JoinRules,
            "",
        )
        join_rule_event = auth_events.get(key)
        if join_rule_event:
            join_rule = join_rule_event.content.get("join_rule",
                                                    JoinRules.INVITE)
        else:
            join_rule = JoinRules.INVITE

        user_level = self._get_user_power_level(event.user_id, auth_events)
        target_level = self._get_user_power_level(target_user_id, auth_events)

        # FIXME (erikj): What should we do here as the default?
        ban_level = self._get_named_level(auth_events, "ban", 50)

        logger.debug(
            "is_membership_change_allowed: %s", {
                "caller_in_room": caller_in_room,
                "caller_invited": caller_invited,
                "target_banned": target_banned,
                "target_in_room": target_in_room,
                "membership": membership,
                "join_rule": join_rule,
                "target_user_id": target_user_id,
                "event.user_id": event.user_id,
            })

        if Membership.INVITE == membership and "third_party_invite" in event.content:
            if not self._verify_third_party_invite(event, auth_events):
                raise AuthError(403, "You are not invited to this room.")
            return True

        if Membership.JOIN != membership:
            if (caller_invited and Membership.LEAVE == membership
                    and target_user_id == event.user_id):
                return True

            if not caller_in_room:  # caller isn't joined
                raise AuthError(
                    403, "%s not in room %s." % (
                        event.user_id,
                        event.room_id,
                    ))

        if Membership.INVITE == membership:
            # TODO (erikj): We should probably handle this more intelligently
            # PRIVATE join rules.

            # Invites are valid iff caller is in the room and target isn't.
            if target_banned:
                raise AuthError(
                    403, "%s is banned from the room" % (target_user_id, ))
            elif target_in_room:  # the target is already in the room.
                raise AuthError(403,
                                "%s is already in the room." % target_user_id)
            else:
                invite_level = self._get_named_level(auth_events, "invite", 0)

                if user_level < invite_level:
                    raise AuthError(
                        403, "You cannot invite user %s." % target_user_id)
        elif Membership.JOIN == membership:
            # Joins are valid iff caller == target and they were:
            # invited: They are accepting the invitation
            # joined: It's a NOOP
            if event.user_id != target_user_id:
                raise AuthError(403, "Cannot force another user to join.")
            elif target_banned:
                raise AuthError(403, "You are banned from this room")
            elif join_rule == JoinRules.PUBLIC:
                pass
            elif join_rule == JoinRules.INVITE:
                if not caller_in_room and not caller_invited:
                    raise AuthError(403, "You are not invited to this room.")
            else:
                # TODO (erikj): may_join list
                # TODO (erikj): private rooms
                raise AuthError(403, "You are not allowed to join this room")
        elif Membership.LEAVE == membership:
            # TODO (erikj): Implement kicks.
            if target_banned and user_level < ban_level:
                raise AuthError(
                    403, "You cannot unban user &s." % (target_user_id, ))
            elif target_user_id != event.user_id:
                kick_level = self._get_named_level(auth_events, "kick", 50)

                if user_level < kick_level or user_level <= target_level:
                    raise AuthError(
                        403, "You cannot kick user %s." % target_user_id)
        elif Membership.BAN == membership:
            if user_level < ban_level or user_level <= target_level:
                raise AuthError(403, "You don't have permission to ban")
        else:
            raise AuthError(500, "Unknown membership %s" % membership)

        return True
Exemplo n.º 48
0
 def parse_roomid(self, s):
     """Parse the string given by 's' as a Room ID and return a RoomID
     object."""
     return RoomID.from_string(s)
Exemplo n.º 49
0
    def is_membership_change_allowed(self, event, auth_events):
        membership = event.content["membership"]

        # Check if this is the room creator joining:
        if len(event.prev_events) == 1 and Membership.JOIN == membership:
            # Get room creation event:
            key = (EventTypes.Create, "", )
            create = auth_events.get(key)
            if create and event.prev_events[0][0] == create.event_id:
                if create.content["creator"] == event.state_key:
                    return True

        target_user_id = event.state_key

        creating_domain = RoomID.from_string(event.room_id).domain
        target_domain = UserID.from_string(target_user_id).domain
        if creating_domain != target_domain:
            if not self.can_federate(event, auth_events):
                raise AuthError(
                    403,
                    "This room has been marked as unfederatable."
                )

        # get info about the caller
        key = (EventTypes.Member, event.user_id, )
        caller = auth_events.get(key)

        caller_in_room = caller and caller.membership == Membership.JOIN
        caller_invited = caller and caller.membership == Membership.INVITE

        # get info about the target
        key = (EventTypes.Member, target_user_id, )
        target = auth_events.get(key)

        target_in_room = target and target.membership == Membership.JOIN
        target_banned = target and target.membership == Membership.BAN

        key = (EventTypes.JoinRules, "", )
        join_rule_event = auth_events.get(key)
        if join_rule_event:
            join_rule = join_rule_event.content.get(
                "join_rule", JoinRules.INVITE
            )
        else:
            join_rule = JoinRules.INVITE

        user_level = self._get_user_power_level(event.user_id, auth_events)
        target_level = self._get_user_power_level(
            target_user_id, auth_events
        )

        # FIXME (erikj): What should we do here as the default?
        ban_level = self._get_named_level(auth_events, "ban", 50)

        logger.debug(
            "is_membership_change_allowed: %s",
            {
                "caller_in_room": caller_in_room,
                "caller_invited": caller_invited,
                "target_banned": target_banned,
                "target_in_room": target_in_room,
                "membership": membership,
                "join_rule": join_rule,
                "target_user_id": target_user_id,
                "event.user_id": event.user_id,
            }
        )

        if Membership.INVITE == membership and "third_party_invite" in event.content:
            if not self._verify_third_party_invite(event, auth_events):
                raise AuthError(403, "You are not invited to this room.")
            return True

        if Membership.JOIN != membership:
            if (caller_invited
                    and Membership.LEAVE == membership
                    and target_user_id == event.user_id):
                return True

            if not caller_in_room:  # caller isn't joined
                raise AuthError(
                    403,
                    "%s not in room %s." % (event.user_id, event.room_id,)
                )

        if Membership.INVITE == membership:
            # TODO (erikj): We should probably handle this more intelligently
            # PRIVATE join rules.

            # Invites are valid iff caller is in the room and target isn't.
            if target_banned:
                raise AuthError(
                    403, "%s is banned from the room" % (target_user_id,)
                )
            elif target_in_room:  # the target is already in the room.
                raise AuthError(403, "%s is already in the room." %
                                     target_user_id)
            else:
                invite_level = self._get_named_level(auth_events, "invite", 0)

                if user_level < invite_level:
                    raise AuthError(
                        403, "You cannot invite user %s." % target_user_id
                    )
        elif Membership.JOIN == membership:
            # Joins are valid iff caller == target and they were:
            # invited: They are accepting the invitation
            # joined: It's a NOOP
            if event.user_id != target_user_id:
                raise AuthError(403, "Cannot force another user to join.")
            elif target_banned:
                raise AuthError(403, "You are banned from this room")
            elif join_rule == JoinRules.PUBLIC:
                pass
            elif join_rule == JoinRules.INVITE:
                if not caller_in_room and not caller_invited:
                    raise AuthError(403, "You are not invited to this room.")
            else:
                # TODO (erikj): may_join list
                # TODO (erikj): private rooms
                raise AuthError(403, "You are not allowed to join this room")
        elif Membership.LEAVE == membership:
            # TODO (erikj): Implement kicks.
            if target_banned and user_level < ban_level:
                raise AuthError(
                    403, "You cannot unban user &s." % (target_user_id,)
                )
            elif target_user_id != event.user_id:
                kick_level = self._get_named_level(auth_events, "kick", 50)

                if user_level < kick_level or user_level <= target_level:
                    raise AuthError(
                        403, "You cannot kick user %s." % target_user_id
                    )
        elif Membership.BAN == membership:
            if user_level < ban_level or user_level <= target_level:
                raise AuthError(403, "You don't have permission to ban")
        else:
            raise AuthError(500, "Unknown membership %s" % membership)

        return True
Exemplo n.º 50
0
 def parse_roomid(self, s):
     """Parse the string given by 's' as a Room ID and return a RoomID
     object."""
     return RoomID.from_string(s, hs=self)
Exemplo n.º 51
0
    def create_room(self, user_id, room_id, config):
        """ Creates a new room.

        Args:
            user_id (str): The ID of the user creating the new room.
            room_id (str): The proposed ID for the new room. Can be None, in
            which case one will be created for you.
            config (dict) : A dict of configuration options.
        Returns:
            The new room ID.
        Raises:
            SynapseError if the room ID was taken, couldn't be stored, or
            something went horribly wrong.
        """
        self.ratelimit(user_id)

        if "room_alias_name" in config:
            room_alias = RoomAlias.create_local(
                config["room_alias_name"],
                self.hs
            )
            mapping = yield self.store.get_association_from_room_alias(
                room_alias
            )

            if mapping:
                raise SynapseError(400, "Room alias already taken")
        else:
            room_alias = None

        invite_list = config.get("invite", [])
        for i in invite_list:
            try:
                self.hs.parse_userid(i)
            except:
                raise SynapseError(400, "Invalid user_id: %s" % (i,))

        is_public = config.get("visibility", None) == "public"

        if room_id:
            # Ensure room_id is the correct type
            room_id_obj = RoomID.from_string(room_id, self.hs)
            if not room_id_obj.is_mine:
                raise SynapseError(400, "Room id must be local")

            yield self.store.store_room(
                room_id=room_id,
                room_creator_user_id=user_id,
                is_public=is_public
            )
        else:
            # autogen room IDs and try to create it. We may clash, so just
            # try a few times till one goes through, giving up eventually.
            attempts = 0
            room_id = None
            while attempts < 5:
                try:
                    random_string = stringutils.random_string(18)
                    gen_room_id = RoomID.create_local(random_string, self.hs)
                    yield self.store.store_room(
                        room_id=gen_room_id.to_string(),
                        room_creator_user_id=user_id,
                        is_public=is_public
                    )
                    room_id = gen_room_id.to_string()
                    break
                except StoreError:
                    attempts += 1
            if not room_id:
                raise StoreError(500, "Couldn't generate a room ID.")

        if room_alias:
            directory_handler = self.hs.get_handlers().directory_handler
            yield directory_handler.create_association(
                user_id=user_id,
                room_id=room_id,
                room_alias=room_alias,
                servers=[self.hs.hostname],
            )

        user = self.hs.parse_userid(user_id)
        creation_events = self._create_events_for_new_room(
            user, room_id, is_public=is_public
        )

        room_member_handler = self.hs.get_handlers().room_member_handler

        @defer.inlineCallbacks
        def handle_event(event):
            snapshot = yield self.store.snapshot_room(event)

            logger.debug("Event: %s", event)

            if event.type == RoomMemberEvent.TYPE:
                yield room_member_handler.change_membership(
                    event,
                    do_auth=True
                )
            else:
                yield self._on_new_room_event(
                    event, snapshot, extra_users=[user], suppress_auth=True
                )

        for event in creation_events:
            yield handle_event(event)

        if "name" in config:
            name = config["name"]
            name_event = self.event_factory.create_event(
                etype=RoomNameEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                content={"name": name},
            )

            yield handle_event(name_event)

        if "topic" in config:
            topic = config["topic"]
            topic_event = self.event_factory.create_event(
                etype=RoomTopicEvent.TYPE,
                room_id=room_id,
                user_id=user_id,
                content={"topic": topic},
            )

            yield handle_event(topic_event)

        content = {"membership": Membership.INVITE}
        for invitee in invite_list:
            invite_event = self.event_factory.create_event(
                etype=RoomMemberEvent.TYPE,
                state_key=invitee,
                room_id=room_id,
                user_id=user_id,
                content=content
            )
            yield handle_event(invite_event)

        result = {"room_id": room_id}

        if room_alias:
            result["room_alias"] = room_alias.to_string()
            yield directory_handler.send_room_alias_update_event(
                user_id, room_id
            )

        defer.returnValue(result)