From 95121ad905fbb2974951f2d854fa2c7eb4d41049 Mon Sep 17 00:00:00 2001 From: dasha_uwu Date: Sat, 17 Jan 2026 04:42:42 +0500 Subject: [PATCH] Add a config option to show all local users in user directory, closes #260 --- src/api/client/user_directory.rs | 102 +++++++++++++++++++------------ src/core/config/mod.rs | 8 +++ tuwunel-example.toml | 6 ++ 3 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/api/client/user_directory.rs b/src/api/client/user_directory.rs index eae78e71..c7839a1f 100644 --- a/src/api/client/user_directory.rs +++ b/src/api/client/user_directory.rs @@ -1,6 +1,7 @@ use axum::extract::State; use futures::{FutureExt, StreamExt, pin_mut}; use ruma::{ + UserId, api::client::user_directory::search_users::{self}, events::room::join_rules::JoinRule, }; @@ -11,6 +12,7 @@ use tuwunel_core::{ stream::{BroadbandExt, ReadyExt}, }, }; +use tuwunel_service::Services; use crate::Ruma; @@ -42,45 +44,19 @@ pub(crate) async fn search_users_route( .broad_filter_map(async |user_id| { let display_name = services.users.displayname(&user_id).await.ok(); - let user_id_matches = user_id - .as_str() - .to_lowercase() - .contains(&search_term); - - let display_name_matches = display_name - .as_deref() - .map(str::to_lowercase) - .is_some_and(|display_name| display_name.contains(&search_term)); - - if !user_id_matches && !display_name_matches { - return None; - } - - let user_in_public_room = services - .state_cache - .rooms_joined(&user_id) - .map(ToOwned::to_owned) - .broad_any(async |room_id| { - services - .state_accessor - .get_join_rules(&room_id) - .map(|rule| matches!(rule, JoinRule::Public)) - .await - }); - - let user_sees_user = services - .state_cache - .user_sees_user(sender_user, &user_id); - - pin_mut!(user_in_public_room, user_sees_user); - user_in_public_room - .or(user_sees_user) - .await - .then_some(search_users::v3::User { - user_id: user_id.clone(), - display_name, - avatar_url: services.users.avatar_url(&user_id).await.ok(), - }) + should_show_user( + &services, + sender_user, + &user_id, + display_name.as_deref(), + &search_term, + ) + .await + .then_some(search_users::v3::User { + user_id: user_id.clone(), + display_name, + avatar_url: services.users.avatar_url(&user_id).await.ok(), + }) }); pin_mut!(users); @@ -89,3 +65,51 @@ pub(crate) async fn search_users_route( Ok(search_users::v3::Response { results, limited }) } + +async fn should_show_user( + services: &Services, + sender_user: &UserId, + target_user: &UserId, + target_display_name: Option<&str>, + search_term: &str, +) -> bool { + let user_id_matches = target_user + .as_str() + .to_lowercase() + .contains(search_term); + + let display_name_matches = target_display_name + .map(str::to_lowercase) + .is_some_and(|display_name| display_name.contains(search_term)); + + if !user_id_matches && !display_name_matches { + return false; + } + + if services + .server + .config + .show_all_local_users_in_user_directory + { + return true; + } + + let user_in_public_room = services + .state_cache + .rooms_joined(target_user) + .map(ToOwned::to_owned) + .broad_any(async |room_id| { + services + .state_accessor + .get_join_rules(&room_id) + .map(|rule| matches!(rule, JoinRule::Public)) + .await + }); + + let user_sees_user = services + .state_cache + .user_sees_user(sender_user, target_user); + + pin_mut!(user_in_public_room, user_sees_user); + user_in_public_room.or(user_sees_user).await +} diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index cb2f1366..2d04eecd 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -674,6 +674,14 @@ pub struct Config { #[serde(default = "true_fn")] pub allow_unlisted_room_search_by_id: bool, + /// Show all local users in user directory. With this set to false, only + /// users in public rooms or those that share a room with the user making + /// the search will be shown. + /// + /// default: false + #[serde(default)] + pub show_all_local_users_in_user_directory: bool, + /// Allow guests/unauthenticated users to access TURN credentials. /// /// This is the equivalent of Synapse's `turn_allow_guests` config option. diff --git a/tuwunel-example.toml b/tuwunel-example.toml index 0baf02cd..424df2f9 100644 --- a/tuwunel-example.toml +++ b/tuwunel-example.toml @@ -538,6 +538,12 @@ # #allow_unlisted_room_search_by_id = true +# Show all local users in user directory. With this set to false, only +# users in public rooms or those that share a room with the user making +# the search will be shown. +# +#show_all_local_users_in_user_directory = false + # Allow guests/unauthenticated users to access TURN credentials. # # This is the equivalent of Synapse's `turn_allow_guests` config option.