mirror of
https://github.com/chatmail/core.git
synced 2026-05-17 13:56:30 +03:00
fix: Remove SecurejoinWait info message when received Alice's key (#7585)
And don't add a `SecurejoinWait` info message at all if we know Alice's key from the start. If we don't remove this info message, it appears in the chat after "Messages are end-to-end encrypted..." which is quite confusing when Bob can already send messages to Alice.
This commit is contained in:
@@ -5,14 +5,16 @@ use anyhow::{Context as _, Result};
|
|||||||
use super::HandshakeMessage;
|
use super::HandshakeMessage;
|
||||||
use super::qrinvite::QrInvite;
|
use super::qrinvite::QrInvite;
|
||||||
use crate::chat::{self, ChatId, is_contact_in_chat};
|
use crate::chat::{self, ChatId, is_contact_in_chat};
|
||||||
|
use crate::chatlist_events;
|
||||||
use crate::constants::{Blocked, Chattype};
|
use crate::constants::{Blocked, Chattype};
|
||||||
use crate::contact::Origin;
|
use crate::contact::Origin;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
use crate::key::self_fingerprint;
|
use crate::key::self_fingerprint;
|
||||||
use crate::message::{Message, Viewtype};
|
use crate::log::LogExt;
|
||||||
|
use crate::message::{Message, MsgId, Viewtype};
|
||||||
use crate::mimeparser::{MimeMessage, SystemMessage};
|
use crate::mimeparser::{MimeMessage, SystemMessage};
|
||||||
use crate::param::Param;
|
use crate::param::{Param, Params};
|
||||||
use crate::securejoin::{ContactId, encrypted_and_signed, verify_sender_by_fingerprint};
|
use crate::securejoin::{ContactId, encrypted_and_signed, verify_sender_by_fingerprint};
|
||||||
use crate::stock_str;
|
use crate::stock_str;
|
||||||
use crate::sync::Sync::*;
|
use crate::sync::Sync::*;
|
||||||
@@ -48,16 +50,16 @@ pub(super) async fn start_protocol(context: &Context, invite: QrInvite) -> Resul
|
|||||||
ContactId::scaleup_origin(context, &[invite.contact_id()], Origin::SecurejoinJoined).await?;
|
ContactId::scaleup_origin(context, &[invite.contact_id()], Origin::SecurejoinJoined).await?;
|
||||||
context.emit_event(EventType::ContactsChanged(None));
|
context.emit_event(EventType::ContactsChanged(None));
|
||||||
|
|
||||||
|
let has_key = context
|
||||||
|
.sql
|
||||||
|
.exists(
|
||||||
|
"SELECT COUNT(*) FROM public_keys WHERE fingerprint=?",
|
||||||
|
(invite.fingerprint().hex(),),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Now start the protocol and initialise the state.
|
// Now start the protocol and initialise the state.
|
||||||
{
|
{
|
||||||
let has_key = context
|
|
||||||
.sql
|
|
||||||
.exists(
|
|
||||||
"SELECT COUNT(*) FROM public_keys WHERE fingerprint=?",
|
|
||||||
(invite.fingerprint().hex(),),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// `joining_chat_id` is `Some` if group chat
|
// `joining_chat_id` is `Some` if group chat
|
||||||
// already exists and we are in the chat.
|
// already exists and we are in the chat.
|
||||||
let joining_chat_id = match invite {
|
let joining_chat_id = match invite {
|
||||||
@@ -142,20 +144,22 @@ pub(super) async fn start_protocol(context: &Context, invite: QrInvite) -> Resul
|
|||||||
Ok(joining_chat_id)
|
Ok(joining_chat_id)
|
||||||
}
|
}
|
||||||
QrInvite::Contact { .. } => {
|
QrInvite::Contact { .. } => {
|
||||||
// For setup-contact the BobState already ensured the 1:1 chat exists because it
|
// For setup-contact the BobState already ensured the 1:1 chat exists because it is
|
||||||
// uses it to send the handshake messages.
|
// used to send the handshake messages.
|
||||||
chat::add_info_msg_with_cmd(
|
if !has_key {
|
||||||
context,
|
chat::add_info_msg_with_cmd(
|
||||||
private_chat_id,
|
context,
|
||||||
&stock_str::securejoin_wait(context).await,
|
private_chat_id,
|
||||||
SystemMessage::SecurejoinWait,
|
&stock_str::securejoin_wait(context).await,
|
||||||
None,
|
SystemMessage::SecurejoinWait,
|
||||||
time(),
|
None,
|
||||||
None,
|
time(),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
)
|
None,
|
||||||
.await?;
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
Ok(private_chat_id)
|
Ok(private_chat_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,6 +181,38 @@ async fn insert_new_db_entry(context: &Context, invite: QrInvite, chat_id: ChatI
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn delete_securejoin_wait_msg(context: &Context, chat_id: ChatId) -> Result<()> {
|
||||||
|
if let Some((msg_id, param)) = context
|
||||||
|
.sql
|
||||||
|
.query_row_optional(
|
||||||
|
"
|
||||||
|
SELECT id, param FROM msgs
|
||||||
|
WHERE timestamp=(SELECT MAX(timestamp) FROM msgs WHERE chat_id=? AND hidden=0)
|
||||||
|
AND chat_id=? AND hidden=0
|
||||||
|
LIMIT 1
|
||||||
|
",
|
||||||
|
(chat_id, chat_id),
|
||||||
|
|row| {
|
||||||
|
let id: MsgId = row.get(0)?;
|
||||||
|
let param: String = row.get(1)?;
|
||||||
|
let param: Params = param.parse().unwrap_or_default();
|
||||||
|
Ok((id, param))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
&& param.get_cmd() == SystemMessage::SecurejoinWait
|
||||||
|
{
|
||||||
|
let on_server = false;
|
||||||
|
msg_id.trash(context, on_server).await?;
|
||||||
|
context.emit_event(EventType::MsgDeleted { chat_id, msg_id });
|
||||||
|
context.emit_msgs_changed_without_msg_id(chat_id);
|
||||||
|
chatlist_events::emit_chatlist_item_changed(context, chat_id);
|
||||||
|
context.emit_msgs_changed_without_ids();
|
||||||
|
chatlist_events::emit_chatlist_changed(context);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Handles `vc-auth-required` and `vg-auth-required` handshake messages.
|
/// Handles `vc-auth-required` and `vg-auth-required` handshake messages.
|
||||||
///
|
///
|
||||||
/// # Bob - the joiner's side
|
/// # Bob - the joiner's side
|
||||||
@@ -213,6 +249,11 @@ pub(super) async fn handle_auth_required(
|
|||||||
|
|
||||||
info!(context, "Fingerprint verified.",);
|
info!(context, "Fingerprint verified.",);
|
||||||
let chat_id = private_chat_id(context, &invite).await?;
|
let chat_id = private_chat_id(context, &invite).await?;
|
||||||
|
delete_securejoin_wait_msg(context, chat_id)
|
||||||
|
.await
|
||||||
|
.context("delete_securejoin_wait_msg")
|
||||||
|
.log_err(context)
|
||||||
|
.ok();
|
||||||
send_handshake_message(context, &invite, chat_id, BobHandshakeMsg::RequestWithAuth).await?;
|
send_handshake_message(context, &invite, chat_id, BobHandshakeMsg::RequestWithAuth).await?;
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
|
|||||||
@@ -100,6 +100,17 @@ async fn test_setup_contact_ex(case: SetupContactCase) {
|
|||||||
bob_chat.why_cant_send(&bob).await.unwrap(),
|
bob_chat.why_cant_send(&bob).await.unwrap(),
|
||||||
Some(CantSendReason::MissingKey)
|
Some(CantSendReason::MissingKey)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Check Bob's info messages.
|
||||||
|
let msg_cnt = 2;
|
||||||
|
let mut i = 0..msg_cnt;
|
||||||
|
let msg = get_chat_msg(&bob, bob_chat.get_id(), i.next().unwrap(), msg_cnt).await;
|
||||||
|
assert!(msg.is_info());
|
||||||
|
assert_eq!(msg.get_text(), messages_e2e_encrypted(&bob).await);
|
||||||
|
let msg = get_chat_msg(&bob, bob_chat.get_id(), i.next().unwrap(), msg_cnt).await;
|
||||||
|
assert!(msg.is_info());
|
||||||
|
assert_eq!(msg.get_text(), stock_str::securejoin_wait(&bob).await);
|
||||||
|
|
||||||
let contact_alice_id = bob.add_or_lookup_contact_no_key(&alice).await.id;
|
let contact_alice_id = bob.add_or_lookup_contact_no_key(&alice).await.id;
|
||||||
let sent = bob.pop_sent_msg().await;
|
let sent = bob.pop_sent_msg().await;
|
||||||
assert!(!sent.payload.contains("Bob Examplenet"));
|
assert!(!sent.payload.contains("Bob Examplenet"));
|
||||||
@@ -272,15 +283,10 @@ async fn test_setup_contact_ex(case: SetupContactCase) {
|
|||||||
assert!(contact_alice.get_name().is_empty());
|
assert!(contact_alice.get_name().is_empty());
|
||||||
assert_eq!(contact_alice.is_bot(), case == SetupContactCase::AliceIsBot);
|
assert_eq!(contact_alice.is_bot(), case == SetupContactCase::AliceIsBot);
|
||||||
|
|
||||||
// Check Bob got expected info messages in his 1:1 chat.
|
// The `SecurejoinWait` info message has been removed, but the e2ee notice remains.
|
||||||
let msg_cnt = 2;
|
let msg = get_chat_msg(&bob, bob_chat.get_id(), 0, 1).await;
|
||||||
let mut i = 0..msg_cnt;
|
|
||||||
let msg = get_chat_msg(&bob, bob_chat.get_id(), i.next().unwrap(), msg_cnt).await;
|
|
||||||
assert!(msg.is_info());
|
assert!(msg.is_info());
|
||||||
assert_eq!(msg.get_text(), messages_e2e_encrypted(&bob).await);
|
assert_eq!(msg.get_text(), messages_e2e_encrypted(&bob).await);
|
||||||
let msg = get_chat_msg(&bob, bob_chat.get_id(), i.next().unwrap(), msg_cnt).await;
|
|
||||||
assert!(msg.is_info());
|
|
||||||
assert_eq!(msg.get_text(), stock_str::securejoin_wait(&bob).await);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
|
|||||||
Reference in New Issue
Block a user