From 9497713a79243eb745a8e06032412a075efe2eec Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sat, 6 Apr 2024 14:10:11 +0100 Subject: [PATCH 1/2] fix(membership): check if server is in room to decide whether to do remote leaves --- src/api/client_server/membership.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index bc84b262..c2ad61ad 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -1398,8 +1398,10 @@ pub async fn leave_all_rooms(user_id: &UserId) -> Result<()> { pub async fn leave_room(user_id: &UserId, room_id: &RoomId, reason: Option) -> Result<()> { // Ask a remote server if we don't have this room - if !services().rooms.metadata.exists(room_id)? - && room_id.server_name() != Some(services().globals.server_name()) + if !services() + .rooms + .state_cache + .server_in_room(services().globals.server_name(), room_id)? { if let Err(e) = remote_leave_room(user_id, room_id).await { warn!("Failed to leave room {} remotely: {}", user_id, e); From 2c73c3adbb1b326bdebcac856225bb93275287b8 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sat, 6 Apr 2024 14:12:18 +0100 Subject: [PATCH 2/2] fix(sync): send phoney leave event where room state is unknown on invite rejection --- src/api/client_server/sync.rs | 46 ++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index da603dcf..e0c6e0b9 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1,5 +1,6 @@ use crate::{ - service::rooms::timeline::PduCount, services, Error, PduEvent, Result, Ruma, RumaResponse, + service::{pdu::EventHash, rooms::timeline::PduCount}, + services, utils, Error, PduEvent, Result, Ruma, RumaResponse, }; use ruma::{ @@ -21,7 +22,7 @@ use ruma::{ StateEventType, TimelineEventType, }, serde::Raw, - uint, DeviceId, JsOption, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId, + uint, DeviceId, EventId, JsOption, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId, }; use std::{ collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet}, @@ -296,8 +297,6 @@ async fn sync_helper( for result in all_left_rooms { let (room_id, _) = result?; - let mut left_state_events = Vec::new(); - { // Get and drop the lock to wait for remaining operations to finish let mutex_insert = Arc::clone( @@ -325,9 +324,48 @@ async fn sync_helper( if !services().rooms.metadata.exists(&room_id)? { // This is just a rejected invite, not a room we know + let event = PduEvent { + event_id: EventId::new(services().globals.server_name()).into(), + sender: sender_user.clone(), + origin_server_ts: utils::millis_since_unix_epoch() + .try_into() + .expect("Timestamp is valid js_int value"), + kind: TimelineEventType::RoomMember, + content: serde_json::from_str(r#"{ "membership": "leave"}"#).unwrap(), + state_key: Some(sender_user.to_string()), + unsigned: None, + // The following keys are dropped on conversion + room_id: room_id.clone(), + prev_events: vec![], + depth: uint!(1), + auth_events: vec![], + redacts: None, + hashes: EventHash { + sha256: String::new(), + }, + signatures: None, + }; + + left_rooms.insert( + room_id, + LeftRoom { + account_data: RoomAccountData { events: Vec::new() }, + timeline: Timeline { + limited: false, + prev_batch: Some(next_batch_string.clone()), + events: Vec::new(), + }, + state: State { + events: vec![event.to_sync_state_event()], + }, + }, + ); + continue; } + let mut left_state_events = Vec::new(); + let since_shortstatehash = services() .rooms .user