diff --git a/synapse/events/spamcheck.py b/synapse/events/spamcheck.py
index 87d66a9703..107c2e1f35 100644
--- a/synapse/events/spamcheck.py
+++ b/synapse/events/spamcheck.py
@@ -46,14 +46,19 @@ class SpamChecker(object):
return self.spam_checker.check_event_for_spam(event)
- def user_may_invite(self, inviter_userid, invitee_userid, room_id, new_room):
+ def user_may_invite(self, inviter_userid, invitee_userid, third_party_invite,
+ room_id, new_room):
"""Checks if a given user may send an invite
If this method returns false, the invite will be rejected.
Args:
inviter_userid (str)
- invitee_userid (str)
+ invitee_userid (str|None): The user ID of the invitee. Is None
+ if this is a third party invite and the 3PID is not bound to a
+ user ID.
+ invitee_userid (dict|None): If a third party invite then is a dict
+ containing the medium and address of the invitee.
room_id (str)
new_room (bool): Wether the user is being invited to the room as
part of a room creation, if so the invitee would have been
@@ -66,7 +71,7 @@ class SpamChecker(object):
return True
return self.spam_checker.user_may_invite(
- inviter_userid, invitee_userid, room_id, new_room,
+ inviter_userid, invitee_userid, third_party_invite, room_id, new_room,
)
def user_may_create_room(self, userid, invite_list, third_party_invite_list,
diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index 1f799a04c1..c106fab0dc 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -1346,7 +1346,8 @@ class FederationHandler(BaseHandler):
raise SynapseError(403, "This server does not accept room invites")
if not self.spam_checker.user_may_invite(
- event.sender, event.state_key, event.room_id, new_room=False,
+ event.sender, event.state_key, None,
+ room_id=event.room_id, new_room=False,
):
raise SynapseError(
403, "This user is not permitted to send invites to this server/user"
diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index a710b51c3d..6f5666e624 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -661,6 +661,7 @@ class RoomCreationHandler(BaseHandler):
id_server,
requester,
txn_id=None,
+ new_room=True,
)
result = {"room_id": room_id}
diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py
index 645f615d74..ee7a390b1c 100644
--- a/synapse/handlers/room_member.py
+++ b/synapse/handlers/room_member.py
@@ -425,7 +425,9 @@ class RoomMemberHandler(object):
block_invite = True
if not self.spam_checker.user_may_invite(
- requester.user.to_string(), target.to_string(), room_id,
+ requester.user.to_string(), target.to_string(),
+ third_party_invite=None,
+ room_id=room_id,
new_room=new_room,
):
logger.info("Blocking invite due to spam checker")
@@ -728,7 +730,8 @@ class RoomMemberHandler(object):
address,
id_server,
requester,
- txn_id
+ txn_id,
+ new_room=False,
):
if self.config.block_non_admin_invites:
is_requester_admin = yield self.auth.is_server_admin(
@@ -744,6 +747,20 @@ class RoomMemberHandler(object):
id_server, medium, address
)
+ if not self.spam_checker.user_may_invite(
+ requester.user.to_string(), invitee,
+ third_party_invite={
+ "medium": medium,
+ "address": address,
+ },
+ room_id=room_id,
+ new_room=new_room,
+ ):
+ logger.info("Blocking invite due to spam checker")
+ raise SynapseError(
+ 403, "Invites have been disabled on this server",
+ )
+
if invitee:
yield self.update_membership(
requester,
diff --git a/synapse/rest/client/v1/room.py b/synapse/rest/client/v1/room.py
index 48da4d557f..17a1503cdb 100644
--- a/synapse/rest/client/v1/room.py
+++ b/synapse/rest/client/v1/room.py
@@ -666,7 +666,8 @@ class RoomMembershipRestServlet(ClientV1RestServlet):
content["address"],
content["id_server"],
requester,
- txn_id
+ txn_id,
+ new_room=False,
)
defer.returnValue((200, {}))
return
diff --git a/synapse/rulecheck/domain_rule_checker.py b/synapse/rulecheck/domain_rule_checker.py
index 48ab62faac..b379bbc5b4 100644
--- a/synapse/rulecheck/domain_rule_checker.py
+++ b/synapse/rulecheck/domain_rule_checker.py
@@ -74,13 +74,19 @@ class DomainRuleChecker(object):
"""
return False
- def user_may_invite(self, inviter_userid, invitee_userid, room_id,
- new_room):
+ def user_may_invite(self, inviter_userid, invitee_userid, third_party_invite,
+ room_id, new_room):
"""Implements synapse.events.SpamChecker.user_may_invite
"""
if self.can_only_invite_during_room_creation and not new_room:
return False
+ if not self.can_invite_by_third_party_id and third_party_invite:
+ return False
+
+ if third_party_invite and not invitee_userid:
+ return True
+
inviter_domain = self._get_domain_from_id(inviter_userid)
invitee_domain = self._get_domain_from_id(invitee_userid)
diff --git a/tests/rulecheck/test_domainrulecheck.py b/tests/rulecheck/test_domainrulecheck.py
index a887249b59..9c9f080f97 100644
--- a/tests/rulecheck/test_domainrulecheck.py
+++ b/tests/rulecheck/test_domainrulecheck.py
@@ -35,13 +35,15 @@ class DomainRuleCheckerTestCase(unittest.TestCase):
}
check = DomainRuleChecker(config)
self.assertTrue(
- check.user_may_invite("test:source_one", "test:target_one", "room", False)
+ check.user_may_invite(
+ "test:source_one", "test:target_one", None, "room", False,
+ )
)
self.assertTrue(
- check.user_may_invite("test:source_one", "test:target_two", "room", False)
+ check.user_may_invite("test:source_one", "test:target_two", None, "room", False)
)
self.assertTrue(
- check.user_may_invite("test:source_two", "test:target_two", "room", False)
+ check.user_may_invite("test:source_two", "test:target_two", None, "room", False)
)
def test_disallowed(self):
@@ -55,16 +57,16 @@ class DomainRuleCheckerTestCase(unittest.TestCase):
}
check = DomainRuleChecker(config)
self.assertFalse(
- check.user_may_invite("test:source_one", "test:target_three", "room", False)
+ check.user_may_invite("test:source_one", "test:target_three", None, "room", False)
)
self.assertFalse(
- check.user_may_invite("test:source_two", "test:target_three", "room", False)
+ check.user_may_invite("test:source_two", "test:target_three", None, "room", False)
)
self.assertFalse(
- check.user_may_invite("test:source_two", "test:target_one", "room", False)
+ check.user_may_invite("test:source_two", "test:target_one", None, "room", False)
)
self.assertFalse(
- check.user_may_invite("test:source_four", "test:target_one", "room", False)
+ check.user_may_invite("test:source_four", "test:target_one", None, "room", False)
)
def test_default_allow(self):
@@ -77,7 +79,7 @@ class DomainRuleCheckerTestCase(unittest.TestCase):
}
check = DomainRuleChecker(config)
self.assertTrue(
- check.user_may_invite("test:source_three", "test:target_one", "room", False)
+ check.user_may_invite("test:source_three", "test:target_one", None, "room", False)
)
def test_default_deny(self):
@@ -90,7 +92,7 @@ class DomainRuleCheckerTestCase(unittest.TestCase):
}
check = DomainRuleChecker(config)
self.assertFalse(
- check.user_may_invite("test:source_three", "test:target_one", "room", False)
+ check.user_may_invite("test:source_three", "test:target_one", None, "room", False)
)
def test_config_parse(self):
|