mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 17:36:29 +03:00
api!: remove Chat.is_protected()
This commit is contained in:
@@ -560,7 +560,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
|||||||
for i in (0..cnt).rev() {
|
for i in (0..cnt).rev() {
|
||||||
let chat = Chat::load_from_db(&context, chatlist.get_chat_id(i)?).await?;
|
let chat = Chat::load_from_db(&context, chatlist.get_chat_id(i)?).await?;
|
||||||
println!(
|
println!(
|
||||||
"{}#{}: {} [{} fresh] {}{}{}{}",
|
"{}#{}: {} [{} fresh] {}{}{}",
|
||||||
chat_prefix(&chat),
|
chat_prefix(&chat),
|
||||||
chat.get_id(),
|
chat.get_id(),
|
||||||
chat.get_name(),
|
chat.get_name(),
|
||||||
@@ -571,7 +571,6 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
|||||||
ChatVisibility::Archived => "📦",
|
ChatVisibility::Archived => "📦",
|
||||||
ChatVisibility::Pinned => "📌",
|
ChatVisibility::Pinned => "📌",
|
||||||
},
|
},
|
||||||
if chat.is_protected() { "🛡️" } else { "" },
|
|
||||||
if chat.is_contact_request() {
|
if chat.is_contact_request() {
|
||||||
"🆕"
|
"🆕"
|
||||||
} else {
|
} else {
|
||||||
@@ -686,7 +685,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
|||||||
format!("{} member(s)", members.len())
|
format!("{} member(s)", members.len())
|
||||||
};
|
};
|
||||||
println!(
|
println!(
|
||||||
"{}#{}: {} [{}]{}{}{} {}",
|
"{}#{}: {} [{}]{}{}{}",
|
||||||
chat_prefix(sel_chat),
|
chat_prefix(sel_chat),
|
||||||
sel_chat.get_id(),
|
sel_chat.get_id(),
|
||||||
sel_chat.get_name(),
|
sel_chat.get_name(),
|
||||||
@@ -704,11 +703,6 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
|||||||
},
|
},
|
||||||
_ => "".to_string(),
|
_ => "".to_string(),
|
||||||
},
|
},
|
||||||
if sel_chat.is_protected() {
|
|
||||||
"🛡️"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
log_msglist(&context, &msglist).await?;
|
log_msglist(&context, &msglist).await?;
|
||||||
if let Some(draft) = sel_chat.get_id().get_draft(&context).await? {
|
if let Some(draft) = sel_chat.get_id().get_draft(&context).await? {
|
||||||
|
|||||||
82
src/chat.rs
82
src/chat.rs
@@ -1219,16 +1219,6 @@ impl ChatId {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the chat is protected.
|
|
||||||
pub(crate) async fn is_protected(self, context: &Context) -> Result<ProtectionStatus> {
|
|
||||||
let protection_status = context
|
|
||||||
.sql
|
|
||||||
.query_get_value("SELECT protected FROM chats WHERE id=?", (self,))
|
|
||||||
.await?
|
|
||||||
.unwrap_or_default();
|
|
||||||
Ok(protection_status)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the sort timestamp for a new message in the chat.
|
/// Returns the sort timestamp for a new message in the chat.
|
||||||
///
|
///
|
||||||
/// `message_timestamp` should be either the message "sent" timestamp or a timestamp of the
|
/// `message_timestamp` should be either the message "sent" timestamp or a timestamp of the
|
||||||
@@ -1691,53 +1681,38 @@ impl Chat {
|
|||||||
!self.is_unpromoted()
|
!self.is_unpromoted()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if chat protection is enabled.
|
|
||||||
///
|
|
||||||
/// UI should display a green checkmark
|
|
||||||
/// in the chat title,
|
|
||||||
/// in the chat profile title and
|
|
||||||
/// in the chatlist item
|
|
||||||
/// if chat protection is enabled.
|
|
||||||
/// UI should also display a green checkmark
|
|
||||||
/// in the contact profile
|
|
||||||
/// if 1:1 chat with this contact exists and is protected.
|
|
||||||
pub fn is_protected(&self) -> bool {
|
|
||||||
self.protected == ProtectionStatus::Protected
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the chat is encrypted.
|
/// Returns true if the chat is encrypted.
|
||||||
pub async fn is_encrypted(&self, context: &Context) -> Result<bool> {
|
pub async fn is_encrypted(&self, context: &Context) -> Result<bool> {
|
||||||
let is_encrypted = self.is_protected()
|
let is_encrypted = match self.typ {
|
||||||
|| match self.typ {
|
Chattype::Single => {
|
||||||
Chattype::Single => {
|
match context
|
||||||
match context
|
.sql
|
||||||
.sql
|
.query_row_optional(
|
||||||
.query_row_optional(
|
"SELECT cc.contact_id, c.fingerprint<>''
|
||||||
"SELECT cc.contact_id, c.fingerprint<>''
|
|
||||||
FROM chats_contacts cc LEFT JOIN contacts c
|
FROM chats_contacts cc LEFT JOIN contacts c
|
||||||
ON c.id=cc.contact_id
|
ON c.id=cc.contact_id
|
||||||
WHERE cc.chat_id=?
|
WHERE cc.chat_id=?
|
||||||
",
|
",
|
||||||
(self.id,),
|
(self.id,),
|
||||||
|row| {
|
|row| {
|
||||||
let id: ContactId = row.get(0)?;
|
let id: ContactId = row.get(0)?;
|
||||||
let is_key: bool = row.get(1)?;
|
let is_key: bool = row.get(1)?;
|
||||||
Ok((id, is_key))
|
Ok((id, is_key))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
Some((id, is_key)) => is_key || id == ContactId::DEVICE,
|
Some((id, is_key)) => is_key || id == ContactId::DEVICE,
|
||||||
None => true,
|
None => true,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Chattype::Group => {
|
}
|
||||||
// Do not encrypt ad-hoc groups.
|
Chattype::Group => {
|
||||||
!self.grpid.is_empty()
|
// Do not encrypt ad-hoc groups.
|
||||||
}
|
!self.grpid.is_empty()
|
||||||
Chattype::Mailinglist => false,
|
}
|
||||||
Chattype::OutBroadcast | Chattype::InBroadcast => true,
|
Chattype::Mailinglist => false,
|
||||||
};
|
Chattype::OutBroadcast | Chattype::InBroadcast => true,
|
||||||
|
};
|
||||||
Ok(is_encrypted)
|
Ok(is_encrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3770,13 +3745,6 @@ pub(crate) async fn add_contact_to_chat_ex(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// else continue and send status mail
|
// else continue and send status mail
|
||||||
if chat.is_protected() && !contact.is_verified(context).await? {
|
|
||||||
error!(
|
|
||||||
context,
|
|
||||||
"Cannot add non-bidirectionally verified contact {contact_id} to protected chat {chat_id}."
|
|
||||||
);
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
if is_contact_in_chat(context, chat_id, contact_id).await? {
|
if is_contact_in_chat(context, chat_id, contact_id).await? {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use deltachat_contact_tools::{addr_cmp, may_be_valid_addr};
|
use deltachat_contact_tools::{addr_cmp, may_be_valid_addr};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::chat::{Chat, ProtectionStatus, get_chat_contacts, send_text_msg};
|
use crate::chat::{Chat, get_chat_contacts, send_text_msg};
|
||||||
use crate::chatlist::Chatlist;
|
use crate::chatlist::Chatlist;
|
||||||
use crate::receive_imf::receive_imf;
|
use crate::receive_imf::receive_imf;
|
||||||
use crate::securejoin::get_securejoin_qr;
|
use crate::securejoin::get_securejoin_qr;
|
||||||
@@ -1320,9 +1320,6 @@ async fn test_self_is_verified() -> Result<()> {
|
|||||||
assert!(contact.get_verifier_id(&alice).await?.is_none());
|
assert!(contact.get_verifier_id(&alice).await?.is_none());
|
||||||
assert!(contact.is_key_contact());
|
assert!(contact.is_key_contact());
|
||||||
|
|
||||||
let chat_id = ChatId::get_for_contact(&alice, ContactId::SELF).await?;
|
|
||||||
assert!(chat_id.is_protected(&alice).await.unwrap() == ProtectionStatus::Protected);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -606,13 +606,10 @@ async fn test_draft_self_report() -> Result<()> {
|
|||||||
let msg = get_chat_msg(&alice, chat_id, 0, 1).await;
|
let msg = get_chat_msg(&alice, chat_id, 0, 1).await;
|
||||||
assert_eq!(msg.get_info_type(), SystemMessage::ChatE2ee);
|
assert_eq!(msg.get_info_type(), SystemMessage::ChatE2ee);
|
||||||
|
|
||||||
let chat = Chat::load_from_db(&alice, chat_id).await?;
|
|
||||||
assert!(chat.is_protected());
|
|
||||||
|
|
||||||
let mut draft = chat_id.get_draft(&alice).await?.unwrap();
|
let mut draft = chat_id.get_draft(&alice).await?.unwrap();
|
||||||
assert!(draft.text.starts_with("core_version"));
|
assert!(draft.text.starts_with("core_version"));
|
||||||
|
|
||||||
// Test that sending into the protected chat works:
|
// Test that sending into the chat works:
|
||||||
let _sent = alice.send_msg(chat_id, &mut draft).await;
|
let _sent = alice.send_msg(chat_id, &mut draft).await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1327,20 +1327,6 @@ impl MimeFactory {
|
|||||||
let command = msg.param.get_cmd();
|
let command = msg.param.get_cmd();
|
||||||
let mut placeholdertext = None;
|
let mut placeholdertext = None;
|
||||||
|
|
||||||
let send_verified_headers = match chat.typ {
|
|
||||||
Chattype::Single => true,
|
|
||||||
Chattype::Group => true,
|
|
||||||
// Mailinglists and broadcast channels can actually never be verified:
|
|
||||||
Chattype::Mailinglist => false,
|
|
||||||
Chattype::OutBroadcast | Chattype::InBroadcast => false,
|
|
||||||
};
|
|
||||||
if chat.is_protected() && send_verified_headers {
|
|
||||||
headers.push((
|
|
||||||
"Chat-Verified",
|
|
||||||
mail_builder::headers::raw::Raw::new("1").into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if chat.typ == Chattype::Group {
|
if chat.typ == Chattype::Group {
|
||||||
// Send group ID unless it is an ad hoc group that has no ID.
|
// Send group ID unless it is an ad hoc group that has no ID.
|
||||||
if !chat.grpid.is_empty() {
|
if !chat.grpid.is_empty() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use anyhow::{Context as _, Result};
|
|||||||
|
|
||||||
use super::HandshakeMessage;
|
use super::HandshakeMessage;
|
||||||
use super::qrinvite::QrInvite;
|
use super::qrinvite::QrInvite;
|
||||||
use crate::chat::{self, ChatId, ProtectionStatus, is_contact_in_chat};
|
use crate::chat::{self, ChatId, is_contact_in_chat};
|
||||||
use crate::constants::{Blocked, Chattype};
|
use crate::constants::{Blocked, Chattype};
|
||||||
use crate::contact::Origin;
|
use crate::contact::Origin;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
@@ -113,21 +113,19 @@ pub(super) async fn start_protocol(context: &Context, invite: QrInvite) -> Resul
|
|||||||
let ts_sort = chat_id
|
let ts_sort = chat_id
|
||||||
.calc_sort_timestamp(context, 0, sort_to_bottom, received, incoming)
|
.calc_sort_timestamp(context, 0, sort_to_bottom, received, incoming)
|
||||||
.await?;
|
.await?;
|
||||||
if chat_id.is_protected(context).await? == ProtectionStatus::Unprotected {
|
let ts_start = time();
|
||||||
let ts_start = time();
|
chat::add_info_msg_with_cmd(
|
||||||
chat::add_info_msg_with_cmd(
|
context,
|
||||||
context,
|
chat_id,
|
||||||
chat_id,
|
&stock_str::securejoin_wait(context).await,
|
||||||
&stock_str::securejoin_wait(context).await,
|
SystemMessage::SecurejoinWait,
|
||||||
SystemMessage::SecurejoinWait,
|
ts_sort,
|
||||||
ts_sort,
|
Some(ts_start),
|
||||||
Some(ts_start),
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
)
|
||||||
)
|
.await?;
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
Ok(chat_id)
|
Ok(chat_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1013,7 +1013,7 @@ impl TestContext {
|
|||||||
};
|
};
|
||||||
writeln!(
|
writeln!(
|
||||||
res,
|
res,
|
||||||
"{}#{}: {} [{}]{}{}{} {}",
|
"{}#{}: {} [{}]{}{}{}",
|
||||||
sel_chat.typ,
|
sel_chat.typ,
|
||||||
sel_chat.get_id(),
|
sel_chat.get_id(),
|
||||||
sel_chat.get_name(),
|
sel_chat.get_name(),
|
||||||
@@ -1031,11 +1031,6 @@ impl TestContext {
|
|||||||
},
|
},
|
||||||
_ => "".to_string(),
|
_ => "".to_string(),
|
||||||
},
|
},
|
||||||
if sel_chat.is_protected() {
|
|
||||||
"🛡️"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -129,19 +129,12 @@ async fn test_create_verified_oneonone_chat() -> Result<()> {
|
|||||||
tcm.send_recv(&fiona_new, &alice, "I have a new device")
|
tcm.send_recv(&fiona_new, &alice, "I have a new device")
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Alice gets a new unprotected chat with new Fiona contact.
|
// Alice gets a new chat with new Fiona contact.
|
||||||
{
|
{
|
||||||
let chat = alice.get_chat(&fiona_new).await;
|
let chat = alice.get_chat(&fiona_new).await;
|
||||||
assert!(!chat.is_protected());
|
|
||||||
|
|
||||||
let msg = get_chat_msg(&alice, chat.id, 1, E2EE_INFO_MSGS + 1).await;
|
let msg = get_chat_msg(&alice, chat.id, 1, E2EE_INFO_MSGS + 1).await;
|
||||||
assert_eq!(msg.text, "I have a new device");
|
assert_eq!(msg.text, "I have a new device");
|
||||||
|
|
||||||
// After recreating the chat, it should still be unprotected
|
|
||||||
chat.id.delete(&alice).await?;
|
|
||||||
|
|
||||||
let chat = alice.create_chat(&fiona_new).await;
|
|
||||||
assert!(!chat.is_protected());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -175,41 +168,6 @@ async fn test_missing_key_reexecute_securejoin() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
||||||
async fn test_create_unverified_oneonone_chat() -> Result<()> {
|
|
||||||
let mut tcm = TestContextManager::new();
|
|
||||||
let alice = tcm.alice().await;
|
|
||||||
let bob = tcm.bob().await;
|
|
||||||
|
|
||||||
// A chat with an unknown contact should be created unprotected
|
|
||||||
let chat = alice.create_chat(&bob).await;
|
|
||||||
assert!(!chat.is_protected());
|
|
||||||
|
|
||||||
receive_imf(
|
|
||||||
&alice,
|
|
||||||
b"From: Bob <bob@example.net>\n\
|
|
||||||
To: alice@example.org\n\
|
|
||||||
Message-ID: <1234-2@example.org>\n\
|
|
||||||
\n\
|
|
||||||
hello\n",
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
chat.id.delete(&alice).await.unwrap();
|
|
||||||
// Now Bob is a known contact, new chats should still be created unprotected
|
|
||||||
let chat = alice.create_chat(&bob).await;
|
|
||||||
assert!(!chat.is_protected());
|
|
||||||
|
|
||||||
tcm.send_recv(&bob, &alice, "hi").await;
|
|
||||||
chat.id.delete(&alice).await.unwrap();
|
|
||||||
// Now we have a public key, new chats should still be created unprotected
|
|
||||||
let chat = alice.create_chat(&bob).await;
|
|
||||||
assert!(!chat.is_protected());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tests that receiving unencrypted message
|
/// Tests that receiving unencrypted message
|
||||||
/// does not disable protection of 1:1 chat.
|
/// does not disable protection of 1:1 chat.
|
||||||
///
|
///
|
||||||
@@ -223,7 +181,6 @@ async fn test_degrade_verified_oneonone_chat() -> Result<()> {
|
|||||||
mark_as_verified(&alice, &bob).await;
|
mark_as_verified(&alice, &bob).await;
|
||||||
|
|
||||||
let alice_chat = alice.create_chat(&bob).await;
|
let alice_chat = alice.create_chat(&bob).await;
|
||||||
assert!(alice_chat.is_protected());
|
|
||||||
|
|
||||||
receive_imf(
|
receive_imf(
|
||||||
&alice,
|
&alice,
|
||||||
@@ -484,8 +441,6 @@ async fn test_message_from_old_dc_setup() -> Result<()> {
|
|||||||
// The outdated Bob's Autocrypt header isn't applied
|
// The outdated Bob's Autocrypt header isn't applied
|
||||||
// and the message goes to another chat, so the verification preserves.
|
// and the message goes to another chat, so the verification preserves.
|
||||||
assert!(contact.is_verified(alice).await.unwrap());
|
assert!(contact.is_verified(alice).await.unwrap());
|
||||||
let chat = alice.get_chat(bob).await;
|
|
||||||
assert!(chat.is_protected());
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,9 +542,9 @@ async fn test_verified_member_added_reordering() -> Result<()> {
|
|||||||
// "Member added" message, so unverified group is created.
|
// "Member added" message, so unverified group is created.
|
||||||
let fiona_received_message = fiona.recv_msg(&bob_sent_message).await;
|
let fiona_received_message = fiona.recv_msg(&bob_sent_message).await;
|
||||||
let fiona_chat = Chat::load_from_db(fiona, fiona_received_message.chat_id).await?;
|
let fiona_chat = Chat::load_from_db(fiona, fiona_received_message.chat_id).await?;
|
||||||
|
assert!(!fiona_chat.can_send(fiona).await?);
|
||||||
|
|
||||||
assert_eq!(fiona_received_message.get_text(), "Hi");
|
assert_eq!(fiona_received_message.get_text(), "Hi");
|
||||||
assert_eq!(fiona_chat.is_protected(), false);
|
|
||||||
|
|
||||||
// Fiona receives late "Member added" message
|
// Fiona receives late "Member added" message
|
||||||
// and the chat becomes protected.
|
// and the chat becomes protected.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Single#Chat#10: bob@example.net [KEY bob@example.net] 🛡️
|
Single#Chat#10: bob@example.net [KEY bob@example.net]
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
Msg#10: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
|
Msg#10: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
|
||||||
Msg#11🔒: Me (Contact#Contact#Self): Test – This is encrypted, signed, and has an Autocrypt Header without prefer-encrypt=mutual. √
|
Msg#11🔒: Me (Contact#Contact#Self): Test – This is encrypted, signed, and has an Autocrypt Header without prefer-encrypt=mutual. √
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Single#Chat#10: bob@example.net [KEY bob@example.net] 🛡️
|
Single#Chat#10: bob@example.net [KEY bob@example.net]
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
Msg#10: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
|
Msg#10: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
|
||||||
Msg#11🔒: (Contact#Contact#10): Heyho from DC [FRESH]
|
Msg#11🔒: (Contact#Contact#10): Heyho from DC [FRESH]
|
||||||
|
|||||||
Reference in New Issue
Block a user