mirror of
https://github.com/chatmail/core.git
synced 2026-05-14 04:16:30 +03:00
fix: Don't sync QR code token before populating the group (#5935)
Otherwise other devices don't yet know about the group and can't handle the sync message correctly.
This commit is contained in:
@@ -62,7 +62,7 @@ def test_qr_setup_contact_svg(acfactory) -> None:
|
|||||||
|
|
||||||
@pytest.mark.parametrize("protect", [True, False])
|
@pytest.mark.parametrize("protect", [True, False])
|
||||||
def test_qr_securejoin(acfactory, protect, tmp_path):
|
def test_qr_securejoin(acfactory, protect, tmp_path):
|
||||||
alice, bob = acfactory.get_online_accounts(2)
|
alice, bob, fiona = acfactory.get_online_accounts(3)
|
||||||
|
|
||||||
# Setup second device for Alice
|
# Setup second device for Alice
|
||||||
# to test observing securejoin protocol.
|
# to test observing securejoin protocol.
|
||||||
@@ -112,6 +112,13 @@ def test_qr_securejoin(acfactory, protect, tmp_path):
|
|||||||
alice2_contact_bob_snapshot = alice2_contact_bob.get_snapshot()
|
alice2_contact_bob_snapshot = alice2_contact_bob.get_snapshot()
|
||||||
assert alice2_contact_bob_snapshot.is_verified
|
assert alice2_contact_bob_snapshot.is_verified
|
||||||
|
|
||||||
|
# The QR code token is synced, so alice2 must be able to handle join requests.
|
||||||
|
logging.info("Fiona joins verified group via alice2")
|
||||||
|
alice.stop_io()
|
||||||
|
fiona.secure_join(qr_code)
|
||||||
|
alice2.wait_for_securejoin_inviter_success()
|
||||||
|
fiona.wait_for_securejoin_joiner_success()
|
||||||
|
|
||||||
|
|
||||||
def test_qr_securejoin_contact_request(acfactory) -> None:
|
def test_qr_securejoin_contact_request(acfactory) -> None:
|
||||||
"""Alice invites Bob to a group when Bob's chat with Alice is in a contact request mode."""
|
"""Alice invites Bob to a group when Bob's chat with Alice is in a contact request mode."""
|
||||||
|
|||||||
25
src/chat.rs
25
src/chat.rs
@@ -1934,8 +1934,8 @@ impl Chat {
|
|||||||
msg.param.set_int(Param::AttachGroupImage, 1);
|
msg.param.set_int(Param::AttachGroupImage, 1);
|
||||||
self.param.remove(Param::Unpromoted);
|
self.param.remove(Param::Unpromoted);
|
||||||
self.update_param(context).await?;
|
self.update_param(context).await?;
|
||||||
// send_sync_msg() is called (usually) a moment later at send_msg_to_smtp()
|
// send_sync_msg() is called a moment later at `smtp::send_smtp_messages()`
|
||||||
// when the group creation message is actually sent through SMTP --
|
// when the group creation message is already in the `smtp` table --
|
||||||
// this makes sure, the other devices are aware of grpid that is used in the sync-message.
|
// this makes sure, the other devices are aware of grpid that is used in the sync-message.
|
||||||
context
|
context
|
||||||
.sync_qr_code_tokens(Some(self.id))
|
.sync_qr_code_tokens(Some(self.id))
|
||||||
@@ -3726,17 +3726,13 @@ pub(crate) async fn add_contact_to_chat_ex(
|
|||||||
bail!("can not add contact because the account is not part of the group/broadcast");
|
bail!("can not add contact because the account is not part of the group/broadcast");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let sync_qr_code_tokens;
|
||||||
if from_handshake && chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 {
|
if from_handshake && chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 {
|
||||||
chat.param.remove(Param::Unpromoted);
|
chat.param.remove(Param::Unpromoted);
|
||||||
chat.update_param(context).await?;
|
chat.update_param(context).await?;
|
||||||
if context
|
sync_qr_code_tokens = true;
|
||||||
.sync_qr_code_tokens(Some(chat_id))
|
} else {
|
||||||
.await
|
sync_qr_code_tokens = false;
|
||||||
.log_err(context)
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
context.scheduler.interrupt_smtp().await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.is_self_addr(contact.get_addr()).await? {
|
if context.is_self_addr(contact.get_addr()).await? {
|
||||||
@@ -3780,6 +3776,15 @@ pub(crate) async fn add_contact_to_chat_ex(
|
|||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
sync = Nosync;
|
sync = Nosync;
|
||||||
|
if sync_qr_code_tokens
|
||||||
|
&& context
|
||||||
|
.sync_qr_code_tokens(Some(chat_id))
|
||||||
|
.await
|
||||||
|
.log_err(context)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
context.scheduler.interrupt_smtp().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
context.emit_event(EventType::ChatModified(chat_id));
|
context.emit_event(EventType::ChatModified(chat_id));
|
||||||
if sync.into() {
|
if sync.into() {
|
||||||
|
|||||||
35
src/sync.rs
35
src/sync.rs
@@ -328,8 +328,10 @@ mod tests {
|
|||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::chat::ProtectionStatus;
|
||||||
use crate::chatlist::Chatlist;
|
use crate::chatlist::Chatlist;
|
||||||
use crate::contact::{Contact, Origin};
|
use crate::contact::{Contact, Origin};
|
||||||
|
use crate::securejoin::get_securejoin_qr;
|
||||||
use crate::test_utils::{TestContext, TestContextManager};
|
use crate::test_utils::{TestContext, TestContextManager};
|
||||||
use crate::tools::SystemTime;
|
use crate::tools::SystemTime;
|
||||||
|
|
||||||
@@ -630,4 +632,37 @@ mod tests {
|
|||||||
assert_eq!(msg.text, "hi");
|
assert_eq!(msg.text, "hi");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
|
async fn test_unpromoted_group_no_qr_sync() -> Result<()> {
|
||||||
|
let mut tcm = TestContextManager::new();
|
||||||
|
let alice = &tcm.alice().await;
|
||||||
|
alice.set_config_bool(Config::SyncMsgs, true).await?;
|
||||||
|
let alice_chatid =
|
||||||
|
chat::create_group_chat(alice, ProtectionStatus::Protected, "the chat").await?;
|
||||||
|
let qr = get_securejoin_qr(alice, Some(alice_chatid)).await?;
|
||||||
|
let msg_id = alice.send_sync_msg().await?;
|
||||||
|
assert!(msg_id.is_none());
|
||||||
|
|
||||||
|
let bob = &tcm.bob().await;
|
||||||
|
tcm.exec_securejoin_qr(bob, alice, &qr).await;
|
||||||
|
let msg_id = alice.send_sync_msg().await?;
|
||||||
|
// The group becomes promoted when Bob joins, so the QR code token is synced.
|
||||||
|
assert!(msg_id.is_some());
|
||||||
|
let sent = alice.pop_sent_msg().await;
|
||||||
|
let msg = alice.parse_msg(&sent).await;
|
||||||
|
let mut sync_items = msg.sync_items.unwrap().items;
|
||||||
|
assert_eq!(sync_items.len(), 1);
|
||||||
|
let data = sync_items.pop().unwrap().data;
|
||||||
|
let SyncDataOrUnknown::SyncData(AddQrToken(_)) = data else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
|
let fiona = &tcm.fiona().await;
|
||||||
|
tcm.exec_securejoin_qr(fiona, alice, &qr).await;
|
||||||
|
let msg_id = alice.send_sync_msg().await?;
|
||||||
|
// The QR code token was already synced before.
|
||||||
|
assert!(msg_id.is_none());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user