Exemple #1
0
    def setUp(self):
        hs = yield setup_test_homeserver(clock=MockClock())

        self.store = PresenceStore(hs)

        self.u_apple = UserID.from_string("@apple:test")
        self.u_banana = UserID.from_string("@banana:test")
Exemple #2
0
    def on_POST(self, request, target_user_id):
        body = parse_json_object_from_request(request, allow_empty_body=True)
        erase = body.get("erase", False)
        if not isinstance(erase, bool):
            raise SynapseError(
                http_client.BAD_REQUEST,
                "Param 'erase' must be a boolean, if given",
                Codes.BAD_JSON,
            )

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

        result = yield self._deactivate_account_handler.deactivate_account(
            target_user_id, erase,
        )
        if result:
            id_server_unbind_result = "success"
        else:
            id_server_unbind_result = "no-support"

        defer.returnValue((200, {
            "id_server_unbind_result": id_server_unbind_result,
        }))
Exemple #3
0
    def setUp(self):
        self.mock_federation = Mock()
        self.mock_registry = Mock()

        self.query_handlers = {}

        def register_query_handler(query_type, handler):
            self.query_handlers[query_type] = handler

        self.mock_registry.register_query_handler = register_query_handler

        hs = yield setup_test_homeserver(
            self.addCleanup,
            http_client=None,
            handlers=None,
            resource_for_federation=Mock(),
            federation_client=self.mock_federation,
            federation_server=Mock(),
            federation_registry=self.mock_registry,
            ratelimiter=NonCallableMock(spec_set=["can_do_action"]),
        )

        self.ratelimiter = hs.get_ratelimiter()
        self.ratelimiter.can_do_action.return_value = (True, 0)

        self.store = hs.get_datastore()

        self.frank = UserID.from_string("@1234ABCD:test")
        self.bob = UserID.from_string("@4567:test")
        self.alice = UserID.from_string("@alice:remote")

        yield self.store.create_profile(self.frank.localpart)

        self.handler = hs.get_profile_handler()
Exemple #4
0
    def appservice_register(self, user_localpart, as_token):
        user = UserID(user_localpart, self.hs.hostname)
        user_id = user.to_string()
        service = yield self.store.get_app_service_by_token(as_token)
        if not service:
            raise AuthError(403, "Invalid application service token.")
        if not service.is_interested_in_user(user_id):
            raise SynapseError(
                400, "Invalid user localpart for this application service.",
                errcode=Codes.EXCLUSIVE
            )

        service_id = service.id if service.is_exclusive_user(user_id) else None

        yield self.check_user_id_not_appservice_exclusive(
            user_id, allowed_appservice=service
        )

        token = self.auth_handler().generate_access_token(user_id)
        yield self.store.register(
            user_id=user_id,
            token=token,
            password_hash="",
            appservice_id=service_id,
        )
        yield registered_user(self.distributor, user)
        defer.returnValue((user_id, token))
Exemple #5
0
    def test_compare(self):
        userA = UserID.from_string("@userA:my.domain")
        userAagain = UserID.from_string("@userA:my.domain")
        userB = UserID.from_string("@userB:my.domain")

        self.assertTrue(userA == userAagain)
        self.assertTrue(userA != userB)
Exemple #6
0
    def create_and_send_event(self, event_dict, ratelimit=True,
                              token_id=None, txn_id=None, is_guest=False):
        """ Given a dict from a client, create and handle a new event.

        Creates an FrozenEvent object, filling out auth_events, prev_events,
        etc.

        Adds display names to Join membership events.

        Persists and notifies local clients and federation.

        Args:
            event_dict (dict): An entire event
        """
        builder = self.event_builder_factory.new(event_dict)

        self.validator.validate_new(builder)

        if ratelimit:
            self.ratelimit(builder.user_id)
        # TODO(paul): Why does 'event' not have a 'user' object?
        user = UserID.from_string(builder.user_id)
        assert self.hs.is_mine(user), "User must be our own: %s" % (user,)

        if builder.type == EventTypes.Member:
            membership = builder.content.get("membership", None)
            if membership == Membership.JOIN:
                joinee = UserID.from_string(builder.state_key)
                # If event doesn't include a display name, add one.
                yield self.distributor.fire(
                    "collect_presencelike_data",
                    joinee,
                    builder.content
                )

        if token_id is not None:
            builder.internal_metadata.token_id = token_id

        if txn_id is not None:
            builder.internal_metadata.txn_id = txn_id

        event, context = yield self._create_new_client_event(
            builder=builder,
        )

        if event.type == EventTypes.Member:
            member_handler = self.hs.get_handlers().room_member_handler
            yield member_handler.change_membership(event, context, is_guest=is_guest)
        else:
            yield self.handle_new_client_event(
                event=event,
                context=context,
            )

        if event.type == EventTypes.Message:
            presence = self.hs.get_handlers().presence_handler
            with PreserveLoggingContext():
                presence.bump_presence_active_time(user)

        defer.returnValue(event)
Exemple #7
0
    def register_saml2(self, localpart):
        """
        Registers email_id as SAML2 Based Auth.
        """
        if types.contains_invalid_mxid_characters(localpart):
            raise SynapseError(
                400,
                "User ID can only contain characters a-z, 0-9, or '=_-./'",
            )
        yield self.auth.check_auth_blocking()
        user = UserID(localpart, self.hs.hostname)
        user_id = user.to_string()

        yield self.check_user_id_not_appservice_exclusive(user_id)
        token = self.macaroon_gen.generate_access_token(user_id)
        try:
            yield self.store.register(
                user_id=user_id,
                token=token,
                password_hash=None,
                create_profile_with_localpart=user.localpart,
            )
        except Exception as e:
            yield self.store.add_access_token_to_user(user_id, token)
            # Ignore Registration errors
            logger.exception(e)
        defer.returnValue((user_id, token))
Exemple #8
0
    def on_POST(self, request, target_user_id):
        """Post request to get specific number of users from Synapse..
        This needs user to have administrator access in Synapse.
        Example:
            http://localhost:8008/_synapse/admin/v1/users_paginate/
            @admin:user?access_token=admin_access_token
        JsonBodyToSend:
            {
                "start": "0",
                "limit": "10
            }
        Returns:
            200 OK with json object {list[dict[str, Any]], count} or empty object.
        """
        yield assert_requester_is_admin(self.auth, request)
        UserID.from_string(target_user_id)

        order = "name"  # order by name in user table
        params = parse_json_object_from_request(request)
        assert_params_in_dict(params, ["limit", "start"])
        limit = params['limit']
        start = params['start']
        logger.info("limit: %s, start: %s", limit, start)

        ret = yield self.handlers.admin_handler.get_users_paginate(
            order, start, limit
        )
        defer.returnValue((200, ret))
Exemple #9
0
    def register_saml2(self, localpart):
        """
        Registers email_id as SAML2 Based Auth.
        """
        if urllib.quote(localpart) != localpart:
            raise SynapseError(
                400,
                "User ID must only contain characters which do not"
                " require URL encoding."
                )
        user = UserID(localpart, self.hs.hostname)
        user_id = user.to_string()

        yield self.check_user_id_is_valid(user_id)
        token = self.auth_handler().generate_access_token(user_id)
        try:
            yield self.store.register(
                user_id=user_id,
                token=token,
                password_hash=None
            )
            yield self.distributor.fire("registered_user", user)
        except Exception, e:
            yield self.store.add_access_token_to_user(user_id, token)
            # Ignore Registration errors
            logger.exception(e)
Exemple #10
0
    def register_saml2(self, localpart):
        """
        Registers email_id as SAML2 Based Auth.
        """
        if urllib.quote(localpart) != localpart:
            raise SynapseError(
                400,
                "User ID must only contain characters which do not"
                " require URL encoding."
            )
        user = UserID(localpart, self.hs.hostname)
        user_id = user.to_string()

        yield self.check_user_id_not_appservice_exclusive(user_id)
        token = self.auth_handler().generate_access_token(user_id)
        try:
            yield self.store.register(
                user_id=user_id,
                token=token,
                password_hash=None,
                create_profile_with_localpart=user.localpart,
            )
        except Exception as e:
            yield self.store.add_access_token_to_user(user_id, token)
            # Ignore Registration errors
            logger.exception(e)
        defer.returnValue((user_id, token))
Exemple #11
0
    def appservice_register(self, user_localpart, as_token):
        user = UserID(user_localpart, self.hs.hostname)
        user_id = user.to_string()
        service = self.store.get_app_service_by_token(as_token)
        if not service:
            raise AuthError(403, "Invalid application service token.")
        if not service.is_interested_in_user(user_id):
            raise SynapseError(
                400, "Invalid user localpart for this application service.",
                errcode=Codes.EXCLUSIVE
            )

        service_id = service.id if service.is_exclusive_user(user_id) else None

        yield self.check_user_id_not_appservice_exclusive(
            user_id, allowed_appservice=service
        )

        yield self.register_with_store(
            user_id=user_id,
            password_hash="",
            appservice_id=service_id,
            create_profile_with_displayname=user.localpart,
        )
        defer.returnValue(user_id)
Exemple #12
0
    def test_compare(self):
        userA = UserID.from_string("@userA:my.domain", hs=mock_homeserver)
        userAagain = UserID.from_string("@userA:my.domain", hs=mock_homeserver)
        userB = UserID.from_string("@userB:my.domain", hs=mock_homeserver)

        self.assertTrue(userA == userAagain)
        self.assertTrue(userA != userB)
Exemple #13
0
    def on_POST(self, request, room_id, membership_action, txn_id=None):
        user, client = yield self.auth.get_user_by_req(request)

        content = _parse_json(request)

        # target user is you unless it is an invite
        state_key = user.to_string()
        if membership_action in ["invite", "ban", "kick"]:
            if "user_id" not in content:
                raise SynapseError(400, "Missing user_id key.")
            state_key = content["user_id"]
            # make sure it looks like a user ID; it'll throw if it's invalid.
            UserID.from_string(state_key)

            if membership_action == "kick":
                membership_action = "leave"

        msg_handler = self.handlers.message_handler
        yield msg_handler.create_and_send_event(
            {
                "type": EventTypes.Member,
                "content": {"membership": unicode(membership_action)},
                "room_id": room_id,
                "sender": user.to_string(),
                "state_key": state_key,
            },
            client=client,
            txn_id=txn_id,
        )

        defer.returnValue((200, {}))
Exemple #14
0
    def check_username(self, localpart, guest_access_token=None):
        yield run_on_reactor()

        if urllib.quote(localpart.encode('utf-8')) != localpart:
            raise SynapseError(
                400,
                "User ID can only contain characters a-z, 0-9, or '_-./'",
                Codes.INVALID_USERNAME
            )

        user = UserID(localpart, self.hs.hostname)
        user_id = user.to_string()

        yield self.check_user_id_is_valid(user_id)

        users = yield self.store.get_users_by_id_case_insensitive(user_id)
        if users:
            if not guest_access_token:
                raise SynapseError(
                    400,
                    "User ID already taken.",
                    errcode=Codes.USER_IN_USE,
                )
            user_data = yield self.auth.get_user_from_macaroon(guest_access_token)
            if not user_data["is_guest"] or user_data["user"].localpart != localpart:
                raise AuthError(
                    403,
                    "Cannot register taken user ID without valid guest "
                    "credentials for that user.",
                    errcode=Codes.FORBIDDEN,
                )
Exemple #15
0
    def on_POST(self, request, room_id, membership_action, txn_id=None):
        user, token_id, is_guest = yield self.auth.get_user_by_req(
            request,
            allow_guest=True
        )

        if is_guest and membership_action not in {Membership.JOIN, Membership.LEAVE}:
            raise AuthError(403, "Guest access not allowed")

        content = _parse_json(request)

        # target user is you unless it is an invite
        state_key = user.to_string()

        if membership_action == "invite" and self._has_3pid_invite_keys(content):
            yield self.handlers.room_member_handler.do_3pid_invite(
                room_id,
                user,
                content["medium"],
                content["address"],
                content["id_server"],
                token_id,
                txn_id
            )
            defer.returnValue((200, {}))
            return
        elif membership_action in ["invite", "ban", "kick"]:
            if "user_id" in content:
                state_key = content["user_id"]
            else:
                raise SynapseError(400, "Missing user_id key.")

            # make sure it looks like a user ID; it'll throw if it's invalid.
            UserID.from_string(state_key)

            if membership_action == "kick":
                membership_action = "leave"

        msg_handler = self.handlers.message_handler

        content = {"membership": unicode(membership_action)}
        if is_guest:
            content["kind"] = "guest"

        yield msg_handler.create_and_send_event(
            {
                "type": EventTypes.Member,
                "content": content,
                "room_id": room_id,
                "sender": user.to_string(),
                "state_key": state_key,
            },
            token_id=token_id,
            txn_id=txn_id,
            is_guest=is_guest,
        )

        defer.returnValue((200, {}))
Exemple #16
0
    def register(self, localpart=None, password=None):
        """Registers a new client on the server.

        Args:
            localpart : The local part of the user ID to register. If None,
              one will be randomly generated.
            password (str) : The password to assign to this user so they can
            login again.
        Returns:
            A tuple of (user_id, access_token).
        Raises:
            RegistrationError if there was a problem registering.
        """
        yield run_on_reactor()
        password_hash = None
        if password:
            password_hash = bcrypt.hashpw(password, bcrypt.gensalt())

        if localpart:
            user = UserID(localpart, self.hs.hostname)
            user_id = user.to_string()

            token = self._generate_token(user_id)
            yield self.store.register(
                user_id=user_id,
                token=token,
                password_hash=password_hash
            )

            yield self.distributor.fire("registered_user", user)
        else:
            # autogen a random user ID
            attempts = 0
            user_id = None
            token = None
            while not user_id and not token:
                try:
                    localpart = self._generate_user_id()
                    user = UserID(localpart, self.hs.hostname)
                    user_id = user.to_string()

                    token = self._generate_token(user_id)
                    yield self.store.register(
                        user_id=user_id,
                        token=token,
                        password_hash=password_hash)

                    self.distributor.fire("registered_user", user)
                except SynapseError:
                    # if user id is taken, just generate another
                    user_id = None
                    token = None
                    attempts += 1
                    if attempts > 5:
                        raise RegistrationError(
                            500, "Cannot generate user ID.")

        defer.returnValue((user_id, token))
Exemple #17
0
    def handle_new_client_event(self, event, context, extra_destinations=[],
                                extra_users=[], suppress_auth=False):
        yield run_on_reactor()

        # We now need to go and hit out to wherever we need to hit out to.

        if not suppress_auth:
            self.auth.check(event, auth_events=context.current_state)

        yield self.store.persist_event(event, context=context)

        federation_handler = self.hs.get_handlers().federation_handler

        if event.type == EventTypes.Member:
            if event.content["membership"] == Membership.INVITE:
                invitee = UserID.from_string(event.state_key)
                if not self.hs.is_mine(invitee):
                    # TODO: Can we add signature from remote server in a nicer
                    # way? If we have been invited by a remote server, we need
                    # to get them to sign the event.
                    returned_invite = yield federation_handler.send_invite(
                        invitee.domain,
                        event,
                    )

                    # TODO: Make sure the signatures actually are correct.
                    event.signatures.update(
                        returned_invite.signatures
                    )

        destinations = set(extra_destinations)
        for k, s in context.current_state.items():
            try:
                if k[0] == EventTypes.Member:
                    if s.content["membership"] == Membership.JOIN:
                        destinations.add(
                            UserID.from_string(s.state_key).domain
                        )
            except SynapseError:
                logger.warn(
                    "Failed to get destination from event %s", s.event_id
                )

        # Don't block waiting on waking up all the listeners.
        d = self.notifier.on_new_room_event(event, extra_users=extra_users)

        def log_failure(f):
            logger.warn(
                "Failed to notify about %s: %s",
                event.event_id, f.value
            )

        d.addErrback(log_failure)

        yield federation_handler.handle_new_event(
            event, destinations=destinations,
        )
Exemple #18
0
 def appservice_register(self, user_localpart, as_token):
     user = UserID(user_localpart, self.hs.hostname)
     user_id = user.to_string()
     service = yield self.store.get_app_service_by_token(as_token)
     if not service:
         raise AuthError(403, "Invalid application service token.")
     if not service.is_interested_in_user(user_id):
         raise SynapseError(400, "Invalid user localpart for this application service.", errcode=Codes.EXCLUSIVE)
     token = self.generate_token(user_id)
     yield self.store.register(user_id=user_id, token=token, password_hash="")
     self.distributor.fire("registered_user", user)
     defer.returnValue((user_id, token))
Exemple #19
0
    def check_username(self, localpart, guest_access_token=None,
                       assigned_user_id=None):
        if types.contains_invalid_mxid_characters(localpart):
            raise SynapseError(
                400,
                "User ID can only contain characters a-z, 0-9, or '=_-./'",
                Codes.INVALID_USERNAME
            )

        if not localpart:
            raise SynapseError(
                400,
                "User ID cannot be empty",
                Codes.INVALID_USERNAME
            )

        if localpart[0] == '_':
            raise SynapseError(
                400,
                "User ID may not begin with _",
                Codes.INVALID_USERNAME
            )

        user = UserID(localpart, self.hs.hostname)
        user_id = user.to_string()

        if assigned_user_id:
            if user_id == assigned_user_id:
                return
            else:
                raise SynapseError(
                    400,
                    "A different user ID has already been registered for this session",
                )

        self.check_user_id_not_appservice_exclusive(user_id)

        users = yield self.store.get_users_by_id_case_insensitive(user_id)
        if users:
            if not guest_access_token:
                raise SynapseError(
                    400,
                    "User ID already taken.",
                    errcode=Codes.USER_IN_USE,
                )
            user_data = yield self.auth.get_user_by_access_token(guest_access_token)
            if not user_data["is_guest"] or user_data["user"].localpart != localpart:
                raise AuthError(
                    403,
                    "Cannot register taken user ID without valid guest "
                    "credentials for that user.",
                    errcode=Codes.FORBIDDEN,
                )
Exemple #20
0
    def get_or_create_user(self, localpart, displayname, duration_seconds):
        """Creates a new user if the user does not exist,
        else revokes all previous access tokens and generates a new one.

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

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

        need_register = True

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

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

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

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

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

        defer.returnValue((user_id, token))
Exemple #21
0
    def setUp(self):
        self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)

        hs = yield setup_test_homeserver(
            datastore=Mock(spec=[
                "has_presence_state",
                "get_presence_state",
                "allow_presence_visible",
                "is_presence_visible",
                "add_presence_list_pending",
                "set_presence_list_accepted",
                "del_presence_list",
                "get_presence_list",
                "insert_client_ip",
            ]),
            http_client=None,
            resource_for_client=self.mock_resource,
            resource_for_federation=self.mock_resource,
        )
        hs.handlers = JustPresenceHandlers(hs)

        self.datastore = hs.get_datastore()
        self.datastore.get_app_service_by_token = Mock(return_value=None)

        def has_presence_state(user_localpart):
            return defer.succeed(
                user_localpart in ("apple", "banana",)
            )
        self.datastore.has_presence_state = has_presence_state

        def _get_user_by_token(token=None):
            return {
                "user": UserID.from_string(myid),
                "admin": False,
                "device_id": None,
                "token_id": 1,
            }

        hs.handlers.room_member_handler = Mock(
            spec=[
                "get_joined_rooms_for_user",
            ]
        )

        hs.get_v1auth().get_user_by_token = _get_user_by_token

        presence.register_servlets(hs, self.mock_resource)

        self.u_apple = UserID.from_string("@apple:test")
        self.u_banana = UserID.from_string("@banana:test")
Exemple #22
0
    def get_or_create_user(self, requester, localpart, displayname,
                           password_hash=None):
        """Creates a new user if the user does not exist,
        else revokes all previous access tokens and generates a new one.

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

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

        need_register = True

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

        user = UserID(localpart, self.hs.hostname)
        user_id = user.to_string()
        token = self.macaroon_gen.generate_access_token(user_id)

        if need_register:
            yield self.store.register(
                user_id=user_id,
                token=token,
                password_hash=password_hash,
                create_profile_with_localpart=user.localpart,
            )
        else:
            yield self._auth_handler.delete_access_tokens_for_user(user_id)
            yield self.store.add_access_token_to_user(user_id=user_id, token=token)

        if displayname is not None:
            logger.info("setting user display name: %s -> %s", user_id, displayname)
            yield self.profile_handler.set_displayname(
                user, requester, displayname, by_admin=True,
            )

        defer.returnValue((user_id, token))
Exemple #23
0
    def check_username(self, localpart):
        yield run_on_reactor()

        if urllib.quote(localpart) != localpart:
            raise SynapseError(400, "User ID must only contain characters which do not" " require URL encoding.")

        user = UserID(localpart, self.hs.hostname)
        user_id = user.to_string()

        yield self.check_user_id_is_valid(user_id)

        users = yield self.store.get_users_by_id_case_insensitive(user_id)
        if users:
            raise SynapseError(400, "User ID already taken.", errcode=Codes.USER_IN_USE)
Exemple #24
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
        )
Exemple #25
0
    def on_POST(self, request, target_user_id):
        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")

        # FIXME: Theoretically there is a race here wherein user resets password
        # using threepid.
        yield self.store.user_delete_access_tokens(target_user_id)
        yield self.store.user_delete_threepids(target_user_id)
        yield self.store.user_set_password_hash(target_user_id, None)

        defer.returnValue((200, {}))
Exemple #26
0
    def _recv_edu(self, origin, content):
        room_id = content["room_id"]
        user_id = content["user_id"]

        # Check that the string is a valid user id
        UserID.from_string(user_id)

        domains = yield self.store.get_joined_hosts_for_room(room_id)

        if self.server_name in domains:
            self._push_update_local(
                room_id=room_id,
                user_id=user_id,
                typing=content["typing"]
            )
Exemple #27
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
Exemple #28
0
    def test_invited_remote_nonexistant(self):
        # Use a different destination, otherwise retry logic might fail the
        # request
        u_rocket = UserID.from_string("@rocket:sun")

        put_json = self.mock_http_client.put_json
        put_json.expect_call_and_return(
            call("sun",
                path="/_matrix/federation/v1/send/1000000/",
                data=_expect_edu("sun", "m.presence_deny",
                    content={
                        "observer_user": "******",
                        "observed_user": "******",
                    }
                ),
                json_data_callback=ANY,
                long_retries=True,
            ),
            defer.succeed((200, "OK"))
        )

        yield self.mock_federation_resource.trigger("PUT",
            "/_matrix/federation/v1/send/1000000/",
            _make_edu_json("sun", "m.presence_invite",
                content={
                    "observer_user": "******",
                    "observed_user": "******",
                }
            )
        )

        yield put_json.await_calls()
Exemple #29
0
    def test_invite_remote(self):
        # Use a different destination, otherwise retry logic might fail the
        # request
        u_rocket = UserID.from_string("@rocket:there")

        put_json = self.mock_http_client.put_json
        put_json.expect_call_and_return(
            call("there",
                path="/_matrix/federation/v1/send/1000000/",
                data=_expect_edu("there", "m.presence_invite",
                    content={
                        "observer_user": "******",
                        "observed_user": "******",
                    }
                ),
                json_data_callback=ANY,
                long_retries=True,
            ),
            defer.succeed((200, "OK"))
        )

        yield self.handler.send_presence_invite(
                observer_user=self.u_apple, observed_user=u_rocket)

        self.assertEquals(
            [{"observed_user_id": "@rocket:there", "accepted": 0}],
            (yield self.datastore.get_presence_list(self.u_apple.localpart))
        )

        yield put_json.await_calls()
Exemple #30
0
 def _get_user_by_token(token=None):
     return {
         "user": UserID.from_string(self.auth_user_id),
         "admin": False,
         "device_id": None,
         "token_id": 1,
     }
class RoomTypingTestCase(RestTestCase):
    """ Tests /rooms/$room_id/typing/$user_id REST API. """
    user_id = "@sid:red"

    user = UserID.from_string(user_id)

    @defer.inlineCallbacks
    def setUp(self):
        self.clock = MockClock()

        self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
        self.auth_user_id = self.user_id

        hs = yield setup_test_homeserver(
            "red",
            clock=self.clock,
            http_client=None,
            replication_layer=Mock(),
            ratelimiter=NonCallableMock(spec_set=[
                "send_message",
            ]),
        )
        self.hs = hs

        self.event_source = hs.get_event_sources().sources["typing"]

        self.ratelimiter = hs.get_ratelimiter()
        self.ratelimiter.send_message.return_value = (True, 0)

        hs.get_handlers().federation_handler = Mock()

        def get_user_by_access_token(token=None, allow_guest=False):
            return {
                "user": UserID.from_string(self.auth_user_id),
                "token_id": 1,
                "is_guest": False,
            }

        hs.get_v1auth().get_user_by_access_token = get_user_by_access_token

        def _insert_client_ip(*args, **kwargs):
            return defer.succeed(None)

        hs.get_datastore().insert_client_ip = _insert_client_ip

        def get_room_members(room_id):
            if room_id == self.room_id:
                return defer.succeed([self.user])
            else:
                return defer.succeed([])

        @defer.inlineCallbacks
        def fetch_room_distributions_into(room_id,
                                          localusers=None,
                                          remotedomains=None,
                                          ignore_user=None):
            members = yield get_room_members(room_id)
            for member in members:
                if ignore_user is not None and member == ignore_user:
                    continue

                if hs.is_mine(member):
                    if localusers is not None:
                        localusers.add(member)
                else:
                    if remotedomains is not None:
                        remotedomains.add(member.domain)

        hs.get_handlers().room_member_handler.fetch_room_distributions_into = (
            fetch_room_distributions_into)

        synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)

        self.room_id = yield self.create_room_as(self.user_id)
        # Need another user to make notifications actually work
        yield self.join(self.room_id, user="******")

    @defer.inlineCallbacks
    def test_set_typing(self):
        (code, _) = yield self.mock_resource.trigger(
            "PUT", "/rooms/%s/typing/%s" % (self.room_id, self.user_id),
            '{"typing": true, "timeout": 30000}')
        self.assertEquals(200, code)

        self.assertEquals(self.event_source.get_current_key(), 1)
        events = yield self.event_source.get_new_events(
            from_key=0,
            room_ids=[self.room_id],
        )
        self.assertEquals(events[0], [{
            "type": "m.typing",
            "room_id": self.room_id,
            "content": {
                "user_ids": [self.user_id],
            }
        }])

    @defer.inlineCallbacks
    def test_set_not_typing(self):
        (code, _) = yield self.mock_resource.trigger(
            "PUT", "/rooms/%s/typing/%s" % (self.room_id, self.user_id),
            '{"typing": false}')
        self.assertEquals(200, code)

    @defer.inlineCallbacks
    def test_typing_timeout(self):
        (code, _) = yield self.mock_resource.trigger(
            "PUT", "/rooms/%s/typing/%s" % (self.room_id, self.user_id),
            '{"typing": true, "timeout": 30000}')
        self.assertEquals(200, code)

        self.assertEquals(self.event_source.get_current_key(), 1)

        self.clock.advance_time(36)

        self.assertEquals(self.event_source.get_current_key(), 2)

        (code, _) = yield self.mock_resource.trigger(
            "PUT", "/rooms/%s/typing/%s" % (self.room_id, self.user_id),
            '{"typing": true, "timeout": 30000}')
        self.assertEquals(200, code)

        self.assertEquals(self.event_source.get_current_key(), 3)
Exemple #32
0
    async def create_group(
        self, group_id: str, requester_user_id: str, content: JsonDict
    ) -> JsonDict:
        logger.info("Attempting to create group with ID: %r", group_id)

        # parsing the id into a GroupID validates it.
        group_id_obj = GroupID.from_string(group_id)

        group = await self.check_group_is_ours(group_id, requester_user_id)
        if group:
            raise SynapseError(400, "Group already exists")

        is_admin = await self.auth.is_server_admin(
            UserID.from_string(requester_user_id)
        )
        if not is_admin:
            if not self.hs.config.groups.enable_group_creation:
                raise SynapseError(
                    403, "Only a server admin can create groups on this server"
                )
            localpart = group_id_obj.localpart
            if not localpart.startswith(self.hs.config.groups.group_creation_prefix):
                raise SynapseError(
                    400,
                    "Can only create groups with prefix %r on this server"
                    % (self.hs.config.groups.group_creation_prefix,),
                )

        profile = content.get("profile", {})
        name = profile.get("name")
        avatar_url = profile.get("avatar_url")
        short_description = profile.get("short_description")
        long_description = profile.get("long_description")
        user_profile = content.get("user_profile", {})

        await self.store.create_group(
            group_id,
            requester_user_id,
            name=name,
            avatar_url=avatar_url,
            short_description=short_description,
            long_description=long_description,
        )

        if not self.hs.is_mine_id(requester_user_id):
            remote_attestation = content["attestation"]

            await self.attestations.verify_attestation(
                remote_attestation, user_id=requester_user_id, group_id=group_id
            )

            local_attestation: Optional[
                JsonDict
            ] = self.attestations.create_attestation(group_id, requester_user_id)
        else:
            local_attestation = None
            remote_attestation = None

        await self.store.add_user_to_group(
            group_id,
            requester_user_id,
            is_admin=True,
            is_public=True,  # TODO
            local_attestation=local_attestation,
            remote_attestation=remote_attestation,
        )

        if not self.hs.is_mine_id(requester_user_id):
            await self.store.add_remote_profile_cache(
                requester_user_id,
                displayname=user_profile.get("displayname"),
                avatar_url=user_profile.get("avatar_url"),
            )

        return {"group_id": group_id}
Exemple #33
0
    async def delete_group(self, group_id: str, requester_user_id: str) -> None:
        """Deletes a group, kicking out all current members.

        Only group admins or server admins can call this request

        Args:
            group_id: The group ID to delete.
            requester_user_id: The user requesting to delete the group.
        """

        await self.check_group_is_ours(group_id, requester_user_id, and_exists=True)

        # Only server admins or group admins can delete groups.

        is_admin = await self.store.is_user_admin_in_group(group_id, requester_user_id)

        if not is_admin:
            is_admin = await self.auth.is_server_admin(
                UserID.from_string(requester_user_id)
            )

        if not is_admin:
            raise SynapseError(403, "User is not an admin")

        # Before deleting the group lets kick everyone out of it
        users = await self.store.get_users_in_group(group_id, include_private=True)

        async def _kick_user_from_group(user_id):
            if self.hs.is_mine_id(user_id):
                groups_local = self.hs.get_groups_local_handler()
                assert isinstance(
                    groups_local, GroupsLocalHandler
                ), "Workers cannot kick users from groups."
                await groups_local.user_removed_from_group(group_id, user_id, {})
            else:
                await self.transport_client.remove_user_from_group_notification(
                    get_domain_from_id(user_id), group_id, user_id, {}
                )
                await self.store.maybe_delete_remote_profile_cache(user_id)

        # We kick users out in the order of:
        #   1. Non-admins
        #   2. Other admins
        #   3. The requester
        #
        # This is so that if the deletion fails for some reason other admins or
        # the requester still has auth to retry.
        non_admins = []
        admins = []
        for u in users:
            if u["user_id"] == requester_user_id:
                continue
            if u["is_admin"]:
                admins.append(u["user_id"])
            else:
                non_admins.append(u["user_id"])

        await concurrently_execute(_kick_user_from_group, non_admins, 10)
        await concurrently_execute(_kick_user_from_group, admins, 10)
        await _kick_user_from_group(requester_user_id)

        await self.store.delete_group(group_id)
 def get_user_by_access_token(token=None, allow_guest=False):
     return {
         "user": UserID.from_string(self.auth_user_id),
         "token_id": 1,
         "is_guest": False,
     }