mirror of
https://github.com/chatmail/core.git
synced 2026-05-19 06:46:32 +03:00
fix: Add "member added" messages to OutBroadcast when executing SetPgpContacts sync message (#7952)
If one of broadcast owner's devices didn't add a new subscriber for any reason, e.g. because of missing SecureJoin messages, this device shall add "member added" messages when syncing the member list from the `SetPgpContacts` message.
This commit is contained in:
31
src/chat.rs
31
src/chat.rs
@@ -1,7 +1,7 @@
|
|||||||
//! # Chat module.
|
//! # Chat module.
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::marker::Sync;
|
use std::marker::Sync;
|
||||||
@@ -5031,18 +5031,18 @@ async fn set_contacts_by_fingerprints(
|
|||||||
matches!(chat.typ, Chattype::Group | Chattype::OutBroadcast),
|
matches!(chat.typ, Chattype::Group | Chattype::OutBroadcast),
|
||||||
"{id} is not a group or broadcast",
|
"{id} is not a group or broadcast",
|
||||||
);
|
);
|
||||||
let mut contacts = HashSet::new();
|
let mut contacts = BTreeSet::new();
|
||||||
for (fingerprint, addr) in fingerprint_addrs {
|
for (fingerprint, addr) in fingerprint_addrs {
|
||||||
let contact = Contact::add_or_lookup_ex(context, "", addr, fingerprint, Origin::Hidden)
|
let contact = Contact::add_or_lookup_ex(context, "", addr, fingerprint, Origin::Hidden)
|
||||||
.await?
|
.await?
|
||||||
.0;
|
.0;
|
||||||
contacts.insert(contact);
|
contacts.insert(contact);
|
||||||
}
|
}
|
||||||
let contacts_old = HashSet::<ContactId>::from_iter(get_chat_contacts(context, id).await?);
|
let contacts_old = BTreeSet::<ContactId>::from_iter(get_chat_contacts(context, id).await?);
|
||||||
if contacts == contacts_old {
|
if contacts == contacts_old {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
context
|
let broadcast_contacts_added = context
|
||||||
.sql
|
.sql
|
||||||
.transaction(move |transaction| {
|
.transaction(move |transaction| {
|
||||||
// For broadcast channels, we only add members,
|
// For broadcast channels, we only add members,
|
||||||
@@ -5059,12 +5059,31 @@ async fn set_contacts_by_fingerprints(
|
|||||||
let mut statement = transaction.prepare(
|
let mut statement = transaction.prepare(
|
||||||
"INSERT OR IGNORE INTO chats_contacts (chat_id, contact_id) VALUES (?, ?)",
|
"INSERT OR IGNORE INTO chats_contacts (chat_id, contact_id) VALUES (?, ?)",
|
||||||
)?;
|
)?;
|
||||||
|
let mut broadcast_contacts_added = Vec::new();
|
||||||
for contact_id in &contacts {
|
for contact_id in &contacts {
|
||||||
statement.execute((id, contact_id))?;
|
if statement.execute((id, contact_id))? > 0 && chat.typ == Chattype::OutBroadcast {
|
||||||
|
broadcast_contacts_added.push(*contact_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(broadcast_contacts_added)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
let timestamp = smeared_time(context);
|
||||||
|
for added_id in broadcast_contacts_added {
|
||||||
|
let msg = stock_str::msg_add_member_local(context, added_id, ContactId::UNDEFINED).await;
|
||||||
|
add_info_msg_with_cmd(
|
||||||
|
context,
|
||||||
|
id,
|
||||||
|
&msg,
|
||||||
|
SystemMessage::MemberAddedToGroup,
|
||||||
|
Some(timestamp),
|
||||||
|
timestamp,
|
||||||
|
None,
|
||||||
|
Some(ContactId::SELF),
|
||||||
|
Some(added_id),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
context.emit_event(EventType::ChatModified(id));
|
context.emit_event(EventType::ChatModified(id));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2997,18 +2997,41 @@ async fn test_broadcast_recipients_sync1() -> Result<()> {
|
|||||||
alice2.recv_msg_trash(&request_with_auth).await;
|
alice2.recv_msg_trash(&request_with_auth).await;
|
||||||
|
|
||||||
let member_added = alice1.pop_sent_msg().await;
|
let member_added = alice1.pop_sent_msg().await;
|
||||||
let a2_member_added = alice2.recv_msg(&member_added).await;
|
let a2_charlie_added = alice2.recv_msg(&member_added).await;
|
||||||
let _c_member_added = charlie.recv_msg(&member_added).await;
|
let _c_member_added = charlie.recv_msg(&member_added).await;
|
||||||
|
let a2_chatlist = Chatlist::try_load(alice2, 0, Some("Channel"), None).await?;
|
||||||
|
assert_eq!(a2_chatlist.get_msg_id(0)?.unwrap(), a2_charlie_added.id);
|
||||||
|
|
||||||
// Alice1 will now sync the full member list to Alice2:
|
// Alice1 will now sync the full member list to Alice2:
|
||||||
sync(alice1, alice2).await;
|
sync(alice1, alice2).await;
|
||||||
let a2_chatlist = Chatlist::try_load(alice2, 0, Some("Channel"), None).await?;
|
|
||||||
assert_eq!(a2_chatlist.get_msg_id(0)?.unwrap(), a2_member_added.id);
|
|
||||||
|
|
||||||
let a2_bob_contact = alice2.add_or_lookup_contact_id(bob).await;
|
let a2_bob_contact = alice2.add_or_lookup_contact_id(bob).await;
|
||||||
let a2_charlie_contact = alice2.add_or_lookup_contact_id(charlie).await;
|
let a2_charlie_contact = alice2.add_or_lookup_contact_id(charlie).await;
|
||||||
|
let a2_chatlist = Chatlist::try_load(alice2, 0, Some("Channel"), None).await?;
|
||||||
|
let msg_id = a2_chatlist.get_msg_id(0)?.unwrap();
|
||||||
|
let a2_bob_added = Message::load_from_db(alice2, msg_id).await?;
|
||||||
|
assert_ne!(a2_bob_added.id, a2_charlie_added.id);
|
||||||
|
assert_eq!(
|
||||||
|
a2_bob_added.text,
|
||||||
|
stock_str::msg_add_member_local(alice2, a2_bob_contact, ContactId::UNDEFINED).await
|
||||||
|
);
|
||||||
|
assert_eq!(a2_bob_added.from_id, ContactId::SELF);
|
||||||
|
assert_eq!(
|
||||||
|
a2_bob_added.param.get_cmd(),
|
||||||
|
SystemMessage::MemberAddedToGroup
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ContactId::new(
|
||||||
|
a2_bob_added
|
||||||
|
.param
|
||||||
|
.get_int(Param::ContactAddedRemoved)
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap()
|
||||||
|
),
|
||||||
|
a2_bob_contact
|
||||||
|
);
|
||||||
|
|
||||||
let a2_chat_members = get_chat_contacts(alice2, a2_member_added.chat_id).await?;
|
let a2_chat_members = get_chat_contacts(alice2, a2_charlie_added.chat_id).await?;
|
||||||
assert!(a2_chat_members.contains(&a2_bob_contact));
|
assert!(a2_chat_members.contains(&a2_bob_contact));
|
||||||
assert!(a2_chat_members.contains(&a2_charlie_contact));
|
assert!(a2_chat_members.contains(&a2_charlie_contact));
|
||||||
assert_eq!(a2_chat_members.len(), 2);
|
assert_eq!(a2_chat_members.len(), 2);
|
||||||
|
|||||||
Reference in New Issue
Block a user