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 CredentialType, KeystoreError, LeafError, MlsConversation, MlsConversationConfiguration, 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)]
62 pub async fn new_conversation(
63 &self,
64 id: &ConversationIdRef,
65 creator_credential_type: CredentialType,
66 config: MlsConversationConfiguration,
67 ) -> Result<()> {
68 if self.conversation_exists(id).await? || self.pending_conversation_exists(id).await? {
69 return Err(LeafError::ConversationAlreadyExists(id.to_owned()).into());
70 }
71 let conversation = MlsConversation::create(
72 id.to_owned(),
73 &self.session().await?,
74 creator_credential_type,
75 config,
76 &self.mls_provider().await?,
77 )
78 .await
79 .map_err(RecursiveError::mls_conversation("creating conversation"))?;
80
81 self.mls_groups().await?.insert(id, conversation);
82
83 Ok(())
84 }
85
86 pub async fn conversation_exists(&self, id: &ConversationIdRef) -> Result<bool> {
88 self.mls_groups()
89 .await?
90 .get_fetch(id, &self.mls_provider().await?.keystore(), None)
91 .await
92 .map(|option| option.is_some())
93 .map_err(RecursiveError::root("fetching conversation from mls groups by id"))
94 .map_err(Into::into)
95 }
96}