Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update group membership action #29

Merged
merged 4 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading