Adding members to a group
Immediate operation
Members can be added to the group atomically with the .add_members()
function. The application needs to fetch the corresponding key packages from every new member from the Delivery Service first.
let (mls_message_out, welcome, group_info) = alice_group
.add_members(provider, &alice_signature_keys, &[bob_key_package])
.expect("Could not add members.");
The function returns the tuple (MlsMessageOut, Welcome)
. The MlsMessageOut
contains a Commit message that needs to be fanned out to existing group members. The Welcome
message must be sent to the newly added members.
Proposal
Members can also be added as a proposal (without the corresponding Commit message) by using the .propose_add_member()
function:
let (mls_message_out, _proposal_ref) = alice_group
.propose_add_member(provider, &alice_signature_keys, &bob_key_package)
.expect("Could not create proposal to add Bob");
In this case, the function returns an MlsMessageOut
that needs to be fanned out to existing group members.
External proposal
Parties outside the group can also make proposals to add themselves to the group with an external proposal. Since those proposals are crafted by outsiders, they are always plaintext messages.
let proposal = JoinProposal::new(
bob_key_package,
alice_group.group_id().clone(),
alice_group.epoch(),
&bob_signature_keys,
)
.expect("Could not create external Add proposal");
It is then up to the group members to validate the proposal and commit it. Note that in this scenario it is up to the application to define a proper authorization policy to grant the sender.
let alice_processed_message = alice_group
.process_message(
provider,
proposal
.into_protocol_message()
.expect("Unexpected message type."),
)
.expect("Could not process message.");
match alice_processed_message.into_content() {
ProcessedMessageContent::ExternalJoinProposalMessage(proposal) => {
alice_group.store_pending_proposal(*proposal);
let (_commit, welcome, _group_info) = alice_group
.commit_to_pending_proposals(provider, &alice_signature_keys)
.expect("Could not commit");
assert_eq!(alice_group.members().count(), 1);
alice_group
.merge_pending_commit(provider)
.expect("Could not merge commit");
assert_eq!(alice_group.members().count(), 2);
let bob_group = MlsGroup::new_from_welcome(
provider,
mls_group_create_config.join_config(),
welcome
.unwrap()
.into_welcome()
.expect("Unexpected message type."),
None,
)
.expect("Bob could not join the group");
assert_eq!(bob_group.members().count(), 2);
}
_ => unreachable!(),
}