allow searching in left rooms

The spec states that

> The search API allows clients to perform full text search across
> events in all rooms that the user has been in, including those that they
> have left. Only events that the user is allowed to see will be
> searched, e.g. it won’t include events in rooms that happened after
> you left.

<https://spec.matrix.org/v1.10/client-server-api/#server-side-search>
This commit is contained in:
Benjamin Lee 2024-06-03 19:54:50 -07:00
parent 857131e959
commit 697c5ac534
No known key found for this signature in database
GPG key ID: FB9624E2885D55A4
4 changed files with 50 additions and 2 deletions

View file

@ -35,7 +35,7 @@ pub(crate) async fn search_events_route(
services()
.rooms
.state_cache
.rooms_joined(sender_user)
.rooms_once_joined(sender_user)
.filter_map(Result::ok)
.collect()
});
@ -51,7 +51,7 @@ pub(crate) async fn search_events_route(
let mut searches = Vec::new();
for room_id in room_ids {
if !services().rooms.state_cache.is_joined(sender_user, &room_id)? {
if !services().rooms.state_cache.once_joined(sender_user, &room_id)? {
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"You don't have permission to view this room.",

View file

@ -615,6 +615,39 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
))
}
/// Returns an iterator over all rooms a user has been in.
#[tracing::instrument(skip(self))]
fn rooms_once_joined<'a>(
&'a self,
user_id: &UserId,
) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
let mut prefix = user_id.as_bytes().to_vec();
prefix.push(0xFF);
Box::new(self.roomuseroncejoinedids.scan_prefix(prefix).map(
|(key, _)| {
RoomId::parse(
utils::string_from_bytes(
key.rsplit(|&b| b == 0xFF)
.next()
.expect("rsplit always returns an element"),
)
.map_err(|_| {
Error::bad_database(
"Room ID in roomuseroncejoinedids is invalid \
unicode.",
)
})?,
)
.map_err(|_| {
Error::bad_database(
"Room ID in roomuseroncejoinedids is invalid.",
)
})
},
))
}
#[tracing::instrument(skip(self))]
fn once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
let mut userroom_id = user_id.as_bytes().to_vec();

View file

@ -387,6 +387,15 @@ impl Service {
self.db.rooms_left(user_id)
}
/// Returns an iterator over all rooms a user has been in.
#[tracing::instrument(skip(self))]
pub(crate) fn rooms_once_joined<'a>(
&'a self,
user_id: &UserId,
) -> impl Iterator<Item = Result<OwnedRoomId>> + 'a {
self.db.rooms_once_joined(user_id)
}
#[tracing::instrument(skip(self))]
pub(crate) fn once_joined(
&self,

View file

@ -125,6 +125,12 @@ pub(crate) trait Data: Send + Sync {
+ 'a,
>;
/// Returns an iterator over all rooms a user has been in.
fn rooms_once_joined<'a>(
&'a self,
user_id: &UserId,
) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a>;
fn once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool>;
fn is_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool>;