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