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

Commit f7b034a

Browse files
David Robertsonrichvdh
David Robertson
andauthored
Consistently exclude from user_directory (#10960)
* Introduce `should_include_local_users_in_dir` We exclude three kinds of local users from the user_directory tables. At present we don't consistently exclude all three in the same places. This commit introduces a new function to gather those exclusion conditions together. Because we have to handle local and remote users in different ways, I've made that function only consider the case of remote users. It's the caller's responsibility to make the local versus remote distinction clear and correct. A test fixup is required. The test now hits a path which makes db queries against the users table. The expected rows were missing, because we were using a dummy user that hadn't actually been registered. We also add new test cases to covert the exclusion logic. ---- By my reading this makes these changes: * When an app service user registers or changes their profile, they will _not_ be added to the user directory. (Previously only support and deactivated users were excluded). This is consistent with the logic that rebuilds the user directory. See also [the discussion here](#10914 (comment)). * When rebuilding the directory, exclude support and disabled users from room sharing tables. Previously only appservice users were excluded. * Exclude all three categories of local users when rebuilding the directory. Previously `_populate_user_directory_process_users` didn't do any exclusion. Co-authored-by: Richard van der Hoff <[email protected]>
1 parent a0f48ee commit f7b034a

File tree

7 files changed

+409
-57
lines changed

7 files changed

+409
-57
lines changed

changelog.d/10960.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a long-standing bug where rebuilding the user directory wouldn't exclude support and disabled users.

synapse/handlers/user_directory.py

+9-18
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,7 @@ async def handle_local_profile_change(
132132
# FIXME(#3714): We should probably do this in the same worker as all
133133
# the other changes.
134134

135-
# Support users are for diagnostics and should not appear in the user directory.
136-
is_support = await self.store.is_support_user(user_id)
137-
# When change profile information of deactivated user it should not appear in the user directory.
138-
is_deactivated = await self.store.get_user_deactivated_status(user_id)
139-
140-
if not (is_support or is_deactivated):
135+
if await self.store.should_include_local_user_in_dir(user_id):
141136
await self.store.update_profile_in_user_dir(
142137
user_id, profile.display_name, profile.avatar_url
143138
)
@@ -229,8 +224,10 @@ async def _handle_deltas(self, deltas: List[Dict[str, Any]]) -> None:
229224
else:
230225
logger.debug("Server is still in room: %r", room_id)
231226

232-
is_support = await self.store.is_support_user(state_key)
233-
if not is_support:
227+
include_in_dir = not self.is_mine_id(
228+
state_key
229+
) or await self.store.should_include_local_user_in_dir(state_key)
230+
if include_in_dir:
234231
if change is MatchChange.no_change:
235232
# Handle any profile changes
236233
await self._handle_profile_change(
@@ -356,13 +353,7 @@ async def _handle_new_user(
356353

357354
# First, if they're our user then we need to update for every user
358355
if self.is_mine_id(user_id):
359-
360-
is_appservice = self.store.get_if_app_services_interested_in_user(
361-
user_id
362-
)
363-
364-
# We don't care about appservice users.
365-
if not is_appservice:
356+
if await self.store.should_include_local_user_in_dir(user_id):
366357
for other_user_id in other_users_in_room:
367358
if user_id == other_user_id:
368359
continue
@@ -374,10 +365,10 @@ async def _handle_new_user(
374365
if user_id == other_user_id:
375366
continue
376367

377-
is_appservice = self.store.get_if_app_services_interested_in_user(
368+
include_other_user = self.is_mine_id(
378369
other_user_id
379-
)
380-
if self.is_mine_id(other_user_id) and not is_appservice:
370+
) and await self.store.should_include_local_user_in_dir(other_user_id)
371+
if include_other_user:
381372
to_insert.add((other_user_id, user_id))
382373

383374
if to_insert:

synapse/storage/databases/main/user_directory.py

+33-13
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@
4040

4141
logger = logging.getLogger(__name__)
4242

43-
4443
TEMP_TABLE = "_temp_populate_user_directory"
4544

4645

4746
class UserDirectoryBackgroundUpdateStore(StateDeltasStore):
48-
4947
# How many records do we calculate before sending it to
5048
# add_users_who_share_private_rooms?
5149
SHARE_PRIVATE_WORKING_SET = 500
@@ -235,6 +233,13 @@ def _get_next_batch(
235233
)
236234

237235
users_with_profile = await self.get_users_in_room_with_profiles(room_id)
236+
# Throw away users excluded from the directory.
237+
users_with_profile = {
238+
user_id: profile
239+
for user_id, profile in users_with_profile.items()
240+
if not self.hs.is_mine_id(user_id)
241+
or await self.should_include_local_user_in_dir(user_id)
242+
}
238243

239244
# Update each user in the user directory.
240245
for user_id, profile in users_with_profile.items():
@@ -246,22 +251,19 @@ def _get_next_batch(
246251

247252
if is_public:
248253
for user_id in users_with_profile:
249-
if self.get_if_app_services_interested_in_user(user_id):
250-
continue
251-
252254
to_insert.add(user_id)
253255

254256
if to_insert:
255257
await self.add_users_in_public_rooms(room_id, to_insert)
256258
to_insert.clear()
257259
else:
258260
for user_id in users_with_profile:
261+
# We want the set of pairs (L, M) where L and M are
262+
# in `users_with_profile` and L is local.
263+
# Do so by looking for the local user L first.
259264
if not self.hs.is_mine_id(user_id):
260265
continue
261266

262-
if self.get_if_app_services_interested_in_user(user_id):
263-
continue
264-
265267
for other_user_id in users_with_profile:
266268
if user_id == other_user_id:
267269
continue
@@ -349,10 +351,11 @@ def _get_next_batch(txn: LoggingTransaction) -> Optional[List[str]]:
349351
)
350352

351353
for user_id in users_to_work_on:
352-
profile = await self.get_profileinfo(get_localpart_from_id(user_id))
353-
await self.update_profile_in_user_dir(
354-
user_id, profile.display_name, profile.avatar_url
355-
)
354+
if await self.should_include_local_user_in_dir(user_id):
355+
profile = await self.get_profileinfo(get_localpart_from_id(user_id))
356+
await self.update_profile_in_user_dir(
357+
user_id, profile.display_name, profile.avatar_url
358+
)
356359

357360
# We've finished processing a user. Delete it from the table.
358361
await self.db_pool.simple_delete_one(
@@ -369,6 +372,24 @@ def _get_next_batch(txn: LoggingTransaction) -> Optional[List[str]]:
369372

370373
return len(users_to_work_on)
371374

375+
async def should_include_local_user_in_dir(self, user: str) -> bool:
376+
"""Certain classes of local user are omitted from the user directory.
377+
Is this user one of them?
378+
"""
379+
# App service users aren't usually contactable, so exclude them.
380+
if self.get_if_app_services_interested_in_user(user):
381+
# TODO we might want to make this configurable for each app service
382+
return False
383+
384+
# Support users are for diagnostics and should not appear in the user directory.
385+
if await self.is_support_user(user):
386+
return False
387+
388+
# Deactivated users aren't contactable, so should not appear in the user directory.
389+
if await self.get_user_deactivated_status(user):
390+
return False
391+
return True
392+
372393
async def is_room_world_readable_or_publicly_joinable(self, room_id: str) -> bool:
373394
"""Check if the room is either world_readable or publically joinable"""
374395

@@ -537,7 +558,6 @@ async def update_user_directory_stream_pos(self, stream_id: Optional[int]) -> No
537558

538559

539560
class UserDirectoryStore(UserDirectoryBackgroundUpdateStore):
540-
541561
# How many records do we calculate before sending it to
542562
# add_users_who_share_private_rooms?
543563
SHARE_PRIVATE_WORKING_SET = 500

0 commit comments

Comments
 (0)