diff --git a/CHANGELOG.md b/CHANGELOG.md index 34909fcb5..30546d356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ### Changes +- (AEAP) When one of your contacts changed their address, they are + only replaced in the chat where you got a message from them + for now #3491 + ### Fixes - replace musl libc name resolution errors with a better message #3485 - handle updates for not yet downloaded webxdc instances #3487 diff --git a/src/peerstate.rs b/src/peerstate.rs index 283a305d7..02126a8a8 100644 --- a/src/peerstate.rs +++ b/src/peerstate.rs @@ -4,12 +4,13 @@ use std::collections::HashSet; use std::fmt; use crate::aheader::{Aheader, EncryptPreference}; -use crate::chat::{self, is_contact_in_chat, Chat}; +use crate::chat::{self, is_contact_in_chat, Chat, ChatId}; use crate::chatlist::Chatlist; use crate::constants::Chattype; use crate::contact::{addr_cmp, Contact, Origin}; use crate::context::Context; use crate::events::EventType; +use crate::headerdef::HeaderDef; use crate::key::{DcKey, Fingerprint, SignedPublicKey}; use crate::message::Message; use crate::mimeparser::SystemMessage; @@ -521,16 +522,6 @@ impl Peerstate { PeerstateChange::FingerprintChange => { stock_str::contact_setup_changed(context, self.addr.clone()).await } - PeerstateChange::Aeap(new_addr) => { - let old_contact = Contact::load_from_db(context, contact_id).await?; - stock_str::aeap_addr_changed( - context, - old_contact.get_display_name(), - &self.addr, - new_addr, - ) - .await - } }; let timestamp_sort = if let Some(msg_id) = msg_id { let lastmsg = Message::load_from_db(context, *msg_id).await?; @@ -556,22 +547,6 @@ impl Peerstate { None, ) .await?; - - if let PeerstateChange::Aeap(new_addr) = &change { - let chat = Chat::load_from_db(context, *chat_id).await?; - if chat.typ == Chattype::Group || chat.typ == Chattype::Broadcast { - chat::remove_from_chat_contacts_table(context, *chat_id, contact_id).await?; - - let (new_contact_id, _) = - Contact::add_or_lookup(context, "", new_addr, Origin::IncomingUnknownFrom) - .await?; - if !is_contact_in_chat(context, *chat_id, new_contact_id).await? { - chat::add_to_chat_contacts_table(context, *chat_id, new_contact_id).await?; - } - - context.emit_event(EventType::ChatModified(*chat_id)); - } - } } Ok(()) @@ -621,15 +596,63 @@ pub async fn maybe_do_aeap_transition( && mime_parser.from_is_signed && info.message_time > peerstate.last_seen { - // Add an info messages to all chats with this contact - // - peerstate - .handle_setup_change( - context, - info.message_time, - PeerstateChange::Aeap(info.from.clone()), + // Add an info messages to the chat + let contact_id = context + .sql + .query_get_value( + "SELECT id FROM contacts WHERE addr=? COLLATE NOCASE;", + paramsv![peerstate.addr], ) - .await?; + .await? + .with_context(|| { + format!("contact with addr {:?} not found", &peerstate.addr) + })?; + + let old_contact = Contact::load_from_db(context, contact_id).await?; + let msg = stock_str::aeap_addr_changed( + context, + old_contact.get_display_name(), + &peerstate.addr, + &from.addr, + ) + .await; + + let grpid = match mime_parser.get_header(HeaderDef::ChatGroupId) { + Some(h) => h, + None => return Ok(()), + }; + let (chat_id, protected, _blocked) = + match chat::get_chat_id_by_grpid(context, grpid).await? { + Some(s) => s, + None => return Ok(()), + }; + + if protected && !peerstate.has_verified_key(&mime_parser.signatures) { + return Ok(()); + } + + chat::add_info_msg(context, chat_id, &msg, info.message_time).await?; + + let (new_contact_id, _) = + Contact::add_or_lookup(context, "", &from.addr, Origin::IncomingUnknownFrom) + .await?; + + let chat = Chat::load_from_db(context, chat_id).await?; + if chat.typ == Chattype::Group || chat.typ == Chattype::Broadcast { + chat::remove_from_chat_contacts_table(context, chat_id, contact_id).await?; + + if !is_contact_in_chat(context, chat_id, new_contact_id).await? { + chat::add_to_chat_contacts_table(context, chat_id, new_contact_id).await?; + } + + context.emit_event(EventType::ChatModified(chat_id)); + } + + // Create a chat with the new address with the same blocked-level as the old chat + let new_chat_id = + ChatId::create_for_contact_with_blocked(context, new_contact_id, chat.blocked) + .await?; + chat::add_info_msg(context, new_chat_id, &msg, info.message_time).await?; peerstate.addr = info.from.clone(); let header = info.autocrypt_header.as_ref().context( @@ -655,9 +678,9 @@ enum PeerstateChange { /// The contact's public key fingerprint changed, likely because /// the contact uses a new device and didn't transfer their key. FingerprintChange, - /// The contact changed their address to the given new address - /// (Automatic Email Address Porting). - Aeap(String), + // /// The contact changed their address to the given new address + // /// (Automatic Email Address Porting). + // Aeap(String), (currently unused) } /// Removes duplicate peerstates from `acpeerstates` database table. diff --git a/src/tests/aeap.rs b/src/tests/aeap.rs index 9badf9705..5eaee0169 100644 --- a/src/tests/aeap.rs +++ b/src/tests/aeap.rs @@ -69,24 +69,24 @@ Message w/out In-Reply-To } enum ChatForTransition { - OneToOne, + // OneToOne, GroupChat, VerifiedGroup, } use ChatForTransition::*; -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_aeap_transition_0() { - check_aeap_transition(OneToOne, false, false).await; -} +// #[tokio::test(flavor = "multi_thread", worker_threads = 2)] +// async fn test_aeap_transition_0() { +// check_aeap_transition(OneToOne, false, false).await; +// } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_aeap_transition_1() { check_aeap_transition(GroupChat, false, false).await; } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_aeap_transition_0_verified() { - check_aeap_transition(OneToOne, true, false).await; -} +// #[tokio::test(flavor = "multi_thread", worker_threads = 2)] +// async fn test_aeap_transition_0_verified() { +// check_aeap_transition(OneToOne, true, false).await; +// } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_aeap_transition_1_verified() { check_aeap_transition(GroupChat, true, false).await; @@ -96,18 +96,18 @@ async fn test_aeap_transition_2_verified() { check_aeap_transition(VerifiedGroup, true, false).await; } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_aeap_transition_0_bob_knew_new_addr() { - check_aeap_transition(OneToOne, false, true).await; -} +// #[tokio::test(flavor = "multi_thread", worker_threads = 2)] +// async fn test_aeap_transition_0_bob_knew_new_addr() { +// check_aeap_transition(OneToOne, false, true).await; +// } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_aeap_transition_1_bob_knew_new_addr() { check_aeap_transition(GroupChat, false, true).await; } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn test_aeap_transition_0_verified_bob_knew_new_addr() { - check_aeap_transition(OneToOne, true, true).await; -} +// #[tokio::test(flavor = "multi_thread", worker_threads = 2)] +// async fn test_aeap_transition_0_verified_bob_knew_new_addr() { +// check_aeap_transition(OneToOne, true, true).await; +// } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_aeap_transition_1_verified_bob_knew_new_addr() { check_aeap_transition(GroupChat, true, true).await; @@ -206,7 +206,7 @@ async fn check_aeap_transition( tcm.section("Alice sends another message to Bob, this time from her new addr"); // No matter which chat Alice sends to, the transition should be done in all groups let chat_to_send = match chat_for_transition { - OneToOne => alice.create_chat(&bob).await.id, + // OneToOne => alice.create_chat(&bob).await.id, GroupChat => group1_alice, VerifiedGroup => group3_alice.expect("No verified group"), }; @@ -219,7 +219,8 @@ async fn check_aeap_transition( tcm.section("Check that the AEAP transition worked"); check_that_transition_worked( - &groups, + // The transition is only done in the chat where the message was sent for now: + &[recvd.chat_id], &alice, "alice@example.org", ALICE_NEW_ADDR, @@ -246,7 +247,8 @@ async fn check_aeap_transition( assert_eq!(recvd.text.unwrap(), "Hello from my old addr!"); check_that_transition_worked( - &groups, + // The transition is only done in the chat where the message was sent for now: + &[recvd.chat_id], &alice, // Note that "alice@example.org" and ALICE_NEW_ADDR are switched now: ALICE_NEW_ADDR,