Add a config option to show all local users in user directory, closes #260
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use futures::{FutureExt, StreamExt, pin_mut};
|
use futures::{FutureExt, StreamExt, pin_mut};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
|
UserId,
|
||||||
api::client::user_directory::search_users::{self},
|
api::client::user_directory::search_users::{self},
|
||||||
events::room::join_rules::JoinRule,
|
events::room::join_rules::JoinRule,
|
||||||
};
|
};
|
||||||
@@ -11,6 +12,7 @@ use tuwunel_core::{
|
|||||||
stream::{BroadbandExt, ReadyExt},
|
stream::{BroadbandExt, ReadyExt},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use tuwunel_service::Services;
|
||||||
|
|
||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
|
|
||||||
@@ -42,45 +44,19 @@ pub(crate) async fn search_users_route(
|
|||||||
.broad_filter_map(async |user_id| {
|
.broad_filter_map(async |user_id| {
|
||||||
let display_name = services.users.displayname(&user_id).await.ok();
|
let display_name = services.users.displayname(&user_id).await.ok();
|
||||||
|
|
||||||
let user_id_matches = user_id
|
should_show_user(
|
||||||
.as_str()
|
&services,
|
||||||
.to_lowercase()
|
sender_user,
|
||||||
.contains(&search_term);
|
&user_id,
|
||||||
|
display_name.as_deref(),
|
||||||
let display_name_matches = display_name
|
&search_term,
|
||||||
.as_deref()
|
)
|
||||||
.map(str::to_lowercase)
|
.await
|
||||||
.is_some_and(|display_name| display_name.contains(&search_term));
|
.then_some(search_users::v3::User {
|
||||||
|
user_id: user_id.clone(),
|
||||||
if !user_id_matches && !display_name_matches {
|
display_name,
|
||||||
return None;
|
avatar_url: services.users.avatar_url(&user_id).await.ok(),
|
||||||
}
|
})
|
||||||
|
|
||||||
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(),
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
pin_mut!(users);
|
pin_mut!(users);
|
||||||
@@ -89,3 +65,51 @@ pub(crate) async fn search_users_route(
|
|||||||
|
|
||||||
Ok(search_users::v3::Response { results, limited })
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -674,6 +674,14 @@ pub struct Config {
|
|||||||
#[serde(default = "true_fn")]
|
#[serde(default = "true_fn")]
|
||||||
pub allow_unlisted_room_search_by_id: bool,
|
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.
|
/// Allow guests/unauthenticated users to access TURN credentials.
|
||||||
///
|
///
|
||||||
/// This is the equivalent of Synapse's `turn_allow_guests` config option.
|
/// This is the equivalent of Synapse's `turn_allow_guests` config option.
|
||||||
|
|||||||
@@ -538,6 +538,12 @@
|
|||||||
#
|
#
|
||||||
#allow_unlisted_room_search_by_id = true
|
#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.
|
# Allow guests/unauthenticated users to access TURN credentials.
|
||||||
#
|
#
|
||||||
# This is the equivalent of Synapse's `turn_allow_guests` config option.
|
# This is the equivalent of Synapse's `turn_allow_guests` config option.
|
||||||
|
|||||||
Reference in New Issue
Block a user