feat: Allow local server admins to bypass summary visibility checks

feat: Allow local server admins to bypass summary visibility checks

Also improve error messages so they aren't so damn long.
This commit is contained in:
timedout
2025-12-31 20:01:29 +00:00
committed by Jade Ellis
parent 8a561fcd3a
commit a7e6e6e83f
+28 -22
View File
@@ -1,12 +1,13 @@
use axum::extract::State; use axum::extract::State;
use axum_client_ip::InsecureClientIp; use axum_client_ip::InsecureClientIp;
use conduwuit::{ use conduwuit::{
Err, Result, debug_warn, trace, Err, Result, debug, debug_warn, info, trace,
utils::{IterStream, future::TryExtExt}, utils::{IterStream, future::TryExtExt},
warn,
}; };
use futures::{ use futures::{
FutureExt, StreamExt, FutureExt, StreamExt, TryFutureExt,
future::{OptionFuture, join3}, future::{OptionFuture, join, join3},
stream::FuturesUnordered, stream::FuturesUnordered,
}; };
use ruma::{ use ruma::{
@@ -111,14 +112,13 @@ async fn local_room_summary_response(
sender_user: Option<&UserId>, sender_user: Option<&UserId>,
) -> Result<get_summary::msc3266::Response> { ) -> Result<get_summary::msc3266::Response> {
trace!(?sender_user, "Sending local room summary response for {room_id:?}"); trace!(?sender_user, "Sending local room summary response for {room_id:?}");
let join_rule = services.rooms.state_accessor.get_join_rules(room_id); let join_rule = services.rooms.state_accessor.get_join_rules(room_id).await;
// Synapse allows server admins to bypass visibility checks.
// That seems neat so we'll copy that behaviour.
if sender_user.is_none() || !services.users.is_admin(sender_user.unwrap()).await {
let world_readable = services.rooms.state_accessor.is_world_readable(room_id); let world_readable = services.rooms.state_accessor.is_world_readable(room_id);
let guest_can_join = services.rooms.state_accessor.guest_can_join(room_id); let guest_can_join = services.rooms.state_accessor.guest_can_join(room_id);
let (world_readable, guest_can_join) = join(world_readable, guest_can_join).await;
let (join_rule, world_readable, guest_can_join) =
join3(join_rule, world_readable, guest_can_join).await;
trace!("{join_rule:?}, {world_readable:?}, {guest_can_join:?}"); trace!("{join_rule:?}, {world_readable:?}, {guest_can_join:?}");
user_can_see_summary( user_can_see_summary(
@@ -131,6 +131,7 @@ async fn local_room_summary_response(
sender_user, sender_user,
) )
.await?; .await?;
}
let canonical_alias = services let canonical_alias = services
.rooms .rooms
@@ -231,15 +232,27 @@ async fn remote_room_summary_hierarchy_response(
"Federaton of room {room_id} is currently disabled on this server." "Federaton of room {room_id} is currently disabled on this server."
))); )));
} }
if servers.is_empty() {
return Err!(Request(MissingParam(
"No servers were provided to fetch the room over federation"
)));
}
let request = get_hierarchy::v1::Request::new(room_id.to_owned()); let request = get_hierarchy::v1::Request::new(room_id.to_owned());
let mut requests: FuturesUnordered<_> = servers let mut requests: FuturesUnordered<_> = servers
.iter() .iter()
.map(|server| { .map(|server| {
info!("Fetching room summary for {room_id} from server {server}");
services services
.sending .sending
.send_federation_request(server, request.clone()) .send_federation_request(server, request.clone())
.inspect_ok(|v| {
debug!("Fetched room summary for {room_id} from server {server}: {v:?}");
})
.inspect_err(|e| {
info!("Failed to fetch room summary for {room_id} from server {server}: {e}");
})
}) })
.collect(); .collect();
@@ -255,6 +268,7 @@ async fn remote_room_summary_hierarchy_response(
continue; continue;
} }
if sender_user.is_none() || !services.users.is_admin(sender_user.unwrap()).await {
return user_can_see_summary( return user_can_see_summary(
services, services,
room_id, room_id,
@@ -267,11 +281,10 @@ async fn remote_room_summary_hierarchy_response(
.await .await
.map(|()| room); .map(|()| room);
} }
return Ok(room);
}
Err!(Request(NotFound( Err!(Request(NotFound("Room not found or is not accessible")))
"Room is unknown to this server and was unable to fetch over federation with the \
provided servers available"
)))
} }
async fn user_can_see_summary<'a, I>( async fn user_can_see_summary<'a, I>(
@@ -311,21 +324,14 @@ where
return Ok(()); return Ok(());
} }
Err!(Request(Forbidden( Err!(Request(Forbidden("Room is not accessible")))
"Room is not world readable, not publicly accessible/joinable, restricted room \
conditions not met, and guest access is forbidden. Not allowed to see details \
of this room."
)))
}, },
| None => { | None => {
if is_public_room || world_readable { if is_public_room || world_readable {
return Ok(()); return Ok(());
} }
Err!(Request(Forbidden( Err!(Request(Forbidden("Room is not accessible")))
"Room is not world readable or publicly accessible/joinable, authentication is \
required"
)))
}, },
} }
} }