Additional configuration options for auto-join rooms (#7763)

This commit is contained in:
Patrick Cloke 2020-06-30 15:41:36 -04:00 committed by GitHub
parent a99658074d
commit 71cccf1593
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 543 additions and 72 deletions

1
changelog.d/7763.feature Normal file
View File

@ -0,0 +1 @@
Expand the configuration options for auto-join rooms.

View File

@ -1210,7 +1210,11 @@ account_threepid_delegates:
#enable_3pid_changes: false #enable_3pid_changes: false
# Users who register on this homeserver will automatically be joined # Users who register on this homeserver will automatically be joined
# to these rooms # to these rooms.
#
# By default, any room aliases included in this list will be created
# as a publicly joinable room when the first user registers for the
# homeserver. This behaviour can be customised with the settings below.
# #
#auto_join_rooms: #auto_join_rooms:
# - "#example:example.com" # - "#example:example.com"
@ -1218,10 +1222,62 @@ account_threepid_delegates:
# Where auto_join_rooms are specified, setting this flag ensures that the # Where auto_join_rooms are specified, setting this flag ensures that the
# the rooms exist by creating them when the first user on the # the rooms exist by creating them when the first user on the
# homeserver registers. # homeserver registers.
#
# By default the auto-created rooms are publicly joinable from any federated
# server. Use the autocreate_auto_join_rooms_federated and
# autocreate_auto_join_room_preset settings below to customise this behaviour.
#
# Setting to false means that if the rooms are not manually created, # Setting to false means that if the rooms are not manually created,
# users cannot be auto-joined since they do not exist. # users cannot be auto-joined since they do not exist.
# #
#autocreate_auto_join_rooms: true # Defaults to true. Uncomment the following line to disable automatically
# creating auto-join rooms.
#
#autocreate_auto_join_rooms: false
# Whether the auto_join_rooms that are auto-created are available via
# federation. Only has an effect if autocreate_auto_join_rooms is true.
#
# Note that whether a room is federated cannot be modified after
# creation.
#
# Defaults to true: the room will be joinable from other servers.
# Uncomment the following to prevent users from other homeservers from
# joining these rooms.
#
#autocreate_auto_join_rooms_federated: false
# The room preset to use when auto-creating one of auto_join_rooms. Only has an
# effect if autocreate_auto_join_rooms is true.
#
# This can be one of "public_chat", "private_chat", or "trusted_private_chat".
# If a value of "private_chat" or "trusted_private_chat" is used then
# auto_join_mxid_localpart must also be configured.
#
# Defaults to "public_chat", meaning that the room is joinable by anyone, including
# federated servers if autocreate_auto_join_rooms_federated is true (the default).
# Uncomment the following to require an invitation to join these rooms.
#
#autocreate_auto_join_room_preset: private_chat
# The local part of the user id which is used to create auto_join_rooms if
# autocreate_auto_join_rooms is true. If this is not provided then the
# initial user account that registers will be used to create the rooms.
#
# The user id is also used to invite new users to any auto-join rooms which
# are set to invite-only.
#
# It *must* be configured if autocreate_auto_join_room_preset is set to
# "private_chat" or "trusted_private_chat".
#
# Note that this must be specified in order for new users to be correctly
# invited to any auto-join rooms which have been set to invite-only (either
# at the time of creation or subsequently).
#
# Note that, if the room already exists, this user must be joined and
# have the appropriate permissions to invite new members.
#
#auto_join_mxid_localpart: system
# When auto_join_rooms is specified, setting this flag to false prevents # When auto_join_rooms is specified, setting this flag to false prevents
# guest accounts from being automatically joined to the rooms. # guest accounts from being automatically joined to the rooms.

View File

@ -18,8 +18,9 @@ from distutils.util import strtobool
import pkg_resources import pkg_resources
from synapse.api.constants import RoomCreationPreset
from synapse.config._base import Config, ConfigError from synapse.config._base import Config, ConfigError
from synapse.types import RoomAlias from synapse.types import RoomAlias, UserID
from synapse.util.stringutils import random_string_with_symbols from synapse.util.stringutils import random_string_with_symbols
@ -127,7 +128,50 @@ class RegistrationConfig(Config):
for room_alias in self.auto_join_rooms: for room_alias in self.auto_join_rooms:
if not RoomAlias.is_valid(room_alias): if not RoomAlias.is_valid(room_alias):
raise ConfigError("Invalid auto_join_rooms entry %s" % (room_alias,)) raise ConfigError("Invalid auto_join_rooms entry %s" % (room_alias,))
# Options for creating auto-join rooms if they do not exist yet.
self.autocreate_auto_join_rooms = config.get("autocreate_auto_join_rooms", True) self.autocreate_auto_join_rooms = config.get("autocreate_auto_join_rooms", True)
self.autocreate_auto_join_rooms_federated = config.get(
"autocreate_auto_join_rooms_federated", True
)
self.autocreate_auto_join_room_preset = (
config.get("autocreate_auto_join_room_preset")
or RoomCreationPreset.PUBLIC_CHAT
)
self.auto_join_room_requires_invite = self.autocreate_auto_join_room_preset in {
RoomCreationPreset.PRIVATE_CHAT,
RoomCreationPreset.TRUSTED_PRIVATE_CHAT,
}
# Pull the creater/inviter from the configuration, this gets used to
# send invites for invite-only rooms.
mxid_localpart = config.get("auto_join_mxid_localpart")
self.auto_join_user_id = None
if mxid_localpart:
# Convert the localpart to a full mxid.
self.auto_join_user_id = UserID(
mxid_localpart, self.server_name
).to_string()
if self.autocreate_auto_join_rooms:
# Ensure the preset is a known value.
if self.autocreate_auto_join_room_preset not in {
RoomCreationPreset.PUBLIC_CHAT,
RoomCreationPreset.PRIVATE_CHAT,
RoomCreationPreset.TRUSTED_PRIVATE_CHAT,
}:
raise ConfigError("Invalid value for autocreate_auto_join_room_preset")
# If the preset requires invitations to be sent, ensure there's a
# configured user to send them from.
if self.auto_join_room_requires_invite:
if not mxid_localpart:
raise ConfigError(
"The configuration option `auto_join_mxid_localpart` is required if "
"`autocreate_auto_join_room_preset` is set to private_chat or trusted_private_chat, such that "
"Synapse knows who to send invitations from. Please "
"configure `auto_join_mxid_localpart`."
)
self.auto_join_rooms_for_guests = config.get("auto_join_rooms_for_guests", True) self.auto_join_rooms_for_guests = config.get("auto_join_rooms_for_guests", True)
self.enable_set_displayname = config.get("enable_set_displayname", True) self.enable_set_displayname = config.get("enable_set_displayname", True)
@ -357,7 +401,11 @@ class RegistrationConfig(Config):
#enable_3pid_changes: false #enable_3pid_changes: false
# Users who register on this homeserver will automatically be joined # Users who register on this homeserver will automatically be joined
# to these rooms # to these rooms.
#
# By default, any room aliases included in this list will be created
# as a publicly joinable room when the first user registers for the
# homeserver. This behaviour can be customised with the settings below.
# #
#auto_join_rooms: #auto_join_rooms:
# - "#example:example.com" # - "#example:example.com"
@ -365,10 +413,62 @@ class RegistrationConfig(Config):
# Where auto_join_rooms are specified, setting this flag ensures that the # Where auto_join_rooms are specified, setting this flag ensures that the
# the rooms exist by creating them when the first user on the # the rooms exist by creating them when the first user on the
# homeserver registers. # homeserver registers.
#
# By default the auto-created rooms are publicly joinable from any federated
# server. Use the autocreate_auto_join_rooms_federated and
# autocreate_auto_join_room_preset settings below to customise this behaviour.
#
# Setting to false means that if the rooms are not manually created, # Setting to false means that if the rooms are not manually created,
# users cannot be auto-joined since they do not exist. # users cannot be auto-joined since they do not exist.
# #
#autocreate_auto_join_rooms: true # Defaults to true. Uncomment the following line to disable automatically
# creating auto-join rooms.
#
#autocreate_auto_join_rooms: false
# Whether the auto_join_rooms that are auto-created are available via
# federation. Only has an effect if autocreate_auto_join_rooms is true.
#
# Note that whether a room is federated cannot be modified after
# creation.
#
# Defaults to true: the room will be joinable from other servers.
# Uncomment the following to prevent users from other homeservers from
# joining these rooms.
#
#autocreate_auto_join_rooms_federated: false
# The room preset to use when auto-creating one of auto_join_rooms. Only has an
# effect if autocreate_auto_join_rooms is true.
#
# This can be one of "public_chat", "private_chat", or "trusted_private_chat".
# If a value of "private_chat" or "trusted_private_chat" is used then
# auto_join_mxid_localpart must also be configured.
#
# Defaults to "public_chat", meaning that the room is joinable by anyone, including
# federated servers if autocreate_auto_join_rooms_federated is true (the default).
# Uncomment the following to require an invitation to join these rooms.
#
#autocreate_auto_join_room_preset: private_chat
# The local part of the user id which is used to create auto_join_rooms if
# autocreate_auto_join_rooms is true. If this is not provided then the
# initial user account that registers will be used to create the rooms.
#
# The user id is also used to invite new users to any auto-join rooms which
# are set to invite-only.
#
# It *must* be configured if autocreate_auto_join_room_preset is set to
# "private_chat" or "trusted_private_chat".
#
# Note that this must be specified in order for new users to be correctly
# invited to any auto-join rooms which have been set to invite-only (either
# at the time of creation or subsequently).
#
# Note that, if the room already exists, this user must be joined and
# have the appropriate permissions to invite new members.
#
#auto_join_mxid_localpart: system
# When auto_join_rooms is specified, setting this flag to false prevents # When auto_join_rooms is specified, setting this flag to false prevents
# guest accounts from being automatically joined to the rooms. # guest accounts from being automatically joined to the rooms.

View File

@ -17,7 +17,7 @@
import logging import logging
from synapse import types from synapse import types
from synapse.api.constants import MAX_USERID_LENGTH, LoginType from synapse.api.constants import MAX_USERID_LENGTH, EventTypes, JoinRules, LoginType
from synapse.api.errors import AuthError, Codes, ConsentNotGivenError, SynapseError from synapse.api.errors import AuthError, Codes, ConsentNotGivenError, SynapseError
from synapse.config.server import is_threepid_reserved from synapse.config.server import is_threepid_reserved
from synapse.http.servlet import assert_params_in_dict from synapse.http.servlet import assert_params_in_dict
@ -26,7 +26,8 @@ from synapse.replication.http.register import (
ReplicationPostRegisterActionsServlet, ReplicationPostRegisterActionsServlet,
ReplicationRegisterServlet, ReplicationRegisterServlet,
) )
from synapse.types import RoomAlias, RoomID, UserID, create_requester from synapse.storage.state import StateFilter
from synapse.types import RoomAlias, UserID, create_requester
from synapse.util.async_helpers import Linearizer from synapse.util.async_helpers import Linearizer
from ._base import BaseHandler from ._base import BaseHandler
@ -270,51 +271,83 @@ class RegistrationHandler(BaseHandler):
return user_id return user_id
async def _auto_join_rooms(self, user_id): async def _create_and_join_rooms(self, user_id: str):
"""Automatically joins users to auto join rooms - creating the room in the first place """
if the user is the first to be created. Create the auto-join rooms and join or invite the user to them.
This should only be called when the first "real" user registers.
Args: Args:
user_id(str): The user to join user_id: The user to join
""" """
# auto-join the user to any rooms we're supposed to dump them into # Getting the handlers during init gives a dependency loop.
fake_requester = create_requester(user_id) room_creation_handler = self.hs.get_room_creation_handler()
room_member_handler = self.hs.get_room_member_handler()
# try to create the room if we're the first real user on the server. Note # Generate a stub for how the rooms will be configured.
# that an auto-generated support or bot user is not a real user and will never be stub_config = {
# the user to create the room "preset": self.hs.config.registration.autocreate_auto_join_room_preset,
should_auto_create_rooms = False }
is_real_user = await self.store.is_real_user(user_id)
if self.hs.config.autocreate_auto_join_rooms and is_real_user: # If the configuration providers a user ID to create rooms with, use
count = await self.store.count_real_users() # that instead of the first user registered.
should_auto_create_rooms = count == 1 requires_join = False
for r in self.hs.config.auto_join_rooms: if self.hs.config.registration.auto_join_user_id:
fake_requester = create_requester(
self.hs.config.registration.auto_join_user_id
)
# If the room requires an invite, add the user to the list of invites.
if self.hs.config.registration.auto_join_room_requires_invite:
stub_config["invite"] = [user_id]
# If the room is being created by a different user, the first user
# registered needs to join it. Note that in the case of an invitation
# being necessary this will occur after the invite was sent.
requires_join = True
else:
fake_requester = create_requester(user_id)
# Choose whether to federate the new room.
if not self.hs.config.registration.autocreate_auto_join_rooms_federated:
stub_config["creation_content"] = {"m.federate": False}
for r in self.hs.config.registration.auto_join_rooms:
logger.info("Auto-joining %s to %s", user_id, r) logger.info("Auto-joining %s to %s", user_id, r)
try:
if should_auto_create_rooms:
room_alias = RoomAlias.from_string(r)
if self.hs.hostname != room_alias.domain:
logger.warning(
"Cannot create room alias %s, "
"it does not match server domain",
r,
)
else:
# create room expects the localpart of the room alias
room_alias_localpart = room_alias.localpart
# getting the RoomCreationHandler during init gives a dependency try:
# loop room_alias = RoomAlias.from_string(r)
await self.hs.get_room_creation_handler().create_room(
fake_requester, if self.hs.hostname != room_alias.domain:
config={ logger.warning(
"preset": "public_chat", "Cannot create room alias %s, "
"room_alias_name": room_alias_localpart, "it does not match server domain",
}, r,
)
else:
# A shallow copy is OK here since the only key that is
# modified is room_alias_name.
config = stub_config.copy()
# create room expects the localpart of the room alias
config["room_alias_name"] = room_alias.localpart
info, _ = await room_creation_handler.create_room(
fake_requester, config=config, ratelimit=False,
)
# If the room does not require an invite, but another user
# created it, then ensure the first user joins it.
if requires_join:
await room_member_handler.update_membership(
requester=create_requester(user_id),
target=UserID.from_string(user_id),
room_id=info["room_id"],
# Since it was just created, there are no remote hosts.
remote_room_hosts=[],
action="join",
ratelimit=False, ratelimit=False,
) )
else:
await self._join_user_to_room(fake_requester, r)
except ConsentNotGivenError as e: except ConsentNotGivenError as e:
# Technically not necessary to pull out this error though # Technically not necessary to pull out this error though
# moving away from bare excepts is a good thing to do. # moving away from bare excepts is a good thing to do.
@ -322,6 +355,103 @@ class RegistrationHandler(BaseHandler):
except Exception as e: except Exception as e:
logger.error("Failed to join new user to %r: %r", r, e) logger.error("Failed to join new user to %r: %r", r, e)
async def _join_rooms(self, user_id: str):
"""
Join or invite the user to the auto-join rooms.
Args:
user_id: The user to join
"""
room_member_handler = self.hs.get_room_member_handler()
for r in self.hs.config.registration.auto_join_rooms:
logger.info("Auto-joining %s to %s", user_id, r)
try:
room_alias = RoomAlias.from_string(r)
if RoomAlias.is_valid(r):
(
room_id,
remote_room_hosts,
) = await room_member_handler.lookup_room_alias(room_alias)
room_id = room_id.to_string()
else:
raise SynapseError(
400, "%s was not legal room ID or room alias" % (r,)
)
# Calculate whether the room requires an invite or can be
# joined directly. Note that unless a join rule of public exists,
# it is treated as requiring an invite.
requires_invite = True
state = await self.store.get_filtered_current_state_ids(
room_id, StateFilter.from_types([(EventTypes.JoinRules, "")])
)
event_id = state.get((EventTypes.JoinRules, ""))
if event_id:
join_rules_event = await self.store.get_event(
event_id, allow_none=True
)
if join_rules_event:
join_rule = join_rules_event.content.get("join_rule", None)
requires_invite = join_rule and join_rule != JoinRules.PUBLIC
# Send the invite, if necessary.
if requires_invite:
await room_member_handler.update_membership(
requester=create_requester(
self.hs.config.registration.auto_join_user_id
),
target=UserID.from_string(user_id),
room_id=room_id,
remote_room_hosts=remote_room_hosts,
action="invite",
ratelimit=False,
)
# Send the join.
await room_member_handler.update_membership(
requester=create_requester(user_id),
target=UserID.from_string(user_id),
room_id=room_id,
remote_room_hosts=remote_room_hosts,
action="join",
ratelimit=False,
)
except ConsentNotGivenError as e:
# Technically not necessary to pull out this error though
# moving away from bare excepts is a good thing to do.
logger.error("Failed to join new user to %r: %r", r, e)
except Exception as e:
logger.error("Failed to join new user to %r: %r", r, e)
async def _auto_join_rooms(self, user_id: str):
"""Automatically joins users to auto join rooms - creating the room in the first place
if the user is the first to be created.
Args:
user_id: The user to join
"""
# auto-join the user to any rooms we're supposed to dump them into
# try to create the room if we're the first real user on the server. Note
# that an auto-generated support or bot user is not a real user and will never be
# the user to create the room
should_auto_create_rooms = False
is_real_user = await self.store.is_real_user(user_id)
if self.hs.config.registration.autocreate_auto_join_rooms and is_real_user:
count = await self.store.count_real_users()
should_auto_create_rooms = count == 1
if should_auto_create_rooms:
await self._create_and_join_rooms(user_id)
else:
await self._join_rooms(user_id)
async def post_consent_actions(self, user_id): async def post_consent_actions(self, user_id):
"""A series of registration actions that can only be carried out once consent """A series of registration actions that can only be carried out once consent
has been granted has been granted
@ -392,30 +522,6 @@ class RegistrationHandler(BaseHandler):
self._next_generated_user_id += 1 self._next_generated_user_id += 1
return str(id) return str(id)
async def _join_user_to_room(self, requester, room_identifier):
room_member_handler = self.hs.get_room_member_handler()
if RoomID.is_valid(room_identifier):
room_id = room_identifier
elif RoomAlias.is_valid(room_identifier):
room_alias = RoomAlias.from_string(room_identifier)
room_id, remote_room_hosts = await room_member_handler.lookup_room_alias(
room_alias
)
room_id = room_id.to_string()
else:
raise SynapseError(
400, "%s was not legal room ID or room alias" % (room_identifier,)
)
await room_member_handler.update_membership(
requester=requester,
target=requester.user,
room_id=room_id,
remote_room_hosts=remote_room_hosts,
action="join",
ratelimit=False,
)
def check_registration_ratelimit(self, address): def check_registration_ratelimit(self, address):
"""A simple helper method to check whether the registration rate limit has been hit """A simple helper method to check whether the registration rate limit has been hit
for a given IP address for a given IP address

View File

@ -15,7 +15,7 @@
import logging import logging
from typing import List, Optional from typing import List, Optional
from synapse.api.constants import EventTypes, JoinRules, Membership from synapse.api.constants import EventTypes, JoinRules, Membership, RoomCreationPreset
from synapse.api.errors import Codes, NotFoundError, SynapseError from synapse.api.errors import Codes, NotFoundError, SynapseError
from synapse.http.servlet import ( from synapse.http.servlet import (
RestServlet, RestServlet,
@ -77,7 +77,7 @@ class ShutdownRoomRestServlet(RestServlet):
info, stream_id = await self._room_creation_handler.create_room( info, stream_id = await self._room_creation_handler.create_room(
room_creator_requester, room_creator_requester,
config={ config={
"preset": "public_chat", "preset": RoomCreationPreset.PUBLIC_CHAT,
"name": room_name, "name": room_name,
"power_level_content_override": {"users_default": -10}, "power_level_content_override": {"users_default": -10},
}, },

View File

@ -22,6 +22,8 @@ from synapse.api.errors import Codes, ResourceLimitError, SynapseError
from synapse.handlers.register import RegistrationHandler from synapse.handlers.register import RegistrationHandler
from synapse.types import RoomAlias, UserID, create_requester from synapse.types import RoomAlias, UserID, create_requester
from tests.unittest import override_config
from .. import unittest from .. import unittest
@ -145,9 +147,9 @@ class RegistrationTestCase(unittest.HomeserverTestCase):
rooms = self.get_success(self.store.get_rooms_for_user(user_id)) rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertEqual(len(rooms), 0) self.assertEqual(len(rooms), 0)
@override_config({"auto_join_rooms": ["#room:test"]})
def test_auto_create_auto_join_rooms(self): def test_auto_create_auto_join_rooms(self):
room_alias_str = "#room:test" room_alias_str = "#room:test"
self.hs.config.auto_join_rooms = [room_alias_str]
user_id = self.get_success(self.handler.register_user(localpart="jeff")) user_id = self.get_success(self.handler.register_user(localpart="jeff"))
rooms = self.get_success(self.store.get_rooms_for_user(user_id)) rooms = self.get_success(self.store.get_rooms_for_user(user_id))
directory_handler = self.hs.get_handlers().directory_handler directory_handler = self.hs.get_handlers().directory_handler
@ -193,9 +195,9 @@ class RegistrationTestCase(unittest.HomeserverTestCase):
room_alias = RoomAlias.from_string(room_alias_str) room_alias = RoomAlias.from_string(room_alias_str)
self.get_failure(directory_handler.get_association(room_alias), SynapseError) self.get_failure(directory_handler.get_association(room_alias), SynapseError)
@override_config({"auto_join_rooms": ["#room:test"]})
def test_auto_create_auto_join_rooms_when_user_is_the_first_real_user(self): def test_auto_create_auto_join_rooms_when_user_is_the_first_real_user(self):
room_alias_str = "#room:test" room_alias_str = "#room:test"
self.hs.config.auto_join_rooms = [room_alias_str]
self.store.count_real_users = Mock(return_value=defer.succeed(1)) self.store.count_real_users = Mock(return_value=defer.succeed(1))
self.store.is_real_user = Mock(return_value=defer.succeed(True)) self.store.is_real_user = Mock(return_value=defer.succeed(True))
@ -218,6 +220,212 @@ class RegistrationTestCase(unittest.HomeserverTestCase):
rooms = self.get_success(self.store.get_rooms_for_user(user_id)) rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertEqual(len(rooms), 0) self.assertEqual(len(rooms), 0)
@override_config(
{
"auto_join_rooms": ["#room:test"],
"autocreate_auto_join_rooms_federated": False,
}
)
def test_auto_create_auto_join_rooms_federated(self):
"""
Auto-created rooms that are private require an invite to go to the user
(instead of directly joining it).
"""
room_alias_str = "#room:test"
user_id = self.get_success(self.handler.register_user(localpart="jeff"))
# Ensure the room was created.
directory_handler = self.hs.get_handlers().directory_handler
room_alias = RoomAlias.from_string(room_alias_str)
room_id = self.get_success(directory_handler.get_association(room_alias))
# Ensure the room is properly not federated.
room = self.get_success(self.store.get_room_with_stats(room_id["room_id"]))
self.assertFalse(room["federatable"])
self.assertFalse(room["public"])
self.assertEqual(room["join_rules"], "public")
self.assertIsNone(room["guest_access"])
# The user should be in the room.
rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertIn(room_id["room_id"], rooms)
@override_config(
{"auto_join_rooms": ["#room:test"], "auto_join_mxid_localpart": "support"}
)
def test_auto_join_mxid_localpart(self):
"""
Ensure the user still needs up in the room created by a different user.
"""
# Ensure the support user exists.
inviter = "@support:test"
room_alias_str = "#room:test"
user_id = self.get_success(self.handler.register_user(localpart="jeff"))
# Ensure the room was created.
directory_handler = self.hs.get_handlers().directory_handler
room_alias = RoomAlias.from_string(room_alias_str)
room_id = self.get_success(directory_handler.get_association(room_alias))
# Ensure the room is properly a public room.
room = self.get_success(self.store.get_room_with_stats(room_id["room_id"]))
self.assertEqual(room["join_rules"], "public")
# Both users should be in the room.
rooms = self.get_success(self.store.get_rooms_for_user(inviter))
self.assertIn(room_id["room_id"], rooms)
rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertIn(room_id["room_id"], rooms)
# Register a second user, which should also end up in the room.
user_id = self.get_success(self.handler.register_user(localpart="bob"))
rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertIn(room_id["room_id"], rooms)
@override_config(
{
"auto_join_rooms": ["#room:test"],
"autocreate_auto_join_room_preset": "private_chat",
"auto_join_mxid_localpart": "support",
}
)
def test_auto_create_auto_join_room_preset(self):
"""
Auto-created rooms that are private require an invite to go to the user
(instead of directly joining it).
"""
# Ensure the support user exists.
inviter = "@support:test"
room_alias_str = "#room:test"
user_id = self.get_success(self.handler.register_user(localpart="jeff"))
# Ensure the room was created.
directory_handler = self.hs.get_handlers().directory_handler
room_alias = RoomAlias.from_string(room_alias_str)
room_id = self.get_success(directory_handler.get_association(room_alias))
# Ensure the room is properly a private room.
room = self.get_success(self.store.get_room_with_stats(room_id["room_id"]))
self.assertFalse(room["public"])
self.assertEqual(room["join_rules"], "invite")
self.assertEqual(room["guest_access"], "can_join")
# Both users should be in the room.
rooms = self.get_success(self.store.get_rooms_for_user(inviter))
self.assertIn(room_id["room_id"], rooms)
rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertIn(room_id["room_id"], rooms)
# Register a second user, which should also end up in the room.
user_id = self.get_success(self.handler.register_user(localpart="bob"))
rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertIn(room_id["room_id"], rooms)
@override_config(
{
"auto_join_rooms": ["#room:test"],
"autocreate_auto_join_room_preset": "private_chat",
"auto_join_mxid_localpart": "support",
}
)
def test_auto_create_auto_join_room_preset_guest(self):
"""
Auto-created rooms that are private require an invite to go to the user
(instead of directly joining it).
This should also work for guests.
"""
inviter = "@support:test"
room_alias_str = "#room:test"
user_id = self.get_success(
self.handler.register_user(localpart="jeff", make_guest=True)
)
# Ensure the room was created.
directory_handler = self.hs.get_handlers().directory_handler
room_alias = RoomAlias.from_string(room_alias_str)
room_id = self.get_success(directory_handler.get_association(room_alias))
# Ensure the room is properly a private room.
room = self.get_success(self.store.get_room_with_stats(room_id["room_id"]))
self.assertFalse(room["public"])
self.assertEqual(room["join_rules"], "invite")
self.assertEqual(room["guest_access"], "can_join")
# Both users should be in the room.
rooms = self.get_success(self.store.get_rooms_for_user(inviter))
self.assertIn(room_id["room_id"], rooms)
rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertIn(room_id["room_id"], rooms)
@override_config(
{
"auto_join_rooms": ["#room:test"],
"autocreate_auto_join_room_preset": "private_chat",
"auto_join_mxid_localpart": "support",
}
)
def test_auto_create_auto_join_room_preset_invalid_permissions(self):
"""
Auto-created rooms that are private require an invite, check that
registration doesn't completely break if the inviter doesn't have proper
permissions.
"""
inviter = "@support:test"
# Register an initial user to create the room and such (essentially this
# is a subset of test_auto_create_auto_join_room_preset).
room_alias_str = "#room:test"
user_id = self.get_success(self.handler.register_user(localpart="jeff"))
# Ensure the room was created.
directory_handler = self.hs.get_handlers().directory_handler
room_alias = RoomAlias.from_string(room_alias_str)
room_id = self.get_success(directory_handler.get_association(room_alias))
# Ensure the room exists.
self.get_success(self.store.get_room_with_stats(room_id["room_id"]))
# Both users should be in the room.
rooms = self.get_success(self.store.get_rooms_for_user(inviter))
self.assertIn(room_id["room_id"], rooms)
rooms = self.get_success(self.store.get_rooms_for_user(user_id))
self.assertIn(room_id["room_id"], rooms)
# Lower the permissions of the inviter.
event_creation_handler = self.hs.get_event_creation_handler()
requester = create_requester(inviter)
event, context = self.get_success(
event_creation_handler.create_event(
requester,
{
"type": "m.room.power_levels",
"state_key": "",
"room_id": room_id["room_id"],
"content": {"invite": 100, "users": {inviter: 0}},
"sender": inviter,
},
)
)
self.get_success(
event_creation_handler.send_nonmember_event(requester, event, context)
)
# Register a second user, which won't be be in the room (or even have an invite)
# since the inviter no longer has the proper permissions.
user_id = self.get_success(self.handler.register_user(localpart="bob"))
# This user should not be in any rooms.
rooms = self.get_success(self.store.get_rooms_for_user(user_id))
invited_rooms = self.get_success(
self.store.get_invited_rooms_for_local_user(user_id)
)
self.assertEqual(rooms, set())
self.assertEqual(invited_rooms, [])
def test_auto_create_auto_join_where_no_consent(self): def test_auto_create_auto_join_where_no_consent(self):
"""Test to ensure that the first user is not auto-joined to a room if """Test to ensure that the first user is not auto-joined to a room if
they have not given general consent. they have not given general consent.