core_crypto/transaction_context/conversation/
mod.rs1pub mod external_commit;
4mod external_proposal;
5pub mod external_sender;
6pub(crate) mod proposal;
7pub mod welcome;
8
9use core_crypto_keystore::{connection::FetchFromDatabase as _, entities::PersistedMlsPendingGroup};
10
11use super::{Error, Result, TransactionContext};
12use crate::{
13 KeystoreError, LeafError, MlsConversation, MlsConversationConfiguration, MlsCredentialType, RecursiveError,
14 mls::conversation::{ConversationGuard, ConversationIdRef, pending_conversation::PendingConversation},
15};
16
17impl TransactionContext {
18 pub async fn conversation(&self, id: &ConversationIdRef) -> Result<ConversationGuard> {
22 let keystore = self.mls_provider().await?.keystore();
23 let inner = self
24 .mls_groups()
25 .await?
26 .get_fetch(id, &keystore, None)
27 .await
28 .map_err(RecursiveError::root("fetching conversation from mls groups by id"))?;
29
30 if let Some(inner) = inner {
31 return Ok(ConversationGuard::new(inner, self.clone()));
32 }
33 let pending = self.pending_conversation(id).await.map(Error::PendingConversation)?;
36 Err(pending)
37 }
38
39 pub(crate) async fn pending_conversation(&self, id: &ConversationIdRef) -> Result<PendingConversation> {
40 let keystore = self.keystore().await?;
41 let Some(pending_group) = keystore
42 .find::<PersistedMlsPendingGroup>(id)
43 .await
44 .map_err(KeystoreError::wrap("finding persisted mls pending group"))?
45 else {
46 return Err(LeafError::ConversationNotFound(id.to_owned()).into());
47 };
48 Ok(PendingConversation::new(pending_group, self.clone()))
49 }
50
51 #[cfg_attr(test, crate::dispotent)]
63 pub async fn new_conversation(
64 &self,
65 id: &ConversationIdRef,
66 creator_credential_type: MlsCredentialType,
67 config: MlsConversationConfiguration,
68 ) -> Result<()> {
69 if self.conversation_exists(id).await? || self.pending_conversation_exists(id).await? {
70 return Err(LeafError::ConversationAlreadyExists(id.to_owned()).into());
71 }
72 let conversation = MlsConversation::create(
73 id.to_owned(),
74 &self.session().await?,
75 creator_credential_type,
76 config,
77 &self.mls_provider().await?,
78 )
79 .await
80 .map_err(RecursiveError::mls_conversation("creating conversation"))?;
81
82 self.mls_groups().await?.insert(id, conversation);
83
84 Ok(())
85 }
86
87 pub async fn conversation_exists(&self, id: &ConversationIdRef) -> Result<bool> {
89 self.mls_groups()
90 .await?
91 .get_fetch(id, &self.mls_provider().await?.keystore(), None)
92 .await
93 .map(|option| option.is_some())
94 .map_err(RecursiveError::root("fetching conversation from mls groups by id"))
95 .map_err(Into::into)
96 }
97}