def _check_namespaces( self, namespaces: Optional[JsonDict]) -> Dict[str, List[Namespace]]: # Sanity check that it is of the form: # { # users: [ {regex: "[A-z]+.*", exclusive: true}, ...], # aliases: [ {regex: "[A-z]+.*", exclusive: true}, ...], # rooms: [ {regex: "[A-z]+.*", exclusive: true}, ...], # } if namespaces is None: namespaces = {} result: Dict[str, List[Namespace]] = {} for ns in ApplicationService.NS_LIST: result[ns] = [] if ns not in namespaces: continue if not isinstance(namespaces[ns], list): raise ValueError("Bad namespace value for '%s'" % ns) for regex_obj in namespaces[ns]: if not isinstance(regex_obj, dict): raise ValueError("Expected dict regex for ns '%s'" % ns) exclusive = regex_obj.get("exclusive") if not isinstance(exclusive, bool): raise ValueError( "Expected bool for 'exclusive' in ns '%s'" % ns) group_id = regex_obj.get("group_id") if group_id: if not isinstance(group_id, str): raise ValueError( "Expected string for 'group_id' in ns '%s'" % ns) try: GroupID.from_string(group_id) except Exception: raise ValueError( "Expected valid group ID for 'group_id' in ns '%s'" % ns) if get_domain_from_id(group_id) != self.server_name: raise ValueError( "Expected 'group_id' to be this host in ns '%s'" % ns) regex = regex_obj.get("regex") if not isinstance(regex, str): raise ValueError("Expected string for 'regex' in ns '%s'" % ns) # Pre-compile regex. result[ns].append( Namespace(exclusive, group_id, re.compile(regex))) return result
def test_validate(self): bad_ids = ["$badsigil:domain", "+:empty" ] + ["+group" + c + ":domain" for c in "A%?æ£"] for id_string in bad_ids: try: GroupID.from_string(id_string) self.fail("Parsing '%s' should raise exception" % id_string) except SynapseError as exc: self.assertEqual(400, exc.code) self.assertEqual("M_INVALID_PARAM", exc.errcode)
def test_validate(self): bad_ids = ["$badsigil:domain", "+:empty"] + [ "+group" + c + ":domain" for c in "A%?æ£" ] for id_string in bad_ids: try: GroupID.from_string(id_string) self.fail("Parsing '%s' should raise exception" % id_string) except SynapseError as exc: self.assertEqual(400, exc.code) self.assertEqual("M_UNKNOWN", exc.errcode)
def _check_namespaces(self, namespaces): # Sanity check that it is of the form: # { # users: [ {regex: "[A-z]+.*", exclusive: true}, ...], # aliases: [ {regex: "[A-z]+.*", exclusive: true}, ...], # rooms: [ {regex: "[A-z]+.*", exclusive: true}, ...], # } if not namespaces: namespaces = {} for ns in ApplicationService.NS_LIST: if ns not in namespaces: namespaces[ns] = [] continue if type(namespaces[ns]) != list: raise ValueError("Bad namespace value for '%s'" % ns) for regex_obj in namespaces[ns]: if not isinstance(regex_obj, dict): raise ValueError("Expected dict regex for ns '%s'" % ns) if not isinstance(regex_obj.get("exclusive"), bool): raise ValueError( "Expected bool for 'exclusive' in ns '%s'" % ns ) group_id = regex_obj.get("group_id") if group_id: if not isinstance(group_id, str): raise ValueError( "Expected string for 'group_id' in ns '%s'" % ns ) try: GroupID.from_string(group_id) except Exception: raise ValueError( "Expected valid group ID for 'group_id' in ns '%s'" % ns ) if get_domain_from_id(group_id) != self.server_name: raise ValueError( "Expected 'group_id' to be this host in ns '%s'" % ns ) regex = regex_obj.get("regex") if isinstance(regex, string_types): regex_obj["regex"] = re.compile(regex) # Pre-compile regex else: raise ValueError( "Expected string for 'regex' in ns '%s'" % ns ) return namespaces
def _validate_group_id(group_id): """Validates the group ID is valid for creation on this home server """ localpart = GroupID.from_string(group_id).localpart if localpart.lower() != localpart: raise SynapseError(400, "Group ID must be lower case") if urllib.quote(localpart.encode('utf-8')) != localpart: raise SynapseError( 400, "Group ID can only contain characters a-z, 0-9, or '_-./'", )
def create_group(self, group_id, requester_user_id, content): group = yield self.check_group_is_ours(group_id, requester_user_id) 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) if group: raise SynapseError(400, "Group already exists") is_admin = yield self.auth.is_server_admin(UserID.from_string(requester_user_id)) if not is_admin: if not self.hs.config.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.group_creation_prefix): raise SynapseError( 400, "Can only create groups with prefix %r on this server" % ( self.hs.config.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", {}) yield 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"] yield self.attestations.verify_attestation( remote_attestation, user_id=requester_user_id, group_id=group_id, ) local_attestation = self.attestations.create_attestation( group_id, requester_user_id, ) else: local_attestation = None remote_attestation = None yield 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): yield self.store.add_remote_profile_cache( requester_user_id, displayname=user_profile.get("displayname"), avatar_url=user_profile.get("avatar_url"), ) defer.returnValue({ "group_id": group_id, })
def test_parse(self): group_id = GroupID.from_string("+group/=_-.123:my.domain") self.assertEqual("group/=_-.123", group_id.localpart) self.assertEqual("my.domain", group_id.domain)
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.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.group_creation_prefix): raise SynapseError( 400, "Can only create groups with prefix %r on this server" % (self.hs.config.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 = self.attestations.create_attestation( group_id, requester_user_id ) # type: Optional[JsonDict] 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}
def create_group(self, group_id, user_id, content): group = yield self.check_group_is_ours(group_id) _validate_group_id(group_id) logger.info("Attempting to create group with ID: %r", group_id) if group: raise SynapseError(400, "Group already exists") is_admin = yield self.auth.is_server_admin(UserID.from_string(user_id)) if not is_admin: if not self.hs.config.enable_group_creation: raise SynapseError( 403, "Only server admin can create group on this server", ) localpart = GroupID.from_string(group_id).localpart if not localpart.startswith(self.hs.config.group_creation_prefix): raise SynapseError( 400, "Can only create groups with prefix %r on this server" % (self.hs.config.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", {}) yield self.store.create_group( group_id, user_id, name=name, avatar_url=avatar_url, short_description=short_description, long_description=long_description, ) if not self.hs.is_mine_id(user_id): remote_attestation = content["attestation"] yield self.attestations.verify_attestation( remote_attestation, user_id=user_id, group_id=group_id, ) local_attestation = self.attestations.create_attestation( group_id, user_id) else: local_attestation = None remote_attestation = None yield self.store.add_user_to_group( group_id, user_id, is_admin=True, is_public=True, # TODO local_attestation=local_attestation, remote_attestation=remote_attestation, ) if not self.hs.is_mine_id(user_id): yield self.store.add_remote_profile_cache( user_id, displayname=user_profile.get("displayname"), avatar_url=user_profile.get("avatar_url"), ) defer.returnValue({ "group_id": group_id, })