mirror of
https://github.com/chatmail/core.git
synced 2026-05-22 16:26:31 +03:00
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:
@@ -6,6 +6,7 @@
|
|||||||
- send normal messages with higher priority than MDNs #3243
|
- send normal messages with higher priority than MDNs #3243
|
||||||
- make Scheduler stateless #3302
|
- make Scheduler stateless #3302
|
||||||
- support `source_code_url` from Webxdc manifests #3314
|
- support `source_code_url` from Webxdc manifests #3314
|
||||||
|
- improve chat encryption info, make it easier to find contacts without keys #3318
|
||||||
|
|
||||||
### API-Changes
|
### API-Changes
|
||||||
- deprecate unused `marker1before` argument of `dc_get_chat_msgs`
|
- deprecate unused `marker1before` argument of `dc_get_chat_msgs`
|
||||||
|
|||||||
@@ -689,7 +689,7 @@ def test_gossip_encryption_preference(acfactory, lp):
|
|||||||
msg = ac1._evtracker.wait_next_incoming_message()
|
msg = ac1._evtracker.wait_next_incoming_message()
|
||||||
assert msg.text == "first message"
|
assert msg.text == "first message"
|
||||||
assert not msg.is_encrypted()
|
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
|
assert msg.chat.get_encryption_info() == res
|
||||||
lp.sec("ac2 learns that ac3 prefers encryption")
|
lp.sec("ac2 learns that ac3 prefers encryption")
|
||||||
ac2.create_chat(ac3)
|
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")
|
lp.sec("ac3 does not know that ac1 prefers encryption")
|
||||||
ac1.create_chat(ac3)
|
ac1.create_chat(ac3)
|
||||||
chat = ac3.create_chat(ac1)
|
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
|
assert chat.get_encryption_info() == res
|
||||||
msg = chat.send_text("not encrypted")
|
msg = chat.send_text("not encrypted")
|
||||||
msg = ac1._evtracker.wait_next_incoming_message()
|
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 = ac1.create_group_chat("hello")
|
||||||
group_chat.add_contact(ac2)
|
group_chat.add_contact(ac2)
|
||||||
encryption_info = group_chat.get_encryption_info()
|
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
|
assert encryption_info == res
|
||||||
msg = group_chat.send_text("hi")
|
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")
|
lp.sec("ac3 learns that ac1 prefers encryption")
|
||||||
msg = ac3._evtracker.wait_next_incoming_message()
|
msg = ac3._evtracker.wait_next_incoming_message()
|
||||||
encryption_info = msg.chat.get_encryption_info().splitlines()
|
encryption_info = msg.chat.get_encryption_info().splitlines()
|
||||||
res = "{} End-to-end encryption preferred.".format(ac1.get_config("addr"))
|
assert encryption_info[0] == "End-to-end encryption preferred:"
|
||||||
assert res in encryption_info
|
assert ac1.get_config("addr") in encryption_info[1:]
|
||||||
res = "{} End-to-end encryption preferred.".format(ac2.get_config("addr"))
|
assert ac2.get_config("addr") in encryption_info[1:]
|
||||||
assert res in encryption_info
|
|
||||||
msg = chat.send_text("encrypted")
|
msg = chat.send_text("encrypted")
|
||||||
assert msg.is_encrypted()
|
assert msg.is_encrypted()
|
||||||
|
|
||||||
|
|||||||
94
src/chat.rs
94
src/chat.rs
@@ -842,7 +842,9 @@ impl ChatId {
|
|||||||
///
|
///
|
||||||
/// To get more verbose summary for a contact, including its key fingerprint, use [`Contact::get_encrinfo`].
|
/// 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> {
|
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)
|
for contact_id in get_chat_contacts(context, self)
|
||||||
.await?
|
.await?
|
||||||
@@ -853,7 +855,7 @@ impl ChatId {
|
|||||||
let addr = contact.get_addr();
|
let addr = contact.get_addr();
|
||||||
let peerstate = Peerstate::from_addr(context, addr).await?;
|
let peerstate = Peerstate::from_addr(context, addr).await?;
|
||||||
|
|
||||||
let stock_message = match peerstate
|
match peerstate
|
||||||
.filter(|peerstate| {
|
.filter(|peerstate| {
|
||||||
peerstate
|
peerstate
|
||||||
.peek_key(PeerstateVerifiedStatus::Unverified)
|
.peek_key(PeerstateVerifiedStatus::Unverified)
|
||||||
@@ -861,15 +863,36 @@ impl ChatId {
|
|||||||
})
|
})
|
||||||
.map(|peerstate| peerstate.prefer_encrypt)
|
.map(|peerstate| peerstate.prefer_encrypt)
|
||||||
{
|
{
|
||||||
Some(EncryptPreference::Mutual) => stock_str::e2e_preferred(context).await,
|
Some(EncryptPreference::Mutual) => ret_mutual += &format!("{}\n", addr),
|
||||||
Some(EncryptPreference::NoPreference) => stock_str::e2e_available(context).await,
|
Some(EncryptPreference::NoPreference) => ret_nopreference += &format!("{}\n", addr),
|
||||||
Some(EncryptPreference::Reset) => stock_str::encr_none(context).await,
|
Some(EncryptPreference::Reset) | None => ret_reset += &format!("{}\n", addr),
|
||||||
None => stock_str::encr_none(context).await,
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
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)
|
Ok(ret)
|
||||||
@@ -5374,4 +5397,59 @@ mod tests {
|
|||||||
|
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -889,7 +889,7 @@ impl Contact {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ret += &format!(
|
ret += &format!(
|
||||||
"{}\n{}:",
|
"{}.\n{}:",
|
||||||
stock_message,
|
stock_message,
|
||||||
stock_str::finger_prints(context).await
|
stock_str::finger_prints(context).await
|
||||||
);
|
);
|
||||||
@@ -1961,7 +1961,7 @@ mod tests {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let encrinfo = Contact::get_encrinfo(&alice, contact_bob_id).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 bob = TestContext::new_bob().await;
|
||||||
let chat_alice = bob
|
let chat_alice = bob
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ pub enum StockMessage {
|
|||||||
#[strum(props(fallback = "Encrypted message"))]
|
#[strum(props(fallback = "Encrypted message"))]
|
||||||
EncryptedMsg = 24,
|
EncryptedMsg = 24,
|
||||||
|
|
||||||
#[strum(props(fallback = "End-to-end encryption available."))]
|
#[strum(props(fallback = "End-to-end encryption available"))]
|
||||||
E2eAvailable = 25,
|
E2eAvailable = 25,
|
||||||
|
|
||||||
#[strum(props(fallback = "No encryption."))]
|
#[strum(props(fallback = "No encryption"))]
|
||||||
EncrNone = 28,
|
EncrNone = 28,
|
||||||
|
|
||||||
#[strum(props(fallback = "This message was encrypted for another setup."))]
|
#[strum(props(fallback = "This message was encrypted for another setup."))]
|
||||||
@@ -94,7 +94,7 @@ pub enum StockMessage {
|
|||||||
#[strum(props(fallback = "Group image deleted."))]
|
#[strum(props(fallback = "Group image deleted."))]
|
||||||
MsgGrpImgDeleted = 33,
|
MsgGrpImgDeleted = 33,
|
||||||
|
|
||||||
#[strum(props(fallback = "End-to-end encryption preferred."))]
|
#[strum(props(fallback = "End-to-end encryption preferred"))]
|
||||||
E2ePreferred = 34,
|
E2ePreferred = 34,
|
||||||
|
|
||||||
#[strum(props(fallback = "%1$s verified."))]
|
#[strum(props(fallback = "%1$s verified."))]
|
||||||
|
|||||||
Reference in New Issue
Block a user