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")
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, }))
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()
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))
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)
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)
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))
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))
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)
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))
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)
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)
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, {}))
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, )
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, {}))
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))
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, )
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))
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, )
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))
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")
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))
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)
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 )
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, {}))
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"] )
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
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()
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()
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)
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}
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, }