From 89a73d775ef87d12e025d57c8ddfbb2532b1a623 Mon Sep 17 00:00:00 2001 From: iequidoo Date: Thu, 3 Apr 2025 03:08:29 -0300 Subject: [PATCH] fix: Set GroupNameTimestamp on group promotion (#6729) Otherwise if an invite link is generated and the group is renamed then before the promotion, the joined member will have the group name from the invite link, not the new one. --- src/chat.rs | 8 ++++++-- src/receive_imf.rs | 5 +++-- src/receive_imf/receive_imf_tests.rs | 23 +++++++++++++++++++++++ src/tools.rs | 2 +- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index b8854b320..67de10669 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2063,7 +2063,9 @@ impl Chat { && self.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 { msg.param.set_int(Param::AttachGroupImage, 1); - self.param.remove(Param::Unpromoted); + self.param + .remove(Param::Unpromoted) + .set_i64(Param::GroupNameTimestamp, timestamp); self.update_param(context).await?; // TODO: Remove this compat code needed because Core <= v1.143: // - doesn't accept synchronization of QR code tokens for unpromoted groups, so we also @@ -3917,7 +3919,9 @@ pub(crate) async fn add_contact_to_chat_ex( let sync_qr_code_tokens; if from_handshake && chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 1 { - chat.param.remove(Param::Unpromoted); + chat.param + .remove(Param::Unpromoted) + .set_i64(Param::GroupNameTimestamp, smeared_time(context)); chat.update_param(context).await?; sync_qr_code_tokens = true; } else { diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 55db0d9c5..b7ab3e713 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -2450,16 +2450,16 @@ async fn apply_group_changes( .filter(|grpname| grpname.len() < 200) { let grpname = &sanitize_single_line(grpname); - let old_name = &sanitize_single_line(old_name); let chat_group_name_timestamp = chat.param.get_i64(Param::GroupNameTimestamp).unwrap_or(0); let group_name_timestamp = group_name_timestamp.unwrap_or(mime_parser.timestamp_sent); // To provide group name consistency, compare names if timestamps are equal. - if (chat_group_name_timestamp, grpname) < (group_name_timestamp, old_name) + if (chat_group_name_timestamp, grpname) < (group_name_timestamp, &chat.name) && chat_id .update_timestamp(context, Param::GroupNameTimestamp, group_name_timestamp) .await? + && grpname != &chat.name { info!(context, "Updating grpname for chat {chat_id}."); context @@ -2472,6 +2472,7 @@ async fn apply_group_changes( .get_header(HeaderDef::ChatGroupNameChanged) .is_some() { + let old_name = &sanitize_single_line(old_name); better_msg.get_or_insert( stock_str::msg_grp_name(context, old_name, grpname, from_id).await, ); diff --git a/src/receive_imf/receive_imf_tests.rs b/src/receive_imf/receive_imf_tests.rs index 649971835..e33ee6775 100644 --- a/src/receive_imf/receive_imf_tests.rs +++ b/src/receive_imf/receive_imf_tests.rs @@ -5433,6 +5433,29 @@ async fn test_rename_chat_on_missing_message() -> Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_rename_chat_after_creating_invite() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let bob = &tcm.bob().await; + for populate_before_securejoin in [false, true] { + let alice_chat_id = create_group_chat(alice, ProtectionStatus::Protected, "Group").await?; + let qr = get_securejoin_qr(alice, Some(alice_chat_id)).await?; + + SystemTime::shift(Duration::from_secs(60)); + chat::set_chat_name(alice, alice_chat_id, "Renamed").await?; + if populate_before_securejoin { + send_text_msg(alice, alice_chat_id, "populate".to_string()).await?; + alice.pop_sent_msg().await; + } + + let bob_chat_id = tcm.exec_securejoin_qr(bob, alice, &qr).await; + let bob_chat = Chat::load_from_db(bob, bob_chat_id).await?; + assert_eq!(bob_chat.get_name(), "Renamed"); + } + Ok(()) +} + /// Tests that creating a group /// is preferred over assigning message to existing /// chat based on `In-Reply-To` and `References`. diff --git a/src/tools.rs b/src/tools.rs index 579df342a..58b176c21 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -179,7 +179,7 @@ pub(crate) fn gm2local_offset() -> i64 { /// Returns the current smeared timestamp, /// -/// The returned timestamp MUST NOT be sent out. +/// The returned timestamp MAY NOT be unique and MUST NOT go to "Date" header. pub(crate) fn smeared_time(context: &Context) -> i64 { let now = time(); let ts = context.smeared_timestamp.current();