diff --git a/src/chat.rs b/src/chat.rs index c8c7b76ab..4d245b88d 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -3850,7 +3850,10 @@ pub(crate) async fn create_broadcast_ex( if sync.into() { let id = SyncId::Grpid(grpid); - let action = SyncAction::CreateBroadcast { chat_name, secret }; + let action = SyncAction::CreateOutBroadcast { + chat_name, + shared_secret: secret, + }; self::sync(context, id, action).await.log_err(context).ok(); } @@ -3873,16 +3876,17 @@ pub(crate) async fn load_broadcast_shared_secret( pub(crate) async fn save_broadcast_shared_secret( context: &Context, chat_id: ChatId, - shared_secret: &str, + secret: &str, ) -> Result<()> { context .sql .execute( "INSERT INTO broadcasts_shared_secrets (chat_id, secret) VALUES (?, ?) ON CONFLICT(chat_id) DO UPDATE SET secret=excluded.chat_id", - (chat_id, shared_secret), + (chat_id, secret), ) .await?; + Ok(()) } @@ -5087,9 +5091,13 @@ pub(crate) enum SyncAction { SetVisibility(ChatVisibility), SetMuted(MuteDuration), /// Create broadcast channel with the given name. - CreateBroadcast { + CreateOutBroadcast { chat_name: String, - secret: String, + shared_secret: String, + }, + CreateInBroadcast { + chat_name: String, + shared_secret: String, }, Rename(String), /// Set chat contacts by their addresses. @@ -5153,7 +5161,11 @@ impl Context { .id } SyncId::Grpid(grpid) => { - if let SyncAction::CreateBroadcast { chat_name, secret } = action { + if let SyncAction::CreateOutBroadcast { + chat_name, + shared_secret: secret, + } = action + { create_broadcast_ex( self, Nosync, @@ -5184,7 +5196,7 @@ impl Context { SyncAction::Accept => chat_id.accept_ex(self, Nosync).await, SyncAction::SetVisibility(v) => chat_id.set_visibility_ex(self, Nosync, *v).await, SyncAction::SetMuted(duration) => set_muted_ex(self, Nosync, chat_id, *duration).await, - SyncAction::CreateBroadcast { .. } => { + SyncAction::CreateOutBroadcast { .. } | SyncAction::CreateInBroadcast { .. } => { Err(anyhow!("sync_alter_chat({id:?}, {action:?}): Bad request.")) } SyncAction::Rename(to) => rename_ex(self, Nosync, chat_id, to).await, diff --git a/src/chat/chat_tests.rs b/src/chat/chat_tests.rs index 25ac00fe9..aa92ef693 100644 --- a/src/chat/chat_tests.rs +++ b/src/chat/chat_tests.rs @@ -2277,7 +2277,8 @@ async fn test_only_minimal_data_are_forwarded() -> Result<()> { let group_id = create_group_chat(&bob, ProtectionStatus::Unprotected, "group2").await?; add_contact_to_chat(&bob, group_id, charlie_id).await?; let broadcast_id = create_broadcast(&bob, "Channel".to_string()).await?; - add_contact_to_chat(&bob, broadcast_id, charlie_id).await?; + let qr = get_securejoin_qr(&bob, Some(broadcast_id)).await?; + tcm.exec_securejoin_qr(&charlie, &bob, &qr).await; for chat_id in &[single_id, group_id, broadcast_id] { forward_msgs(&bob, &[orig_msg.id], *chat_id).await?; let sent_msg = bob.pop_sent_msg().await; @@ -3060,8 +3061,9 @@ async fn test_leave_broadcast_multidevice() -> Result<()> { tcm.section("Alice creates broadcast channel with Bob."); let alice_chat_id = create_broadcast(alice, "foo".to_string()).await?; - let bob_contact = alice.add_or_lookup_contact(bob0).await.id; - add_contact_to_chat(alice, alice_chat_id, bob_contact).await?; + let qr = get_securejoin_qr(alice, Some(alice_chat_id)).await.unwrap(); + tcm.exec_securejoin_qr(bob0, alice, &qr).await; + sync(bob0, bob1).await; tcm.section("Alice sends first message to broadcast."); let sent_msg = alice.send_text(alice_chat_id, "Hello!").await; diff --git a/src/securejoin/bob.rs b/src/securejoin/bob.rs index 9f18f3997..e83d404d7 100644 --- a/src/securejoin/bob.rs +++ b/src/securejoin/bob.rs @@ -12,7 +12,7 @@ use crate::contact::Origin; use crate::context::Context; use crate::events::EventType; use crate::key::self_fingerprint; -use crate::log::info; +use crate::log::{LogExt as _, info}; use crate::message::{Message, Viewtype}; use crate::mimeparser::{MimeMessage, SystemMessage}; use crate::param::Param; @@ -58,13 +58,26 @@ pub(super) async fn start_protocol(context: &Context, invite: QrInvite) -> Resul ContactId::scaleup_origin(context, &[invite.contact_id()], Origin::SecurejoinJoined).await?; context.emit_event(EventType::ContactsChanged(None)); - if let QrInvite::Broadcast { shared_secret, .. } = &invite { + if let QrInvite::Broadcast { + shared_secret, + grpid, + broadcast_name, + .. + } = &invite + { // TODO this causes some performance penalty because joining_chat_id is used again below, // but maybe it's fine let broadcast_chat_id = joining_chat_id(context, &invite, chat_id).await?; - // TODO save the secret to the second device + save_broadcast_shared_secret(context, broadcast_chat_id, shared_secret).await?; + let id = chat::SyncId::Grpid(grpid.to_string()); + let action = chat::SyncAction::CreateInBroadcast { + chat_name: broadcast_name.to_string(), + shared_secret: shared_secret.to_string(), + }; + chat::sync(context, id, action).await.log_err(context).ok(); + if verify_sender_by_fingerprint(context, invite.fingerprint(), invite.contact_id()).await? { info!(context, "Using fast securejoin with symmetric encryption");