implement more robust (not_)rooms filter for search

The previous code only handled the rooms field, and ignored not_rooms.
This commit is contained in:
Benjamin Lee 2024-06-04 19:54:21 -07:00
parent fe5626e93a
commit d2fab35868
No known key found for this signature in database
GPG key ID: FB9624E2885D55A4
2 changed files with 28 additions and 18 deletions

View file

@ -1,4 +1,4 @@
use std::collections::BTreeMap; use std::{borrow::Cow, collections::BTreeMap};
use ruma::{ use ruma::{
api::client::{ api::client::{
@ -14,7 +14,11 @@ use ruma::{
uint, UInt, uint, UInt,
}; };
use crate::{services, Ar, Error, Ra, Result}; use crate::{
services,
utils::filter::{AllowDenyList, CompiledRoomEventFilter},
Ar, Error, Ra, Result,
};
/// # `POST /_matrix/client/r0/search` /// # `POST /_matrix/client/r0/search`
/// ///
@ -30,15 +34,28 @@ pub(crate) async fn search_events_route(
let search_criteria = body.search_categories.room_events.as_ref().unwrap(); let search_criteria = body.search_categories.room_events.as_ref().unwrap();
let filter = &search_criteria.filter; let filter = &search_criteria.filter;
let Ok(compiled_filter) = CompiledRoomEventFilter::try_from(filter) else {
return Err(Error::BadRequest(
ErrorKind::InvalidParam,
"invalid 'filter' parameter",
));
};
let room_ids = filter.rooms.clone().unwrap_or_else(|| { let mut room_ids = vec![];
services() if let AllowDenyList::Allow(allow_set) = &compiled_filter.rooms {
.rooms for &room_id in allow_set {
.state_cache if services().rooms.state_cache.is_joined(sender_user, room_id)? {
.rooms_joined(sender_user) room_ids.push(Cow::Borrowed(room_id));
.filter_map(Result::ok) }
.collect() }
}); } else {
for result in services().rooms.state_cache.rooms_joined(sender_user) {
let room_id = result?;
if compiled_filter.rooms.allowed(&room_id) {
room_ids.push(Cow::Owned(room_id));
}
}
}
// Use limit or else 10, with maximum 100 // Use limit or else 10, with maximum 100
let limit = filter let limit = filter
@ -51,13 +68,6 @@ pub(crate) async fn search_events_route(
let mut searches = Vec::new(); let mut searches = Vec::new();
for room_id in room_ids { for room_id in room_ids {
if !services().rooms.state_cache.is_joined(sender_user, &room_id)? {
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"You don't have permission to view this room.",
));
}
if let Some(search) = services() if let Some(search) = services()
.rooms .rooms
.search .search

View file

@ -182,7 +182,7 @@ pub(crate) struct CompiledRoomEventFilter<'a> {
// AllowDenyList<TimelineEventType> when none of the type patterns // AllowDenyList<TimelineEventType> when none of the type patterns
// include a wildcard. // include a wildcard.
types: WildcardAllowDenyList, types: WildcardAllowDenyList,
rooms: AllowDenyList<'a, RoomId>, pub(crate) rooms: AllowDenyList<'a, RoomId>,
senders: AllowDenyList<'a, UserId>, senders: AllowDenyList<'a, UserId>,
url_filter: Option<UrlFilter>, url_filter: Option<UrlFilter>,
} }