fix: spaces with restricted rooms

merge-requests/508/head
Timo Kösters 12 months ago
parent edd4a3733f
commit 0b4e3de9c0
No known key found for this signature in database
GPG Key ID: 0B25E636FBA7E4CB

@ -5,11 +5,10 @@ use ruma::{
api::{ api::{
client::{ client::{
error::ErrorKind, error::ErrorKind,
space::{get_hierarchy, SpaceHierarchyRoomsChunk, SpaceRoomJoinRule}, space::{get_hierarchy, SpaceHierarchyRoomsChunk},
}, },
federation, federation,
}, },
directory::PublicRoomJoinRule,
events::{ events::{
room::{ room::{
avatar::RoomAvatarEventContent, avatar::RoomAvatarEventContent,
@ -18,11 +17,11 @@ use ruma::{
guest_access::{GuestAccess, RoomGuestAccessEventContent}, guest_access::{GuestAccess, RoomGuestAccessEventContent},
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent}, history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
join_rules::{JoinRule, RoomJoinRulesEventContent}, join_rules::{JoinRule, RoomJoinRulesEventContent},
name::RoomNameEventContent,
topic::RoomTopicEventContent, topic::RoomTopicEventContent,
}, },
StateEventType, StateEventType,
}, },
space::SpaceRoomJoinRule,
OwnedRoomId, RoomId, UserId, OwnedRoomId, RoomId, UserId,
}; };
@ -30,10 +29,15 @@ use tracing::{debug, error, warn};
use crate::{services, Error, PduEvent, Result}; use crate::{services, Error, PduEvent, Result};
pub enum CachedJoinRule {
Simplified(SpaceRoomJoinRule),
Full(JoinRule),
}
pub struct CachedSpaceChunk { pub struct CachedSpaceChunk {
chunk: SpaceHierarchyRoomsChunk, chunk: SpaceHierarchyRoomsChunk,
children: Vec<OwnedRoomId>, children: Vec<OwnedRoomId>,
join_rule: JoinRule, join_rule: CachedJoinRule,
} }
pub struct Service { pub struct Service {
@ -79,9 +83,15 @@ impl Service {
.as_ref() .as_ref()
{ {
if let Some(cached) = cached { if let Some(cached) = cached {
if let Some(_join_rule) = let allowed = match &cached.join_rule {
self.handle_join_rule(&cached.join_rule, sender_user, &current_room)? CachedJoinRule::Simplified(s) => {
{ self.handle_simplified_join_rule(s, sender_user, &current_room)?
}
CachedJoinRule::Full(f) => {
self.handle_join_rule(f, sender_user, &current_room)?
}
};
if allowed {
if left_to_skip > 0 { if left_to_skip > 0 {
left_to_skip -= 1; left_to_skip -= 1;
} else { } else {
@ -152,7 +162,7 @@ impl Service {
Some(CachedSpaceChunk { Some(CachedSpaceChunk {
chunk, chunk,
children: children_ids.clone(), children: children_ids.clone(),
join_rule, join_rule: CachedJoinRule::Full(join_rule),
}), }),
); );
} }
@ -182,7 +192,6 @@ impl Service {
.await .await
{ {
warn!("Got response from {server} for /hierarchy\n{response:?}"); warn!("Got response from {server} for /hierarchy\n{response:?}");
let join_rule = self.translate_pjoinrule(&response.room.join_rule)?;
let chunk = SpaceHierarchyRoomsChunk { let chunk = SpaceHierarchyRoomsChunk {
canonical_alias: response.room.canonical_alias, canonical_alias: response.room.canonical_alias,
name: response.room.name, name: response.room.name,
@ -192,7 +201,7 @@ impl Service {
world_readable: response.room.world_readable, world_readable: response.room.world_readable,
guest_can_join: response.room.guest_can_join, guest_can_join: response.room.guest_can_join,
avatar_url: response.room.avatar_url, avatar_url: response.room.avatar_url,
join_rule: self.translate_sjoinrule(&response.room.join_rule)?, join_rule: response.room.join_rule.clone(),
room_type: response.room.room_type, room_type: response.room.room_type,
children_state: response.room.children_state, children_state: response.room.children_state,
}; };
@ -202,9 +211,11 @@ impl Service {
.map(|c| c.room_id.clone()) .map(|c| c.room_id.clone())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if let Some(_join_rule) = if self.handle_simplified_join_rule(
self.handle_join_rule(&join_rule, sender_user, &current_room)? &response.room.join_rule,
{ sender_user,
&current_room,
)? {
if left_to_skip > 0 { if left_to_skip > 0 {
left_to_skip -= 1; left_to_skip -= 1;
} else { } else {
@ -220,7 +231,7 @@ impl Service {
Some(CachedSpaceChunk { Some(CachedSpaceChunk {
chunk, chunk,
children, children,
join_rule, join_rule: CachedJoinRule::Simplified(response.room.join_rule),
}), }),
); );
@ -349,15 +360,17 @@ impl Service {
}) })
.transpose()? .transpose()?
.unwrap_or(JoinRule::Invite); .unwrap_or(JoinRule::Invite);
self.handle_join_rule(&join_rule, sender_user, room_id)?
.ok_or_else(|| { if !self.handle_join_rule(&join_rule, sender_user, room_id)? {
debug!("User is not allowed to see room {room_id}"); debug!("User is not allowed to see room {room_id}");
// This error will be caught later // This error will be caught later
Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::Forbidden, ErrorKind::Forbidden,
"User is not allowed to see the room", "User is not allowed to see the room",
) ));
})? }
self.translate_joinrule(&join_rule)?
}, },
room_type: services() room_type: services()
.rooms .rooms
@ -378,20 +391,35 @@ impl Service {
}) })
} }
fn translate_pjoinrule(&self, join_rule: &PublicRoomJoinRule) -> Result<JoinRule> { fn translate_joinrule(&self, join_rule: &JoinRule) -> Result<SpaceRoomJoinRule> {
match join_rule { match join_rule {
PublicRoomJoinRule::Knock => Ok(JoinRule::Knock), JoinRule::Invite => Ok(SpaceRoomJoinRule::Invite),
PublicRoomJoinRule::Public => Ok(JoinRule::Public), JoinRule::Knock => Ok(SpaceRoomJoinRule::Knock),
JoinRule::Private => Ok(SpaceRoomJoinRule::Private),
JoinRule::Restricted(_) => Ok(SpaceRoomJoinRule::Restricted),
JoinRule::KnockRestricted(_) => Ok(SpaceRoomJoinRule::KnockRestricted),
JoinRule::Public => Ok(SpaceRoomJoinRule::Public),
_ => Err(Error::BadServerResponse("Unknown join rule")), _ => Err(Error::BadServerResponse("Unknown join rule")),
} }
} }
fn translate_sjoinrule(&self, join_rule: &PublicRoomJoinRule) -> Result<SpaceRoomJoinRule> { fn handle_simplified_join_rule(
match join_rule { &self,
PublicRoomJoinRule::Knock => Ok(SpaceRoomJoinRule::Knock), join_rule: &SpaceRoomJoinRule,
PublicRoomJoinRule::Public => Ok(SpaceRoomJoinRule::Public), sender_user: &UserId,
_ => Err(Error::BadServerResponse("Unknown join rule")), room_id: &RoomId,
} ) -> Result<bool> {
let allowed = match join_rule {
SpaceRoomJoinRule::Public => true,
SpaceRoomJoinRule::Knock => true,
SpaceRoomJoinRule::Invite => services()
.rooms
.state_cache
.is_joined(sender_user, &room_id)?,
_ => false,
};
Ok(allowed)
} }
fn handle_join_rule( fn handle_join_rule(
@ -399,30 +427,25 @@ impl Service {
join_rule: &JoinRule, join_rule: &JoinRule,
sender_user: &UserId, sender_user: &UserId,
room_id: &RoomId, room_id: &RoomId,
) -> Result<Option<SpaceRoomJoinRule>> { ) -> Result<bool> {
if self.handle_simplified_join_rule(
&self.translate_joinrule(join_rule)?,
sender_user,
room_id,
)? {
return Ok(true);
}
match join_rule { match join_rule {
JoinRule::Public => Ok::<_, Error>(Some(SpaceRoomJoinRule::Public)), JoinRule::Restricted(_) => {
JoinRule::Knock => Ok(Some(SpaceRoomJoinRule::Knock)),
JoinRule::Invite => {
if services()
.rooms
.state_cache
.is_joined(sender_user, &room_id)?
{
Ok(Some(SpaceRoomJoinRule::Invite))
} else {
Ok(None)
}
}
JoinRule::Restricted(_r) => {
// TODO: Check rules // TODO: Check rules
Ok(None) Ok(false)
} }
JoinRule::KnockRestricted(_r) => { JoinRule::KnockRestricted(_) => {
// TODO: Check rules // TODO: Check rules
Ok(None) Ok(false)
} }
_ => Ok(None), _ => Ok(false),
} }
} }
} }

Loading…
Cancel
Save