diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs index 33806013..d79079db 100644 --- a/src/client_server/membership.rs +++ b/src/client_server/membership.rs @@ -103,6 +103,7 @@ pub async fn leave_room_route( ErrorKind::BadState, "Cannot leave a room you are not a member of.", ))? + .1 .content, ) .expect("from_value::> can never fail") @@ -193,6 +194,7 @@ pub async fn kick_user_route( ErrorKind::BadState, "Cannot kick member that's not in the room.", ))? + .1 .content, ) .expect("Raw::from_value always works") @@ -249,7 +251,7 @@ pub async fn ban_user_route( is_direct: None, third_party_invite: None, }), - |event| { + |(_, event)| { let mut event = serde_json::from_value::>(event.content) .expect("Raw::from_value always works") @@ -301,6 +303,7 @@ pub async fn unban_user_route( ErrorKind::BadState, "Cannot unban a user who is not banned.", ))? + .1 .content, ) .expect("from_value::> can never fail") diff --git a/src/client_server/profile.rs b/src/client_server/profile.rs index d754aceb..3fa1da65 100644 --- a/src/client_server/profile.rs +++ b/src/client_server/profile.rs @@ -48,6 +48,7 @@ pub async fn set_displayname_route( "Tried to send displayname update for user not in the room.", ) })? + .1 .content .clone(), ) @@ -142,6 +143,7 @@ pub async fn set_avatar_url_route( "Tried to send avatar url update for user not in the room.", ) })? + .1 .content .clone(), ) diff --git a/src/client_server/room.rs b/src/client_server/room.rs index d1d051f1..eeab68b2 100644 --- a/src/client_server/room.rs +++ b/src/client_server/room.rs @@ -395,6 +395,7 @@ pub async fn upgrade_room_route( db.rooms .room_state_get(&body.room_id, &EventType::RoomCreate, "")? .ok_or_else(|| Error::bad_database("Found room without m.room.create event."))? + .1 .content, ) .expect("Raw::from_value always works") @@ -470,7 +471,7 @@ pub async fn upgrade_room_route( // Replicate transferable state events to the new room for event_type in transferable_state_events { let event_content = match db.rooms.room_state_get(&body.room_id, &event_type, "")? { - Some(v) => v.content.clone(), + Some((_, v)) => v.content.clone(), None => continue, // Skipping missing events. }; @@ -502,6 +503,7 @@ pub async fn upgrade_room_route( db.rooms .room_state_get(&body.room_id, &EventType::RoomPowerLevels, "")? .ok_or_else(|| Error::bad_database("Found room without m.room.create event."))? + .1 .content, ) .expect("database contains invalid PDU") diff --git a/src/client_server/state.rs b/src/client_server/state.rs index eae96b5b..dbc7fdd4 100644 --- a/src/client_server/state.rs +++ b/src/client_server/state.rs @@ -109,7 +109,7 @@ pub async fn get_state_events_route( if !matches!( db.rooms .room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")? - .map(|event| { + .map(|(_, event)| { serde_json::from_value::(event.content) .map_err(|_| { Error::bad_database( @@ -154,7 +154,7 @@ pub async fn get_state_events_for_key_route( if !matches!( db.rooms .room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")? - .map(|event| { + .map(|(_, event)| { serde_json::from_value::(event.content) .map_err(|_| { Error::bad_database( @@ -178,7 +178,8 @@ pub async fn get_state_events_for_key_route( .ok_or(Error::BadRequest( ErrorKind::NotFound, "State event not found.", - ))?; + ))? + .1; Ok(get_state_events_for_key::Response { content: serde_json::value::to_raw_value(&event.content) @@ -203,7 +204,7 @@ pub async fn get_state_events_for_empty_key_route( if !matches!( db.rooms .room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")? - .map(|event| { + .map(|(_, event)| { serde_json::from_value::(event.content) .map_err(|_| { Error::bad_database( @@ -227,7 +228,8 @@ pub async fn get_state_events_for_empty_key_route( .ok_or(Error::BadRequest( ErrorKind::NotFound, "State event not found.", - ))?; + ))? + .1; Ok(get_state_events_for_empty_key::Response { content: serde_json::value::to_raw_value(&event) diff --git a/src/client_server/sync.rs b/src/client_server/sync.rs index caab9ea1..360691ab 100644 --- a/src/client_server/sync.rs +++ b/src/client_server/sync.rs @@ -440,23 +440,8 @@ pub async fn sync_events_route( let mut left_rooms = BTreeMap::new(); for room_id in db.rooms.rooms_left(&sender_user) { let room_id = room_id?; - let pdus = db.rooms.pdus_since(&sender_user, &room_id, since)?; - let room_events = pdus - .filter_map(|pdu| pdu.ok()) // Filter out buggy events - .map(|(_, pdu)| pdu.to_sync_room_event()) - .collect(); - let left_room = sync_events::LeftRoom { - account_data: sync_events::AccountData { events: Vec::new() }, - timeline: sync_events::Timeline { - limited: false, - prev_batch: Some(next_batch.clone()), - events: room_events, - }, - state: sync_events::State { events: Vec::new() }, - }; - - let since_member = db + let since_member = if let Some(since_member) = db .rooms .pdus_after(sender_user, &room_id, since) .next() @@ -475,20 +460,25 @@ pub async fn sync_events_route( .ok_or_else(|| Error::bad_database("State hash in db doesn't have a state.")) .ok() }) - .and_then(|pdu| { + .and_then(|(pdu_id, pdu)| { serde_json::from_value::>( - pdu.content, + pdu.content.clone(), ) .expect("Raw::from_value always works") .deserialize() .map_err(|_| Error::bad_database("Invalid PDU in database.")) + .map(|content| (pdu_id, pdu, content)) .ok() - }); + }) { + since_member + } else { + // We couldn't find the since_member event. This is very weird - we better abort + continue; + }; - let left_since_last_sync = - since_member.map_or(false, |member| member.membership == MembershipState::Join); + let left_since_last_sync = since_member.2.membership == MembershipState::Join; - if left_since_last_sync { + let left_room = if left_since_last_sync { device_list_left.extend( db.rooms .room_members(&room_id) @@ -503,7 +493,35 @@ pub async fn sync_events_route( !share_encrypted_room(&db, sender_user, user_id, &room_id) }), ); - } + + let pdus = db.rooms.pdus_since(&sender_user, &room_id, since)?; + let mut room_events = pdus + .filter_map(|pdu| pdu.ok()) // Filter out buggy events + .take_while(|(pdu_id, _)| since_member.0 != pdu_id) + .map(|(_, pdu)| pdu.to_sync_room_event()) + .collect::>(); + room_events.push(since_member.1.to_sync_room_event()); + + sync_events::LeftRoom { + account_data: sync_events::AccountData { events: Vec::new() }, + timeline: sync_events::Timeline { + limited: false, + prev_batch: Some(next_batch.clone()), + events: room_events, + }, + state: sync_events::State { events: Vec::new() }, + } + } else { + sync_events::LeftRoom { + account_data: sync_events::AccountData { events: Vec::new() }, + timeline: sync_events::Timeline { + limited: false, + prev_batch: Some(next_batch.clone()), + events: Vec::new(), + }, + state: sync_events::State { events: Vec::new() }, + } + }; if !left_room.is_empty() { left_rooms.insert(room_id.clone(), left_room); diff --git a/src/database/rooms.rs b/src/database/rooms.rs index 1cc20a43..05abe03e 100644 --- a/src/database/rooms.rs +++ b/src/database/rooms.rs @@ -169,7 +169,7 @@ impl Rooms { state_hash: &StateHashId, event_type: &EventType, state_key: &str, - ) -> Result> { + ) -> Result> { let mut key = state_hash.to_vec(); key.push(0xff); key.extend_from_slice(&event_type.to_string().as_bytes()); @@ -177,14 +177,15 @@ impl Rooms { key.extend_from_slice(&state_key.as_bytes()); self.stateid_pduid.get(&key)?.map_or(Ok(None), |pdu_id| { - Ok::<_, Error>(Some( + Ok::<_, Error>(Some(( + pdu_id.clone(), serde_json::from_slice::( - &self.pduid_pdu.get(pdu_id)?.ok_or_else(|| { + &self.pduid_pdu.get(&pdu_id)?.ok_or_else(|| { Error::bad_database("PDU in state not found in database.") })?, ) .map_err(|_| Error::bad_database("Invalid PDU bytes in room state."))?, - )) + ))) }) } @@ -216,7 +217,7 @@ impl Rooms { let mut events = StateMap::new(); for (event_type, state_key) in auth_events { - if let Some(pdu) = self.room_state_get(room_id, &event_type, &state_key)? { + if let Some((_, pdu)) = self.room_state_get(room_id, &event_type, &state_key)? { events.insert((event_type, state_key), pdu); } } @@ -299,7 +300,7 @@ impl Rooms { room_id: &RoomId, event_type: &EventType, state_key: &str, - ) -> Result> { + ) -> Result> { if let Some(current_state_hash) = self.current_state_hash(room_id)? { self.state_get(¤t_state_hash, event_type, state_key) } else { @@ -653,7 +654,7 @@ impl Rooms { }, }) }, - |power_levels| { + |(_, power_levels)| { Ok(serde_json::from_value::>( power_levels.content, ) @@ -664,15 +665,18 @@ impl Rooms { )?; let sender_membership = self .room_state_get(&room_id, &EventType::RoomMember, &sender.to_string())? - .map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| { - Ok( - serde_json::from_value::>(pdu.content) - .expect("Raw::from_value always works.") - .deserialize() - .map_err(|_| Error::bad_database("Invalid Member event in db."))? - .membership, - ) - })?; + .map_or( + Ok::<_, Error>(member::MembershipState::Leave), + |(_, pdu)| { + Ok( + serde_json::from_value::>(pdu.content) + .expect("Raw::from_value always works.") + .deserialize() + .map_err(|_| Error::bad_database("Invalid Member event in db."))? + .membership, + ) + }, + )?; let sender_power = power_levels.users.get(&sender).map_or_else( || { @@ -759,7 +763,7 @@ impl Rooms { let mut unsigned = unsigned.unwrap_or_default(); if let Some(state_key) = &state_key { - if let Some(prev_pdu) = self.room_state_get(&room_id, &event_type, &state_key)? { + if let Some((_, prev_pdu)) = self.room_state_get(&room_id, &event_type, &state_key)? { unsigned.insert("prev_content".to_owned(), prev_pdu.content); unsigned.insert( "prev_sender".to_owned(), @@ -1017,7 +1021,7 @@ impl Rooms { // Check if the room has a predecessor if let Some(predecessor) = self .room_state_get(&room_id, &EventType::RoomCreate, "")? - .and_then(|create| { + .and_then(|(_, create)| { serde_json::from_value::< Raw, >(create.content)