diff --git a/bindings_ffi/src/mls.rs b/bindings_ffi/src/mls.rs index 497d7f49d..bde83c03e 100644 --- a/bindings_ffi/src/mls.rs +++ b/bindings_ffi/src/mls.rs @@ -22,6 +22,7 @@ use xmtp_mls::groups::group_permissions::MetadataBasePolicies; use xmtp_mls::groups::group_permissions::MetadataPolicies; use xmtp_mls::groups::group_permissions::PermissionsBasePolicies; use xmtp_mls::groups::group_permissions::PermissionsPolicies; +use xmtp_mls::groups::group_permissions::PolicySet; use xmtp_mls::groups::intents::PermissionPolicyOption; use xmtp_mls::groups::intents::PermissionUpdateType; use xmtp_mls::groups::GroupMetadataOptions; @@ -389,7 +390,7 @@ pub struct FfiConversations { inner_client: Arc, } -#[derive(uniffi::Enum, Debug)] +#[derive(uniffi::Enum, Clone, Debug)] pub enum FfiGroupPermissionsOptions { AllMembers, AdminOnly, @@ -417,7 +418,7 @@ impl From<&FfiPermissionUpdateType> for PermissionUpdateType { } } -#[derive(uniffi::Enum, Debug, PartialEq, Eq)] +#[derive(uniffi::Enum, Clone, Debug, PartialEq, Eq)] pub enum FfiPermissionPolicy { Allow, Deny, @@ -441,6 +442,49 @@ impl TryInto for FfiPermissionPolicy { } } +impl TryInto for FfiPermissionPolicy { + type Error = GroupMutablePermissionsError; + + fn try_into(self) -> Result { + match self { + FfiPermissionPolicy::Allow => Ok(MembershipPolicies::allow()), + FfiPermissionPolicy::Deny => Ok(MembershipPolicies::deny()), + FfiPermissionPolicy::Admin => Ok(MembershipPolicies::allow_if_actor_admin()), + FfiPermissionPolicy::SuperAdmin => Ok(MembershipPolicies::allow_if_actor_super_admin()), + _ => Err(GroupMutablePermissionsError::InvalidPermissionPolicyOption), + } + } +} + +impl TryInto for FfiPermissionPolicy { + type Error = GroupMutablePermissionsError; + + fn try_into(self) -> Result { + match self { + FfiPermissionPolicy::Allow => Ok(MetadataPolicies::allow()), + FfiPermissionPolicy::Deny => Ok(MetadataPolicies::deny()), + FfiPermissionPolicy::Admin => Ok(MetadataPolicies::allow_if_actor_admin()), + FfiPermissionPolicy::SuperAdmin => Ok(MetadataPolicies::allow_if_actor_super_admin()), + _ => Err(GroupMutablePermissionsError::InvalidPermissionPolicyOption), + } + } +} + +impl TryInto for FfiPermissionPolicy { + type Error = GroupMutablePermissionsError; + + fn try_into(self) -> Result { + match self { + FfiPermissionPolicy::Deny => Ok(PermissionsPolicies::deny()), + FfiPermissionPolicy::Admin => Ok(PermissionsPolicies::allow_if_actor_admin()), + FfiPermissionPolicy::SuperAdmin => { + Ok(PermissionsPolicies::allow_if_actor_super_admin()) + } + _ => Err(GroupMutablePermissionsError::InvalidPermissionPolicyOption), + } + } +} + impl From<&MembershipPolicies> for FfiPermissionPolicy { fn from(policies: &MembershipPolicies) -> Self { if let MembershipPolicies::Standard(base_policy) = policies { @@ -488,7 +532,7 @@ impl From<&PermissionsPolicies> for FfiPermissionPolicy { } } -#[derive(uniffi::Record, Debug, PartialEq, Eq)] +#[derive(uniffi::Record, Clone, Debug, PartialEq, Eq)] pub struct FfiPermissionPolicySet { pub add_member_policy: FfiPermissionPolicy, pub remove_member_policy: FfiPermissionPolicy, @@ -509,6 +553,38 @@ impl From for FfiGroupPermissionsOptions { } } +impl TryFrom for PolicySet { + type Error = GroupMutablePermissionsError; + fn try_from(policy_set: FfiPermissionPolicySet) -> Result { + let mut metadata_permissions_map: HashMap = HashMap::new(); + metadata_permissions_map.insert( + MetadataField::GroupName.to_string(), + policy_set.update_group_name_policy.try_into()?, + ); + metadata_permissions_map.insert( + MetadataField::Description.to_string(), + policy_set.update_group_description_policy.try_into()?, + ); + metadata_permissions_map.insert( + MetadataField::GroupImageUrlSquare.to_string(), + policy_set.update_group_image_url_square_policy.try_into()?, + ); + metadata_permissions_map.insert( + MetadataField::GroupPinnedFrameUrl.to_string(), + policy_set.update_group_pinned_frame_url_policy.try_into()?, + ); + + Ok(PolicySet { + add_member_policy: policy_set.add_member_policy.try_into()?, + remove_member_policy: policy_set.remove_member_policy.try_into()?, + add_admin_policy: policy_set.add_admin_policy.try_into()?, + remove_admin_policy: policy_set.remove_admin_policy.try_into()?, + update_metadata_policy: metadata_permissions_map, + update_permissions_policy: PermissionsPolicies::allow_if_actor_super_admin(), + }) + } +} + #[derive(uniffi::Enum, Debug)] pub enum FfiMetadataField { GroupName, @@ -540,19 +616,40 @@ impl FfiConversations { account_addresses.join(", ") ); + if let Some(FfiGroupPermissionsOptions::CustomPolicy) = opts.permissions { + if opts.custom_permission_policy_set.is_none() { + return Err(GenericError::Generic { + err: "CustomPolicy must include policy set".to_string(), + }); + } + } else if opts.custom_permission_policy_set.is_some() { + return Err(GenericError::Generic { + err: "Only CustomPolicy may specify a policy set".to_string(), + }); + } + + let metadata_options = opts.clone().into_group_metadata_options(); + let group_permissions = match opts.permissions { Some(FfiGroupPermissionsOptions::AllMembers) => { - Some(xmtp_mls::groups::PreconfiguredPolicies::AllMembers) + Some(xmtp_mls::groups::PreconfiguredPolicies::AllMembers.to_policy_set()) } Some(FfiGroupPermissionsOptions::AdminOnly) => { - Some(xmtp_mls::groups::PreconfiguredPolicies::AdminsOnly) + Some(xmtp_mls::groups::PreconfiguredPolicies::AdminsOnly.to_policy_set()) + } + Some(FfiGroupPermissionsOptions::CustomPolicy) => { + if let Some(policy_set) = opts.custom_permission_policy_set { + Some(policy_set.try_into()?) + } else { + None + } } _ => None, }; let convo = self .inner_client - .create_group(group_permissions, opts.into_group_metadata_options())?; + .create_group(group_permissions, metadata_options)?; if !account_addresses.is_empty() { convo .add_members(&self.inner_client, account_addresses) @@ -672,13 +769,14 @@ pub struct FfiListMessagesOptions { pub delivery_status: Option, } -#[derive(uniffi::Record, Default)] +#[derive(uniffi::Record, Clone, Default)] pub struct FfiCreateGroupOptions { pub permissions: Option, pub group_name: Option, pub group_image_url_square: Option, pub group_description: Option, pub group_pinned_frame_url: Option, + pub custom_permission_policy_set: Option, } impl FfiCreateGroupOptions { @@ -1986,6 +2084,7 @@ mod tests { group_image_url_square: Some("url".to_string()), group_description: Some("group description".to_string()), group_pinned_frame_url: Some("pinned frame".to_string()), + custom_permission_policy_set: None, }, ) .await @@ -2568,4 +2667,220 @@ mod tests { ); assert_eq!(alix_group.group_name().unwrap(), ""); } + + #[tokio::test(flavor = "multi_thread", worker_threads = 5)] + async fn test_group_creation_custom_permissions() { + let alix = new_test_client().await; + let bola = new_test_client().await; + + let custom_permissions = FfiPermissionPolicySet { + add_admin_policy: FfiPermissionPolicy::Admin, + remove_admin_policy: FfiPermissionPolicy::Admin, + update_group_name_policy: FfiPermissionPolicy::Admin, + update_group_description_policy: FfiPermissionPolicy::Allow, + update_group_image_url_square_policy: FfiPermissionPolicy::Admin, + update_group_pinned_frame_url_policy: FfiPermissionPolicy::Admin, + add_member_policy: FfiPermissionPolicy::Allow, + remove_member_policy: FfiPermissionPolicy::Deny, + }; + + let create_group_options = FfiCreateGroupOptions { + permissions: Some(FfiGroupPermissionsOptions::CustomPolicy), + group_name: Some("Test Group".to_string()), + group_image_url_square: Some("https://example.com/image.png".to_string()), + group_description: Some("A test group".to_string()), + group_pinned_frame_url: Some("https://example.com/frame.png".to_string()), + custom_permission_policy_set: Some(custom_permissions), + }; + + let alix_group = alix + .conversations() + .create_group(vec![bola.account_address.clone()], create_group_options) + .await + .unwrap(); + + // Verify the group was created with the correct permissions + let group_permissions_policy_set = alix_group + .group_permissions() + .unwrap() + .policy_set() + .unwrap(); + assert_eq!( + group_permissions_policy_set.add_admin_policy, + FfiPermissionPolicy::Admin + ); + assert_eq!( + group_permissions_policy_set.remove_admin_policy, + FfiPermissionPolicy::Admin + ); + assert_eq!( + group_permissions_policy_set.update_group_name_policy, + FfiPermissionPolicy::Admin + ); + assert_eq!( + group_permissions_policy_set.update_group_description_policy, + FfiPermissionPolicy::Allow + ); + assert_eq!( + group_permissions_policy_set.update_group_image_url_square_policy, + FfiPermissionPolicy::Admin + ); + assert_eq!( + group_permissions_policy_set.update_group_pinned_frame_url_policy, + FfiPermissionPolicy::Admin + ); + assert_eq!( + group_permissions_policy_set.add_member_policy, + FfiPermissionPolicy::Allow + ); + assert_eq!( + group_permissions_policy_set.remove_member_policy, + FfiPermissionPolicy::Deny + ); + + // Verify that Bola can not update the group name + let bola_conversations = bola.conversations(); + let _ = bola_conversations.sync().await; + let bola_groups = bola_conversations + .list(crate::FfiListConversationsOptions { + created_after_ns: None, + created_before_ns: None, + limit: None, + }) + .await + .unwrap(); + + let bola_group = bola_groups.first().unwrap(); + bola_group + .update_group_name("new_name".to_string()) + .await + .unwrap_err(); + let result = bola_group + .update_group_name("New Group Name".to_string()) + .await; + assert!(result.is_err()); + + // Verify that Alix can update the group name + let result = alix_group + .update_group_name("New Group Name".to_string()) + .await; + assert!(result.is_ok()); + + // Verify that Bola can update the group description + let result = bola_group + .update_group_description("New Description".to_string()) + .await; + assert!(result.is_ok()); + + // Verify that Alix can not remove bola even though they are a super admin + let result = alix_group + .remove_members(vec![bola.account_address.clone()]) + .await; + assert!(result.is_err()); + } + + #[tokio::test(flavor = "multi_thread", worker_threads = 5)] + async fn test_group_creation_custom_permissions_fails_when_invalid() { + let alix = new_test_client().await; + let bola = new_test_client().await; + + // Add / Remove Admin must be Admin or Super Admin or Deny + let custom_permissions_invalid_1 = FfiPermissionPolicySet { + add_admin_policy: FfiPermissionPolicy::Allow, + remove_admin_policy: FfiPermissionPolicy::Admin, + update_group_name_policy: FfiPermissionPolicy::Admin, + update_group_description_policy: FfiPermissionPolicy::Allow, + update_group_image_url_square_policy: FfiPermissionPolicy::Admin, + update_group_pinned_frame_url_policy: FfiPermissionPolicy::Admin, + add_member_policy: FfiPermissionPolicy::Allow, + remove_member_policy: FfiPermissionPolicy::Deny, + }; + + let custom_permissions_valid = FfiPermissionPolicySet { + add_admin_policy: FfiPermissionPolicy::Admin, + remove_admin_policy: FfiPermissionPolicy::Admin, + update_group_name_policy: FfiPermissionPolicy::Admin, + update_group_description_policy: FfiPermissionPolicy::Allow, + update_group_image_url_square_policy: FfiPermissionPolicy::Admin, + update_group_pinned_frame_url_policy: FfiPermissionPolicy::Admin, + add_member_policy: FfiPermissionPolicy::Allow, + remove_member_policy: FfiPermissionPolicy::Deny, + }; + + let create_group_options_invalid_1 = FfiCreateGroupOptions { + permissions: Some(FfiGroupPermissionsOptions::CustomPolicy), + group_name: Some("Test Group".to_string()), + group_image_url_square: Some("https://example.com/image.png".to_string()), + group_description: Some("A test group".to_string()), + group_pinned_frame_url: Some("https://example.com/frame.png".to_string()), + custom_permission_policy_set: Some(custom_permissions_invalid_1), + }; + + let results_1 = alix + .conversations() + .create_group( + vec![bola.account_address.clone()], + create_group_options_invalid_1, + ) + .await; + + assert!(results_1.is_err()); + + let create_group_options_invalid_2 = FfiCreateGroupOptions { + permissions: Some(FfiGroupPermissionsOptions::AllMembers), + group_name: Some("Test Group".to_string()), + group_image_url_square: Some("https://example.com/image.png".to_string()), + group_description: Some("A test group".to_string()), + group_pinned_frame_url: Some("https://example.com/frame.png".to_string()), + custom_permission_policy_set: Some(custom_permissions_valid.clone()), + }; + + let results_2 = alix + .conversations() + .create_group( + vec![bola.account_address.clone()], + create_group_options_invalid_2, + ) + .await; + + assert!(results_2.is_err()); + + let create_group_options_invalid_3 = FfiCreateGroupOptions { + permissions: None, + group_name: Some("Test Group".to_string()), + group_image_url_square: Some("https://example.com/image.png".to_string()), + group_description: Some("A test group".to_string()), + group_pinned_frame_url: Some("https://example.com/frame.png".to_string()), + custom_permission_policy_set: Some(custom_permissions_valid.clone()), + }; + + let results_3 = alix + .conversations() + .create_group( + vec![bola.account_address.clone()], + create_group_options_invalid_3, + ) + .await; + + assert!(results_3.is_err()); + + let create_group_options_valid = FfiCreateGroupOptions { + permissions: Some(FfiGroupPermissionsOptions::CustomPolicy), + group_name: Some("Test Group".to_string()), + group_image_url_square: Some("https://example.com/image.png".to_string()), + group_description: Some("A test group".to_string()), + group_pinned_frame_url: Some("https://example.com/frame.png".to_string()), + custom_permission_policy_set: Some(custom_permissions_valid), + }; + + let results_4 = alix + .conversations() + .create_group( + vec![bola.account_address.clone()], + create_group_options_valid, + ) + .await; + + assert!(results_4.is_ok()); + } } diff --git a/bindings_node/src/conversations.rs b/bindings_node/src/conversations.rs index 8f167e22f..21a5dae60 100644 --- a/bindings_node/src/conversations.rs +++ b/bindings_node/src/conversations.rs @@ -68,8 +68,12 @@ impl NapiConversations { }; let group_permissions = match options.permissions { - Some(NapiGroupPermissionsOptions::AllMembers) => Some(PreconfiguredPolicies::AllMembers), - Some(NapiGroupPermissionsOptions::AdminOnly) => Some(PreconfiguredPolicies::AdminsOnly), + Some(NapiGroupPermissionsOptions::AllMembers) => { + Some(PreconfiguredPolicies::AllMembers.to_policy_set()) + } + Some(NapiGroupPermissionsOptions::AdminOnly) => { + Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()) + } _ => None, }; diff --git a/examples/cli/cli-client.rs b/examples/cli/cli-client.rs index 14713aafb..ccc9f4d80 100755 --- a/examples/cli/cli-client.rs +++ b/examples/cli/cli-client.rs @@ -314,7 +314,10 @@ async fn main() { .unwrap(); let group = client - .create_group(Some(group_permissions), GroupMetadataOptions::default()) + .create_group( + Some(group_permissions.to_policy_set()), + GroupMetadataOptions::default(), + ) .expect("failed to create group"); let group_id = hex::encode(group.group_id); info!("Created group {}", group_id, { command_output: true, group_id: group_id}) diff --git a/xmtp_mls/src/client.rs b/xmtp_mls/src/client.rs index f201bf2fa..fc9270c29 100644 --- a/xmtp_mls/src/client.rs +++ b/xmtp_mls/src/client.rs @@ -33,8 +33,8 @@ use xmtp_proto::xmtp::mls::api::v1::{ use crate::{ api::ApiClientWrapper, groups::{ - validated_commit::CommitValidationError, GroupError, GroupMetadataOptions, IntentError, - MlsGroup, PreconfiguredPolicies, + group_permissions::PolicySet, validated_commit::CommitValidationError, GroupError, + GroupMetadataOptions, IntentError, MlsGroup, }, identity::{parse_credential, Identity, IdentityError}, identity_updates::IdentityUpdateError, @@ -331,7 +331,7 @@ where /// Create a new group with the default settings pub fn create_group( &self, - permissions: Option, + permissions_policy_set: Option, opts: GroupMetadataOptions, ) -> Result { log::info!("creating group"); @@ -339,7 +339,7 @@ where let group = MlsGroup::create_and_insert( self.context.clone(), GroupMembershipState::Allowed, - permissions, + permissions_policy_set.unwrap_or_default(), opts, ) .map_err(Box::new)?; diff --git a/xmtp_mls/src/groups/group_permissions.rs b/xmtp_mls/src/groups/group_permissions.rs index 90df943ff..443ef9bc2 100644 --- a/xmtp_mls/src/groups/group_permissions.rs +++ b/xmtp_mls/src/groups/group_permissions.rs @@ -1100,6 +1100,11 @@ pub(crate) fn policy_admin_only() -> PolicySet { PermissionsPolicies::allow_if_actor_super_admin(), ) } +impl Default for PolicySet { + fn default() -> Self { + PreconfiguredPolicies::default().to_policy_set() + } +} #[derive(Debug, Clone, PartialEq, Default)] pub enum PreconfiguredPolicies { diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index 2757158f1..fab5e49df 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -259,7 +259,7 @@ impl MlsGroup { pub fn create_and_insert( context: Arc, membership_state: GroupMembershipState, - permissions: Option, + permissions_policy_set: PolicySet, opts: GroupMetadataOptions, ) -> Result { let conn = context.store.conn()?; @@ -268,8 +268,7 @@ impl MlsGroup { build_protected_metadata_extension(&context.identity, Purpose::Conversation)?; let mutable_metadata = build_mutable_metadata_extension_default(&context.identity, opts)?; let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); - let mutable_permissions = - build_mutable_permissions_extension(permissions.unwrap_or_default().to_policy_set())?; + let mutable_permissions = build_mutable_permissions_extension(permissions_policy_set)?; let group_config = build_group_config( protected_metadata, mutable_metadata, @@ -1827,7 +1826,7 @@ mod tests { let amal_group = amal .create_group( - Some(PreconfiguredPolicies::AdminsOnly), + Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()), GroupMetadataOptions::default(), ) .unwrap(); @@ -1893,7 +1892,7 @@ mod tests { let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; let amal_group = amal .create_group( - Some(PreconfiguredPolicies::AdminsOnly), + Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()), GroupMetadataOptions::default(), ) .unwrap(); @@ -1918,9 +1917,9 @@ mod tests { let bola = ClientBuilder::new_test_client(&generate_local_wallet()).await; // Create a group and verify it has the default group name - let policies = Some(PreconfiguredPolicies::AdminsOnly); + let policy_set = Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()); let amal_group: MlsGroup = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -1999,9 +1998,9 @@ mod tests { let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; // Create a group and verify it has the default group name - let policies = Some(PreconfiguredPolicies::AdminsOnly); + let policy_set = Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()); let amal_group: MlsGroup = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -2033,9 +2032,9 @@ mod tests { let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; // Create a group and verify it has the default group name - let policies = Some(PreconfiguredPolicies::AdminsOnly); + let policy_set = Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()); let amal_group: MlsGroup = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -2069,9 +2068,9 @@ mod tests { let bola = ClientBuilder::new_test_client(&bola_wallet).await; // Create a group and verify it has the default group name - let policies = Some(PreconfiguredPolicies::AllMembers); + let policy_set = Some(PreconfiguredPolicies::AllMembers.to_policy_set()); let amal_group: MlsGroup = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -2147,9 +2146,9 @@ mod tests { let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; let charlie = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let policies = Some(PreconfiguredPolicies::AdminsOnly); + let policy_set = Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()); let amal_group = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -2235,9 +2234,9 @@ mod tests { let bola = ClientBuilder::new_test_client(&generate_local_wallet()).await; let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let policies = Some(PreconfiguredPolicies::AdminsOnly); + let policy_set = Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()); let amal_group = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -2323,9 +2322,9 @@ mod tests { let bola = ClientBuilder::new_test_client(&generate_local_wallet()).await; let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let policies = Some(PreconfiguredPolicies::AdminsOnly); + let policy_set = Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()); let amal_group = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -2457,9 +2456,9 @@ mod tests { #[tokio::test] async fn test_can_read_group_creator_inbox_id() { let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let policies = Some(PreconfiguredPolicies::AllMembers); + let policy_set = Some(PreconfiguredPolicies::AllMembers.to_policy_set()); let amal_group = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -2480,9 +2479,9 @@ mod tests { async fn test_can_update_gce_after_failed_commit() { // Step 1: Amal creates a group let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let policies = Some(PreconfiguredPolicies::AllMembers); + let policy_set = Some(PreconfiguredPolicies::AllMembers.to_policy_set()); let amal_group = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); amal_group.sync(&amal).await.unwrap(); @@ -2539,9 +2538,9 @@ mod tests { #[tokio::test] async fn test_can_update_permissions_after_group_creation() { let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let policies = Some(PreconfiguredPolicies::AdminsOnly); + let policy_set = Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()); let amal_group: MlsGroup = amal - .create_group(policies, GroupMetadataOptions::default()) + .create_group(policy_set, GroupMetadataOptions::default()) .unwrap(); // Step 2: Amal adds Bola to the group