core_crypto/mls/conversation/
welcome.rs1use core_crypto_keystore::{Database, entities::PersistedMlsPendingGroup, traits::FetchFromDatabase};
2use openmls::prelude::{MlsGroup, Welcome};
3use openmls_traits::OpenMlsCryptoProvider;
4
5use super::{Error, Result};
6use crate::{
7 ConversationId, LeafError, MlsConversation, MlsConversationConfiguration, MlsError,
8 e2e_identity::NewCrlDistributionPoints, group_store::GroupStore, mls_provider::MlsCryptoProvider,
9};
10
11#[derive(Debug)]
13pub struct WelcomeBundle {
14 pub id: ConversationId,
16 pub crl_new_distribution_points: NewCrlDistributionPoints,
18}
19
20impl MlsConversation {
21 pub(crate) async fn from_welcome_message(
25 welcome: Welcome,
26 configuration: MlsConversationConfiguration,
27 provider: &MlsCryptoProvider,
28 database: &Database,
29 mls_groups: &mut GroupStore<MlsConversation>,
30 ) -> Result<Self> {
31 let mls_group_config = configuration.as_openmls_default_configuration()?;
32
33 let group = MlsGroup::new_from_welcome(provider, &mls_group_config, welcome, None)
34 .await
35 .map_err(|err| {
36 use openmls::prelude::WelcomeError;
37 match err {
38 WelcomeError::NoMatchingKeyPackage | WelcomeError::NoMatchingEncryptionKey => Error::OrphanWelcome,
39 _ => MlsError::wrap("group could not be created from welcome")(err).into(),
40 }
41 })?;
42
43 let id = ConversationId::from(group.group_id().as_slice());
44 let existing_conversation = mls_groups.get_fetch(&id, database, None).await;
45 let conversation_exists = existing_conversation.ok().flatten().is_some();
46
47 let pending_group = provider
48 .key_store()
49 .get_borrowed::<PersistedMlsPendingGroup>(id.as_ref())
50 .await;
51 let pending_group_exists = pending_group.ok().flatten().is_some();
52
53 if conversation_exists || pending_group_exists {
54 return Err(LeafError::ConversationAlreadyExists(id).into());
55 }
56
57 Self::from_mls_group(group, configuration, database).await
58 }
59}