mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 02:46:29 +03:00
feat: Don't update self-{avatar,status} from received messages (#7002)
The normal way of synchronizing self-avatar and -status nowadays is sync messages.
This commit is contained in:
@@ -278,7 +278,6 @@ async fn test_sync() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sync message mustn't be sent if self-{status,avatar} is changed by a self-sent message.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_no_sync_on_self_sent_msg() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
@@ -288,7 +287,7 @@ async fn test_no_sync_on_self_sent_msg() -> Result<()> {
|
||||
a.set_config_bool(Config::SyncMsgs, true).await?;
|
||||
}
|
||||
|
||||
let status = "Synced via usual message";
|
||||
let status = "Sent via usual message";
|
||||
alice0.set_config(Config::Selfstatus, Some(status)).await?;
|
||||
alice0.send_sync_msg().await?;
|
||||
alice0.pop_sent_sync_msg().await;
|
||||
@@ -297,7 +296,7 @@ async fn test_no_sync_on_self_sent_msg() -> Result<()> {
|
||||
tcm.send_recv(alice0, alice1, "hi Alice!").await;
|
||||
assert_eq!(
|
||||
alice1.get_config(Config::Selfstatus).await?,
|
||||
Some(status.to_string())
|
||||
Some(status1.to_string())
|
||||
);
|
||||
sync(alice1, alice0).await;
|
||||
assert_eq!(
|
||||
@@ -328,7 +327,7 @@ async fn test_no_sync_on_self_sent_msg() -> Result<()> {
|
||||
alice1
|
||||
.get_config(Config::Selfavatar)
|
||||
.await?
|
||||
.filter(|path| path.ends_with(".png"))
|
||||
.filter(|path| path.ends_with(".jpg"))
|
||||
.is_some()
|
||||
);
|
||||
sync(alice1, alice0).await;
|
||||
|
||||
@@ -383,20 +383,16 @@ async fn import_vcard_contact(context: &Context, contact: &VcardContact) -> Resu
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
if let Some(path) = path {
|
||||
// Currently this value doesn't matter as we don't import the contact of self.
|
||||
let was_encrypted = false;
|
||||
if let Err(e) =
|
||||
set_profile_image(context, id, &AvatarAction::Change(path), was_encrypted).await
|
||||
{
|
||||
warn!(
|
||||
context,
|
||||
"import_vcard_contact: Could not set avatar for {}: {e:#}.", contact.addr
|
||||
);
|
||||
}
|
||||
if let Some(path) = path
|
||||
&& let Err(e) = set_profile_image(context, id, &AvatarAction::Change(path)).await
|
||||
{
|
||||
warn!(
|
||||
context,
|
||||
"import_vcard_contact: Could not set avatar for {}: {e:#}.", contact.addr
|
||||
);
|
||||
}
|
||||
if let Some(biography) = &contact.biography
|
||||
&& let Err(e) = set_status(context, id, biography.to_owned(), false, false).await
|
||||
&& let Err(e) = set_status(context, id, biography.to_owned()).await
|
||||
{
|
||||
warn!(
|
||||
context,
|
||||
@@ -1824,25 +1820,19 @@ WHERE type=? AND id IN (
|
||||
/// The given profile image is expected to be already in the blob directory
|
||||
/// as profile images can be set only by receiving messages, this should be always the case, however.
|
||||
///
|
||||
/// For contact SELF, the image is not saved in the contact-database but as Config::Selfavatar;
|
||||
/// this typically happens if we see message with our own profile image.
|
||||
/// For contact SELF, the image is not saved in the contact-database but as Config::Selfavatar.
|
||||
pub(crate) async fn set_profile_image(
|
||||
context: &Context,
|
||||
contact_id: ContactId,
|
||||
profile_image: &AvatarAction,
|
||||
was_encrypted: bool,
|
||||
) -> Result<()> {
|
||||
let mut contact = Contact::get_by_id(context, contact_id).await?;
|
||||
let changed = match profile_image {
|
||||
AvatarAction::Change(profile_image) => {
|
||||
if contact_id == ContactId::SELF {
|
||||
if was_encrypted {
|
||||
context
|
||||
.set_config_ex(Nosync, Config::Selfavatar, Some(profile_image))
|
||||
.await?;
|
||||
} else {
|
||||
info!(context, "Do not use unencrypted selfavatar.");
|
||||
}
|
||||
context
|
||||
.set_config_ex(Nosync, Config::Selfavatar, Some(profile_image))
|
||||
.await?;
|
||||
} else {
|
||||
contact.param.set(Param::ProfileImage, profile_image);
|
||||
}
|
||||
@@ -1850,13 +1840,9 @@ pub(crate) async fn set_profile_image(
|
||||
}
|
||||
AvatarAction::Delete => {
|
||||
if contact_id == ContactId::SELF {
|
||||
if was_encrypted {
|
||||
context
|
||||
.set_config_ex(Nosync, Config::Selfavatar, None)
|
||||
.await?;
|
||||
} else {
|
||||
info!(context, "Do not use unencrypted selfavatar deletion.");
|
||||
}
|
||||
context
|
||||
.set_config_ex(Nosync, Config::Selfavatar, None)
|
||||
.await?;
|
||||
} else {
|
||||
contact.param.remove(Param::ProfileImage);
|
||||
}
|
||||
@@ -1873,22 +1859,16 @@ pub(crate) async fn set_profile_image(
|
||||
|
||||
/// Sets contact status.
|
||||
///
|
||||
/// For contact SELF, the status is not saved in the contact table, but as Config::Selfstatus. This
|
||||
/// is only done if message is sent from Delta Chat and it is encrypted, to synchronize signature
|
||||
/// between Delta Chat devices.
|
||||
/// For contact SELF, the status is not saved in the contact table, but as Config::Selfstatus.
|
||||
pub(crate) async fn set_status(
|
||||
context: &Context,
|
||||
contact_id: ContactId,
|
||||
status: String,
|
||||
encrypted: bool,
|
||||
has_chat_version: bool,
|
||||
) -> Result<()> {
|
||||
if contact_id == ContactId::SELF {
|
||||
if encrypted && has_chat_version {
|
||||
context
|
||||
.set_config_ex(Nosync, Config::Selfstatus, Some(&status))
|
||||
.await?;
|
||||
}
|
||||
context
|
||||
.set_config_ex(Nosync, Config::Selfstatus, Some(&status))
|
||||
.await?;
|
||||
} else {
|
||||
let mut contact = Contact::get_by_id(context, contact_id).await?;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use super::*;
|
||||
use crate::chat::{Chat, get_chat_contacts, send_text_msg};
|
||||
use crate::chatlist::Chatlist;
|
||||
use crate::receive_imf::receive_imf;
|
||||
use crate::test_utils::{self, TestContext, TestContextManager, TimeShiftFalsePositiveNote};
|
||||
use crate::test_utils::{self, TestContext, TestContextManager, TimeShiftFalsePositiveNote, sync};
|
||||
|
||||
#[test]
|
||||
fn test_contact_id_values() {
|
||||
@@ -850,8 +850,7 @@ CCCB 5AA9 F6E1 141C 9431
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that status is synchronized when sending encrypted BCC-self messages and not
|
||||
/// synchronized when the message is not encrypted.
|
||||
/// Tests that self-status is not synchronized from outgoing messages.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_synchronize_status() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
@@ -870,21 +869,12 @@ async fn test_synchronize_status() -> Result<()> {
|
||||
.await?;
|
||||
let chat = alice1.create_email_chat(bob).await;
|
||||
|
||||
// Alice sends a message to Bob from the first device.
|
||||
// Alice sends an unencrypted message to Bob from the first device.
|
||||
send_text_msg(alice1, chat.id, "Hello".to_string()).await?;
|
||||
let sent_msg = alice1.pop_sent_msg().await;
|
||||
|
||||
// Message is not encrypted.
|
||||
let message = sent_msg.load_from_db().await;
|
||||
assert!(!message.get_showpadlock());
|
||||
|
||||
// Alice's second devices receives a copy of outgoing message.
|
||||
alice2.recv_msg(&sent_msg).await;
|
||||
|
||||
// Bob receives message.
|
||||
bob.recv_msg(&sent_msg).await;
|
||||
|
||||
// Message was not encrypted, so status is not copied.
|
||||
assert_eq!(alice2.get_config(Config::Selfstatus).await?, default_status);
|
||||
|
||||
// Alice sends encrypted message.
|
||||
@@ -892,17 +882,9 @@ async fn test_synchronize_status() -> Result<()> {
|
||||
send_text_msg(alice1, chat.id, "Hello".to_string()).await?;
|
||||
let sent_msg = alice1.pop_sent_msg().await;
|
||||
|
||||
// Second message is encrypted.
|
||||
let message = sent_msg.load_from_db().await;
|
||||
assert!(message.get_showpadlock());
|
||||
|
||||
// Alice's second devices receives a copy of second outgoing message.
|
||||
alice2.recv_msg(&sent_msg).await;
|
||||
|
||||
assert_eq!(
|
||||
alice2.get_config(Config::Selfstatus).await?,
|
||||
Some("New status".to_string())
|
||||
);
|
||||
assert_eq!(alice2.get_config(Config::Selfstatus).await?, default_status);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -915,9 +897,9 @@ async fn test_selfavatar_changed_event() -> Result<()> {
|
||||
// Alice has two devices.
|
||||
let alice1 = &tcm.alice().await;
|
||||
let alice2 = &tcm.alice().await;
|
||||
|
||||
// Bob has one device.
|
||||
let bob = &tcm.bob().await;
|
||||
for a in [alice1, alice2] {
|
||||
a.set_config_bool(Config::SyncMsgs, true).await?;
|
||||
}
|
||||
|
||||
assert_eq!(alice1.get_config(Config::Selfavatar).await?, None);
|
||||
|
||||
@@ -933,17 +915,7 @@ async fn test_selfavatar_changed_event() -> Result<()> {
|
||||
.get_matching(|e| matches!(e, EventType::SelfavatarChanged))
|
||||
.await;
|
||||
|
||||
// Alice sends a message.
|
||||
let alice1_chat_id = alice1.create_chat(bob).await.id;
|
||||
send_text_msg(alice1, alice1_chat_id, "Hello".to_string()).await?;
|
||||
let sent_msg = alice1.pop_sent_msg().await;
|
||||
|
||||
// The message is encrypted.
|
||||
let message = sent_msg.load_from_db().await;
|
||||
assert!(message.get_showpadlock());
|
||||
|
||||
// Alice's second device receives a copy of the outgoing message.
|
||||
alice2.recv_msg(&sent_msg).await;
|
||||
sync(alice1, alice2).await;
|
||||
|
||||
// Alice's second device applies the selfavatar.
|
||||
assert!(alice2.get_config(Config::Selfavatar).await?.is_some());
|
||||
|
||||
@@ -991,42 +991,6 @@ Content-Disposition: reaction\n\
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Regression test for reaction resetting self-status.
|
||||
///
|
||||
/// Reactions do not contain the status,
|
||||
/// but should not result in self-status being reset on other devices.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_reaction_status_multidevice() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice1 = tcm.alice().await;
|
||||
let alice2 = tcm.alice().await;
|
||||
|
||||
alice1
|
||||
.set_config(Config::Selfstatus, Some("New status"))
|
||||
.await?;
|
||||
|
||||
let alice2_msg = tcm.send_recv(&alice1, &alice2, "Hi!").await;
|
||||
assert_eq!(
|
||||
alice2.get_config(Config::Selfstatus).await?.as_deref(),
|
||||
Some("New status")
|
||||
);
|
||||
|
||||
// Alice reacts to own message from second device,
|
||||
// first device receives rection.
|
||||
{
|
||||
send_reaction(&alice2, alice2_msg.id, "👍").await?;
|
||||
let msg = alice2.pop_sent_msg().await;
|
||||
alice1.recv_msg_hidden(&msg).await;
|
||||
}
|
||||
|
||||
// Check that the status is still the same.
|
||||
assert_eq!(
|
||||
alice1.get_config(Config::Selfstatus).await?.as_deref(),
|
||||
Some("New status")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_send_reaction_multidevice() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
|
||||
@@ -885,13 +885,11 @@ pub(crate) async fn receive_imf_inner(
|
||||
}
|
||||
|
||||
if let Some(avatar_action) = &mime_parser.user_avatar
|
||||
&& from_id != ContactId::UNDEFINED
|
||||
&& !matches!(from_id, ContactId::UNDEFINED | ContactId::SELF)
|
||||
&& context
|
||||
.update_contacts_timestamp(from_id, Param::AvatarTimestamp, mime_parser.timestamp_sent)
|
||||
.await?
|
||||
&& let Err(err) =
|
||||
contact::set_profile_image(context, from_id, avatar_action, mime_parser.was_encrypted())
|
||||
.await
|
||||
&& let Err(err) = contact::set_profile_image(context, from_id, avatar_action).await
|
||||
{
|
||||
warn!(context, "receive_imf cannot update profile image: {err:#}.");
|
||||
};
|
||||
@@ -899,18 +897,11 @@ pub(crate) async fn receive_imf_inner(
|
||||
// Ignore footers from mailinglists as they are often created or modified by the mailinglist software.
|
||||
if let Some(footer) = &mime_parser.footer
|
||||
&& !mime_parser.is_mailinglist_message()
|
||||
&& from_id != ContactId::UNDEFINED
|
||||
&& !matches!(from_id, ContactId::UNDEFINED | ContactId::SELF)
|
||||
&& context
|
||||
.update_contacts_timestamp(from_id, Param::StatusTimestamp, mime_parser.timestamp_sent)
|
||||
.await?
|
||||
&& let Err(err) = contact::set_status(
|
||||
context,
|
||||
from_id,
|
||||
footer.to_string(),
|
||||
mime_parser.was_encrypted(),
|
||||
mime_parser.has_chat_version(),
|
||||
)
|
||||
.await
|
||||
&& let Err(err) = contact::set_status(context, from_id, footer.to_string()).await
|
||||
{
|
||||
warn!(context, "Cannot update contact status: {err:#}.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user