mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 13:36:30 +03:00
Compare commits
7 Commits
v2.25.0
...
sk/delete_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7436368b50 | ||
|
|
c9fdfc32f2 | ||
|
|
0ce2f35909 | ||
|
|
5096a43831 | ||
|
|
2db390b25a | ||
|
|
028b0211c9 | ||
|
|
3a03c9993c |
@@ -2,6 +2,7 @@
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::VecDeque;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
|
||||
@@ -1713,6 +1714,35 @@ pub(crate) async fn delete_msg_locally(context: &Context, msg: &Message) -> Resu
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn get_webxdc_info_messages(
|
||||
context: &Context,
|
||||
msg: &Message,
|
||||
) -> Result<Vec<MsgId>> {
|
||||
let msg_ids = context
|
||||
.sql
|
||||
.query_map(
|
||||
r#"SELECT id, param
|
||||
FROM msgs
|
||||
WHERE chat_id=?1 AND hidden=0 AND mime_in_reply_to = ?2
|
||||
"#,
|
||||
(msg.chat_id, &msg.rfc724_mid),
|
||||
|row| {
|
||||
let info_msg_id: MsgId = row.get(0)?;
|
||||
let last_param: Params = row.get::<_, String>(1)?.parse().unwrap_or_default();
|
||||
Ok((info_msg_id, last_param))
|
||||
},
|
||||
|row| {
|
||||
Ok(row
|
||||
.filter_map(Result::ok)
|
||||
.filter(|(_, param)| param.get_cmd() == SystemMessage::WebxdcInfoMessage)
|
||||
.map(|(msg_id, _)| msg_id)
|
||||
.collect::<Vec<_>>())
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
Ok(msg_ids)
|
||||
}
|
||||
|
||||
/// Do final events and jobs after batch deletion using calls to delete_msg_locally().
|
||||
/// To avoid additional database queries, collecting data is up to the caller.
|
||||
pub(crate) async fn delete_msgs_locally_done(
|
||||
@@ -1751,8 +1781,10 @@ pub async fn delete_msgs_ex(
|
||||
let mut modified_chat_ids = HashSet::new();
|
||||
let mut deleted_rfc724_mid = Vec::new();
|
||||
let mut res = Ok(());
|
||||
let mut msg_ids_queue = VecDeque::from_iter(msg_ids.iter().copied());
|
||||
let mut msg_ids = Vec::from(msg_ids);
|
||||
|
||||
for &msg_id in msg_ids {
|
||||
while let Some(msg_id) = msg_ids_queue.pop_front() {
|
||||
let msg = Message::load_from_db(context, msg_id).await?;
|
||||
ensure!(
|
||||
!delete_for_all || msg.from_id == ContactId::SELF,
|
||||
@@ -1763,6 +1795,11 @@ pub async fn delete_msgs_ex(
|
||||
"Cannot request deletion of unencrypted message for others"
|
||||
);
|
||||
|
||||
if msg.viewtype == Viewtype::Webxdc {
|
||||
let info_msgs = get_webxdc_info_messages(context, &msg).await?;
|
||||
msg_ids_queue.extend(&info_msgs);
|
||||
msg_ids.extend(info_msgs);
|
||||
}
|
||||
modified_chat_ids.insert(msg.chat_id);
|
||||
deleted_rfc724_mid.push(msg.rfc724_mid.clone());
|
||||
|
||||
@@ -1808,11 +1845,11 @@ pub async fn delete_msgs_ex(
|
||||
.await?;
|
||||
}
|
||||
|
||||
for &msg_id in msg_ids {
|
||||
for &msg_id in &msg_ids {
|
||||
let msg = Message::load_from_db(context, msg_id).await?;
|
||||
delete_msg_locally(context, &msg).await?;
|
||||
}
|
||||
delete_msgs_locally_done(context, msg_ids, modified_chat_ids).await?;
|
||||
delete_msgs_locally_done(context, &msg_ids, modified_chat_ids).await?;
|
||||
|
||||
// Interrupt Inbox loop to start message deletion, run housekeeping and call send_sync_msg().
|
||||
context.scheduler.interrupt_inbox().await;
|
||||
|
||||
@@ -33,7 +33,8 @@ use crate::log::LogExt;
|
||||
use crate::log::{info, warn};
|
||||
use crate::logged_debug_assert;
|
||||
use crate::message::{
|
||||
self, Message, MessageState, MessengerMessage, MsgId, Viewtype, rfc724_mid_exists,
|
||||
self, Message, MessageState, MessengerMessage, MsgId, Viewtype, get_webxdc_info_messages,
|
||||
rfc724_mid_exists,
|
||||
};
|
||||
use crate::mimeparser::{AvatarAction, MimeMessage, SystemMessage, parse_message_ids};
|
||||
use crate::param::{Param, Params};
|
||||
@@ -2295,12 +2296,18 @@ async fn handle_edit_delete(
|
||||
let mut modified_chat_ids = HashSet::new();
|
||||
let mut msg_ids = Vec::new();
|
||||
|
||||
let mut deleted_info_msgs = vec![];
|
||||
let rfc724_mid_vec: Vec<&str> = rfc724_mid_list.split_whitespace().collect();
|
||||
for rfc724_mid in rfc724_mid_vec {
|
||||
if let Some((msg_id, _)) =
|
||||
message::rfc724_mid_exists(context, rfc724_mid).await?
|
||||
{
|
||||
if let Some(msg) = Message::load_from_db_optional(context, msg_id).await? {
|
||||
if msg.viewtype == Viewtype::Webxdc {
|
||||
let info_msgs = get_webxdc_info_messages(context, &msg).await?;
|
||||
deleted_info_msgs.extend(&info_msgs);
|
||||
}
|
||||
|
||||
if msg.from_id == from_id {
|
||||
message::delete_msg_locally(context, &msg).await?;
|
||||
msg_ids.push(msg.id);
|
||||
@@ -2315,6 +2322,15 @@ async fn handle_edit_delete(
|
||||
warn!(context, "Delete message: {rfc724_mid:?} not found.");
|
||||
}
|
||||
}
|
||||
if !deleted_info_msgs.is_empty() {
|
||||
message::delete_msgs(context, &deleted_info_msgs).await?;
|
||||
for msg_id in deleted_info_msgs {
|
||||
if let Some(msg) = Message::load_from_db_optional(context, msg_id).await? {
|
||||
message::delete_msg_locally(context, &msg).await?;
|
||||
msg_ids.push(msg.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
message::delete_msgs_locally_done(context, &msg_ids, modified_chat_ids).await?;
|
||||
} else {
|
||||
warn!(context, "Delete message: Not encrypted.");
|
||||
|
||||
16
src/sync.rs
16
src/sync.rs
@@ -11,7 +11,7 @@ use crate::contact::ContactId;
|
||||
use crate::context::Context;
|
||||
use crate::log::LogExt;
|
||||
use crate::log::{info, warn};
|
||||
use crate::message::{Message, MsgId, Viewtype};
|
||||
use crate::message::{Message, MsgId, Viewtype, get_webxdc_info_messages};
|
||||
use crate::mimeparser::SystemMessage;
|
||||
use crate::param::Param;
|
||||
use crate::sync::SyncData::{AddQrToken, AlterChat, DeleteQrToken};
|
||||
@@ -306,10 +306,15 @@ impl Context {
|
||||
|
||||
async fn sync_message_deletion(&self, msgs: &Vec<String>) -> Result<()> {
|
||||
let mut modified_chat_ids = HashSet::new();
|
||||
let mut deleted_info_msgs = vec![];
|
||||
let mut msg_ids = Vec::new();
|
||||
for rfc724_mid in msgs {
|
||||
if let Some((msg_id, _)) = message::rfc724_mid_exists(self, rfc724_mid).await? {
|
||||
if let Some(msg) = Message::load_from_db_optional(self, msg_id).await? {
|
||||
if msg.viewtype == Viewtype::Webxdc {
|
||||
let info_msgs = get_webxdc_info_messages(&self, &msg).await?;
|
||||
deleted_info_msgs.extend(&info_msgs);
|
||||
}
|
||||
message::delete_msg_locally(self, &msg).await?;
|
||||
msg_ids.push(msg.id);
|
||||
modified_chat_ids.insert(msg.chat_id);
|
||||
@@ -320,6 +325,15 @@ impl Context {
|
||||
warn!(self, "Sync message delete: {rfc724_mid:?} not found.");
|
||||
}
|
||||
}
|
||||
if !deleted_info_msgs.is_empty() {
|
||||
message::delete_msgs(&self, &deleted_info_msgs).await?;
|
||||
for msg_id in deleted_info_msgs {
|
||||
if let Some(msg) = Message::load_from_db_optional(&self, msg_id).await? {
|
||||
message::delete_msg_locally(&self, &msg).await?;
|
||||
msg_ids.push(msg.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
message::delete_msgs_locally_done(self, &msg_ids, modified_chat_ids).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ use crate::chatlist::Chatlist;
|
||||
use crate::config::Config;
|
||||
use crate::download::DownloadState;
|
||||
use crate::ephemeral;
|
||||
use crate::message::delete_msgs;
|
||||
use crate::receive_imf::{receive_imf, receive_imf_from_inbox};
|
||||
use crate::test_utils::{E2EE_INFO_MSGS, TestContext, TestContextManager};
|
||||
use crate::tools::{self, SystemTime};
|
||||
@@ -1616,6 +1617,26 @@ async fn test_webxdc_info_msg_no_cleanup_on_interrupted_series() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_webxdc_info_msg_delete() -> Result<()> {
|
||||
let t = TestContext::new_alice().await;
|
||||
let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "c").await?;
|
||||
let instance = send_webxdc_instance(&t, chat_id).await?;
|
||||
|
||||
t.send_webxdc_status_update(instance.id, r#"{"info":"i1", "payload":1}"#)
|
||||
.await?;
|
||||
assert_eq!(chat_id.get_msg_cnt(&t).await?, 2);
|
||||
send_text_msg(&t, chat_id, "msg between info".to_string()).await?;
|
||||
assert_eq!(chat_id.get_msg_cnt(&t).await?, 3);
|
||||
t.send_webxdc_status_update(instance.id, r#"{"info":"i2", "payload":2}"#)
|
||||
.await?;
|
||||
assert_eq!(chat_id.get_msg_cnt(&t).await?, 4);
|
||||
delete_msgs(&t, &[instance.id]).await?;
|
||||
assert_eq!(chat_id.get_msg_cnt(&t).await?, 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// check that `info.internet_access` is not set for normal, non-integrated webxdc -
|
||||
// even if they use the deprecated option `request_internet_access` in manifest.toml
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
|
||||
Reference in New Issue
Block a user