Skip to content

Commit d221512

Browse files
authored
SS: Implement $ME support (#17469)
`$ME` can be used as a substitute for the requester's user ID.
1 parent ed0face commit d221512

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

changelog.d/17469.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Implement handling of `$ME` as a state key in sliding sync.

synapse/handlers/sliding_sync.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ class StateValues:
329329
# `sender` in the timeline). We only give special meaning to this value when it's a
330330
# `state_key`.
331331
LAZY: Final = "$LAZY"
332+
# Subsitute with the requester's user ID. Typically used by clients to get
333+
# the user's membership.
334+
ME: Final = "$ME"
332335

333336

334337
class SlidingSyncHandler:
@@ -504,7 +507,6 @@ async def current_sync_for_user(
504507
# Also see `StateFilter.must_await_full_state(...)` for comparison
505508
lazy_loading = (
506509
membership_state_keys is not None
507-
and len(membership_state_keys) == 1
508510
and StateValues.LAZY in membership_state_keys
509511
)
510512

@@ -1662,6 +1664,8 @@ async def get_room_sync_data(
16621664

16631665
# FIXME: We probably also care about invite, ban, kick, targets, etc
16641666
# but the spec only mentions "senders".
1667+
elif state_key == StateValues.ME:
1668+
required_state_types.append((state_type, user.to_string()))
16651669
else:
16661670
required_state_types.append((state_type, state_key))
16671671

tests/rest/client/test_sync.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3714,6 +3714,80 @@ def test_rooms_required_state_lazy_loading_room_members(self) -> None:
37143714
)
37153715
self.assertIsNone(channel.json_body["rooms"][room_id1].get("invite_state"))
37163716

3717+
def test_rooms_required_state_me(self) -> None:
3718+
"""
3719+
Test `rooms.required_state` correctly handles $ME.
3720+
"""
3721+
user1_id = self.register_user("user1", "pass")
3722+
user1_tok = self.login(user1_id, "pass")
3723+
user2_id = self.register_user("user2", "pass")
3724+
user2_tok = self.login(user2_id, "pass")
3725+
3726+
room_id1 = self.helper.create_room_as(user2_id, tok=user2_tok)
3727+
self.helper.join(room_id1, user1_id, tok=user1_tok)
3728+
3729+
self.helper.send(room_id1, "1", tok=user2_tok)
3730+
3731+
# Also send normal state events with state keys of the users, first
3732+
# change the power levels to allow this.
3733+
self.helper.send_state(
3734+
room_id1,
3735+
event_type=EventTypes.PowerLevels,
3736+
body={"users": {user1_id: 50, user2_id: 100}},
3737+
tok=user2_tok,
3738+
)
3739+
self.helper.send_state(
3740+
room_id1,
3741+
event_type="org.matrix.foo",
3742+
state_key=user1_id,
3743+
body={},
3744+
tok=user1_tok,
3745+
)
3746+
self.helper.send_state(
3747+
room_id1,
3748+
event_type="org.matrix.foo",
3749+
state_key=user2_id,
3750+
body={},
3751+
tok=user2_tok,
3752+
)
3753+
3754+
# Make the Sliding Sync request with a request for '$ME'.
3755+
channel = self.make_request(
3756+
"POST",
3757+
self.sync_endpoint,
3758+
{
3759+
"lists": {
3760+
"foo-list": {
3761+
"ranges": [[0, 1]],
3762+
"required_state": [
3763+
[EventTypes.Create, ""],
3764+
[EventTypes.Member, StateValues.ME],
3765+
["org.matrix.foo", StateValues.ME],
3766+
],
3767+
"timeline_limit": 3,
3768+
}
3769+
}
3770+
},
3771+
access_token=user1_tok,
3772+
)
3773+
self.assertEqual(channel.code, 200, channel.json_body)
3774+
3775+
state_map = self.get_success(
3776+
self.storage_controllers.state.get_current_state(room_id1)
3777+
)
3778+
3779+
# Only user2 and user3 sent events in the 3 events we see in the `timeline`
3780+
self._assertRequiredStateIncludes(
3781+
channel.json_body["rooms"][room_id1]["required_state"],
3782+
{
3783+
state_map[(EventTypes.Create, "")],
3784+
state_map[(EventTypes.Member, user1_id)],
3785+
state_map[("org.matrix.foo", user1_id)],
3786+
},
3787+
exact=True,
3788+
)
3789+
self.assertIsNone(channel.json_body["rooms"][room_id1].get("invite_state"))
3790+
37173791
@parameterized.expand([(Membership.LEAVE,), (Membership.BAN,)])
37183792
def test_rooms_required_state_leave_ban(self, stop_membership: str) -> None:
37193793
"""

0 commit comments

Comments
 (0)