Skip to main content

core_crypto/mls/conversation/immutable/
clients.rs

1use std::collections::HashSet;
2
3use log::trace;
4use openmls::prelude::{LeafNodeIndex, Proposal};
5
6use crate::ClientId;
7
8impl super::Conversation {
9    /// Exports the clients from a conversation
10    ///
11    /// # Arguments
12    /// * `conversation_id` - the group/conversation id
13    pub async fn get_client_ids(&self) -> Vec<ClientId> {
14        self.group()
15            .await
16            .members()
17            .map(|kp| ClientId::from(kp.credential.identity().to_owned()))
18            .collect()
19    }
20
21    /// Gather pending remove proposals
22    async fn pending_removals(&self) -> Vec<LeafNodeIndex> {
23        self.group()
24            .await
25            .pending_proposals()
26            .filter_map(|proposal| match proposal.proposal() {
27                Proposal::Remove(remove) => Some(remove.removed()),
28                _ => None,
29            })
30            .collect::<Vec<_>>()
31    }
32
33    /// Get actual group members and subtract pending remove proposals
34    pub async fn members_in_next_epoch(&self) -> Vec<ClientId> {
35        let pending_removals = self.pending_removals().await;
36        let existing_clients = self
37            .group()
38            .await
39            .members()
40            .filter_map(|kp| {
41                if !pending_removals.contains(&kp.index) {
42                    Some(kp.credential.identity().to_owned().into())
43                } else {
44                    trace!(client_index:% = kp.index; "Client is pending removal");
45                    None
46                }
47            })
48            .collect::<HashSet<_>>();
49        existing_clients.into_iter().collect()
50    }
51}