mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Only do the AEAP transition in the chat where it happened (#3491)
* Only do the AEAP transition in the chat where it happened * Create a chat with the new contact * changelog
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user