non-blocking group QR joins (#2508)

* refactor: cleanup send_handshake_msg()

- rename to send_alice_handshake_msg() as used by Alice only

- remove dead code from Bob
  (Bob's code is at BobState::send_handshake_message() since some time)

- take a contact_id and not a chat_id;
  this makes things less confusing when
  info-messages are put to the final group chat

* always directly return chat-id from dc_join_securejoin()

* take care not to create a group twice

* adapt documentation

* add info-msg on group invites; add inviter directly after creation

* document existing 'joinqr' command in repl tool

* do not create empty one-to-one chats for group-joins

* refactor: cleanup fingerprint_equals_sender()

- the function takes a contact_id directly now.
  before it consumes the first contact of a one-to-one chat -
  which may be easily confused with the group-chat in creation.
  moreover, the conversion contact_id -> chat_id -> contact_id
  is unneeded overhead.

* show info-messages in destination chat for alice

* fingerprint_equals_sender() returns Err on database failure

* tweak documentation

* clarify what an 'unfinished tasks' task is.

* add regression test for create_for_contact_with_blocked()

* rename Blocked::Manually to better fitting Blocked::Yes

* tweak test_secure_join() and make sure, Alice and Bob have only on chat after a group-join
This commit is contained in:
bjoern
2021-10-26 16:34:07 +02:00
committed by GitHub
parent 63207eb681
commit 3b7b8ea0f1
12 changed files with 287 additions and 232 deletions

View File

@@ -175,8 +175,8 @@ impl ChatId {
}
/// Same as `create_for_contact()` with an additional `create_blocked` parameter
/// that is used in case the chat does not exist.
/// If the chat exists already, `create_blocked` is ignored.
/// that is used in case the chat does not exist or to unblock existing chats.
/// `create_blocked` won't block already unblocked chats again.
pub(crate) async fn create_for_contact_with_blocked(
context: &Context,
contact_id: u32,
@@ -184,7 +184,7 @@ impl ChatId {
) -> Result<Self> {
let chat_id = match ChatIdBlocked::lookup_by_contact(context, contact_id).await? {
Some(chat) => {
if chat.blocked != Blocked::Not {
if create_blocked == Blocked::Not && chat.blocked != Blocked::Not {
chat.id.unblock(context).await?;
}
chat.id
@@ -304,7 +304,7 @@ impl ChatId {
self.delete(context).await?;
}
Chattype::Mailinglist => {
if self.set_blocked(context, Blocked::Manually).await? {
if self.set_blocked(context, Blocked::Yes).await? {
context.emit_event(EventType::ChatModified(self));
}
}
@@ -3891,7 +3891,7 @@ mod tests {
// create contact, then blocked chat
let contact_id = Contact::create(&ctx, "", "claire@foo.de").await.unwrap();
let chat_id = ChatIdBlocked::get_for_contact(&ctx, contact_id, Blocked::Manually)
let chat_id = ChatIdBlocked::get_for_contact(&ctx, contact_id, Blocked::Yes)
.await
.unwrap()
.id;
@@ -3900,7 +3900,7 @@ mod tests {
.unwrap()
.unwrap();
assert_eq!(chat_id, chat2.id);
assert_eq!(chat2.blocked, Blocked::Manually);
assert_eq!(chat2.blocked, Blocked::Yes);
// test nonexistent contact
let found = ChatId::lookup_by_contact(&ctx, 1234).await.unwrap();
@@ -4410,4 +4410,38 @@ mod tests {
Ok(())
}
#[async_std::test]
async fn test_create_for_contact_with_blocked() -> Result<()> {
let t = TestContext::new().await;
let (contact_id, _) =
Contact::add_or_lookup(&t, "", "foo@bar.org", Origin::ManuallyCreated).await?;
// create a blocked chat
let chat_id_orig =
ChatId::create_for_contact_with_blocked(&t, contact_id, Blocked::Yes).await?;
assert!(!chat_id_orig.is_special());
let chat = Chat::load_from_db(&t, chat_id_orig).await?;
assert_eq!(chat.blocked, Blocked::Yes);
// repeating the call, the same chat must still be blocked
let chat_id = ChatId::create_for_contact_with_blocked(&t, contact_id, Blocked::Yes).await?;
assert_eq!(chat_id, chat_id_orig);
let chat = Chat::load_from_db(&t, chat_id).await?;
assert_eq!(chat.blocked, Blocked::Yes);
// already created chats are unblocked if requested
let chat_id = ChatId::create_for_contact_with_blocked(&t, contact_id, Blocked::Not).await?;
assert_eq!(chat_id, chat_id_orig);
let chat = Chat::load_from_db(&t, chat_id).await?;
assert_eq!(chat.blocked, Blocked::Not);
// however, already created chats are not re-blocked
let chat_id = ChatId::create_for_contact_with_blocked(&t, contact_id, Blocked::Yes).await?;
assert_eq!(chat_id, chat_id_orig);
let chat = Chat::load_from_db(&t, chat_id).await?;
assert_eq!(chat.blocked, Blocked::Not);
Ok(())
}
}