implement room.state.(not_)rooms filter on /sync

This commit is contained in:
Benjamin Lee 2024-05-03 17:09:19 -07:00
parent c48abf9f13
commit e6f2b6c9ad
No known key found for this signature in database
GPG key ID: FB9624E2885D55A4
2 changed files with 177 additions and 155 deletions

View file

@ -443,6 +443,8 @@ async fn load_joined_room(
let since_shortstatehash = let since_shortstatehash =
services().rooms.user.get_token_shortstatehash(room_id, since)?; services().rooms.user.get_token_shortstatehash(room_id, since)?;
let skip_state_events = !filter.room.state.room_allowed(room_id);
let ( let (
heroes, heroes,
joined_member_count, joined_member_count,
@ -583,6 +585,7 @@ async fn load_joined_room(
let mut state_events = Vec::new(); let mut state_events = Vec::new();
let mut lazy_loaded = HashSet::new(); let mut lazy_loaded = HashSet::new();
if !skip_state_events {
let mut i = 0; let mut i = 0;
for (shortstatekey, id) in current_state_ids { for (shortstatekey, id) in current_state_ids {
let (event_type, state_key) = services() let (event_type, state_key) = services()
@ -591,7 +594,8 @@ async fn load_joined_room(
.get_statekey_from_short(shortstatekey)?; .get_statekey_from_short(shortstatekey)?;
if event_type != StateEventType::RoomMember { if event_type != StateEventType::RoomMember {
let Some(pdu) = services().rooms.timeline.get_pdu(&id)? let Some(pdu) =
services().rooms.timeline.get_pdu(&id)?
else { else {
error!("Pdu in state not found: {}", id); error!("Pdu in state not found: {}", id);
continue; continue;
@ -608,7 +612,8 @@ async fn load_joined_room(
// TODO: Delete the following line when this is resolved: https://github.com/vector-im/element-web/issues/22565 // TODO: Delete the following line when this is resolved: https://github.com/vector-im/element-web/issues/22565
|| *sender_user == state_key || *sender_user == state_key
{ {
let Some(pdu) = services().rooms.timeline.get_pdu(&id)? let Some(pdu) =
services().rooms.timeline.get_pdu(&id)?
else { else {
error!("Pdu in state not found: {}", id); error!("Pdu in state not found: {}", id);
continue; continue;
@ -627,6 +632,7 @@ async fn load_joined_room(
} }
} }
} }
}
// Reset lazy loading because this is an initial sync // Reset lazy loading because this is an initial sync
services().rooms.lazy_loading.lazy_load_reset( services().rooms.lazy_loading.lazy_load_reset(
@ -792,6 +798,9 @@ async fn load_joined_room(
(None, None, Vec::new()) (None, None, Vec::new())
}; };
let state_events = if skip_state_events {
vec![]
} else {
let mut state_events = delta_state_events; let mut state_events = delta_state_events;
let mut lazy_loaded = HashSet::new(); let mut lazy_loaded = HashSet::new();
@ -808,25 +817,33 @@ async fn load_joined_room(
lazy_loaded.insert(state_key_userid); lazy_loaded.insert(state_key_userid);
} }
Err(e) => { Err(e) => {
error!("Invalid state key for member event: {}", e); error!(
"Invalid state key for member event: {}",
e
);
} }
} }
} }
} }
// Fetch contextual member state events for events from the // Fetch contextual member state events for events from the
// timeline, and mark them as lazy-loaded as well. // timeline, and mark them as lazy-loaded as
// well.
for (_, event) in &timeline_pdus { for (_, event) in &timeline_pdus {
if lazy_loaded.contains(&event.sender) { if lazy_loaded.contains(&event.sender) {
continue; continue;
} }
if !services().rooms.lazy_loading.lazy_load_was_sent_before( if !services()
.rooms
.lazy_loading
.lazy_load_was_sent_before(
sender_user, sender_user,
sender_device, sender_device,
room_id, room_id,
&event.sender, &event.sender,
)? || lazy_load_send_redundant )?
|| lazy_load_send_redundant
{ {
if let Some(member_event) = if let Some(member_event) =
services().rooms.state_accessor.room_state_get( services().rooms.state_accessor.room_state_get(
@ -853,6 +870,9 @@ async fn load_joined_room(
) )
.await; .await;
state_events
};
( (
heroes, heroes,
joined_member_count, joined_member_count,
@ -1026,7 +1046,11 @@ async fn handle_left_room(
} }
}; };
if !services().rooms.metadata.exists(&room_id)? { let state = if !filter.room.state.room_allowed(&room_id) {
State {
events: vec![],
}
} else if !services().rooms.metadata.exists(&room_id)? {
// This is just a rejected invite, not a room we know // This is just a rejected invite, not a room we know
let event = PduEvent { let event = PduEvent {
event_id: EventId::new(services().globals.server_name()).into(), event_id: EventId::new(services().globals.server_name()).into(),
@ -1051,29 +1075,19 @@ async fn handle_left_room(
signatures: None, signatures: None,
}; };
left_rooms.insert( State {
room_id,
LeftRoom {
account_data: RoomAccountData {
events: Vec::new(),
},
timeline,
state: State {
events: vec![event.to_sync_state_event()], events: vec![event.to_sync_state_event()],
},
},
);
return Ok(());
} }
} else {
let mut left_state_events = Vec::new(); let mut left_state_events = Vec::new();
let since_shortstatehash = let since_shortstatehash =
services().rooms.user.get_token_shortstatehash(&room_id, since)?; services().rooms.user.get_token_shortstatehash(&room_id, since)?;
let since_state_ids = match since_shortstatehash { let since_state_ids = match since_shortstatehash {
Some(s) => services().rooms.state_accessor.state_full_ids(s).await?, Some(s) => {
services().rooms.state_accessor.state_full_ids(s).await?
}
None => HashMap::new(), None => HashMap::new(),
}; };
@ -1088,8 +1102,10 @@ async fn handle_left_room(
return Ok(()); return Ok(());
}; };
let Some(left_shortstatehash) = let Some(left_shortstatehash) = services()
services().rooms.state_accessor.pdu_shortstatehash(&left_event_id)? .rooms
.state_accessor
.pdu_shortstatehash(&left_event_id)?
else { else {
error!("Leave event has no state"); error!("Leave event has no state");
return Ok(()); return Ok(());
@ -1121,7 +1137,8 @@ async fn handle_left_room(
// TODO: Delete the following line when this is resolved: https://github.com/vector-im/element-web/issues/22565 // TODO: Delete the following line when this is resolved: https://github.com/vector-im/element-web/issues/22565
|| *sender_user == state_key || *sender_user == state_key
{ {
let Some(pdu) = services().rooms.timeline.get_pdu(&id)? else { let Some(pdu) = services().rooms.timeline.get_pdu(&id)?
else {
error!("Pdu in state not found: {}", id); error!("Pdu in state not found: {}", id);
continue; continue;
}; };
@ -1136,6 +1153,11 @@ async fn handle_left_room(
} }
} }
State {
events: left_state_events,
}
};
left_rooms.insert( left_rooms.insert(
room_id.clone(), room_id.clone(),
LeftRoom { LeftRoom {
@ -1143,9 +1165,7 @@ async fn handle_left_room(
events: Vec::new(), events: Vec::new(),
}, },
timeline, timeline,
state: State { state,
events: left_state_events,
},
}, },
); );

View file

@ -159,6 +159,7 @@ pub(crate) struct CompiledFilterDefinition<'a> {
pub(crate) struct CompiledRoomFilter<'a> { pub(crate) struct CompiledRoomFilter<'a> {
rooms: AllowDenyList<'a, RoomId>, rooms: AllowDenyList<'a, RoomId>,
pub(crate) timeline: CompiledRoomEventFilter<'a>, pub(crate) timeline: CompiledRoomEventFilter<'a>,
pub(crate) state: CompiledRoomEventFilter<'a>,
} }
pub(crate) struct CompiledRoomEventFilter<'a> { pub(crate) struct CompiledRoomEventFilter<'a> {
@ -197,6 +198,7 @@ impl<'a> TryFrom<&'a RoomFilter> for CompiledRoomFilter<'a> {
&source.not_rooms, &source.not_rooms,
), ),
timeline: (&source.timeline).try_into()?, timeline: (&source.timeline).try_into()?,
state: (&source.state).try_into()?,
}) })
} }
} }