diff --git a/deltachat-jsonrpc/src/api/types/events.rs b/deltachat-jsonrpc/src/api/types/events.rs index 2113a9d7ad..5c75d28457 100644 --- a/deltachat-jsonrpc/src/api/types/events.rs +++ b/deltachat-jsonrpc/src/api/types/events.rs @@ -1,4 +1,5 @@ use deltachat::{Event as CoreEvent, EventType as CoreEventType}; +use num_traits::ToPrimitive; use serde::Serialize; use typescript_type_def::TypeDef; @@ -303,6 +304,11 @@ pub enum EventType { /// ID of the contact that wants to join. contact_id: u32, + /// The type of the joined chat. + /// This can take the same values + /// as `BasicChat.chatType` ([`crate::api::types::chat::BasicChat::chat_type`]). + chat_type: u32, + /// Progress as: /// 300=vg-/vc-request received, typically shown as "bob@addr joins". /// 600=vg-/vc-request-with-auth received and verified, typically shown as "bob@addr verified". @@ -553,9 +559,11 @@ impl From for EventType { }, CoreEventType::SecurejoinInviterProgress { contact_id, + chat_type, progress, } => SecurejoinInviterProgress { contact_id: contact_id.to_u32(), + chat_type: chat_type.to_u32().unwrap_or(0), progress, }, CoreEventType::SecurejoinJoinerProgress { diff --git a/src/events/payload.rs b/src/events/payload.rs index fb0d972a34..5aa32ba93d 100644 --- a/src/events/payload.rs +++ b/src/events/payload.rs @@ -5,6 +5,7 @@ use std::path::PathBuf; use crate::chat::ChatId; use crate::config::Config; +use crate::constants::Chattype; use crate::contact::ContactId; use crate::ephemeral::Timer as EphemeralTimer; use crate::message::MsgId; @@ -272,6 +273,9 @@ pub enum EventType { /// ID of the contact that wants to join. contact_id: ContactId, + /// The type of the joined chat. + chat_type: Chattype, + /// Progress as: /// 300=vg-/vc-request received, typically shown as "bob@addr joins". /// 600=vg-/vc-request-with-auth received and verified, typically shown as "bob@addr verified". diff --git a/src/securejoin.rs b/src/securejoin.rs index 888fe05565..1311262e24 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -32,16 +32,29 @@ use qrinvite::QrInvite; use crate::token::Namespace; -fn inviter_progress(context: &Context, contact_id: ContactId, progress: usize) { +fn inviter_progress( + context: &Context, + contact_id: ContactId, + step: &str, + progress: usize, +) -> Result<()> { logged_debug_assert!( context, progress <= 1000, "inviter_progress: contact {contact_id}, progress={progress}, but value in range 0..1000 expected with: 0=error, 1..999=progress, 1000=success." ); + let chat_type = match step.get(..3) { + Some("vc-") => Chattype::Single, + Some("vg-") => Chattype::Group, + _ => bail!("Unknown securejoin step {step}"), + }; context.emit_event(EventType::SecurejoinInviterProgress { contact_id, + chat_type, progress, }); + + Ok(()) } /// Generates a Secure Join QR code. @@ -310,7 +323,7 @@ pub(crate) async fn handle_securejoin_handshake( return Ok(HandshakeMessage::Ignore); } - inviter_progress(context, contact_id, 300); + inviter_progress(context, contact_id, step, 300)?; let from_addr = ContactAddress::new(&mime_message.from.addr)?; let autocrypt_fingerprint = mime_message.autocrypt_fingerprint.as_deref().unwrap_or(""); @@ -405,7 +418,7 @@ pub(crate) async fn handle_securejoin_handshake( ChatId::create_for_contact(context, contact_id).await?; } context.emit_event(EventType::ContactsChanged(Some(contact_id))); - inviter_progress(context, contact_id, 600); + inviter_progress(context, contact_id, step, 600)?; if let Some(group_chat_id) = group_chat_id { // Join group. secure_connection_established( @@ -417,8 +430,8 @@ pub(crate) async fn handle_securejoin_handshake( .await?; chat::add_contact_to_chat_ex(context, Nosync, group_chat_id, contact_id, true) .await?; - inviter_progress(context, contact_id, 800); - inviter_progress(context, contact_id, 1000); + inviter_progress(context, contact_id, step, 800)?; + inviter_progress(context, contact_id, step, 1000)?; // IMAP-delete the message to avoid handling it by another device and adding the // member twice. Another device will know the member's key from Autocrypt-Gossip. Ok(HandshakeMessage::Done) @@ -435,7 +448,7 @@ pub(crate) async fn handle_securejoin_handshake( .await .context("failed sending vc-contact-confirm message")?; - inviter_progress(context, contact_id, 1000); + inviter_progress(context, contact_id, step, 1000)?; Ok(HandshakeMessage::Ignore) // "Done" would delete the message and break multi-device (the key from Autocrypt-header is needed) } } @@ -555,10 +568,10 @@ pub(crate) async fn observe_securejoin_on_other_device( ChatId::set_protection_for_contact(context, contact_id, mime_message.timestamp_sent).await?; if step == "vg-member-added" { - inviter_progress(context, contact_id, 800); + inviter_progress(context, contact_id, step, 800)?; } if step == "vg-member-added" || step == "vc-contact-confirm" { - inviter_progress(context, contact_id, 1000); + inviter_progress(context, contact_id, step, 1000)?; } if step == "vg-request-with-auth" || step == "vc-request-with-auth" { diff --git a/src/securejoin/securejoin_tests.rs b/src/securejoin/securejoin_tests.rs index 981640640c..b502ccea03 100644 --- a/src/securejoin/securejoin_tests.rs +++ b/src/securejoin/securejoin_tests.rs @@ -365,6 +365,29 @@ async fn test_setup_contact_bob_knows_alice() -> Result<()> { alice.recv_msg_trash(&sent).await; assert_eq!(contact_bob.is_verified(alice).await?, true); + // Check Alice signalled success via the SecurejoinInviterProgress event. + let event = alice + .evtracker + .get_matching(|evt| { + matches!( + evt, + EventType::SecurejoinInviterProgress { progress: 1000, .. } + ) + }) + .await; + match event { + EventType::SecurejoinInviterProgress { + contact_id, + chat_type, + progress, + } => { + assert_eq!(contact_id, contact_bob.id); + assert_eq!(chat_type, Chattype::Single); + assert_eq!(progress, 1000); + } + _ => unreachable!(), + } + let sent = alice.pop_sent_msg().await; let msg = bob.parse_msg(&sent).await; assert!(msg.was_encrypted()); @@ -515,6 +538,29 @@ async fn test_secure_join() -> Result<()> { alice.recv_msg_trash(&sent).await; assert_eq!(contact_bob.is_verified(&alice).await?, true); + // Check Alice signalled success via the SecurejoinInviterProgress event. + let event = alice + .evtracker + .get_matching(|evt| { + matches!( + evt, + EventType::SecurejoinInviterProgress { progress: 1000, .. } + ) + }) + .await; + match event { + EventType::SecurejoinInviterProgress { + contact_id, + chat_type, + progress, + } => { + assert_eq!(contact_id, contact_bob.id); + assert_eq!(chat_type, Chattype::Group); + assert_eq!(progress, 1000); + } + _ => unreachable!(), + } + let sent = alice.pop_sent_msg().await; let msg = bob.parse_msg(&sent).await; assert!(msg.was_encrypted());