core_crypto/mls/conversation/
wipe.rs

1use super::Result;
2use crate::{MlsError, prelude::MlsConversation};
3use mls_crypto_provider::MlsCryptoProvider;
4use openmls_traits::OpenMlsCryptoProvider;
5
6impl MlsConversation {
7    pub(crate) async fn wipe_associated_entities(&mut self, backend: &MlsCryptoProvider) -> Result<()> {
8        // the own client may or may not have generated an epoch keypair in the previous epoch
9        // Since it is a terminal operation, ignoring the error is fine here.
10        let _ = self.group.delete_previous_epoch_keypairs(backend).await;
11
12        let pending_proposals = self.group.pending_proposals().cloned().collect::<Vec<_>>();
13        for proposal in pending_proposals {
14            // Update proposals rekey the own leaf node. Hence the associated encryption keypair has to be cleared
15            self.group
16                .remove_pending_proposal(backend.key_store(), proposal.proposal_reference())
17                .await
18                .map_err(MlsError::wrap("removing pending proposal"))?;
19        }
20
21        Ok(())
22    }
23}
24
25#[cfg(test)]
26mod tests {
27    use crate::{mls::conversation::ConversationWithMls as _, test_utils::*};
28    use wasm_bindgen_test::*;
29
30    wasm_bindgen_test_configure!(run_in_browser);
31
32    // should delete anything related to this conversation
33    #[apply(all_cred_cipher)]
34    #[wasm_bindgen_test]
35    async fn should_cascade_deletion(case: TestContext) {
36        let [alice] = case.sessions().await;
37        Box::pin(async move {
38            let conversation = case.create_conversation([&alice]).await;
39            assert!(conversation.guard().await.conversation().await.group.is_active());
40            let initial_count = alice.transaction.count_entities().await;
41
42            let conversation = conversation.update_proposal_notify().await;
43            let post_proposal_count = alice.transaction.count_entities().await;
44            assert_eq!(
45                post_proposal_count.encryption_keypair,
46                initial_count.encryption_keypair + 1
47            );
48
49            conversation.guard().await.wipe().await.unwrap();
50
51            let final_count = alice.transaction.count_entities().await;
52            assert!(!alice.transaction.conversation_exists(conversation.id()).await.unwrap());
53            assert_eq!(final_count.group, 0);
54            assert_eq!(final_count.encryption_keypair, final_count.key_package);
55            assert_eq!(final_count.epoch_encryption_keypair, 0);
56        })
57        .await
58    }
59}