From bc0fd8f17023d235809fcdb8ed901a766873eced Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 18 Jun 2019 14:54:19 +0100 Subject: Add tests for room creation hook --- tests/rest/client/test_room_access_rules.py | 136 ++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 tests/rest/client/test_room_access_rules.py (limited to 'tests/rest/client/test_room_access_rules.py') diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py new file mode 100644 index 0000000000..85347b3b0c --- /dev/null +++ b/tests/rest/client/test_room_access_rules.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 New Vector Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +import json + +import synapse.rest.admin +from synapse.config._base import ConfigError +from synapse.rest import admin +from synapse.rest.client.v1 import login, room +from synapse.rulecheck.domain_rule_checker import DomainRuleChecker +from synapse.third_party_rules.access_rules import ( + ACCESS_RULES_TYPE, + ACCESS_RULE_DIRECT, + ACCESS_RULE_RESTRICTED, + ACCESS_RULE_UNRESTRICTED, +) + +from tests import unittest + + +class RoomAccessEventTestCase(unittest.HomeserverTestCase): + + servlets = [ + admin.register_servlets, + login.register_servlets, + room.register_servlets, + ] + + def make_homeserver(self, reactor, clock): + config = self.default_config() + + config["third_party_event_rules"] = { + "module": "synapse.third_party_rules.access_rules.RoomAccessRules", + "config": { + "domains_forbidden_when_restricted": [ + "forbidden_domain" + ], + "id_server": "testis", + } + } + + self.hs = self.setup_test_homeserver(config=config) + + return self.hs + + def prepare(self, reactor, clock, homeserver): + self.user_id = self.register_user("kermit", "monkey") + self.tok = self.login("kermit", "monkey") + + self.restricted_room = self.create_room() + self.unrestricted_room = self.create_room(rule=ACCESS_RULE_UNRESTRICTED) + self.direct_room = self.create_room(direct=True) + + def test_create_room_no_rule(self): + """Tests that creating a room with no rule will set the default value.""" + room_id = self.create_room() + rule = self.current_rule_in_room(room_id) + + self.assertEqual(rule, ACCESS_RULE_RESTRICTED) + + def test_create_room_direct_no_rule(self): + """Tests that creating a direct room with no rule will set the default value.""" + room_id = self.create_room(direct=True) + rule = self.current_rule_in_room(room_id) + + self.assertEqual(rule, ACCESS_RULE_DIRECT) + + def test_create_room_valid_rule(self): + """Tests that creating a room with a valid rule will set the right value.""" + room_id = self.create_room(rule=ACCESS_RULE_UNRESTRICTED) + rule = self.current_rule_in_room(room_id) + + self.assertEqual(rule, ACCESS_RULE_UNRESTRICTED) + + def test_create_room_invalid_rule(self): + """Tests that creating a room with an invalid rule will set the default value.""" + self.create_room(rule=ACCESS_RULE_DIRECT, expected_code=400) + + def test_create_room_direct_invalid_rule(self): + """Tests that creating a direct room with an invalid rule will set the default + value. + """ + self.create_room(direct=True, rule=ACCESS_RULE_RESTRICTED, expected_code=400) + + # def test_limited + + def create_room(self, direct=False, rule=None, expected_code=200): + content = { + "is_direct": direct, + } + + if rule: + content["initial_state"] = [{ + "type": ACCESS_RULES_TYPE, + "state_key": "", + "content": { + "rule": rule, + } + }] + + request, channel = self.make_request( + "POST", + "/_matrix/client/r0/createRoom", + json.dumps(content), + access_token=self.tok, + ) + self.render(request) + + self.assertEqual(channel.code, expected_code, channel.result) + + if expected_code == 200: + return channel.json_body["room_id"] + + def current_rule_in_room(self, room_id): + request, channel = self.make_request( + "GET", + "/_matrix/client/r0/rooms/%s/state/%s" % (room_id, ACCESS_RULES_TYPE), + access_token=self.tok, + ) + self.render(request) + + self.assertEqual(channel.code, 200, channel.result) + return channel.json_body["rule"] -- cgit 1.5.1 From a09767d57d701b624854cc1e6868ae3840fb3845 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 18 Jun 2019 14:55:24 +0100 Subject: Lint --- tests/rest/client/test_room_access_rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/rest/client/test_room_access_rules.py') diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py index 85347b3b0c..8052fae94e 100644 --- a/tests/rest/client/test_room_access_rules.py +++ b/tests/rest/client/test_room_access_rules.py @@ -22,10 +22,10 @@ from synapse.rest import admin from synapse.rest.client.v1 import login, room from synapse.rulecheck.domain_rule_checker import DomainRuleChecker from synapse.third_party_rules.access_rules import ( - ACCESS_RULES_TYPE, ACCESS_RULE_DIRECT, ACCESS_RULE_RESTRICTED, ACCESS_RULE_UNRESTRICTED, + ACCESS_RULES_TYPE, ) from tests import unittest -- cgit 1.5.1 From 2a1f35193b478a9c097061dbec92e22fb1cbdb8f Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 18 Jun 2019 14:57:04 +0100 Subject: Remove unused imports --- tests/rest/client/test_room_access_rules.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'tests/rest/client/test_room_access_rules.py') diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py index 8052fae94e..1f43902421 100644 --- a/tests/rest/client/test_room_access_rules.py +++ b/tests/rest/client/test_room_access_rules.py @@ -16,11 +16,8 @@ import json -import synapse.rest.admin -from synapse.config._base import ConfigError from synapse.rest import admin from synapse.rest.client.v1 import login, room -from synapse.rulecheck.domain_rule_checker import DomainRuleChecker from synapse.third_party_rules.access_rules import ( ACCESS_RULE_DIRECT, ACCESS_RULE_RESTRICTED, -- cgit 1.5.1 From 145291108da2c550eac45037122ec723d694ee97 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 18 Jun 2019 16:32:54 +0100 Subject: Add tests for inviting with access rules --- tests/rest/client/test_room_access_rules.py | 104 +++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) (limited to 'tests/rest/client/test_room_access_rules.py') diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py index 1f43902421..de655fa580 100644 --- a/tests/rest/client/test_room_access_rules.py +++ b/tests/rest/client/test_room_access_rules.py @@ -16,6 +16,11 @@ import json +from mock import Mock + +from twisted.internet import defer + +from synapse.federation.federation_base import event_from_pdu_json from synapse.rest import admin from synapse.rest.client.v1 import login, room from synapse.third_party_rules.access_rules import ( @@ -49,7 +54,18 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): } } - self.hs = self.setup_test_homeserver(config=config) + def send_invite(destination, room_id, event_id, pdu): + return defer.succeed(pdu) + + federation_client = Mock(spec=[ + "send_invite", + ]) + federation_client.send_invite.side_effect = send_invite + + self.hs = self.setup_test_homeserver( + config=config, + federation_client=federation_client, + ) return self.hs @@ -61,6 +77,16 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): self.unrestricted_room = self.create_room(rule=ACCESS_RULE_UNRESTRICTED) self.direct_room = self.create_room(direct=True) + self.invitee_id = self.register_user("invitee", "test") + self.invitee_tok = self.login("invitee", "test") + + self.helper.invite( + room=self.direct_room, + src=self.user_id, + targ=self.invitee_id, + tok=self.tok, + ) + def test_create_room_no_rule(self): """Tests that creating a room with no rule will set the default value.""" room_id = self.create_room() @@ -92,7 +118,81 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): """ self.create_room(direct=True, rule=ACCESS_RULE_RESTRICTED, expected_code=400) - # def test_limited + def test_restricted(self): + """Tests that in restricted mode we're unable to invite users from blacklisted + servers but can invite other users. + """ + self.helper.invite( + room=self.restricted_room, + src=self.user_id, + targ="@test:forbidden_domain", + tok=self.tok, + expect_code=403, + ) + + self.helper.invite( + room=self.restricted_room, + src=self.user_id, + targ="@test:not_forbidden_domain", + tok=self.tok, + expect_code=200, + ) + + 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 + """ + self.helper.invite( + room=self.direct_room, + src=self.user_id, + targ="@not_invited:test", + tok=self.tok, + expect_code=403, + ) + + self.helper.join( + room=self.direct_room, + user=self.invitee_id, + tok=self.invitee_tok, + expect_code=200, + ) + + self.helper.leave( + room=self.direct_room, + user=self.invitee_id, + tok=self.invitee_tok, + expect_code=200, + ) + + self.helper.invite( + room=self.direct_room, + src=self.user_id, + targ=self.invitee_id, + tok=self.tok, + expect_code=200, + ) + + def test_unrestricted(self): + """Tests that, in unrestricted mode, we can invite whoever we want. + """ + self.helper.invite( + room=self.unrestricted_room, + src=self.user_id, + targ="@test:forbidden_domain", + tok=self.tok, + expect_code=200, + ) + + self.helper.invite( + room=self.unrestricted_room, + src=self.user_id, + targ="@test:not_forbidden_domain", + tok=self.tok, + expect_code=200, + ) def create_room(self, direct=False, rule=None, expected_code=200): content = { -- cgit 1.5.1 From 1532369dcd54b6d9ecfb2e5c7b66f9e288e67c4c Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 18 Jun 2019 16:46:57 +0100 Subject: Remove unused import --- tests/rest/client/test_room_access_rules.py | 1 - 1 file changed, 1 deletion(-) (limited to 'tests/rest/client/test_room_access_rules.py') diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py index de655fa580..01cbb3f4d8 100644 --- a/tests/rest/client/test_room_access_rules.py +++ b/tests/rest/client/test_room_access_rules.py @@ -20,7 +20,6 @@ from mock import Mock from twisted.internet import defer -from synapse.federation.federation_base import event_from_pdu_json from synapse.rest import admin from synapse.rest.client.v1 import login, room from synapse.third_party_rules.access_rules import ( -- cgit 1.5.1 From 9b3c69f66129819bac87b78c91b072df8e57846c Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 18 Jun 2019 17:59:07 +0100 Subject: Add tests for 3PID invites --- tests/rest/client/test_room_access_rules.py | 158 +++++++++++++++++++++++++--- 1 file changed, 146 insertions(+), 12 deletions(-) (limited to 'tests/rest/client/test_room_access_rules.py') diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py index 01cbb3f4d8..4b8359762a 100644 --- a/tests/rest/client/test_room_access_rules.py +++ b/tests/rest/client/test_room_access_rules.py @@ -15,6 +15,8 @@ import json +import random +import string from mock import Mock @@ -32,7 +34,7 @@ from synapse.third_party_rules.access_rules import ( from tests import unittest -class RoomAccessEventTestCase(unittest.HomeserverTestCase): +class RoomAccessTestCase(unittest.HomeserverTestCase): servlets = [ admin.register_servlets, @@ -52,18 +54,51 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): "id_server": "testis", } } + config["trusted_third_party_id_servers"] = [ + "testis", + ] def send_invite(destination, room_id, event_id, pdu): return defer.succeed(pdu) - federation_client = Mock(spec=[ + def get_json(uri, args={}, headers=None): + address_domain = args["address"].split("@")[1] + return defer.succeed({"hs": address_domain}) + + def post_urlencoded_get_json(uri, args={}, headers=None): + token = ''.join(random.choice(string.ascii_letters) for _ in range(10)) + return defer.succeed({ + "token": token, + "public_keys": [ + { + "public_key": "serverpublickey", + "key_validity_url": "https://testis/pubkey/isvalid", + }, + { + "public_key": "phemeralpublickey", + "key_validity_url": "https://testis/pubkey/ephemeral/isvalid", + }, + ], + "display_name": "f...@b...", + }) + + mock_federation_client = Mock(spec=[ "send_invite", ]) - federation_client.send_invite.side_effect = send_invite + mock_federation_client.send_invite.side_effect = send_invite + mock_http_client = Mock(spec=[ + "get_json", + "post_urlencoded_get_json" + ]) + # Mocking the response for /info on the IS API. + mock_http_client.get_json.side_effect = get_json + # Mocking the response for /store-invite on the IS API. + mock_http_client.post_urlencoded_get_json.side_effect = post_urlencoded_get_json self.hs = self.setup_test_homeserver( config=config, - federation_client=federation_client, + federation_client=mock_federation_client, + simple_http_client=mock_http_client, ) return self.hs @@ -74,13 +109,17 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): self.restricted_room = self.create_room() self.unrestricted_room = self.create_room(rule=ACCESS_RULE_UNRESTRICTED) - self.direct_room = self.create_room(direct=True) + self.direct_rooms = [ + self.create_room(direct=True), + self.create_room(direct=True), + self.create_room(direct=True), + ] self.invitee_id = self.register_user("invitee", "test") self.invitee_tok = self.login("invitee", "test") self.helper.invite( - room=self.direct_room, + room=self.direct_rooms[0], src=self.user_id, targ=self.invitee_id, tok=self.tok, @@ -121,6 +160,7 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): """Tests that in restricted mode we're unable to invite users from blacklisted servers but can invite other users. """ + # We can't invite a user from a forbidden HS. self.helper.invite( room=self.restricted_room, src=self.user_id, @@ -129,54 +169,117 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): expect_code=403, ) + # We can invite a user which HS isn't forbidden. self.helper.invite( room=self.restricted_room, src=self.user_id, - targ="@test:not_forbidden_domain", + targ="@test:allowed_domain", tok=self.tok, expect_code=200, ) + # We can't send a 3PID invite to an address that is mapped to a forbidden HS. + self.send_threepid_invite( + address="test@forbidden_domain", + room_id=self.restricted_room, + expected_code=403, + ) + + # We can send a 3PID invite to an address that is mapped to an HS that's not + # forbidden. + self.send_threepid_invite( + address="test@allowed_domain", + room_id=self.restricted_room, + expected_code=200, + ) + 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 + in restricted mode) can be invited. """ + not_invited_user = "@not_invited:forbidden_domain" + + # We can't invite a new user to the room. self.helper.invite( - room=self.direct_room, + room=self.direct_rooms[0], src=self.user_id, - targ="@not_invited:test", + targ=not_invited_user, tok=self.tok, expect_code=403, ) + # The invited user can join the room. self.helper.join( - room=self.direct_room, + room=self.direct_rooms[0], user=self.invitee_id, tok=self.invitee_tok, expect_code=200, ) + # The invited user can leave the room. self.helper.leave( - room=self.direct_room, + room=self.direct_rooms[0], user=self.invitee_id, tok=self.invitee_tok, expect_code=200, ) + # The invited user can be re-invited to the room. self.helper.invite( - room=self.direct_room, + room=self.direct_rooms[0], src=self.user_id, targ=self.invitee_id, tok=self.tok, expect_code=200, ) + # If we're alone in the room and have always been the only member, we can invite + # someone. + self.helper.invite( + room=self.direct_rooms[1], + src=self.user_id, + targ=not_invited_user, + tok=self.tok, + expect_code=200, + ) + + # We can't send a 3PID invite to a room that already has two members. + self.send_threepid_invite( + address="test@allowed_domain", + room_id=self.direct_rooms[0], + expected_code=403, + ) + + # We can't send a 3PID invite to a room that already has a pending invite. + self.send_threepid_invite( + address="test@allowed_domain", + room_id=self.direct_rooms[1], + expected_code=403, + ) + + # We can send a 3PID invite to a room in which we've always been the only member. + self.send_threepid_invite( + address="test@forbidden_domain", + room_id=self.direct_rooms[2], + expected_code=200, + ) + + # We can send a 3PID invite to a room in which there's a 3PID invite. + self.send_threepid_invite( + address="test@forbidden_domain", + room_id=self.direct_rooms[2], + expected_code=403, + ) + def test_unrestricted(self): """Tests that, in unrestricted mode, we can invite whoever we want. """ + # We can invite self.helper.invite( room=self.unrestricted_room, src=self.user_id, @@ -193,6 +296,21 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): expect_code=200, ) + # We can send a 3PID invite to an address that is mapped to a forbidden HS. + self.send_threepid_invite( + address="test@forbidden_domain", + room_id=self.unrestricted_room, + expected_code=200, + ) + + # We can send a 3PID invite to an address that is mapped to an HS that's not + # forbidden. + self.send_threepid_invite( + address="test@allowed_domain", + room_id=self.unrestricted_room, + expected_code=200, + ) + def create_room(self, direct=False, rule=None, expected_code=200): content = { "is_direct": direct, @@ -230,3 +348,19 @@ class RoomAccessEventTestCase(unittest.HomeserverTestCase): self.assertEqual(channel.code, 200, channel.result) return channel.json_body["rule"] + + def send_threepid_invite(self, address, room_id, expected_code=200): + params = { + "id_server": "testis", + "medium": "email", + "address": address, + } + + request, channel = self.make_request( + "POST", + "/_matrix/client/r0/rooms/%s/invite" % room_id, + json.dumps(params), + access_token=self.tok, + ) + self.render(request) + self.assertEqual(channel.code, expected_code, channel.result) -- cgit 1.5.1 From c1bc48f9d4dcb127d31723e03fe9d9df1cd484c6 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 18 Jun 2019 18:07:05 +0100 Subject: Add tests for constraints on changing the rule for a room --- tests/rest/client/test_room_access_rules.py | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'tests/rest/client/test_room_access_rules.py') diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py index 4b8359762a..5c46dabf32 100644 --- a/tests/rest/client/test_room_access_rules.py +++ b/tests/rest/client/test_room_access_rules.py @@ -311,6 +311,52 @@ class RoomAccessTestCase(unittest.HomeserverTestCase): expected_code=200, ) + def test_change_rules(self): + """Tests that we can only change the current rule from restricted to + unrestricted. + """ + # We can change the rule from restricted to unrestricted. + self.change_rule_in_room( + room_id=self.restricted_room, + new_rule=ACCESS_RULE_UNRESTRICTED, + expected_code=200, + ) + + # We can't change the rule from restricted to direct. + self.change_rule_in_room( + room_id=self.restricted_room, + new_rule=ACCESS_RULE_DIRECT, + expected_code=403, + ) + + # We can't change the rule from unrestricted to restricted. + self.change_rule_in_room( + room_id=self.unrestricted_room, + new_rule=ACCESS_RULE_RESTRICTED, + expected_code=403, + ) + + # We can't change the rule from unrestricted to direct. + self.change_rule_in_room( + room_id=self.unrestricted_room, + new_rule=ACCESS_RULE_DIRECT, + expected_code=403, + ) + + # We can't change the rule from direct to restricted. + self.change_rule_in_room( + room_id=self.direct_rooms[0], + new_rule=ACCESS_RULE_RESTRICTED, + expected_code=403, + ) + + # We can't change the rule from direct to unrestricted. + self.change_rule_in_room( + room_id=self.direct_rooms[0], + new_rule=ACCESS_RULE_UNRESTRICTED, + expected_code=403, + ) + def create_room(self, direct=False, rule=None, expected_code=200): content = { "is_direct": direct, @@ -349,6 +395,20 @@ class RoomAccessTestCase(unittest.HomeserverTestCase): self.assertEqual(channel.code, 200, channel.result) return channel.json_body["rule"] + def change_rule_in_room(self, room_id, new_rule, expected_code=200): + data = { + "rule": new_rule, + } + request, channel = self.make_request( + "PUT", + "/_matrix/client/r0/rooms/%s/state/%s" % (room_id, ACCESS_RULES_TYPE), + json.dumps(data), + access_token=self.tok, + ) + self.render(request) + + self.assertEqual(channel.code, expected_code, channel.result) + def send_threepid_invite(self, address, room_id, expected_code=200): params = { "id_server": "testis", -- cgit 1.5.1