Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions deltachat-jsonrpc/src/api/types/events.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use deltachat::{Event as CoreEvent, EventType as CoreEventType};
use num_traits::ToPrimitive;
use serde::Serialize;
use typescript_type_def::TypeDef;

Expand Down Expand Up @@ -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".
Expand Down Expand Up @@ -553,9 +559,11 @@ impl From<CoreEventType> 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 {
Expand Down
4 changes: 4 additions & 0 deletions src/events/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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".
Expand Down
29 changes: 21 additions & 8 deletions src/securejoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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("");
Expand Down Expand Up @@ -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(
Expand All @@ -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)
Expand All @@ -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)
}
}
Expand Down Expand Up @@ -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" {
Expand Down
46 changes: 46 additions & 0 deletions src/securejoin/securejoin_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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());
Expand Down
Loading