Honour ratelimit flag for application services for invite ratelimiting (#9302)

This commit is contained in:
Erik Johnston 2021-02-03 10:17:37 +00:00 committed by GitHub
parent eec9ab3225
commit ff55300b91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 13 additions and 51 deletions

1
changelog.d/9302.bugfix Normal file
View File

@ -0,0 +1 @@
Fix new ratelimiting for invites to respect the `ratelimit` flag on application services. Introduced in v1.27.0rc1.

View File

@ -1619,7 +1619,9 @@ class FederationHandler(BaseHandler):
# We retrieve the room member handler here as to not cause a cyclic dependency # We retrieve the room member handler here as to not cause a cyclic dependency
member_handler = self.hs.get_room_member_handler() member_handler = self.hs.get_room_member_handler()
member_handler.ratelimit_invite(event.room_id, event.state_key) # We don't rate limit based on room ID, as that should be done by
# sending server.
member_handler.ratelimit_invite(None, event.state_key)
# keep a record of the room version, if we don't yet know it. # keep a record of the room version, if we don't yet know it.
# (this may get overwritten if we later get a different room version in a # (this may get overwritten if we later get a different room version in a

View File

@ -155,10 +155,14 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
""" """
raise NotImplementedError() raise NotImplementedError()
def ratelimit_invite(self, room_id: str, invitee_user_id: str): def ratelimit_invite(self, room_id: Optional[str], invitee_user_id: str):
"""Ratelimit invites by room and by target user. """Ratelimit invites by room and by target user.
If room ID is missing then we just rate limit by target user.
""" """
if room_id:
self._invites_per_room_limiter.ratelimit(room_id) self._invites_per_room_limiter.ratelimit(room_id)
self._invites_per_user_limiter.ratelimit(invitee_user_id) self._invites_per_user_limiter.ratelimit(invitee_user_id)
async def _local_membership_update( async def _local_membership_update(
@ -406,6 +410,8 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
if effective_membership_state == Membership.INVITE: if effective_membership_state == Membership.INVITE:
target_id = target.to_string() target_id = target.to_string()
if ratelimit: if ratelimit:
# Don't ratelimit application services.
if not requester.app_service or requester.app_service.is_rate_limited():
self.ratelimit_invite(room_id, target_id) self.ratelimit_invite(room_id, target_id)
# block any attempts to invite the server notices mxid # block any attempts to invite the server notices mxid

View File

@ -191,53 +191,6 @@ class FederationTestCase(unittest.HomeserverTestCase):
self.assertEqual(sg, sg2) self.assertEqual(sg, sg2)
@unittest.override_config(
{"rc_invites": {"per_room": {"per_second": 0.5, "burst_count": 3}}}
)
def test_invite_by_room_ratelimit(self):
"""Tests that invites from federation in a room are actually rate-limited.
"""
other_server = "otherserver"
other_user = "@otheruser:" + other_server
# create the room
user_id = self.register_user("kermit", "test")
tok = self.login("kermit", "test")
room_id = self.helper.create_room_as(room_creator=user_id, tok=tok)
room_version = self.get_success(self.store.get_room_version(room_id))
def create_invite_for(local_user):
return event_from_pdu_json(
{
"type": EventTypes.Member,
"content": {"membership": "invite"},
"room_id": room_id,
"sender": other_user,
"state_key": local_user,
"depth": 32,
"prev_events": [],
"auth_events": [],
"origin_server_ts": self.clock.time_msec(),
},
room_version,
)
for i in range(3):
self.get_success(
self.handler.on_invite_request(
other_server,
create_invite_for("@user-%d:test" % (i,)),
room_version,
)
)
self.get_failure(
self.handler.on_invite_request(
other_server, create_invite_for("@user-4:test"), room_version,
),
exc=LimitExceededError,
)
@unittest.override_config( @unittest.override_config(
{"rc_invites": {"per_user": {"per_second": 0.5, "burst_count": 3}}} {"rc_invites": {"per_user": {"per_second": 0.5, "burst_count": 3}}}
) )