core_crypto/transaction_context/conversation/
welcome.rs1use openmls::prelude::{MlsMessageIn, MlsMessageInBody};
4
5use super::{Error, Result, TransactionContext};
6use crate::{ConversationConfiguration, ConversationId};
7
8impl TransactionContext {
9 #[cfg_attr(test, crate::dispotent)]
22 pub async fn process_welcome_message(&self, welcome: impl Into<MlsMessageIn>) -> Result<ConversationId> {
23 let MlsMessageInBody::Welcome(welcome) = welcome.into().extract() else {
24 return Err(Error::CallerError(
25 "the message provided to process_welcome_message was not a welcome message",
26 ));
27 };
28
29 let configuration = ConversationConfiguration {
30 cipher_suite: welcome.ciphersuite().into(),
31 ..Default::default()
32 };
33
34 let conversation = self
35 .persist_conversation_from_welcome_message(welcome, configuration)
36 .await?;
37
38 let id = conversation.id().to_owned();
39
40 Ok(id)
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use crate::test_utils::*;
47
48 #[apply(all_cred_cipher)]
49 async fn joining_from_welcome_should_prune_local_key_material(case: TestContext) {
50 let [alice, bob] = case.sessions().await;
51 Box::pin(async move {
52 let commit_guard = case.create_conversation([&alice]).await.invite([&bob]).await;
55
56 let prev_count = bob.transaction.count_entities().await;
58 commit_guard.notify_members().await;
60
61 let next_count = bob.transaction.count_entities().await;
64 assert_eq!(next_count.key_package, prev_count.key_package - 1);
65 assert_eq!(next_count.hpke_private_key, prev_count.hpke_private_key - 1);
66 assert_eq!(next_count.encryption_keypair, prev_count.encryption_keypair - 1);
67 })
68 .await;
69 }
70
71 #[apply(all_cred_cipher)]
72 async fn process_welcome_should_fail_when_already_exists(case: TestContext) {
73 use crate::LeafError;
74
75 let [alice, bob] = case.sessions().await;
76 Box::pin(async move {
77 let credential_ref = &bob.initial_credential;
78 let commit = case.create_conversation([&alice]).await.invite([&bob]).await;
79 let conversation = commit.conversation();
80 let id = conversation.id().clone();
81 bob
83 .transaction
84 .new_conversation(&id, credential_ref, case.cfg.clone())
85 .await
86 .unwrap();
87
88 let welcome = conversation.transport().await.latest_welcome_message().await;
89 let join_welcome = bob
90 .transaction
91 .process_welcome_message(welcome)
92 .await;
93 assert!(innermost_source_matches!(join_welcome.unwrap_err(), LeafError::ConversationAlreadyExists(i) if i == &id));
94 })
95 .await;
96 }
97}