diff --git a/src/chat.rs b/src/chat.rs index 4db51c6c5..db8a955d7 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -4083,6 +4083,67 @@ mod tests { Ok(()) } + /// Test simultaneous removal of user from the chat and leaving the group. + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_simultaneous_member_remove() -> Result<()> { + let mut tcm = TestContextManager::new(); + + let alice = tcm.alice().await; + let bob = tcm.bob().await; + + alice.set_config(Config::E2eeEnabled, Some("0")).await?; + bob.set_config(Config::E2eeEnabled, Some("0")).await?; + + let alice_bob_contact_id = Contact::create(&alice, "Bob", "bob@example.net").await?; + let alice_fiona_contact_id = Contact::create(&alice, "Fiona", "fiona@example.net").await?; + let alice_claire_contact_id = + Contact::create(&alice, "Claire", "claire@example.net").await?; + + // Create and promote a group. + let alice_chat_id = + create_group_chat(&alice, ProtectionStatus::Unprotected, "Group chat").await?; + add_contact_to_chat(&alice, alice_chat_id, alice_bob_contact_id).await?; + add_contact_to_chat(&alice, alice_chat_id, alice_fiona_contact_id).await?; + let alice_sent_msg = alice + .send_text(alice_chat_id, "Hi! I created a group.") + .await; + let bob_received_msg = bob.recv_msg(&alice_sent_msg).await; + + let bob_chat_id = bob_received_msg.get_chat_id(); + bob_chat_id.accept(&bob).await?; + + // Alice adds Claire to the chat. + add_contact_to_chat(&alice, alice_chat_id, alice_claire_contact_id).await?; + let alice_sent_add_msg = alice.pop_sent_msg().await; + + // Alice removes Bob from the chat. + remove_contact_from_chat(&alice, alice_chat_id, alice_bob_contact_id).await?; + let alice_sent_remove_msg = alice.pop_sent_msg().await; + + // Bob leaves the chat. + remove_contact_from_chat(&bob, bob_chat_id, ContactId::SELF).await?; + + // Bob receives a msg about Alice adding Claire to the group. + let bob_received_add_msg = bob.recv_msg(&alice_sent_add_msg).await; + + // Test that add message is rewritten. + assert_eq!( + bob_received_add_msg.get_text(), + "Member claire@example.net added by alice@example.org." + ); + + // Bob receives a msg about Alice removing him from the group. + let bob_received_remove_msg = bob.recv_msg(&alice_sent_remove_msg).await; + + // Test that remove message is rewritten. + assert_eq!( + bob_received_remove_msg.get_text(), + "Member Me (bob@example.net) removed by alice@example.org." + ); + + Ok(()) + } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_modify_chat_multi_device() -> Result<()> { let a1 = TestContext::new_alice().await; diff --git a/src/receive_imf.rs b/src/receive_imf.rs index a146cb416..6db785650 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -1682,6 +1682,13 @@ async fn apply_group_changes( if let Some(removed_addr) = mime_parser.get_header(HeaderDef::ChatGroupMemberRemoved) { removed_id = Contact::lookup_id_by_addr(context, removed_addr, Origin::Unknown).await?; + + better_msg = if removed_id == Some(from_id) { + Some(stock_str::msg_group_left_local(context, from_id).await) + } else { + Some(stock_str::msg_del_member_local(context, removed_addr, from_id).await) + }; + if let Some(contact_id) = removed_id { if allow_member_list_changes { // Remove a single member from the chat. @@ -1689,12 +1696,6 @@ async fn apply_group_changes( chat::remove_from_chat_contacts_table(context, chat_id, contact_id).await?; send_event_chat_modified = true; } - - better_msg = if contact_id == from_id { - Some(stock_str::msg_group_left_local(context, from_id).await) - } else { - Some(stock_str::msg_del_member_local(context, removed_addr, from_id).await) - }; } else { info!( context, @@ -1705,6 +1706,8 @@ async fn apply_group_changes( warn!(context, "Removed {removed_addr:?} has no contact id.") } } else if let Some(added_addr) = mime_parser.get_header(HeaderDef::ChatGroupMemberAdded) { + better_msg = Some(stock_str::msg_add_member_local(context, added_addr, from_id).await); + if allow_member_list_changes { // Add a single member to the chat. if !recreate_member_list { @@ -1717,8 +1720,6 @@ async fn apply_group_changes( warn!(context, "Added {added_addr:?} has no contact id.") } } - - better_msg = Some(stock_str::msg_add_member_local(context, added_addr, from_id).await); } else { info!(context, "Ignoring addition of {added_addr:?} to {chat_id}."); }