forked from MirrorHub/synapse
Synapse 1.19.1rc1 (2020-08-25)
============================== Bugfixes -------- - Fix a bug introduced in v1.19.0 where appservices with ratelimiting disabled would still be ratelimited when joining rooms. ([\#8139](https://github.com/matrix-org/synapse/issues/8139)) - Fix a bug introduced in v1.19.0 that would cause e.g. profile updates to fail due to incorrect application of rate limits on join requests. ([\#8153](https://github.com/matrix-org/synapse/issues/8153)) -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdVkXOgzrGzds0jtrHgFcFF8ZFs0FAl9FIKkACgkQHgFcFF8Z Fs3zIw/9H40ieb73Iay6ecQeOSfHiMVMzvJqYbKgho/a6h5JDHir+NGpwuLFdeGM eHR07QkQgUU9+dLNTMOQpCKTIsU70wvzH1vTDINS3ChjnRBdrHKqhAG6ZyEt1dJx kxYX54zsQUwiwshMKbJ+DPclHaBFnL+SY5OFfqCNjvaNob59DbHAL3tlSktPc2go tGmj81q0dWY6maMCGI3IIYcrW7oLi+4TwosZual5Hz/xgRBiGaKHXRIJnInvkXpl R+rSOmpYraapfDPHzPyQgLN4Dt7aAccGho843tt7dAVfd2GRSaUkLGXVXCdoruQG CRjY1P3BRBzRBx6o80Uw7Ah0hsoVgpJTSzY008KigJce+IiRWG5sgPjoubhfK0MA BqzmCa3/lrR+/WUOf4+w6HSfRncKawgAp7Y7wVj4nQF5fc8mwpFLz4pA/C2YOyjp nYXCHf60/KSBDhnr0ZRAhAby4MJoYSf03djFG1oef5SVzOzHD7zho9oBnEz15Tab XXkg1iJ7AhNFiQjsY4H1sl2onoF4T7B53NOnUEwD0oll+nXIYGe6hlNuq6x4j6l9 39ZlMoe9zK28LoKKWa1RDug8z+PmarKRJ2zATlHIb2RGeVX+oFfaKVsIbJtupJVC 8HSFt7gcgLCdUazk6taKpOHeVyGxK6WUkLnCMHzD2rzPhzpSyws= =0rHM -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdVkXOgzrGzds0jtrHgFcFF8ZFs0FAl9FJK4ACgkQHgFcFF8Z Fs0O2xAAgxqCfAHylVuwunRppwV49Bvq6H0mMM29hYBogGB5cmh1vRnUm5GsPQt0 9vTKlwMz6XKjLs3TLqYsnZfXqK+lyaN0xFXd7xWCNzFtEXoIvDnq+u3h5WGaKOC9 PcXb2LSZoHC5yECBpoh58ZQEPKtYILEjo+OSDboIqHz4N5HSjMSPGPvMkUn6xMNG roWTAWKPd9juyE2dPzZxIoBWwJGn3D8EMkeTQDlExTTvmnDPyPvJ5MVUY/xaHLgy XV8lapFu/SzWAKotc5+9qkVN64obaxwovYTU9JnlqEc5+WlD+Jl+g0258Q1bV1H9 341aQQJX08iYw3xw13xVgT0zLPRbp82O3/SHC3S1nz27HUWKXqUtsm6woDbgHIz5 UPvKFQsp2dEN4tFXxkEHiossIVNGuXdRYwEjFQrxOwayCuS4cQwDADhqnzDU4hio LSVhtxs9rgLps4iKpcaRAqK8kifTrsomlQfh/7axPJQ43pmBR2PiItetlBW/9Le6 KTH90ghLQzJwKFkIcFcvPhFMVqSyXI32+g5++YAPmNVy9M/7LdJxuEc9ifTWgwds LtV3/F8xlqd0qwl5IbwC6Wf19N06jdlRv/q1zL/Hb6qu3FLQeGd+/1aiC0rsbq15 grdHVZkZi1iVF/zrOx24ctxQvgLyGHA+M7n/oIaIgxlT1S6+FUI= =49ZC -----END PGP SIGNATURE----- Merge tag 'v1.19.1rc1' into develop Synapse 1.19.1rc1 (2020-08-25) ============================== Bugfixes -------- - Fix a bug introduced in v1.19.0 where appservices with ratelimiting disabled would still be ratelimited when joining rooms. ([\#8139](https://github.com/matrix-org/synapse/issues/8139)) - Fix a bug introduced in v1.19.0 that would cause e.g. profile updates to fail due to incorrect application of rate limits on join requests. ([\#8153](https://github.com/matrix-org/synapse/issues/8153))
This commit is contained in:
commit
6e1c64a668
5 changed files with 129 additions and 26 deletions
10
CHANGES.md
10
CHANGES.md
|
@ -12,6 +12,16 @@ from Synapse as most users have updated their client. Further context can be
|
||||||
found at [\#6766](https://github.com/matrix-org/synapse/issues/6766).
|
found at [\#6766](https://github.com/matrix-org/synapse/issues/6766).
|
||||||
|
|
||||||
|
|
||||||
|
Synapse 1.19.1rc1 (2020-08-25)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Fix a bug introduced in v1.19.0 where appservices with ratelimiting disabled would still be ratelimited when joining rooms. ([\#8139](https://github.com/matrix-org/synapse/issues/8139))
|
||||||
|
- Fix a bug introduced in v1.19.0 that would cause e.g. profile updates to fail due to incorrect application of rate limits on join requests. ([\#8153](https://github.com/matrix-org/synapse/issues/8153))
|
||||||
|
|
||||||
|
|
||||||
Synapse 1.19.0 (2020-08-17)
|
Synapse 1.19.0 (2020-08-17)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
__version__ = "1.19.0"
|
__version__ = "1.19.1rc1"
|
||||||
|
|
||||||
if bool(os.environ.get("SYNAPSE_TEST_PATCH_LOG_CONTEXTS", False)):
|
if bool(os.environ.get("SYNAPSE_TEST_PATCH_LOG_CONTEXTS", False)):
|
||||||
# We import here so that we don't have to install a bunch of deps when
|
# We import here so that we don't have to install a bunch of deps when
|
||||||
|
|
|
@ -225,24 +225,40 @@ class RoomMemberHandler(object):
|
||||||
_, stream_id = await self.store.get_event_ordering(duplicate.event_id)
|
_, stream_id = await self.store.get_event_ordering(duplicate.event_id)
|
||||||
return duplicate.event_id, stream_id
|
return duplicate.event_id, stream_id
|
||||||
|
|
||||||
stream_id = await self.event_creation_handler.handle_new_client_event(
|
|
||||||
requester, event, context, extra_users=[target], ratelimit=ratelimit,
|
|
||||||
)
|
|
||||||
|
|
||||||
prev_state_ids = await context.get_prev_state_ids()
|
prev_state_ids = await context.get_prev_state_ids()
|
||||||
|
|
||||||
prev_member_event_id = prev_state_ids.get((EventTypes.Member, user_id), None)
|
prev_member_event_id = prev_state_ids.get((EventTypes.Member, user_id), None)
|
||||||
|
|
||||||
|
newly_joined = False
|
||||||
if event.membership == Membership.JOIN:
|
if event.membership == Membership.JOIN:
|
||||||
# Only fire user_joined_room if the user has actually joined the
|
|
||||||
# room. Don't bother if the user is just changing their profile
|
|
||||||
# info.
|
|
||||||
newly_joined = True
|
newly_joined = True
|
||||||
if prev_member_event_id:
|
if prev_member_event_id:
|
||||||
prev_member_event = await self.store.get_event(prev_member_event_id)
|
prev_member_event = await self.store.get_event(prev_member_event_id)
|
||||||
newly_joined = prev_member_event.membership != Membership.JOIN
|
newly_joined = prev_member_event.membership != Membership.JOIN
|
||||||
|
|
||||||
|
# Only rate-limit if the user actually joined the room, otherwise we'll end
|
||||||
|
# up blocking profile updates.
|
||||||
if newly_joined:
|
if newly_joined:
|
||||||
await self._user_joined_room(target, room_id)
|
time_now_s = self.clock.time()
|
||||||
|
(
|
||||||
|
allowed,
|
||||||
|
time_allowed,
|
||||||
|
) = self._join_rate_limiter_local.can_requester_do_action(requester)
|
||||||
|
|
||||||
|
if not allowed:
|
||||||
|
raise LimitExceededError(
|
||||||
|
retry_after_ms=int(1000 * (time_allowed - time_now_s))
|
||||||
|
)
|
||||||
|
|
||||||
|
stream_id = await self.event_creation_handler.handle_new_client_event(
|
||||||
|
requester, event, context, extra_users=[target], ratelimit=ratelimit,
|
||||||
|
)
|
||||||
|
|
||||||
|
if event.membership == Membership.JOIN and newly_joined:
|
||||||
|
# Only fire user_joined_room if the user has actually joined the
|
||||||
|
# room. Don't bother if the user is just changing their profile
|
||||||
|
# info.
|
||||||
|
await self._user_joined_room(target, room_id)
|
||||||
elif event.membership == Membership.LEAVE:
|
elif event.membership == Membership.LEAVE:
|
||||||
if prev_member_event_id:
|
if prev_member_event_id:
|
||||||
prev_member_event = await self.store.get_event(prev_member_event_id)
|
prev_member_event = await self.store.get_event(prev_member_event_id)
|
||||||
|
@ -497,19 +513,7 @@ class RoomMemberHandler(object):
|
||||||
# so don't really fit into the general auth process.
|
# so don't really fit into the general auth process.
|
||||||
raise AuthError(403, "Guest access not allowed")
|
raise AuthError(403, "Guest access not allowed")
|
||||||
|
|
||||||
if is_host_in_room:
|
if not is_host_in_room:
|
||||||
time_now_s = self.clock.time()
|
|
||||||
(
|
|
||||||
allowed,
|
|
||||||
time_allowed,
|
|
||||||
) = self._join_rate_limiter_local.can_requester_do_action(requester,)
|
|
||||||
|
|
||||||
if not allowed:
|
|
||||||
raise LimitExceededError(
|
|
||||||
retry_after_ms=int(1000 * (time_allowed - time_now_s))
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
time_now_s = self.clock.time()
|
time_now_s = self.clock.time()
|
||||||
(
|
(
|
||||||
allowed,
|
allowed,
|
||||||
|
|
|
@ -28,7 +28,7 @@ from synapse.api.constants import EventContentFields, EventTypes, Membership
|
||||||
from synapse.handlers.pagination import PurgeStatus
|
from synapse.handlers.pagination import PurgeStatus
|
||||||
from synapse.rest.client.v1 import directory, login, profile, room
|
from synapse.rest.client.v1 import directory, login, profile, room
|
||||||
from synapse.rest.client.v2_alpha import account, room_upgrade_rest_servlet
|
from synapse.rest.client.v2_alpha import account, room_upgrade_rest_servlet
|
||||||
from synapse.types import JsonDict, RoomAlias
|
from synapse.types import JsonDict, RoomAlias, UserID
|
||||||
from synapse.util.stringutils import random_string
|
from synapse.util.stringutils import random_string
|
||||||
|
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
@ -675,6 +675,91 @@ class RoomMemberStateTestCase(RoomBase):
|
||||||
self.assertEquals(json.loads(content), channel.json_body)
|
self.assertEquals(json.loads(content), channel.json_body)
|
||||||
|
|
||||||
|
|
||||||
|
class RoomJoinRatelimitTestCase(RoomBase):
|
||||||
|
user_id = "@sid1:red"
|
||||||
|
|
||||||
|
servlets = [
|
||||||
|
profile.register_servlets,
|
||||||
|
room.register_servlets,
|
||||||
|
]
|
||||||
|
|
||||||
|
@unittest.override_config(
|
||||||
|
{"rc_joins": {"local": {"per_second": 3, "burst_count": 3}}}
|
||||||
|
)
|
||||||
|
def test_join_local_ratelimit(self):
|
||||||
|
"""Tests that local joins are actually rate-limited."""
|
||||||
|
for i in range(5):
|
||||||
|
self.helper.create_room_as(self.user_id)
|
||||||
|
|
||||||
|
self.helper.create_room_as(self.user_id, expect_code=429)
|
||||||
|
|
||||||
|
@unittest.override_config(
|
||||||
|
{"rc_joins": {"local": {"per_second": 3, "burst_count": 3}}}
|
||||||
|
)
|
||||||
|
def test_join_local_ratelimit_profile_change(self):
|
||||||
|
"""Tests that sending a profile update into all of the user's joined rooms isn't
|
||||||
|
rate-limited by the rate-limiter on joins."""
|
||||||
|
|
||||||
|
# Create and join more rooms than the rate-limiting config allows in a second.
|
||||||
|
room_ids = [
|
||||||
|
self.helper.create_room_as(self.user_id),
|
||||||
|
self.helper.create_room_as(self.user_id),
|
||||||
|
self.helper.create_room_as(self.user_id),
|
||||||
|
]
|
||||||
|
self.reactor.advance(1)
|
||||||
|
room_ids = room_ids + [
|
||||||
|
self.helper.create_room_as(self.user_id),
|
||||||
|
self.helper.create_room_as(self.user_id),
|
||||||
|
self.helper.create_room_as(self.user_id),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create a profile for the user, since it hasn't been done on registration.
|
||||||
|
store = self.hs.get_datastore()
|
||||||
|
store.create_profile(UserID.from_string(self.user_id).localpart)
|
||||||
|
|
||||||
|
# Update the display name for the user.
|
||||||
|
path = "/_matrix/client/r0/profile/%s/displayname" % self.user_id
|
||||||
|
request, channel = self.make_request("PUT", path, {"displayname": "John Doe"})
|
||||||
|
self.render(request)
|
||||||
|
self.assertEquals(channel.code, 200, channel.json_body)
|
||||||
|
|
||||||
|
# Check that all the rooms have been sent a profile update into.
|
||||||
|
for room_id in room_ids:
|
||||||
|
path = "/_matrix/client/r0/rooms/%s/state/m.room.member/%s" % (
|
||||||
|
room_id,
|
||||||
|
self.user_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
request, channel = self.make_request("GET", path)
|
||||||
|
self.render(request)
|
||||||
|
self.assertEquals(channel.code, 200)
|
||||||
|
|
||||||
|
self.assertIn("displayname", channel.json_body)
|
||||||
|
self.assertEquals(channel.json_body["displayname"], "John Doe")
|
||||||
|
|
||||||
|
@unittest.override_config(
|
||||||
|
{"rc_joins": {"local": {"per_second": 3, "burst_count": 3}}}
|
||||||
|
)
|
||||||
|
def test_join_local_ratelimit_idempotent(self):
|
||||||
|
"""Tests that the room join endpoints remain idempotent despite rate-limiting
|
||||||
|
on room joins."""
|
||||||
|
room_id = self.helper.create_room_as(self.user_id)
|
||||||
|
|
||||||
|
# Let's test both paths to be sure.
|
||||||
|
paths_to_test = [
|
||||||
|
"/_matrix/client/r0/rooms/%s/join",
|
||||||
|
"/_matrix/client/r0/join/%s",
|
||||||
|
]
|
||||||
|
|
||||||
|
for path in paths_to_test:
|
||||||
|
# Make sure we send more requests than the rate-limiting config would allow
|
||||||
|
# if all of these requests ended up joining the user to a room.
|
||||||
|
for i in range(6):
|
||||||
|
request, channel = self.make_request("POST", path % room_id, {})
|
||||||
|
self.render(request)
|
||||||
|
self.assertEquals(channel.code, 200)
|
||||||
|
|
||||||
|
|
||||||
class RoomMessagesTestCase(RoomBase):
|
class RoomMessagesTestCase(RoomBase):
|
||||||
""" Tests /rooms/$room_id/messages/$user_id/$msg_id REST events. """
|
""" Tests /rooms/$room_id/messages/$user_id/$msg_id REST events. """
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,9 @@ class RestHelper(object):
|
||||||
resource = attr.ib()
|
resource = attr.ib()
|
||||||
auth_user_id = attr.ib()
|
auth_user_id = attr.ib()
|
||||||
|
|
||||||
def create_room_as(self, room_creator=None, is_public=True, tok=None):
|
def create_room_as(
|
||||||
|
self, room_creator=None, is_public=True, tok=None, expect_code=200,
|
||||||
|
):
|
||||||
temp_id = self.auth_user_id
|
temp_id = self.auth_user_id
|
||||||
self.auth_user_id = room_creator
|
self.auth_user_id = room_creator
|
||||||
path = "/_matrix/client/r0/createRoom"
|
path = "/_matrix/client/r0/createRoom"
|
||||||
|
@ -54,9 +56,11 @@ class RestHelper(object):
|
||||||
)
|
)
|
||||||
render(request, self.resource, self.hs.get_reactor())
|
render(request, self.resource, self.hs.get_reactor())
|
||||||
|
|
||||||
assert channel.result["code"] == b"200", channel.result
|
assert channel.result["code"] == b"%d" % expect_code, channel.result
|
||||||
self.auth_user_id = temp_id
|
self.auth_user_id = temp_id
|
||||||
return channel.json_body["room_id"]
|
|
||||||
|
if expect_code == 200:
|
||||||
|
return channel.json_body["room_id"]
|
||||||
|
|
||||||
def invite(self, room=None, src=None, targ=None, expect_code=200, tok=None):
|
def invite(self, room=None, src=None, targ=None, expect_code=200, tok=None):
|
||||||
self.change_membership(
|
self.change_membership(
|
||||||
|
|
Loading…
Reference in a new issue