From e7348a4fd8242ad7dbccc71d5396743a16d096de Mon Sep 17 00:00:00 2001 From: link2xt Date: Wed, 22 Oct 2025 17:58:21 +0000 Subject: [PATCH] feat: do not run SecureJoin if we are already in the group --- src/securejoin/bob.rs | 16 ++++++- src/securejoin/securejoin_tests.rs | 43 +++++++++++++++++++ test-data/golden/two_group_securejoins | 2 +- .../golden/verified_chats_editor_reordering | 2 +- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/securejoin/bob.rs b/src/securejoin/bob.rs index 2d7046f5d..50cfbcc15 100644 --- a/src/securejoin/bob.rs +++ b/src/securejoin/bob.rs @@ -65,7 +65,21 @@ pub(super) async fn start_protocol(context: &Context, invite: QrInvite) -> Resul ) .await?; - if has_key + // Chat ID of the group we are joining, unused otherwise. + let group_chat_id = joining_chat_id(context, &invite, chat_id).await?; + if matches!(invite, QrInvite::Group { .. }) + && is_contact_in_chat(context, group_chat_id, ContactId::SELF).await? + { + // If QR code is a group invite + // and we are already in the chat, + // nothing needs to be done. + // Even if Alice is not verified, we don't send anything. + context.emit_event(EventType::SecurejoinJoinerProgress { + contact_id: invite.contact_id(), + progress: JoinerProgress::Succeeded.to_usize(), + }); + return Ok(group_chat_id); + } else if has_key && verify_sender_by_fingerprint(context, invite.fingerprint(), invite.contact_id()) .await? { diff --git a/src/securejoin/securejoin_tests.rs b/src/securejoin/securejoin_tests.rs index 1c33b115e..67e0acb0d 100644 --- a/src/securejoin/securejoin_tests.rs +++ b/src/securejoin/securejoin_tests.rs @@ -959,3 +959,46 @@ async fn test_expired_synced_auth_token() -> Result<()> { Ok(()) } + +/// Tests that attempting to join already joined group does nothing. +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_rejoin_group() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let bob = &tcm.bob().await; + + let alice_chat_id = chat::create_group(alice, "the chat").await?; + + let qr = get_securejoin_qr(alice, Some(alice_chat_id)).await?; + tcm.exec_securejoin_qr(bob, alice, &qr).await; + + // Bob gets two progress events. + for expected_progress in [400, 1000] { + let EventType::SecurejoinJoinerProgress { progress, .. } = bob + .evtracker + .get_matching(|evt| matches!(evt, EventType::SecurejoinJoinerProgress { .. })) + .await + else { + unreachable!(); + }; + assert_eq!(progress, expected_progress); + } + + // Bob scans the QR code again. + join_securejoin(bob, &qr).await?; + + // Bob immediately receives progress 1000 event. + let EventType::SecurejoinJoinerProgress { progress, .. } = bob + .evtracker + .get_matching(|evt| matches!(evt, EventType::SecurejoinJoinerProgress { .. })) + .await + else { + unreachable!(); + }; + assert_eq!(progress, 1000); + + // Bob does not send any more messages by scanning the QR code. + assert!(bob.pop_sent_msg_opt(Duration::ZERO).await.is_none()); + + Ok(()) +} diff --git a/test-data/golden/two_group_securejoins b/test-data/golden/two_group_securejoins index 5e20c36b6..1e857fa60 100644 --- a/test-data/golden/two_group_securejoins +++ b/test-data/golden/two_group_securejoins @@ -4,6 +4,6 @@ Msg#6004: info (Contact#Contact#Info): alice@example.org invited you to join thi Waiting for the device of alice@example.org to reply… [NOTICED][INFO] Msg#6006: info (Contact#Contact#Info): alice@example.org replied, waiting for being added to the group… [NOTICED][INFO] -Msg#6003: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO] +Msg#6002: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO] Msg#6008🔒: (Contact#Contact#6001): Member Me added by alice@example.org. [FRESH][INFO] -------------------------------------------------------------------------------- diff --git a/test-data/golden/verified_chats_editor_reordering b/test-data/golden/verified_chats_editor_reordering index 3bf488c00..a7e5b75d7 100644 --- a/test-data/golden/verified_chats_editor_reordering +++ b/test-data/golden/verified_chats_editor_reordering @@ -4,7 +4,7 @@ Msg#3004: info (Contact#Contact#Info): alice@example.org invited you to join thi Waiting for the device of alice@example.org to reply… [NOTICED][INFO] Msg#3006: info (Contact#Contact#Info): alice@example.org replied, waiting for being added to the group… [NOTICED][INFO] -Msg#3003: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO] +Msg#3002: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO] Msg#3008🔒: (Contact#Contact#3002): [FRESH] Msg#3009: info (Contact#Contact#Info): Member bob@example.net added. [NOTICED][INFO] Msg#3010🔒: (Contact#Contact#3001): Member Me added by alice@example.org. [FRESH][INFO]