Compare commits

...

2 Commits

Author SHA1 Message Date
B. Petersen
4187523311 add missing members receiving non-dc messages 2021-03-14 23:50:06 +01:00
B. Petersen
c6ad6cb0c9 add failing test for alias support 2021-03-14 23:50:05 +01:00

View File

@@ -1164,6 +1164,44 @@ async fn calc_sort_timestamp(
sort_timestamp
}
async fn update_member_list(
context: &Context,
chat_id: ChatId,
self_addr: String,
from_id: u32,
to_ids: &ContactIds,
) -> Result<()> {
if !chat::is_contact_in_chat(context, chat_id, DC_CONTACT_ID_SELF).await {
// Members could have been removed while we were
// absent. We can't use existing member list and need to
// start from scratch.
context
.sql
.execute(
"DELETE FROM chats_contacts WHERE chat_id=?;",
paramsv![chat_id],
)
.await?;
chat::add_to_chat_contacts_table(context, chat_id, DC_CONTACT_ID_SELF).await;
}
if from_id > DC_CONTACT_ID_LAST_SPECIAL
&& !Contact::addr_equals_contact(context, &self_addr, from_id as u32).await
&& !chat::is_contact_in_chat(context, chat_id, from_id).await
{
chat::add_to_chat_contacts_table(context, chat_id, from_id as u32).await;
}
for &to_id in to_ids.iter() {
info!(context, "adding to={:?} to chat id={}", to_id, chat_id);
if !Contact::addr_equals_contact(context, &self_addr, to_id).await
&& !chat::is_contact_in_chat(context, chat_id, to_id).await
{
chat::add_to_chat_contacts_table(context, chat_id, to_id).await;
}
}
Ok(())
}
/// This function tries to extract the group-id from the message and returns the
/// corresponding chat_id. If the chat does not exist, it is created.
/// If the message contains groups commands (name, profile image, changed members),
@@ -1197,6 +1235,11 @@ async fn create_or_lookup_group(
set_better_msg(mime_parser, &better_msg);
}
let self_addr = context
.get_config(Config::ConfiguredAddr)
.await
.unwrap_or_default();
let grpid = if let Some(grpid) = try_getting_grpid(mime_parser) {
grpid
} else {
@@ -1221,6 +1264,11 @@ async fn create_or_lookup_group(
// Otherwise, it could be a reply to an undecipherable
// group message that we previously assigned to a 1:1 chat.
if chat.typ == Chattype::Group {
// If we assign a non-dc-message to an existing chat,
// add missing contacts to the member list.
update_member_list(context, chat.id, self_addr, from_id, to_ids).await?;
context.emit_event(EventType::ChatModified(chat.id));
// Return immediately without attempting to execute group commands,
// as this message does not contain an explicit group-id header.
return Ok((chat.id, chat.blocked));
@@ -1324,10 +1372,6 @@ async fn create_or_lookup_group(
let group_explicitly_left = chat::is_group_explicitly_left(context, &grpid)
.await
.unwrap_or_default();
let self_addr = context
.get_config(Config::ConfiguredAddr)
.await
.unwrap_or_default();
if chat_id.is_unset()
&& !mime_parser.is_mailinglist_message()
@@ -1454,35 +1498,7 @@ async fn create_or_lookup_group(
// add members to group/check members
if recreate_member_list {
if !chat::is_contact_in_chat(context, chat_id, DC_CONTACT_ID_SELF).await {
// Members could have been removed while we were
// absent. We can't use existing member list and need to
// start from scratch.
context
.sql
.execute(
"DELETE FROM chats_contacts WHERE chat_id=?;",
paramsv![chat_id],
)
.await
.ok();
chat::add_to_chat_contacts_table(context, chat_id, DC_CONTACT_ID_SELF).await;
}
if from_id > DC_CONTACT_ID_LAST_SPECIAL
&& !Contact::addr_equals_contact(context, &self_addr, from_id as u32).await
&& !chat::is_contact_in_chat(context, chat_id, from_id).await
{
chat::add_to_chat_contacts_table(context, chat_id, from_id as u32).await;
}
for &to_id in to_ids.iter() {
info!(context, "adding to={:?} to chat id={}", to_id, chat_id);
if !Contact::addr_equals_contact(context, &self_addr, to_id).await
&& !chat::is_contact_in_chat(context, chat_id, to_id).await
{
chat::add_to_chat_contacts_table(context, chat_id, to_id).await;
}
}
update_member_list(context, chat_id, self_addr, from_id, to_ids).await?;
send_EVENT_CHAT_MODIFIED = true;
} else if let Some(contact_id) = removed_id {
chat::remove_from_chat_contacts_table(context, chat_id, contact_id).await;
@@ -2033,7 +2049,7 @@ fn dc_create_incoming_rfc724_mid(
mod tests {
use super::*;
use crate::chat::{get_chat_msgs, ChatItem, ChatVisibility};
use crate::chat::{get_chat_contacts, get_chat_msgs, ChatItem, ChatVisibility};
use crate::chatlist::Chatlist;
use crate::constants::{DC_CHAT_ID_DEADDROP, DC_CONTACT_ID_INFO, DC_GCL_NO_SPECIALS};
use crate::message::ContactRequestDecision::*;
@@ -3471,4 +3487,107 @@ YEAAAAAA!.
assert_eq!(chat.typ, Chattype::Single);
assert_eq!(msg.get_text().unwrap(), "private reply");
}
async fn test_alias() -> (TestContext, Chat) {
// Claire, a customer, sends a support request
// to the alias address <support@example.org> from a classic MUA.
// The alias expands to the supporters Alice and Bob.
// Check that Alice receives the message in a group chat.
let alice = TestContext::new_alice().await;
alice
.set_config(Config::ShowEmails, Some("2"))
.await
.unwrap();
dc_receive_imf(
&alice,
b"To: support@example.org\n\
From: claire@example.org\n\
Subject: i have a question\n\
Message-ID: <non-dc-1@example.org>\n\
Date: Sun, 14 Mar 2021 17:04:36 +0100\n\
Content-Type: text/plain\n\
\n\
hi support! what is the current version?",
"INBOX",
1,
false,
)
.await
.unwrap();
let msg = alice.get_last_msg().await;
assert_eq!(msg.get_subject(), "i have a question");
assert!(msg.get_text().unwrap().contains("hi support!"));
let chat = Chat::load_from_db(&alice, msg.chat_id).await.unwrap();
assert_eq!(chat.typ, Chattype::Group);
assert_eq!(get_chat_msgs(&alice, chat.id, 0, None).await.len(), 1);
assert_eq!(get_chat_contacts(&alice, chat.id).await.len(), 3);
(alice, chat)
}
#[async_std::test]
async fn test_alias_support_answer_from_nondc() {
let (alice, chat) = test_alias().await;
// Bob, the other supporter, answers with a classic MUA.
// Check that Alice gets the message in the same chat.
dc_receive_imf(
&alice,
b"To: support@example.org, claire@example.org\n\
From: bob@example.net\n\
Subject: =?utf-8?q?Re=3A_i_have_a_question?=\n\
References: <non-dc-1@example.org>\n\
In-Reply-To: <non-dc-1@example.org>\n\
Message-ID: <non-dc-2@example.net>\n\
Date: Sun, 14 Mar 2021 16:04:57 +0000\n\
Content-Type: text/plain\n\
\n\
hi claire, the version is 1.0, cheers bob",
"INBOX",
2,
false,
)
.await
.unwrap();
let msg = alice.get_last_msg().await;
assert_eq!(msg.get_subject(), "Re: i have a question");
assert!(msg.get_text().unwrap().contains("the version is 1.0"));
assert_eq!(msg.chat_id, chat.id);
assert_eq!(get_chat_contacts(&alice, chat.id).await.len(), 4);
}
#[async_std::test]
async fn test_alias_answer_from_dc() {
let (alice, chat) = test_alias().await;
// Bob, the other supporter, answers with Delta Chat.
// Check that Alice gets the message in the same chat.
dc_receive_imf(
&alice,
b"To: support@example.org, claire@example.org\n\
From: bob@example.net\n\
Subject: =?utf-8?q?Re=3A_i_have_a_question?=\n\
References: <Gr.af9e810c9b592927.gNm8dVdkZsH@example.net>\n\
In-Reply-To: <non-dc-1@example.org>\n\
Message-ID: <Gr.af9e810c9b592927.gNm8dVdkZsH@example.net>\n\
Date: Sun, 14 Mar 2021 16:04:57 +0000\n\
Chat-Version: 1.0\n\
Chat-Group-ID: af9e810c9b592927\n\
Chat-Group-Name: =?utf-8?q?i_have_a_question?=\n\
Chat-Disposition-Notification-To: bob@example.net\n\
Content-Type: text/plain\n\
\n\
hi claire, the version is 1.0, cheers bob",
"INBOX",
2,
false,
)
.await
.unwrap();
let msg = alice.get_last_msg().await;
assert_eq!(msg.get_subject(), "Re: i have a question");
assert!(msg.get_text().unwrap().contains("the version is 1.0"));
assert_eq!(msg.chat_id, chat.id); // FIXME: that fails
assert_eq!(get_chat_contacts(&alice, chat.id).await.len(), 4); // FIXME: that fails
}
}