Improve Chat.get_encryption_info() format

Group contacts by peerstate and make it easier
to find contacts that prevent encryption by sorting them
to the top of the list.
This commit is contained in:
link2xt
2022-05-13 21:09:53 +00:00
committed by holger krekel
parent c9beaa2aa1
commit 8168bcece5
5 changed files with 98 additions and 20 deletions

View File

@@ -6,6 +6,7 @@
- send normal messages with higher priority than MDNs #3243
- make Scheduler stateless #3302
- support `source_code_url` from Webxdc manifests #3314
- improve chat encryption info, make it easier to find contacts without keys #3318
### API-Changes
- deprecate unused `marker1before` argument of `dc_get_chat_msgs`

View File

@@ -689,7 +689,7 @@ def test_gossip_encryption_preference(acfactory, lp):
msg = ac1._evtracker.wait_next_incoming_message()
assert msg.text == "first message"
assert not msg.is_encrypted()
res = "{} End-to-end encryption preferred.".format(ac2.get_config('addr'))
res = "End-to-end encryption preferred:\n{}\n".format(ac2.get_config('addr'))
assert msg.chat.get_encryption_info() == res
lp.sec("ac2 learns that ac3 prefers encryption")
ac2.create_chat(ac3)
@@ -701,7 +701,7 @@ def test_gossip_encryption_preference(acfactory, lp):
lp.sec("ac3 does not know that ac1 prefers encryption")
ac1.create_chat(ac3)
chat = ac3.create_chat(ac1)
res = "{} No encryption.".format(ac1.get_config('addr'))
res = "No encryption:\n{}\n".format(ac1.get_config('addr'))
assert chat.get_encryption_info() == res
msg = chat.send_text("not encrypted")
msg = ac1._evtracker.wait_next_incoming_message()
@@ -712,7 +712,7 @@ def test_gossip_encryption_preference(acfactory, lp):
group_chat = ac1.create_group_chat("hello")
group_chat.add_contact(ac2)
encryption_info = group_chat.get_encryption_info()
res = "{} End-to-end encryption preferred.".format(ac2.get_config("addr"))
res = "End-to-end encryption preferred:\n{}\n".format(ac2.get_config("addr"))
assert encryption_info == res
msg = group_chat.send_text("hi")
@@ -727,10 +727,9 @@ def test_gossip_encryption_preference(acfactory, lp):
lp.sec("ac3 learns that ac1 prefers encryption")
msg = ac3._evtracker.wait_next_incoming_message()
encryption_info = msg.chat.get_encryption_info().splitlines()
res = "{} End-to-end encryption preferred.".format(ac1.get_config("addr"))
assert res in encryption_info
res = "{} End-to-end encryption preferred.".format(ac2.get_config("addr"))
assert res in encryption_info
assert encryption_info[0] == "End-to-end encryption preferred:"
assert ac1.get_config("addr") in encryption_info[1:]
assert ac2.get_config("addr") in encryption_info[1:]
msg = chat.send_text("encrypted")
assert msg.is_encrypted()

View File

@@ -842,7 +842,9 @@ impl ChatId {
///
/// To get more verbose summary for a contact, including its key fingerprint, use [`Contact::get_encrinfo`].
pub async fn get_encryption_info(self, context: &Context) -> Result<String> {
let mut ret = String::new();
let mut ret_mutual = String::new();
let mut ret_nopreference = String::new();
let mut ret_reset = String::new();
for contact_id in get_chat_contacts(context, self)
.await?
@@ -853,7 +855,7 @@ impl ChatId {
let addr = contact.get_addr();
let peerstate = Peerstate::from_addr(context, addr).await?;
let stock_message = match peerstate
match peerstate
.filter(|peerstate| {
peerstate
.peek_key(PeerstateVerifiedStatus::Unverified)
@@ -861,15 +863,36 @@ impl ChatId {
})
.map(|peerstate| peerstate.prefer_encrypt)
{
Some(EncryptPreference::Mutual) => stock_str::e2e_preferred(context).await,
Some(EncryptPreference::NoPreference) => stock_str::e2e_available(context).await,
Some(EncryptPreference::Reset) => stock_str::encr_none(context).await,
None => stock_str::encr_none(context).await,
Some(EncryptPreference::Mutual) => ret_mutual += &format!("{}\n", addr),
Some(EncryptPreference::NoPreference) => ret_nopreference += &format!("{}\n", addr),
Some(EncryptPreference::Reset) | None => ret_reset += &format!("{}\n", addr),
};
}
let mut ret = String::new();
if !ret_reset.is_empty() {
ret += &stock_str::encr_none(context).await;
ret.push(':');
ret.push('\n');
ret += &ret_reset;
}
if !ret_nopreference.is_empty() {
if !ret.is_empty() {
ret.push('\n')
ret.push('\n');
}
ret += &format!("{} {}", addr, stock_message);
ret += &stock_str::e2e_available(context).await;
ret.push(':');
ret.push('\n');
ret += &ret_nopreference;
}
if !ret_mutual.is_empty() {
if !ret.is_empty() {
ret.push('\n');
}
ret += &stock_str::e2e_preferred(context).await;
ret.push(':');
ret.push('\n');
ret += &ret_mutual;
}
Ok(ret)
@@ -5374,4 +5397,59 @@ mod tests {
Ok(())
}
#[async_std::test]
async fn test_chat_get_encryption_info() -> Result<()> {
let alice = TestContext::new_alice().await;
let bob = TestContext::new_bob().await;
let contact_bob = Contact::create(&alice, "Bob", "bob@example.net").await?;
let contact_fiona = Contact::create(&alice, "", "fiona@example.net").await?;
let chat_id = create_group_chat(&alice, ProtectionStatus::Unprotected, "Group").await?;
assert_eq!(chat_id.get_encryption_info(&alice).await?, "");
add_contact_to_chat(&alice, chat_id, contact_bob).await?;
assert_eq!(
chat_id.get_encryption_info(&alice).await?,
"No encryption:\n\
bob@example.net\n"
);
add_contact_to_chat(&alice, chat_id, contact_fiona).await?;
assert_eq!(
chat_id.get_encryption_info(&alice).await?,
"No encryption:\n\
bob@example.net\n\
fiona@example.net\n"
);
let direct_chat = bob.create_chat(&alice).await;
send_text_msg(&bob, direct_chat.id, "Hello!".to_string()).await?;
alice.recv_msg(&bob.pop_sent_msg().await).await;
assert_eq!(
chat_id.get_encryption_info(&alice).await?,
"No encryption:\n\
fiona@example.net\n\
\n\
End-to-end encryption preferred:\n\
bob@example.net\n"
);
bob.set_config(Config::E2eeEnabled, Some("0")).await?;
send_text_msg(&bob, direct_chat.id, "Hello!".to_string()).await?;
alice.recv_msg(&bob.pop_sent_msg().await).await;
assert_eq!(
chat_id.get_encryption_info(&alice).await?,
"No encryption:\n\
fiona@example.net\n\
\n\
End-to-end encryption available:\n\
bob@example.net\n"
);
Ok(())
}
}

View File

@@ -889,7 +889,7 @@ impl Contact {
};
ret += &format!(
"{}\n{}:",
"{}.\n{}:",
stock_message,
stock_str::finger_prints(context).await
);
@@ -1961,7 +1961,7 @@ mod tests {
.await?;
let encrinfo = Contact::get_encrinfo(&alice, contact_bob_id).await?;
assert_eq!(encrinfo, "No encryption.");
assert_eq!(encrinfo, "No encryption");
let bob = TestContext::new_bob().await;
let chat_alice = bob

View File

@@ -73,10 +73,10 @@ pub enum StockMessage {
#[strum(props(fallback = "Encrypted message"))]
EncryptedMsg = 24,
#[strum(props(fallback = "End-to-end encryption available."))]
#[strum(props(fallback = "End-to-end encryption available"))]
E2eAvailable = 25,
#[strum(props(fallback = "No encryption."))]
#[strum(props(fallback = "No encryption"))]
EncrNone = 28,
#[strum(props(fallback = "This message was encrypted for another setup."))]
@@ -94,7 +94,7 @@ pub enum StockMessage {
#[strum(props(fallback = "Group image deleted."))]
MsgGrpImgDeleted = 33,
#[strum(props(fallback = "End-to-end encryption preferred."))]
#[strum(props(fallback = "End-to-end encryption preferred"))]
E2ePreferred = 34,
#[strum(props(fallback = "%1$s verified."))]