1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
// Copyright (c) 2024 Mozilla Corporation and contributors.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
use mls_platform_api::MessageOrAck;
use mls_platform_api::PlatformError;
//
// Scenario
//
// * Alice, Bob and Charlie create signing identity (generate_signature_keypair)
// * Alice, Bob and Charlie create credentials (generate_credential_basic)
// * Bob and Charlie create key packages (generate_key_package)
// * Alice creates a group (group_create)
// * Alice proposes to add Bob to the group (group_propose_add)
// - Alice decides to clear the proposal
// * Alice can propose to add Charlie to the group
#[test]
fn test_clear_pending_proposals() -> Result<(), PlatformError> {
// Default group configuration
let group_config = mls_platform_api::GroupConfig::default();
// Storage states
let mut state_global = mls_platform_api::state_access("global.db", &[0u8; 32])?;
// Credentials
let alice_cred = mls_platform_api::mls_generate_credential_basic("alice".as_bytes())?;
let bob_cred = mls_platform_api::mls_generate_credential_basic("bob".as_bytes())?;
let charlie_cred = mls_platform_api::mls_generate_credential_basic("charlie".as_bytes())?;
println!("\nAlice credential: {}", hex::encode(&alice_cred));
println!("Bob credential: {}", hex::encode(&bob_cred));
println!("Charlie credential: {}", hex::encode(&charlie_cred));
// Create signature keypairs and store them in the state
let alice_id =
mls_platform_api::mls_generate_identity(&state_global, group_config.ciphersuite)?;
let bob_id = mls_platform_api::mls_generate_identity(&state_global, group_config.ciphersuite)?;
let charlie_id =
mls_platform_api::mls_generate_identity(&state_global, group_config.ciphersuite)?;
println!("\nAlice identifier: {}", hex::encode(&alice_id));
println!("Bob identifier: {}", hex::encode(&bob_id));
println!("Charlie identifier: {}", hex::encode(&charlie_id));
// Create Key Package for Bob
let bob_kp = mls_platform_api::mls_generate_key_package(
&state_global,
&bob_id,
&bob_cred,
&Default::default(),
)?;
// Create Key Package for Charlie
let charlie_kp = mls_platform_api::mls_generate_key_package(
&state_global,
&charlie_id,
&charlie_cred,
&Default::default(),
)?;
// Create a group with Alice
let gide = mls_platform_api::mls_group_create(
&mut state_global,
&alice_id,
&alice_cred,
None,
None,
&Default::default(),
)?;
println!("\nGroup created by Alice: {}", hex::encode(&gide.group_id));
// List the members of the group
let members = mls_platform_api::mls_group_details(&state_global, &gide.group_id, &alice_id)?;
println!("Members (alice, before adding bob): {members:?}");
//
// Alice proposes to add Bob to the group
//
println!("\nAlice proposes to add Bob to the Group");
let _commit_output = mls_platform_api::mls_group_propose_add(
&mut state_global,
&gide.group_id,
&alice_id,
bob_kp,
)?;
// Check if there's a pending proposal
let pending =
mls_platform_api::mls_has_pending_proposals(&state_global, &gide.group_id, &alice_id)?;
assert!(pending);
println!("\nAlice proposes to add Charlie to the Group");
let _commit_output = mls_platform_api::mls_group_propose_add(
&mut state_global,
&gide.group_id,
&alice_id,
charlie_kp.clone(),
)?;
// Check if there's a pending proposal
let pending =
mls_platform_api::mls_has_pending_proposals(&state_global, &gide.group_id, &alice_id)?;
assert!(pending);
// Try to add Charlie while there's a pending proposal - should fail
println!("\nAlice tries to add Charlie while there's a pending proposal");
let result = mls_platform_api::mls_group_add(
&mut state_global,
&gide.group_id,
&alice_id,
vec![charlie_kp.clone()],
);
// Verify we get an error
assert!(result.is_err());
println!("Got expected error when trying to add because of pending proposal: {result:?}");
// Discard the pending proposal
println!("\nAlice discards the pending proposal");
mls_platform_api::mls_clear_pending_proposals(&mut state_global, &gide.group_id, &alice_id)?;
// Check if there's a pending proposal again
let pending =
mls_platform_api::mls_has_pending_proposals(&state_global, &gide.group_id, &alice_id)?;
assert!(!pending);
// Alice can now add Charlie to the group
println!("\nAlice adds Charlie to the Group");
let commit_output = mls_platform_api::mls_group_add(
&mut state_global,
&gide.group_id,
&alice_id,
vec![charlie_kp.clone()],
)?;
// Alice process her own commit
println!("\nAlice process her commit to add Bob to the Group");
mls_platform_api::mls_receive(
&state_global,
&alice_id,
&MessageOrAck::MlsMessage(commit_output.commit),
)?;
// List the members of the group
let members = mls_platform_api::mls_group_details(&state_global, &gide.group_id, &alice_id)?;
println!("Members (alice, after adding charlie): {members:?}");
Ok(())
}
|