diff --git a/src/lib.rs b/src/lib.rs index 348af5eb..89c6cbf0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,51 @@ pub type EventMap = BTreeMap; pub struct StateResolution; impl StateResolution { + /// Check if the `incoming_event` can be included in the given `current_state`. + /// + /// This will authenticate the event against the current state of the room. It + /// is important that the `current_state` argument is accurate and complete. + pub fn apply_event( + room_id: &RoomId, + room_version: &RoomVersionId, + incoming_event: Arc, + current_state: &StateMap, + event_map: Option>>, + store: &dyn StateStore, + ) -> Result { + tracing::info!("Applying a single event, state resolution starting"); + let ev = incoming_event; + + let mut event_map = if let Some(ev_map) = event_map { + ev_map + } else { + EventMap::new() + }; + let prev_event = if let Some(id) = ev.prev_event_ids().first() { + store.get_event(room_id, id).ok() + } else { + None + }; + + let mut auth_events = StateMap::new(); + for key in event_auth::auth_types_for_event( + ev.kind(), + ev.sender(), + Some(ev.state_key()), + ev.content().clone(), + ) { + if let Some(ev_id) = current_state.get(&key) { + if let Some(event) = + StateResolution::get_or_load_event(room_id, ev_id, &mut event_map, store) + { + // TODO synapse checks `rejected_reason` is None here + auth_events.insert(key.clone(), event); + } + } + } + + event_auth::auth_check(room_version, &ev, prev_event, auth_events, None) + } /// Resolve sets of state events as they come in. Internally `StateResolution` builds a graph /// and an auth chain to allow for state conflict resolution. /// diff --git a/tests/state_res.rs b/tests/state_res.rs index 5b973685..7b8110dd 100644 --- a/tests/state_res.rs +++ b/tests/state_res.rs @@ -354,7 +354,7 @@ fn do_check( let resolved = StateResolution::resolve( &room_id(), - &RoomVersionId::Version1, + &RoomVersionId::Version6, &state_sets, Some(event_map.clone()), &store, @@ -398,6 +398,35 @@ fn do_check( &auth_events, prev_events, ); + + // This can be used to sort of test this function + // match StateResolution::apply_event( + // &room_id(), + // &RoomVersionId::Version6, + // Arc::clone(&event), + // &state_after, + // Some(event_map.clone()), + // &store, + // ) { + // Ok(res) => { + // println!( + // "res contains: {} passed: {} for {}\n{:?}", + // state_after + // .get(&(event.kind(), event.state_key())) + // .map(|id| id == &ev_id) + // .unwrap_or_default(), + // res, + // event.event_id().as_str(), + // event + // .prev_event_ids() + // .iter() + // .map(|id| id.to_string()) + // .collect::>() + // ); + // } + // Err(e) => panic!("resolution for {} failed: {}", node, e), + // } + // we have to update our store, an actual user of this lib would // be giving us state from a DB. //