Option to allow server admins to join complex rooms (#7902)
Fixes #7901. Signed-off-by: Niklas Tittjung <nik_t.01@web.de>
This commit is contained in:
parent
349119a340
commit
3857de2194
|
@ -0,0 +1 @@
|
||||||
|
Add option to allow server admins to join rooms which fail complexity checks. Contributed by @lugino-emeritus.
|
|
@ -314,6 +314,10 @@ limit_remote_rooms:
|
||||||
#
|
#
|
||||||
#complexity_error: "This room is too complex."
|
#complexity_error: "This room is too complex."
|
||||||
|
|
||||||
|
# allow server admins to join complex rooms. Default is false.
|
||||||
|
#
|
||||||
|
#admins_can_join: true
|
||||||
|
|
||||||
# Whether to require a user to be in the room to add an alias to it.
|
# Whether to require a user to be in the room to add an alias to it.
|
||||||
# Defaults to 'true'.
|
# Defaults to 'true'.
|
||||||
#
|
#
|
||||||
|
|
|
@ -439,6 +439,9 @@ class ServerConfig(Config):
|
||||||
validator=attr.validators.instance_of(str),
|
validator=attr.validators.instance_of(str),
|
||||||
default=ROOM_COMPLEXITY_TOO_GREAT,
|
default=ROOM_COMPLEXITY_TOO_GREAT,
|
||||||
)
|
)
|
||||||
|
admins_can_join = attr.ib(
|
||||||
|
validator=attr.validators.instance_of(bool), default=False
|
||||||
|
)
|
||||||
|
|
||||||
self.limit_remote_rooms = LimitRemoteRoomsConfig(
|
self.limit_remote_rooms = LimitRemoteRoomsConfig(
|
||||||
**(config.get("limit_remote_rooms") or {})
|
**(config.get("limit_remote_rooms") or {})
|
||||||
|
@ -893,6 +896,10 @@ class ServerConfig(Config):
|
||||||
#
|
#
|
||||||
#complexity_error: "This room is too complex."
|
#complexity_error: "This room is too complex."
|
||||||
|
|
||||||
|
# allow server admins to join complex rooms. Default is false.
|
||||||
|
#
|
||||||
|
#admins_can_join: true
|
||||||
|
|
||||||
# Whether to require a user to be in the room to add an alias to it.
|
# Whether to require a user to be in the room to add an alias to it.
|
||||||
# Defaults to 'true'.
|
# Defaults to 'true'.
|
||||||
#
|
#
|
||||||
|
|
|
@ -952,7 +952,11 @@ class RoomMemberMasterHandler(RoomMemberHandler):
|
||||||
if len(remote_room_hosts) == 0:
|
if len(remote_room_hosts) == 0:
|
||||||
raise SynapseError(404, "No known servers")
|
raise SynapseError(404, "No known servers")
|
||||||
|
|
||||||
if self.hs.config.limit_remote_rooms.enabled:
|
check_complexity = self.hs.config.limit_remote_rooms.enabled
|
||||||
|
if check_complexity and self.hs.config.limit_remote_rooms.admins_can_join:
|
||||||
|
check_complexity = not await self.hs.auth.is_server_admin(user)
|
||||||
|
|
||||||
|
if check_complexity:
|
||||||
# Fetch the room complexity
|
# Fetch the room complexity
|
||||||
too_complex = await self._is_remote_room_too_complex(
|
too_complex = await self._is_remote_room_too_complex(
|
||||||
room_id, remote_room_hosts
|
room_id, remote_room_hosts
|
||||||
|
@ -975,7 +979,7 @@ class RoomMemberMasterHandler(RoomMemberHandler):
|
||||||
|
|
||||||
# Check the room we just joined wasn't too large, if we didn't fetch the
|
# Check the room we just joined wasn't too large, if we didn't fetch the
|
||||||
# complexity of it before.
|
# complexity of it before.
|
||||||
if self.hs.config.limit_remote_rooms.enabled:
|
if check_complexity:
|
||||||
if too_complex is False:
|
if too_complex is False:
|
||||||
# We checked, and we're under the limit.
|
# We checked, and we're under the limit.
|
||||||
return event_id, stream_id
|
return event_id, stream_id
|
||||||
|
|
|
@ -99,6 +99,37 @@ class RoomComplexityTests(unittest.FederatingHomeserverTestCase):
|
||||||
self.assertEqual(f.value.code, 400, f.value)
|
self.assertEqual(f.value.code, 400, f.value)
|
||||||
self.assertEqual(f.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
|
self.assertEqual(f.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
|
||||||
|
|
||||||
|
def test_join_too_large_admin(self):
|
||||||
|
# Check whether an admin can join if option "admins_can_join" is undefined,
|
||||||
|
# this option defaults to false, so the join should fail.
|
||||||
|
|
||||||
|
u1 = self.register_user("u1", "pass", admin=True)
|
||||||
|
|
||||||
|
handler = self.hs.get_room_member_handler()
|
||||||
|
fed_transport = self.hs.get_federation_transport_client()
|
||||||
|
|
||||||
|
# Mock out some things, because we don't want to test the whole join
|
||||||
|
fed_transport.client.get_json = Mock(return_value=defer.succeed({"v1": 9999}))
|
||||||
|
handler.federation_handler.do_invite_join = Mock(
|
||||||
|
return_value=defer.succeed(("", 1))
|
||||||
|
)
|
||||||
|
|
||||||
|
d = handler._remote_join(
|
||||||
|
None,
|
||||||
|
["other.example.com"],
|
||||||
|
"roomid",
|
||||||
|
UserID.from_string(u1),
|
||||||
|
{"membership": "join"},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.pump()
|
||||||
|
|
||||||
|
# The request failed with a SynapseError saying the resource limit was
|
||||||
|
# exceeded.
|
||||||
|
f = self.get_failure(d, SynapseError)
|
||||||
|
self.assertEqual(f.value.code, 400, f.value)
|
||||||
|
self.assertEqual(f.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
|
||||||
|
|
||||||
def test_join_too_large_once_joined(self):
|
def test_join_too_large_once_joined(self):
|
||||||
|
|
||||||
u1 = self.register_user("u1", "pass")
|
u1 = self.register_user("u1", "pass")
|
||||||
|
@ -141,3 +172,81 @@ class RoomComplexityTests(unittest.FederatingHomeserverTestCase):
|
||||||
f = self.get_failure(d, SynapseError)
|
f = self.get_failure(d, SynapseError)
|
||||||
self.assertEqual(f.value.code, 400)
|
self.assertEqual(f.value.code, 400)
|
||||||
self.assertEqual(f.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
|
self.assertEqual(f.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
|
||||||
|
|
||||||
|
|
||||||
|
class RoomComplexityAdminTests(unittest.FederatingHomeserverTestCase):
|
||||||
|
# Test the behavior of joining rooms which exceed the complexity if option
|
||||||
|
# limit_remote_rooms.admins_can_join is True.
|
||||||
|
|
||||||
|
servlets = [
|
||||||
|
admin.register_servlets,
|
||||||
|
room.register_servlets,
|
||||||
|
login.register_servlets,
|
||||||
|
]
|
||||||
|
|
||||||
|
def default_config(self):
|
||||||
|
config = super().default_config()
|
||||||
|
config["limit_remote_rooms"] = {
|
||||||
|
"enabled": True,
|
||||||
|
"complexity": 0.05,
|
||||||
|
"admins_can_join": True,
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
|
||||||
|
def test_join_too_large_no_admin(self):
|
||||||
|
# A user which is not an admin should not be able to join a remote room
|
||||||
|
# which is too complex.
|
||||||
|
|
||||||
|
u1 = self.register_user("u1", "pass")
|
||||||
|
|
||||||
|
handler = self.hs.get_room_member_handler()
|
||||||
|
fed_transport = self.hs.get_federation_transport_client()
|
||||||
|
|
||||||
|
# Mock out some things, because we don't want to test the whole join
|
||||||
|
fed_transport.client.get_json = Mock(return_value=defer.succeed({"v1": 9999}))
|
||||||
|
handler.federation_handler.do_invite_join = Mock(
|
||||||
|
return_value=defer.succeed(("", 1))
|
||||||
|
)
|
||||||
|
|
||||||
|
d = handler._remote_join(
|
||||||
|
None,
|
||||||
|
["other.example.com"],
|
||||||
|
"roomid",
|
||||||
|
UserID.from_string(u1),
|
||||||
|
{"membership": "join"},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.pump()
|
||||||
|
|
||||||
|
# The request failed with a SynapseError saying the resource limit was
|
||||||
|
# exceeded.
|
||||||
|
f = self.get_failure(d, SynapseError)
|
||||||
|
self.assertEqual(f.value.code, 400, f.value)
|
||||||
|
self.assertEqual(f.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
|
||||||
|
|
||||||
|
def test_join_too_large_admin(self):
|
||||||
|
# An admin should be able to join rooms where a complexity check fails.
|
||||||
|
|
||||||
|
u1 = self.register_user("u1", "pass", admin=True)
|
||||||
|
|
||||||
|
handler = self.hs.get_room_member_handler()
|
||||||
|
fed_transport = self.hs.get_federation_transport_client()
|
||||||
|
|
||||||
|
# Mock out some things, because we don't want to test the whole join
|
||||||
|
fed_transport.client.get_json = Mock(return_value=defer.succeed({"v1": 9999}))
|
||||||
|
handler.federation_handler.do_invite_join = Mock(
|
||||||
|
return_value=defer.succeed(("", 1))
|
||||||
|
)
|
||||||
|
|
||||||
|
d = handler._remote_join(
|
||||||
|
None,
|
||||||
|
["other.example.com"],
|
||||||
|
"roomid",
|
||||||
|
UserID.from_string(u1),
|
||||||
|
{"membership": "join"},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.pump()
|
||||||
|
|
||||||
|
# The request success since the user is an admin
|
||||||
|
self.get_success(d)
|
||||||
|
|
Loading…
Reference in New Issue