fix: can_send(): Return false for protected 1:1 chat if contact isn't forward verified (#6222)

Otherwise if the user tries to send a message, that would just fail. `Chat::can_send()` returning
false makes the chat input field unavailable. A protected 1:1 chat with a not forward verified
contact may be a result of AEAP, the user should use the 1:1 chat with the new contact then.
This commit is contained in:
iequidoo
2024-11-20 19:37:19 -03:00
parent 4e798ceae1
commit 156fb6ffd5
2 changed files with 24 additions and 1 deletions

View File

@@ -132,6 +132,9 @@ pub(crate) enum CantSendReason {
/// Temporary state for 1:1 chats while SecureJoin is in progress, after a timeout sending /// Temporary state for 1:1 chats while SecureJoin is in progress, after a timeout sending
/// messages (incl. unencrypted if we don't yet know the contact's pubkey) is allowed. /// messages (incl. unencrypted if we don't yet know the contact's pubkey) is allowed.
SecurejoinWait, SecurejoinWait,
/// The contact isn't forward verified which is needed by protected 1:1 chats.
NoForwardVerification,
} }
impl fmt::Display for CantSendReason { impl fmt::Display for CantSendReason {
@@ -152,6 +155,7 @@ impl fmt::Display for CantSendReason {
} }
Self::NotAMember => write!(f, "not a member of the chat"), Self::NotAMember => write!(f, "not a member of the chat"),
Self::SecurejoinWait => write!(f, "awaiting SecureJoin for 1:1 chat"), Self::SecurejoinWait => write!(f, "awaiting SecureJoin for 1:1 chat"),
Self::NoForwardVerification => write!(f, "contact isn't forward verified"),
} }
} }
} }
@@ -1662,6 +1666,19 @@ impl Chat {
> 0 > 0
{ {
Some(SecurejoinWait) Some(SecurejoinWait)
} else if self.typ == Chattype::Single
&& self.is_protected()
&& match get_chat_contacts(context, self.id).await?.pop() {
Some(contact_id) => {
!Contact::get_by_id(context, contact_id)
.await?
.is_forward_verified(context)
.await?
}
None => false,
}
{
Some(NoForwardVerification)
} else { } else {
None None
}; };
@@ -2769,6 +2786,7 @@ async fn prepare_msg_common(
CantSendReason::ProtectionBroken CantSendReason::ProtectionBroken
| CantSendReason::ContactRequest | CantSendReason::ContactRequest
| CantSendReason::SecurejoinWait | CantSendReason::SecurejoinWait
| CantSendReason::NoForwardVerification
) && msg.param.get_cmd() == SystemMessage::SecurejoinMessage ) && msg.param.get_cmd() == SystemMessage::SecurejoinMessage
{ {
// Send out the message, the securejoin message is supposed to repair the verification. // Send out the message, the securejoin message is supposed to repair the verification.

View File

@@ -1,6 +1,6 @@
use anyhow::Result; use anyhow::Result;
use crate::chat::{self, Chat, ChatId, ProtectionStatus}; use crate::chat::{self, CantSendReason, Chat, ChatId, ProtectionStatus};
use crate::contact; use crate::contact;
use crate::contact::Contact; use crate::contact::Contact;
use crate::contact::ContactId; use crate::contact::ContactId;
@@ -422,6 +422,11 @@ async fn test_write_to_alice_after_aeap() -> Result<()> {
assert!(chat::send_msg(bob, bob_alice_chat.id, &mut msg) assert!(chat::send_msg(bob, bob_alice_chat.id, &mut msg)
.await .await
.is_err()); .is_err());
assert!(!bob_alice_chat.can_send(bob).await?);
assert_eq!(
bob_alice_chat.why_cant_send(bob).await?,
Some(CantSendReason::NoForwardVerification)
);
// But encrypted communication is still possible in unprotected groups with old Alice. // But encrypted communication is still possible in unprotected groups with old Alice.
let sent = bob let sent = bob