fix: don't send new events from left rooms

next
Timo Kösters 2020-10-27 20:25:43 +01:00
parent 2f5df4aac9
commit 0762196963
No known key found for this signature in database
GPG Key ID: 24DA7517711A2BA4
6 changed files with 79 additions and 48 deletions

View File

@ -103,6 +103,7 @@ pub async fn leave_room_route(
ErrorKind::BadState, ErrorKind::BadState,
"Cannot leave a room you are not a member of.", "Cannot leave a room you are not a member of.",
))? ))?
.1
.content, .content,
) )
.expect("from_value::<Raw<..>> can never fail") .expect("from_value::<Raw<..>> can never fail")
@ -193,6 +194,7 @@ pub async fn kick_user_route(
ErrorKind::BadState, ErrorKind::BadState,
"Cannot kick member that's not in the room.", "Cannot kick member that's not in the room.",
))? ))?
.1
.content, .content,
) )
.expect("Raw::from_value always works") .expect("Raw::from_value always works")
@ -249,7 +251,7 @@ pub async fn ban_user_route(
is_direct: None, is_direct: None,
third_party_invite: None, third_party_invite: None,
}), }),
|event| { |(_, event)| {
let mut event = let mut event =
serde_json::from_value::<Raw<member::MemberEventContent>>(event.content) serde_json::from_value::<Raw<member::MemberEventContent>>(event.content)
.expect("Raw::from_value always works") .expect("Raw::from_value always works")
@ -301,6 +303,7 @@ pub async fn unban_user_route(
ErrorKind::BadState, ErrorKind::BadState,
"Cannot unban a user who is not banned.", "Cannot unban a user who is not banned.",
))? ))?
.1
.content, .content,
) )
.expect("from_value::<Raw<..>> can never fail") .expect("from_value::<Raw<..>> can never fail")

View File

@ -48,6 +48,7 @@ pub async fn set_displayname_route(
"Tried to send displayname update for user not in the room.", "Tried to send displayname update for user not in the room.",
) )
})? })?
.1
.content .content
.clone(), .clone(),
) )
@ -142,6 +143,7 @@ pub async fn set_avatar_url_route(
"Tried to send avatar url update for user not in the room.", "Tried to send avatar url update for user not in the room.",
) )
})? })?
.1
.content .content
.clone(), .clone(),
) )

View File

@ -395,6 +395,7 @@ pub async fn upgrade_room_route(
db.rooms db.rooms
.room_state_get(&body.room_id, &EventType::RoomCreate, "")? .room_state_get(&body.room_id, &EventType::RoomCreate, "")?
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))? .ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
.1
.content, .content,
) )
.expect("Raw::from_value always works") .expect("Raw::from_value always works")
@ -470,7 +471,7 @@ pub async fn upgrade_room_route(
// Replicate transferable state events to the new room // Replicate transferable state events to the new room
for event_type in transferable_state_events { for event_type in transferable_state_events {
let event_content = match db.rooms.room_state_get(&body.room_id, &event_type, "")? { 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. None => continue, // Skipping missing events.
}; };
@ -502,6 +503,7 @@ pub async fn upgrade_room_route(
db.rooms db.rooms
.room_state_get(&body.room_id, &EventType::RoomPowerLevels, "")? .room_state_get(&body.room_id, &EventType::RoomPowerLevels, "")?
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))? .ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
.1
.content, .content,
) )
.expect("database contains invalid PDU") .expect("database contains invalid PDU")

View File

@ -109,7 +109,7 @@ pub async fn get_state_events_route(
if !matches!( if !matches!(
db.rooms db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")? .room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|event| { .map(|(_, event)| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content) serde_json::from_value::<HistoryVisibilityEventContent>(event.content)
.map_err(|_| { .map_err(|_| {
Error::bad_database( Error::bad_database(
@ -154,7 +154,7 @@ pub async fn get_state_events_for_key_route(
if !matches!( if !matches!(
db.rooms db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")? .room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|event| { .map(|(_, event)| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content) serde_json::from_value::<HistoryVisibilityEventContent>(event.content)
.map_err(|_| { .map_err(|_| {
Error::bad_database( Error::bad_database(
@ -178,7 +178,8 @@ pub async fn get_state_events_for_key_route(
.ok_or(Error::BadRequest( .ok_or(Error::BadRequest(
ErrorKind::NotFound, ErrorKind::NotFound,
"State event not found.", "State event not found.",
))?; ))?
.1;
Ok(get_state_events_for_key::Response { Ok(get_state_events_for_key::Response {
content: serde_json::value::to_raw_value(&event.content) 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!( if !matches!(
db.rooms db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")? .room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|event| { .map(|(_, event)| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content) serde_json::from_value::<HistoryVisibilityEventContent>(event.content)
.map_err(|_| { .map_err(|_| {
Error::bad_database( Error::bad_database(
@ -227,7 +228,8 @@ pub async fn get_state_events_for_empty_key_route(
.ok_or(Error::BadRequest( .ok_or(Error::BadRequest(
ErrorKind::NotFound, ErrorKind::NotFound,
"State event not found.", "State event not found.",
))?; ))?
.1;
Ok(get_state_events_for_empty_key::Response { Ok(get_state_events_for_empty_key::Response {
content: serde_json::value::to_raw_value(&event) content: serde_json::value::to_raw_value(&event)

View File

@ -440,23 +440,8 @@ pub async fn sync_events_route(
let mut left_rooms = BTreeMap::new(); let mut left_rooms = BTreeMap::new();
for room_id in db.rooms.rooms_left(&sender_user) { for room_id in db.rooms.rooms_left(&sender_user) {
let room_id = room_id?; 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 { let since_member = if let Some(since_member) = db
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
.rooms .rooms
.pdus_after(sender_user, &room_id, since) .pdus_after(sender_user, &room_id, since)
.next() .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_or_else(|| Error::bad_database("State hash in db doesn't have a state."))
.ok() .ok()
}) })
.and_then(|pdu| { .and_then(|(pdu_id, pdu)| {
serde_json::from_value::<Raw<ruma::events::room::member::MemberEventContent>>( serde_json::from_value::<Raw<ruma::events::room::member::MemberEventContent>>(
pdu.content, pdu.content.clone(),
) )
.expect("Raw::from_value always works") .expect("Raw::from_value always works")
.deserialize() .deserialize()
.map_err(|_| Error::bad_database("Invalid PDU in database.")) .map_err(|_| Error::bad_database("Invalid PDU in database."))
.map(|content| (pdu_id, pdu, content))
.ok() .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 = let left_since_last_sync = since_member.2.membership == MembershipState::Join;
since_member.map_or(false, |member| member.membership == MembershipState::Join);
if left_since_last_sync { let left_room = if left_since_last_sync {
device_list_left.extend( device_list_left.extend(
db.rooms db.rooms
.room_members(&room_id) .room_members(&room_id)
@ -503,7 +493,35 @@ pub async fn sync_events_route(
!share_encrypted_room(&db, sender_user, user_id, &room_id) !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::<Vec<_>>();
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() { if !left_room.is_empty() {
left_rooms.insert(room_id.clone(), left_room); left_rooms.insert(room_id.clone(), left_room);

View File

@ -169,7 +169,7 @@ impl Rooms {
state_hash: &StateHashId, state_hash: &StateHashId,
event_type: &EventType, event_type: &EventType,
state_key: &str, state_key: &str,
) -> Result<Option<PduEvent>> { ) -> Result<Option<(IVec, PduEvent)>> {
let mut key = state_hash.to_vec(); let mut key = state_hash.to_vec();
key.push(0xff); key.push(0xff);
key.extend_from_slice(&event_type.to_string().as_bytes()); key.extend_from_slice(&event_type.to_string().as_bytes());
@ -177,14 +177,15 @@ impl Rooms {
key.extend_from_slice(&state_key.as_bytes()); key.extend_from_slice(&state_key.as_bytes());
self.stateid_pduid.get(&key)?.map_or(Ok(None), |pdu_id| { self.stateid_pduid.get(&key)?.map_or(Ok(None), |pdu_id| {
Ok::<_, Error>(Some( Ok::<_, Error>(Some((
pdu_id.clone(),
serde_json::from_slice::<PduEvent>( serde_json::from_slice::<PduEvent>(
&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.") Error::bad_database("PDU in state not found in database.")
})?, })?,
) )
.map_err(|_| Error::bad_database("Invalid PDU bytes in room state."))?, .map_err(|_| Error::bad_database("Invalid PDU bytes in room state."))?,
)) )))
}) })
} }
@ -216,7 +217,7 @@ impl Rooms {
let mut events = StateMap::new(); let mut events = StateMap::new();
for (event_type, state_key) in auth_events { 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); events.insert((event_type, state_key), pdu);
} }
} }
@ -299,7 +300,7 @@ impl Rooms {
room_id: &RoomId, room_id: &RoomId,
event_type: &EventType, event_type: &EventType,
state_key: &str, state_key: &str,
) -> Result<Option<PduEvent>> { ) -> Result<Option<(IVec, PduEvent)>> {
if let Some(current_state_hash) = self.current_state_hash(room_id)? { if let Some(current_state_hash) = self.current_state_hash(room_id)? {
self.state_get(&current_state_hash, event_type, state_key) self.state_get(&current_state_hash, event_type, state_key)
} else { } else {
@ -653,7 +654,7 @@ impl Rooms {
}, },
}) })
}, },
|power_levels| { |(_, power_levels)| {
Ok(serde_json::from_value::<Raw<PowerLevelsEventContent>>( Ok(serde_json::from_value::<Raw<PowerLevelsEventContent>>(
power_levels.content, power_levels.content,
) )
@ -664,7 +665,9 @@ impl Rooms {
)?; )?;
let sender_membership = self let sender_membership = self
.room_state_get(&room_id, &EventType::RoomMember, &sender.to_string())? .room_state_get(&room_id, &EventType::RoomMember, &sender.to_string())?
.map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| { .map_or(
Ok::<_, Error>(member::MembershipState::Leave),
|(_, pdu)| {
Ok( Ok(
serde_json::from_value::<Raw<member::MemberEventContent>>(pdu.content) serde_json::from_value::<Raw<member::MemberEventContent>>(pdu.content)
.expect("Raw::from_value always works.") .expect("Raw::from_value always works.")
@ -672,7 +675,8 @@ impl Rooms {
.map_err(|_| Error::bad_database("Invalid Member event in db."))? .map_err(|_| Error::bad_database("Invalid Member event in db."))?
.membership, .membership,
) )
})?; },
)?;
let sender_power = power_levels.users.get(&sender).map_or_else( let sender_power = power_levels.users.get(&sender).map_or_else(
|| { || {
@ -759,7 +763,7 @@ impl Rooms {
let mut unsigned = unsigned.unwrap_or_default(); let mut unsigned = unsigned.unwrap_or_default();
if let Some(state_key) = &state_key { 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_content".to_owned(), prev_pdu.content);
unsigned.insert( unsigned.insert(
"prev_sender".to_owned(), "prev_sender".to_owned(),
@ -1017,7 +1021,7 @@ impl Rooms {
// Check if the room has a predecessor // Check if the room has a predecessor
if let Some(predecessor) = self if let Some(predecessor) = self
.room_state_get(&room_id, &EventType::RoomCreate, "")? .room_state_get(&room_id, &EventType::RoomCreate, "")?
.and_then(|create| { .and_then(|(_, create)| {
serde_json::from_value::< serde_json::from_value::<
Raw<ruma::events::room::create::CreateEventContent>, Raw<ruma::events::room::create::CreateEventContent>,
>(create.content) >(create.content)