diff --git a/tests/module_api/test_api.py b/tests/module_api/test_api.py
index 807cd65dd6..2d10931b33 100644
--- a/tests/module_api/test_api.py
+++ b/tests/module_api/test_api.py
@@ -12,13 +12,20 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
from synapse.module_api import ModuleApi
+from synapse.rest import admin
+from synapse.rest.client.v1 import login, room
from tests.unittest import HomeserverTestCase
class ModuleApiTestCase(HomeserverTestCase):
+ servlets = [
+ admin.register_servlets,
+ login.register_servlets,
+ room.register_servlets,
+ ]
+
def prepare(self, reactor, clock, homeserver):
self.store = homeserver.get_datastore()
self.module_api = ModuleApi(homeserver, homeserver.get_auth_handler())
@@ -52,3 +59,50 @@ class ModuleApiTestCase(HomeserverTestCase):
# Check that the displayname was assigned
displayname = self.get_success(self.store.get_profile_displayname("bob"))
self.assertEqual(displayname, "Bobberino")
+
+ def test_public_rooms(self):
+ """Tests that a room can be added and removed from the public rooms list,
+ as well as have its public rooms directory state queried.
+ """
+ # Create a user and room to play with
+ user_id = self.register_user("kermit", "monkey")
+ tok = self.login("kermit", "monkey")
+ room_id = self.helper.create_room_as(user_id, tok=tok)
+
+ # The room should not currently be in the public rooms directory
+ is_in_public_rooms = self.get_success(
+ self.module_api.public_room_list_manager.room_is_in_public_room_list(
+ room_id
+ )
+ )
+ self.assertFalse(is_in_public_rooms)
+
+ # Let's try adding it to the public rooms directory
+ self.get_success(
+ self.module_api.public_room_list_manager.add_room_to_public_room_list(
+ room_id
+ )
+ )
+
+ # And checking whether it's in there...
+ is_in_public_rooms = self.get_success(
+ self.module_api.public_room_list_manager.room_is_in_public_room_list(
+ room_id
+ )
+ )
+ self.assertTrue(is_in_public_rooms)
+
+ # Let's remove it again
+ self.get_success(
+ self.module_api.public_room_list_manager.remove_room_from_public_room_list(
+ room_id
+ )
+ )
+
+ # Should be gone
+ is_in_public_rooms = self.get_success(
+ self.module_api.public_room_list_manager.room_is_in_public_room_list(
+ room_id
+ )
+ )
+ self.assertFalse(is_in_public_rooms)
diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py
index fbb482f05b..ae59f8f911 100644
--- a/tests/rest/client/test_room_access_rules.py
+++ b/tests/rest/client/test_room_access_rules.py
@@ -20,14 +20,15 @@ from mock import Mock
from twisted.internet import defer
-from synapse.api.constants import EventTypes, JoinRules, RoomCreationPreset
+from synapse.api.constants import EventTypes, JoinRules, Membership, RoomCreationPreset
from synapse.rest import admin
-from synapse.rest.client.v1 import login, room
+from synapse.rest.client.v1 import directory, login, room
from synapse.third_party_rules.access_rules import (
ACCESS_RULES_TYPE,
AccessRules,
RoomAccessRules,
)
+from synapse.types import create_requester
from tests import unittest
@@ -38,6 +39,7 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
admin.register_servlets,
login.register_servlets,
room.register_servlets,
+ directory.register_servlets,
]
def make_homeserver(self, reactor, clock):
@@ -99,6 +101,8 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
mock_http_client
)
+ self.third_party_event_rules = self.hs.get_third_party_event_rules()
+
return self.hs
def prepare(self, reactor, clock, homeserver):
@@ -200,8 +204,8 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
)
def test_public_room(self):
- """Tests that it's not possible to have a room with the public join rule and an
- access rule that's not restricted.
+ """Tests that it's only possible to have a room listed in the public room list
+ if the access rule is restricted.
"""
# Creating a room with the public_chat preset should succeed and set the access
# rule to restricted.
@@ -224,6 +228,26 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
self.current_rule_in_room(init_state_room_id), AccessRules.RESTRICTED
)
+ # List preset_room_id in the public room list
+ request, channel = self.make_request(
+ "PUT",
+ "/_matrix/client/r0/directory/list/room/%s" % (preset_room_id,),
+ {"visibility": "public"},
+ access_token=self.tok,
+ )
+ self.render(request)
+ self.assertEqual(channel.code, 200, channel.result)
+
+ # List init_state_room_id in the public room list
+ request, channel = self.make_request(
+ "PUT",
+ "/_matrix/client/r0/directory/list/room/%s" % (init_state_room_id,),
+ {"visibility": "public"},
+ access_token=self.tok,
+ )
+ self.render(request)
+ self.assertEqual(channel.code, 200, channel.result)
+
# Changing access rule to unrestricted should fail.
self.change_rule_in_room(
preset_room_id, AccessRules.UNRESTRICTED, expected_code=403
@@ -238,54 +262,25 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
init_state_room_id, AccessRules.DIRECT, expected_code=403
)
- # Changing join rule to public in an unrestricted room should fail.
- self.change_join_rule_in_room(
- self.unrestricted_room, JoinRules.PUBLIC, expected_code=403
- )
- # Changing join rule to public in an direct room should fail.
- self.change_join_rule_in_room(
- self.direct_rooms[0], JoinRules.PUBLIC, expected_code=403
- )
-
- # Creating a new room with the public_chat preset and an access rule that isn't
- # restricted should fail.
- self.create_room(
- preset=RoomCreationPreset.PUBLIC_CHAT,
- rule=AccessRules.UNRESTRICTED,
- expected_code=400,
- )
+ # Creating a new room with the public_chat preset and an access rule of direct
+ # should fail.
self.create_room(
preset=RoomCreationPreset.PUBLIC_CHAT,
rule=AccessRules.DIRECT,
expected_code=400,
)
- # Creating a room with the public join rule in its initial state and an access
- # rule that isn't restricted should fail.
- self.create_room(
- initial_state=[
- {
- "type": "m.room.join_rules",
- "content": {"join_rule": JoinRules.PUBLIC},
- }
- ],
- rule=AccessRules.UNRESTRICTED,
- expected_code=400,
- )
- self.create_room(
- initial_state=[
- {
- "type": "m.room.join_rules",
- "content": {"join_rule": JoinRules.PUBLIC},
- }
- ],
- rule=AccessRules.DIRECT,
- expected_code=400,
+ # Changing join rule to public in an direct room should fail.
+ self.change_join_rule_in_room(
+ self.direct_rooms[0], JoinRules.PUBLIC, expected_code=403
)
def test_restricted(self):
"""Tests that in restricted mode we're unable to invite users from blacklisted
servers but can invite other users.
+
+ Also tests that the room can be published to, and removed from, the public room
+ list.
"""
# We can't invite a user from a forbidden HS.
self.helper.invite(
@@ -320,14 +315,33 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
expected_code=200,
)
+ # We are allowed to publish the room to the public room list
+ url = "/_matrix/client/r0/directory/list/room/%s" % self.restricted_room
+ data = {"visibility": "public"}
+
+ request, channel = self.make_request("PUT", url, data, access_token=self.tok)
+ self.render(request)
+ self.assertEqual(channel.code, 200, channel.result)
+
+ # We are allowed to remove the room from the public room list
+ url = "/_matrix/client/r0/directory/list/room/%s" % self.restricted_room
+ data = {"visibility": "private"}
+
+ request, channel = self.make_request("PUT", url, data, access_token=self.tok)
+ self.render(request)
+ self.assertEqual(channel.code, 200, channel.result)
+
def test_direct(self):
"""Tests that, in direct mode, other users than the initial two can't be invited,
but the following scenario works:
* invited user joins the room
* invited user leaves the room
* room creator re-invites invited user
- Also tests that a user from a HS that's in the list of forbidden domains (to use
+
+ Tests that a user from a HS that's in the list of forbidden domains (to use
in restricted mode) can be invited.
+
+ Tests that the room cannot be published to the public room list.
"""
not_invited_user = "@not_invited:forbidden_domain"
@@ -412,10 +426,20 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
self.hs.config.rc_third_party_invite.burst_count = burst
self.hs.config.rc_third_party_invite.per_second = per_second
+ # We can't publish the room to the public room list
+ url = "/_matrix/client/r0/directory/list/room/%s" % self.direct_rooms[0]
+ data = {"visibility": "public"}
+
+ request, channel = self.make_request("PUT", url, data, access_token=self.tok)
+ self.render(request)
+ self.assertEqual(channel.code, 403, channel.result)
+
def test_unrestricted(self):
"""Tests that, in unrestricted mode, we can invite whoever we want, but we can
only change the power level of users that wouldn't be forbidden in restricted
mode.
+
+ Tests that the room cannot be published to the public room list.
"""
# We can invite
self.helper.invite(
@@ -482,6 +506,14 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
expect_code=403,
)
+ # We can't publish the room to the public room list
+ url = "/_matrix/client/r0/directory/list/room/%s" % self.unrestricted_room
+ data = {"visibility": "public"}
+
+ request, channel = self.make_request("PUT", url, data, access_token=self.tok)
+ self.render(request)
+ self.assertEqual(channel.code, 403, channel.result)
+
def test_change_rules(self):
"""Tests that we can only change the current rule from restricted to
unrestricted.
@@ -526,6 +558,30 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
expected_code=403,
)
+ # We can't publish a room to the public room list and then change its rule to
+ # unrestricted
+
+ # Create a restricted room
+ test_room_id = self.create_room(rule=AccessRules.RESTRICTED)
+
+ # Publish the room to the public room list
+ url = "/_matrix/client/r0/directory/list/room/%s" % test_room_id
+ data = {"visibility": "public"}
+
+ request, channel = self.make_request("PUT", url, data, access_token=self.tok)
+ self.render(request)
+ self.assertEqual(channel.code, 200, channel.result)
+
+ # Attempt to switch the room to "unrestricted"
+ self.change_rule_in_room(
+ room_id=test_room_id, new_rule=AccessRules.UNRESTRICTED, expected_code=403
+ )
+
+ # Attempt to switch the room to "direct"
+ self.change_rule_in_room(
+ room_id=test_room_id, new_rule=AccessRules.DIRECT, expected_code=403
+ )
+
def test_change_room_avatar(self):
"""Tests that changing the room avatar is always allowed unless the room is a
direct chat, in which case it's forbidden.
@@ -670,6 +726,119 @@ class RoomAccessTestCase(unittest.HomeserverTestCase):
tok=self.tok,
)
+ def test_check_event_allowed(self):
+ """Tests that RoomAccessRules.check_event_allowed behaves accordingly.
+
+ It tests that:
+ * forbidden users cannot join restricted rooms.
+ * forbidden users can only join unrestricted rooms if they have an invite.
+ """
+ event_creator = self.hs.get_event_creation_handler()
+
+ # Test that forbidden users cannot join restricted rooms
+ requester = create_requester(self.user_id)
+ allowed_requester = create_requester("@user:allowed_domain")
+ forbidden_requester = create_requester("@user:forbidden_domain")
+
+ # Create a join event for a forbidden user
+ forbidden_join_event, forbidden_join_event_context = self.get_success(
+ event_creator.create_event(
+ forbidden_requester,
+ {
+ "type": EventTypes.Member,
+ "room_id": self.restricted_room,
+ "sender": forbidden_requester.user.to_string(),
+ "content": {"membership": Membership.JOIN},
+ "state_key": forbidden_requester.user.to_string(),
+ },
+ )
+ )
+
+ # Create a join event for an allowed user
+ allowed_join_event, allowed_join_event_context = self.get_success(
+ event_creator.create_event(
+ allowed_requester,
+ {
+ "type": EventTypes.Member,
+ "room_id": self.restricted_room,
+ "sender": allowed_requester.user.to_string(),
+ "content": {"membership": Membership.JOIN},
+ "state_key": allowed_requester.user.to_string(),
+ },
+ )
+ )
+
+ # Assert a join event from a forbidden user to a restricted room is rejected
+ can_join = self.get_success(
+ self.third_party_event_rules.check_event_allowed(
+ forbidden_join_event, forbidden_join_event_context
+ )
+ )
+ self.assertFalse(can_join)
+
+ # But a join event from an non-forbidden user to a restricted room is allowed
+ can_join = self.get_success(
+ self.third_party_event_rules.check_event_allowed(
+ allowed_join_event, allowed_join_event_context
+ )
+ )
+ self.assertTrue(can_join)
+
+ # Test that forbidden users can only join unrestricted rooms if they have an invite
+
+ # Recreate the forbidden join event for the unrestricted room instead
+ forbidden_join_event, forbidden_join_event_context = self.get_success(
+ event_creator.create_event(
+ forbidden_requester,
+ {
+ "type": EventTypes.Member,
+ "room_id": self.unrestricted_room,
+ "sender": forbidden_requester.user.to_string(),
+ "content": {"membership": Membership.JOIN},
+ "state_key": forbidden_requester.user.to_string(),
+ },
+ )
+ )
+
+ # A forbidden user without an invite should not be able to join an unrestricted room
+ can_join = self.get_success(
+ self.third_party_event_rules.check_event_allowed(
+ forbidden_join_event, forbidden_join_event_context
+ )
+ )
+ self.assertFalse(can_join)
+
+ # However, if we then invite this user...
+ self.helper.invite(
+ room=self.unrestricted_room,
+ src=requester.user.to_string(),
+ targ=forbidden_requester.user.to_string(),
+ tok=self.tok,
+ )
+
+ # And create another join event, making sure that its context states it's coming
+ # in after the above invite was made...
+ forbidden_join_event, forbidden_join_event_context = self.get_success(
+ event_creator.create_event(
+ forbidden_requester,
+ {
+ "type": EventTypes.Member,
+ "room_id": self.unrestricted_room,
+ "sender": forbidden_requester.user.to_string(),
+ "content": {"membership": Membership.JOIN},
+ "state_key": forbidden_requester.user.to_string(),
+ },
+ )
+ )
+
+ # Then the forbidden user should be able to join!
+ can_join = self.get_success(
+ self.third_party_event_rules.check_event_allowed(
+ forbidden_join_event, forbidden_join_event_context
+ )
+ )
+ self.assertTrue(can_join)
+
def create_room(
self,
direct=False,
diff --git a/tests/rest/client/third_party_rules.py b/tests/rest/client/third_party_rules.py
index 7167fc56b6..9b79e9de6e 100644
--- a/tests/rest/client/third_party_rules.py
+++ b/tests/rest/client/third_party_rules.py
@@ -12,18 +12,23 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
from synapse.rest import admin
from synapse.rest.client.v1 import login, room
+from synapse.types import Requester
from tests import unittest
class ThirdPartyRulesTestModule(object):
- def __init__(self, config):
+ def __init__(self, config, *args, **kwargs):
pass
- def check_event_allowed(self, event, context):
+ async def on_create_room(
+ self, requester: Requester, config: dict, is_requester_admin: bool
+ ):
+ return True
+
+ async def check_event_allowed(self, event, context):
if event.type == "foo.bar.forbidden":
return False
else:
@@ -51,29 +56,31 @@ class ThirdPartyRulesTestCase(unittest.HomeserverTestCase):
self.hs = self.setup_test_homeserver(config=config)
return self.hs
+ def prepare(self, reactor, clock, homeserver):
+ # Create a user and room to play with during the tests
+ self.user_id = self.register_user("kermit", "monkey")
+ self.tok = self.login("kermit", "monkey")
+
+ self.room_id = self.helper.create_room_as(self.user_id, tok=self.tok)
+
def test_third_party_rules(self):
"""Tests that a forbidden event is forbidden from being sent, but an allowed one
can be sent.
"""
- user_id = self.register_user("kermit", "monkey")
- tok = self.login("kermit", "monkey")
-
- room_id = self.helper.create_room_as(user_id, tok=tok)
-
request, channel = self.make_request(
"PUT",
- "/_matrix/client/r0/rooms/%s/send/foo.bar.allowed/1" % room_id,
+ "/_matrix/client/r0/rooms/%s/send/foo.bar.allowed/1" % self.room_id,
{},
- access_token=tok,
+ access_token=self.tok,
)
self.render(request)
self.assertEquals(channel.result["code"], b"200", channel.result)
request, channel = self.make_request(
"PUT",
- "/_matrix/client/r0/rooms/%s/send/foo.bar.forbidden/1" % room_id,
+ "/_matrix/client/r0/rooms/%s/send/foo.bar.forbidden/1" % self.room_id,
{},
- access_token=tok,
+ access_token=self.tok,
)
self.render(request)
self.assertEquals(channel.result["code"], b"403", channel.result)
|