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