Add a config option to show all local users in user directory, closes #260

This commit is contained in:
dasha_uwu
2026-01-17 04:42:42 +05:00
committed by Jason Volk
parent 62ec58b1ed
commit 95121ad905
3 changed files with 77 additions and 39 deletions

View File

@@ -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
}

View File

@@ -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.

View File

@@ -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.