Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit d58615c

Browse files
Directly lookup local membership instead of getting all members in a room first (get_users_in_room mis-use) (#13608)
See #13575 (comment)
1 parent b93bd95 commit d58615c

File tree

8 files changed

+60
-17
lines changed

8 files changed

+60
-17
lines changed

changelog.d/13608.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Refactor `get_users_in_room(room_id)` mis-use to lookup single local user with dedicated `check_local_user_in_room(...)` function.

synapse/handlers/events.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ async def get_event(
151151
"""Retrieve a single specified event.
152152
153153
Args:
154-
user: The user requesting the event
154+
user: The local user requesting the event
155155
room_id: The expected room id. We'll return None if the
156156
event's room does not match.
157157
event_id: The event ID to obtain.
@@ -173,8 +173,11 @@ async def get_event(
173173
if not event:
174174
return None
175175

176-
users = await self.store.get_users_in_room(event.room_id)
177-
is_peeking = user.to_string() not in users
176+
is_user_in_room = await self.store.check_local_user_in_room(
177+
user_id=user.to_string(), room_id=event.room_id
178+
)
179+
# The user is peeking if they aren't in the room already
180+
is_peeking = not is_user_in_room
178181

179182
filtered = await filter_events_for_client(
180183
self._storage_controllers, user.to_string(), [event], is_peeking=is_peeking

synapse/handlers/message.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -761,8 +761,10 @@ async def _is_exempt_from_privacy_policy(
761761
async def _is_server_notices_room(self, room_id: str) -> bool:
762762
if self.config.servernotices.server_notices_mxid is None:
763763
return False
764-
user_ids = await self.store.get_users_in_room(room_id)
765-
return self.config.servernotices.server_notices_mxid in user_ids
764+
is_server_notices_room = await self.store.check_local_user_in_room(
765+
user_id=self.config.servernotices.server_notices_mxid, room_id=room_id
766+
)
767+
return is_server_notices_room
766768

767769
async def assert_accepted_privacy_policy(self, requester: Requester) -> None:
768770
"""Check if a user has accepted the privacy policy

synapse/handlers/room.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1284,8 +1284,11 @@ async def get_event_context(
12841284
before_limit = math.floor(limit / 2.0)
12851285
after_limit = limit - before_limit
12861286

1287-
users = await self.store.get_users_in_room(room_id)
1288-
is_peeking = user.to_string() not in users
1287+
is_user_in_room = await self.store.check_local_user_in_room(
1288+
user_id=user.to_string(), room_id=room_id
1289+
)
1290+
# The user is peeking if they aren't in the room already
1291+
is_peeking = not is_user_in_room
12891292

12901293
async def filter_evts(events: List[EventBase]) -> List[EventBase]:
12911294
if use_admin_priviledge:

synapse/handlers/room_member.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1620,8 +1620,10 @@ async def _is_host_in_room(self, current_state_ids: StateMap[str]) -> bool:
16201620
async def _is_server_notice_room(self, room_id: str) -> bool:
16211621
if self._server_notices_mxid is None:
16221622
return False
1623-
user_ids = await self.store.get_users_in_room(room_id)
1624-
return self._server_notices_mxid in user_ids
1623+
is_server_notices_room = await self.store.check_local_user_in_room(
1624+
user_id=self._server_notices_mxid, room_id=room_id
1625+
)
1626+
return is_server_notices_room
16251627

16261628

16271629
class RoomMemberMasterHandler(RoomMemberHandler):

synapse/server_notices/server_notices_manager.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ async def maybe_get_notice_room_for_user(self, user_id: str) -> Optional[str]:
102102
Returns:
103103
The room's ID, or None if no room could be found.
104104
"""
105+
# If there is no server notices MXID, then there is no server notices room
106+
if self.server_notices_mxid is None:
107+
return None
108+
105109
rooms = await self._store.get_rooms_for_local_user_where_membership_is(
106110
user_id, [Membership.INVITE, Membership.JOIN]
107111
)
@@ -111,8 +115,10 @@ async def maybe_get_notice_room_for_user(self, user_id: str) -> Optional[str]:
111115
# be joined. This is kinda deliberate, in that if somebody somehow
112116
# manages to invite the system user to a room, that doesn't make it
113117
# the server notices room.
114-
user_ids = await self._store.get_users_in_room(room.room_id)
115-
if len(user_ids) <= 2 and self.server_notices_mxid in user_ids:
118+
is_server_notices_room = await self._store.check_local_user_in_room(
119+
user_id=self.server_notices_mxid, room_id=room.room_id
120+
)
121+
if is_server_notices_room:
116122
# we found a room which our user shares with the system notice
117123
# user
118124
return room.room_id

synapse/storage/databases/main/roommember.py

+26
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,32 @@ async def get_local_users_in_room(self, room_id: str) -> List[str]:
534534
desc="get_local_users_in_room",
535535
)
536536

537+
async def check_local_user_in_room(self, user_id: str, room_id: str) -> bool:
538+
"""
539+
Check whether a given local user is currently joined to the given room.
540+
541+
Returns:
542+
A boolean indicating whether the user is currently joined to the room
543+
544+
Raises:
545+
Exeption when called with a non-local user to this homeserver
546+
"""
547+
if not self.hs.is_mine_id(user_id):
548+
raise Exception(
549+
"Cannot call 'check_local_user_in_room' on "
550+
"non-local user %s" % (user_id,),
551+
)
552+
553+
(
554+
membership,
555+
member_event_id,
556+
) = await self.get_local_current_membership_for_user_in_room(
557+
user_id=user_id,
558+
room_id=room_id,
559+
)
560+
561+
return membership == Membership.JOIN
562+
537563
async def get_local_current_membership_for_user_in_room(
538564
self, user_id: str, room_id: str
539565
) -> Tuple[Optional[str], Optional[str]]:

tests/rest/client/test_relations.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ def assert_annotations(bundled_aggregations: JsonDict) -> None:
999999
bundled_aggregations,
10001000
)
10011001

1002-
self._test_bundled_aggregations(RelationTypes.ANNOTATION, assert_annotations, 6)
1002+
self._test_bundled_aggregations(RelationTypes.ANNOTATION, assert_annotations, 7)
10031003

10041004
def test_annotation_to_annotation(self) -> None:
10051005
"""Any relation to an annotation should be ignored."""
@@ -1035,7 +1035,7 @@ def assert_annotations(bundled_aggregations: JsonDict) -> None:
10351035
bundled_aggregations,
10361036
)
10371037

1038-
self._test_bundled_aggregations(RelationTypes.REFERENCE, assert_annotations, 6)
1038+
self._test_bundled_aggregations(RelationTypes.REFERENCE, assert_annotations, 7)
10391039

10401040
def test_thread(self) -> None:
10411041
"""
@@ -1080,21 +1080,21 @@ def assert_thread(bundled_aggregations: JsonDict) -> None:
10801080

10811081
# The "user" sent the root event and is making queries for the bundled
10821082
# aggregations: they have participated.
1083-
self._test_bundled_aggregations(RelationTypes.THREAD, _gen_assert(True), 8)
1083+
self._test_bundled_aggregations(RelationTypes.THREAD, _gen_assert(True), 9)
10841084
# The "user2" sent replies in the thread and is making queries for the
10851085
# bundled aggregations: they have participated.
10861086
#
10871087
# Note that this re-uses some cached values, so the total number of
10881088
# queries is much smaller.
10891089
self._test_bundled_aggregations(
1090-
RelationTypes.THREAD, _gen_assert(True), 2, access_token=self.user2_token
1090+
RelationTypes.THREAD, _gen_assert(True), 3, access_token=self.user2_token
10911091
)
10921092

10931093
# A user with no interactions with the thread: they have not participated.
10941094
user3_id, user3_token = self._create_user("charlie")
10951095
self.helper.join(self.room, user=user3_id, tok=user3_token)
10961096
self._test_bundled_aggregations(
1097-
RelationTypes.THREAD, _gen_assert(False), 2, access_token=user3_token
1097+
RelationTypes.THREAD, _gen_assert(False), 3, access_token=user3_token
10981098
)
10991099

11001100
def test_thread_with_bundled_aggregations_for_latest(self) -> None:
@@ -1142,7 +1142,7 @@ def assert_thread(bundled_aggregations: JsonDict) -> None:
11421142
bundled_aggregations["latest_event"].get("unsigned"),
11431143
)
11441144

1145-
self._test_bundled_aggregations(RelationTypes.THREAD, assert_thread, 8)
1145+
self._test_bundled_aggregations(RelationTypes.THREAD, assert_thread, 9)
11461146

11471147
def test_nested_thread(self) -> None:
11481148
"""

0 commit comments

Comments
 (0)