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}