mirror of
https://github.com/chatmail/core.git
synced 2026-05-03 05:16:28 +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
|
### 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
|
### Fixes
|
||||||
- replace musl libc name resolution errors with a better message #3485
|
- replace musl libc name resolution errors with a better message #3485
|
||||||
- handle updates for not yet downloaded webxdc instances #3487
|
- handle updates for not yet downloaded webxdc instances #3487
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ use std::collections::HashSet;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::aheader::{Aheader, EncryptPreference};
|
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::chatlist::Chatlist;
|
||||||
use crate::constants::Chattype;
|
use crate::constants::Chattype;
|
||||||
use crate::contact::{addr_cmp, Contact, Origin};
|
use crate::contact::{addr_cmp, Contact, Origin};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
|
use crate::headerdef::HeaderDef;
|
||||||
use crate::key::{DcKey, Fingerprint, SignedPublicKey};
|
use crate::key::{DcKey, Fingerprint, SignedPublicKey};
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
use crate::mimeparser::SystemMessage;
|
use crate::mimeparser::SystemMessage;
|
||||||
@@ -521,16 +522,6 @@ impl Peerstate {
|
|||||||
PeerstateChange::FingerprintChange => {
|
PeerstateChange::FingerprintChange => {
|
||||||
stock_str::contact_setup_changed(context, self.addr.clone()).await
|
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 timestamp_sort = if let Some(msg_id) = msg_id {
|
||||||
let lastmsg = Message::load_from_db(context, *msg_id).await?;
|
let lastmsg = Message::load_from_db(context, *msg_id).await?;
|
||||||
@@ -556,22 +547,6 @@ impl Peerstate {
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await?;
|
.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(())
|
Ok(())
|
||||||
@@ -621,16 +596,64 @@ pub async fn maybe_do_aeap_transition(
|
|||||||
&& mime_parser.from_is_signed
|
&& mime_parser.from_is_signed
|
||||||
&& info.message_time > peerstate.last_seen
|
&& info.message_time > peerstate.last_seen
|
||||||
{
|
{
|
||||||
// Add an info messages to all chats with this contact
|
// Add an info messages to the chat
|
||||||
//
|
let contact_id = context
|
||||||
peerstate
|
.sql
|
||||||
.handle_setup_change(
|
.query_get_value(
|
||||||
context,
|
"SELECT id FROM contacts WHERE addr=? COLLATE NOCASE;",
|
||||||
info.message_time,
|
paramsv![peerstate.addr],
|
||||||
PeerstateChange::Aeap(info.from.clone()),
|
|
||||||
)
|
)
|
||||||
|
.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?;
|
.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();
|
peerstate.addr = info.from.clone();
|
||||||
let header = info.autocrypt_header.as_ref().context(
|
let header = info.autocrypt_header.as_ref().context(
|
||||||
"Internal error: Tried to do an AEAP transition without an autocrypt header??",
|
"Internal error: Tried to do an AEAP transition without an autocrypt header??",
|
||||||
@@ -655,9 +678,9 @@ enum PeerstateChange {
|
|||||||
/// The contact's public key fingerprint changed, likely because
|
/// The contact's public key fingerprint changed, likely because
|
||||||
/// the contact uses a new device and didn't transfer their key.
|
/// the contact uses a new device and didn't transfer their key.
|
||||||
FingerprintChange,
|
FingerprintChange,
|
||||||
/// The contact changed their address to the given new address
|
// /// The contact changed their address to the given new address
|
||||||
/// (Automatic Email Address Porting).
|
// /// (Automatic Email Address Porting).
|
||||||
Aeap(String),
|
// Aeap(String), (currently unused)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes duplicate peerstates from `acpeerstates` database table.
|
/// Removes duplicate peerstates from `acpeerstates` database table.
|
||||||
|
|||||||
@@ -69,24 +69,24 @@ Message w/out In-Reply-To
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum ChatForTransition {
|
enum ChatForTransition {
|
||||||
OneToOne,
|
// OneToOne,
|
||||||
GroupChat,
|
GroupChat,
|
||||||
VerifiedGroup,
|
VerifiedGroup,
|
||||||
}
|
}
|
||||||
use ChatForTransition::*;
|
use ChatForTransition::*;
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_aeap_transition_0() {
|
// async fn test_aeap_transition_0() {
|
||||||
check_aeap_transition(OneToOne, false, false).await;
|
// check_aeap_transition(OneToOne, false, false).await;
|
||||||
}
|
// }
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_aeap_transition_1() {
|
async fn test_aeap_transition_1() {
|
||||||
check_aeap_transition(GroupChat, false, false).await;
|
check_aeap_transition(GroupChat, false, false).await;
|
||||||
}
|
}
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_aeap_transition_0_verified() {
|
// async fn test_aeap_transition_0_verified() {
|
||||||
check_aeap_transition(OneToOne, true, false).await;
|
// check_aeap_transition(OneToOne, true, false).await;
|
||||||
}
|
// }
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_aeap_transition_1_verified() {
|
async fn test_aeap_transition_1_verified() {
|
||||||
check_aeap_transition(GroupChat, true, false).await;
|
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;
|
check_aeap_transition(VerifiedGroup, true, false).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_aeap_transition_0_bob_knew_new_addr() {
|
// async fn test_aeap_transition_0_bob_knew_new_addr() {
|
||||||
check_aeap_transition(OneToOne, false, true).await;
|
// check_aeap_transition(OneToOne, false, true).await;
|
||||||
}
|
// }
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_aeap_transition_1_bob_knew_new_addr() {
|
async fn test_aeap_transition_1_bob_knew_new_addr() {
|
||||||
check_aeap_transition(GroupChat, false, true).await;
|
check_aeap_transition(GroupChat, false, true).await;
|
||||||
}
|
}
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_aeap_transition_0_verified_bob_knew_new_addr() {
|
// async fn test_aeap_transition_0_verified_bob_knew_new_addr() {
|
||||||
check_aeap_transition(OneToOne, true, true).await;
|
// check_aeap_transition(OneToOne, true, true).await;
|
||||||
}
|
// }
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_aeap_transition_1_verified_bob_knew_new_addr() {
|
async fn test_aeap_transition_1_verified_bob_knew_new_addr() {
|
||||||
check_aeap_transition(GroupChat, true, true).await;
|
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");
|
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
|
// No matter which chat Alice sends to, the transition should be done in all groups
|
||||||
let chat_to_send = match chat_for_transition {
|
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,
|
GroupChat => group1_alice,
|
||||||
VerifiedGroup => group3_alice.expect("No verified group"),
|
VerifiedGroup => group3_alice.expect("No verified group"),
|
||||||
};
|
};
|
||||||
@@ -219,7 +219,8 @@ async fn check_aeap_transition(
|
|||||||
|
|
||||||
tcm.section("Check that the AEAP transition worked");
|
tcm.section("Check that the AEAP transition worked");
|
||||||
check_that_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,
|
||||||
"alice@example.org",
|
"alice@example.org",
|
||||||
ALICE_NEW_ADDR,
|
ALICE_NEW_ADDR,
|
||||||
@@ -246,7 +247,8 @@ async fn check_aeap_transition(
|
|||||||
assert_eq!(recvd.text.unwrap(), "Hello from my old addr!");
|
assert_eq!(recvd.text.unwrap(), "Hello from my old addr!");
|
||||||
|
|
||||||
check_that_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,
|
||||||
// Note that "alice@example.org" and ALICE_NEW_ADDR are switched now:
|
// Note that "alice@example.org" and ALICE_NEW_ADDR are switched now:
|
||||||
ALICE_NEW_ADDR,
|
ALICE_NEW_ADDR,
|
||||||
|
|||||||
Reference in New Issue
Block a user