openmls/messages/
external_proposals.rs

1//! External Proposals
2//!
3//! Contains the types and methods to build external proposal to add/remove a client from a MLS group
4//!
5//! `Add` (from external sender), `Remove` & `ReInit are not yet implemented`
6
7use crate::{
8    binary_tree::LeafNodeIndex,
9    extensions::SenderExtensionIndex,
10    framing::{mls_auth_content::AuthenticatedContent, MlsMessageOut, PublicMessage},
11    group::{
12        errors::ProposeRemoveMemberError, mls_group::errors::ProposeAddMemberError, GroupEpoch,
13        GroupId,
14    },
15    key_packages::KeyPackage,
16    messages::{AddProposal, Proposal},
17    storage::{OpenMlsProvider, StorageProvider},
18};
19use openmls_traits::signatures::Signer;
20
21use super::proposals::RemoveProposal;
22
23/// External Add Proposal where sender is [NewMemberProposal](crate::prelude::Sender::NewMemberProposal). A client
24/// outside the group can request joining the group. This proposal should then be committed by a
25/// group member. Note that this is unconstrained i.e. it works for any [MLS group](crate::group::MlsGroup).
26/// This is not the case for the same external proposal with a [Preconfigured sender](crate::prelude::Sender::External)
27pub struct JoinProposal;
28
29/// External Proposal where sender is [External](crate::prelude::Sender::External). A party
30/// outside the group can request to add or remove a member to the group. This proposal should then
31/// be committed by a group member. The sender must be pre configured within the group through the [crate::extensions::ExternalSendersExtension]
32pub struct ExternalProposal;
33
34impl JoinProposal {
35    /// Creates an external Add proposal. For clients requesting to be added to a group. This
36    /// proposal will have to be committed later by a group member.
37    ///
38    /// # Arguments
39    /// * `key_package` - of the joiner
40    /// * `group_id` - unique group identifier of the group to join
41    /// * `epoch` - group's epoch
42    /// * `signer` - of the sender to sign the message
43    #[allow(clippy::new_ret_no_self)]
44    pub fn new<Storage: StorageProvider>(
45        key_package: KeyPackage,
46        group_id: GroupId,
47        epoch: GroupEpoch,
48        signer: &impl Signer,
49    ) -> Result<MlsMessageOut, ProposeAddMemberError<Storage::Error>> {
50        AuthenticatedContent::new_join_proposal(
51            Proposal::Add(AddProposal { key_package }),
52            group_id,
53            epoch,
54            signer,
55        )
56        .map(PublicMessage::from)
57        .map(MlsMessageOut::from)
58        .map_err(ProposeAddMemberError::from)
59    }
60}
61
62impl ExternalProposal {
63    /// Creates an external Remove proposal. For delivery services requesting to remove a client.
64    /// This proposal will have to be committed later by a group member.
65    ///
66    /// # Arguments
67    /// * `removed` - index of the client to remove
68    /// * `group_id` - unique group identifier of the group to join
69    /// * `epoch` - group's epoch
70    /// * `signer` - of the sender to sign the message
71    /// * `sender` - index of the sender of the proposal (in the [crate::extensions::ExternalSendersExtension] array
72    ///   from the Group Context)
73    pub fn new_remove<Provider: OpenMlsProvider>(
74        removed: LeafNodeIndex,
75        group_id: GroupId,
76        epoch: GroupEpoch,
77        signer: &impl Signer,
78        sender_index: SenderExtensionIndex,
79    ) -> Result<MlsMessageOut, ProposeRemoveMemberError<Provider::StorageError>> {
80        AuthenticatedContent::new_external_proposal(
81            Proposal::Remove(RemoveProposal { removed }),
82            group_id,
83            epoch,
84            signer,
85            sender_index,
86        )
87        .map(PublicMessage::from)
88        .map(MlsMessageOut::from)
89        .map_err(ProposeRemoveMemberError::from)
90    }
91
92    /// Creates an external Add proposal. For delivery services requesting to add a client.
93    /// This proposal will have to be committed later by a group member.
94    ///
95    /// # Arguments
96    /// * `key_package` - key package of the client to add
97    /// * `group_id` - unique group identifier of the group to join
98    /// * `epoch` - group's epoch
99    /// * `signer` - of the sender to sign the message
100    /// * `sender` - index of the sender of the proposal (in the [crate::extensions::ExternalSendersExtension] array
101    ///   from the Group Context)
102    pub fn new_add<Provider: OpenMlsProvider>(
103        key_package: KeyPackage,
104        group_id: GroupId,
105        epoch: GroupEpoch,
106        signer: &impl Signer,
107        sender_index: SenderExtensionIndex,
108    ) -> Result<MlsMessageOut, ProposeAddMemberError<Provider::StorageError>> {
109        AuthenticatedContent::new_external_proposal(
110            Proposal::Add(AddProposal { key_package }),
111            group_id,
112            epoch,
113            signer,
114            sender_index,
115        )
116        .map(PublicMessage::from)
117        .map(MlsMessageOut::from)
118        .map_err(ProposeAddMemberError::from)
119    }
120}