Skip to content

Commit

Permalink
Merge pull request #29 from xmtp/nm/update-group-membership-action
Browse files Browse the repository at this point in the history
Update group membership action
  • Loading branch information
nplasterer authored May 24, 2024
2 parents 0239b96 + 8dd6a56 commit 606bf92
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 0 deletions.
20 changes: 20 additions & 0 deletions openmls/src/group/mls_group/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,26 @@ pub enum RemoveMembersError<StorageError> {
StorageError(StorageError),
}

/// Update group membership error
#[derive(Error, Debug, PartialEq, Clone)]
pub enum UpdateGroupMembershipError<StorageError> {
/// See [`LibraryError`] for more details.
#[error(transparent)]
LibraryError(#[from] LibraryError),
/// See [`CreateCommitError`] for more details.
#[error(transparent)]
CreateCommitError(#[from] CreateCommitError<StorageError>),
/// See [`MlsGroupStateError`] for more details.
#[error(transparent)]
GroupStateError(#[from] MlsGroupStateError<StorageError>),
/// The member that should be removed can not be found.
#[error("The member that should be removed can not be found.")]
UnknownMember,
/// Error writing to storage
#[error("Error writing to storage: {0}")]
StorageError(StorageError),
}

/// Leave group error
#[derive(Error, Debug, PartialEq, Clone)]
pub enum LeaveGroupError<StorageError> {
Expand Down
70 changes: 70 additions & 0 deletions openmls/src/group/mls_group/membership.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,77 @@ use crate::{
storage::OpenMlsProvider, treesync::LeafNode,
};

type UpdateResult<Provider> = Result<
(MlsMessageOut, Option<MlsMessageOut>, Option<GroupInfo>),
UpdateGroupMembershipError<<Provider as OpenMlsProvider>::StorageError>,
>;

impl MlsGroup {
/// Updates the group membership using only inline proposals.
/// Adds and removes members and updates the group context.
pub fn update_group_membership<Provider: OpenMlsProvider>(
&mut self,
provider: &Provider,
signer: &impl Signer,
key_packages_to_add: &[KeyPackage],
leaf_nodes_to_remove: &[LeafNodeIndex],
new_extensions: Extensions,
) -> UpdateResult<Provider> {
self.is_operational()?;

// Create inline add proposals from any provided key packages
let add_proposals = key_packages_to_add
.iter()
.map(|key_package| {
Proposal::Add(AddProposal {
key_package: key_package.clone(),
})
})
.collect::<Vec<Proposal>>();

let extensions_proposals = vec![Proposal::GroupContextExtensions(
GroupContextExtensionProposal {
extensions: new_extensions,
},
)];

let mut remove_proposals = Vec::new();
for member in leaf_nodes_to_remove.iter() {
remove_proposals.push(Proposal::Remove(RemoveProposal { removed: *member }))
}

let proposals = [add_proposals, extensions_proposals, remove_proposals].concat();

let params = CreateCommitParams::builder()
.framing_parameters(self.framing_parameters())
.proposal_store(&self.proposal_store)
.inline_proposals(proposals)
.build();
let create_commit_result = self.group.create_commit(params, provider, signer)?;

// Convert PublicMessage messages to MLSMessage and encrypt them if required by
// the configuration
let mls_messages = self.content_to_mls_message(create_commit_result.commit, provider)?;

// Set the current group state to [`MlsGroupState::PendingCommit`],
// storing the current [`StagedCommit`] from the commit results
self.group_state = MlsGroupState::PendingCommit(Box::new(PendingCommitState::Member(
create_commit_result.staged_commit,
)));

provider
.storage()
.write_group_state(self.group_id(), &self.group_state)
.map_err(UpdateGroupMembershipError::StorageError)?;

Ok((
mls_messages,
create_commit_result
.welcome_option
.map(|w| MlsMessageOut::from_welcome(w, self.group.version())),
create_commit_result.group_info,
))
}
/// Adds members to the group.
///
/// New members are added by providing a `KeyPackage` for each member.
Expand Down

0 comments on commit 606bf92

Please sign in to comment.