diff --git a/src/canister_tests/src/api/internet_identity/api_v2.rs b/src/canister_tests/src/api/internet_identity/api_v2.rs index 185cee59fe..5d58e63762 100644 --- a/src/canister_tests/src/api/internet_identity/api_v2.rs +++ b/src/canister_tests/src/api/internet_identity/api_v2.rs @@ -7,7 +7,7 @@ use std::collections::HashMap; pub fn captcha_create( env: &StateMachine, canister_id: CanisterId, -) -> Result, CallError> { +) -> Result, CallError> { call_candid(env, canister_id, "captcha_create", ()).map(|(x,)| x) } @@ -18,7 +18,7 @@ pub fn identity_register( authn_method: &AuthnMethodData, challenge_attempt: &ChallengeAttempt, temp_key: Option, -) -> Result, CallError> { +) -> Result, CallError> { call_candid_as( env, canister_id, @@ -34,7 +34,7 @@ pub fn identity_info( canister_id: CanisterId, sender: Principal, identity_number: IdentityNumber, -) -> Result, CallError> { +) -> Result, CallError> { call_candid_as( env, canister_id, @@ -51,7 +51,7 @@ pub fn identity_metadata_replace( sender: Principal, identity_number: IdentityNumber, metadata: &HashMap, -) -> Result, CallError> { +) -> Result, CallError> { call_candid_as( env, canister_id, @@ -68,7 +68,7 @@ pub fn authn_method_add( sender: Principal, identity_number: IdentityNumber, authn_method: &AuthnMethodData, -) -> Result, CallError> { +) -> Result, CallError> { call_candid_as( env, canister_id, @@ -85,7 +85,7 @@ pub fn authn_method_remove( sender: Principal, identity_number: IdentityNumber, public_key: &PublicKey, -) -> Result, CallError> { +) -> Result, CallError> { call_candid_as( env, canister_id, diff --git a/src/canister_tests/src/framework.rs b/src/canister_tests/src/framework.rs index c7c141da4e..8aa0a21162 100644 --- a/src/canister_tests/src/framework.rs +++ b/src/canister_tests/src/framework.rs @@ -684,27 +684,3 @@ pub fn test_principal(n: u64) -> Principal { bytes.push(0xfe); // internal marker for user test ids Principal::from_slice(&bytes[..]) } - -/// Macro to easily match a value against a pattern, and panic if the match fails. -/// -/// This makes API v2 return types easier to handle. -/// API v2 calls all return variants, requiring a match on the result. -/// This macro allows to write the match in terms of the expected variant, with a fallback -/// on unexpected variants. -/// Example: -/// ``` -/// use canister_tests::match_value; -/// match_value!( -/// api_v2::identity_info(&env, canister_id, principal, identity_number)?, // value -/// Some(IdentityInfoResponse::Ok(identity_info)) // expected pattern, with binding to identity_info -/// ); -/// ``` -#[macro_export] -#[rustfmt::skip] // cargo fmt seems to have a bug with this macro (it indents the panic! way too far) -macro_rules! match_value { - ($target: expr, $pat: pat_param) => { - let $pat = $target else { - panic!("expected {}", stringify!($pat)); - }; - }; -} diff --git a/src/internet_identity/internet_identity.did b/src/internet_identity/internet_identity.did index 8d6ff6e46f..5c2ac2490d 100644 --- a/src/internet_identity/internet_identity.did +++ b/src/internet_identity/internet_identity.did @@ -313,16 +313,16 @@ type PublicKeyAuthn = record { // The authentication methods currently supported by II. type AuthnMethod = variant { - webauthn: WebAuthn; - pubkey: PublicKeyAuthn; + WebAuthn: WebAuthn; + Puubkey: PublicKeyAuthn; }; // This describes whether an authentication method is "protected" or not. // When protected, a authentication method can only be updated or removed if the // user is authenticated with that very authentication method. type AuthnMethodProtection = variant { - protected; - unprotected; + Protected; + Unprotected; }; type AuthnMethodData = record { @@ -358,36 +358,17 @@ type IdentityInfo = record { metadata: MetadataMap; }; -type CaptchaCreateResponse = variant { - ok: Challenge; -}; - -type IdentityRegisterResponse = variant { - // Registration successful. - ok: IdentityNumber; +type IdentityRegisterError = variant { // No more registrations are possible in this instance of the II service canister. - canister_full; + CanisterFull; // The captcha check was not successful. - bad_captcha; + BadCaptcha; // The metadata of the provided authentication method contains invalid entries. - invalid_metadata: text; -}; - -type IdentityInfoResponse = variant { - ok: IdentityInfo; -}; - -type AuthnMethodAddResponse = variant { - ok; - invalid_metadata: text; -}; - -type AuthnMethodRemoveResponse = variant { - ok; + InvalidMetadata: text; }; -type IdentityMetadataReplaceResponse = variant { - ok; +type AuthnMethodAddError = variant { + InvalidMetadata: text; }; type PrepareIdAliasRequest = record { @@ -482,36 +463,35 @@ service : (opt InternetIdentityInit) -> { // WARNING: The following methods are experimental and may change in the future. // // Note: the responses of v2 API calls are `opt` for compatibility reasons - // with future variant extensions. - // A client decoding a response as `null` indicates outdated type information - // and should be treated as an error. + // while the API is still in development (there will breaking changes). + // When the API is stable, the `opt` will be removed. // Creates a new captcha. The solution needs to be submitted using the // `identity_register` call. - captcha_create: () -> (opt CaptchaCreateResponse); + captcha_create: () -> (opt variant {Ok: Challenge; Err;}); // Registers a new identity with the given authn_method. // A valid captcha solution to a previously generated captcha (using create_captcha) must be provided. // The sender needs to match the supplied authn_method. - identity_register: (AuthnMethodData, CaptchaResult, opt principal) -> (opt IdentityRegisterResponse); + identity_register: (AuthnMethodData, CaptchaResult, opt principal) -> (opt variant {Ok: IdentityNumber; Err: IdentityRegisterError;}); // Returns information about the identity with the given number. // Requires authentication. - identity_info: (IdentityNumber) -> (opt IdentityInfoResponse); + identity_info: (IdentityNumber) -> (opt variant {Ok: IdentityInfo; Err;}); // Replaces the authentication method independent metadata map. // The existing metadata map will be overwritten. // Requires authentication. - identity_metadata_replace: (IdentityNumber, MetadataMap) -> (opt IdentityMetadataReplaceResponse); + identity_metadata_replace: (IdentityNumber, MetadataMap) -> (opt variant {Ok; Err;}); // Adds a new authentication method to the identity. // Requires authentication. - authn_method_add: (IdentityNumber, AuthnMethodData) -> (opt AuthnMethodAddResponse); + authn_method_add: (IdentityNumber, AuthnMethodData) -> (opt variant {Ok; Err: AuthnMethodAddError;}); // Removes the authentication method associated with the public key from the identity. // Requires authentication. - authn_method_remove: (IdentityNumber, PublicKey) -> (opt AuthnMethodRemoveResponse); + authn_method_remove: (IdentityNumber, PublicKey) -> (opt variant {Ok; Err;}); // Attribute Sharing MVP API // The methods below are used to generate ID-alias credentials during attribute sharing flow. diff --git a/src/internet_identity/src/main.rs b/src/internet_identity/src/main.rs index e383db6581..51ede20541 100644 --- a/src/internet_identity/src/main.rs +++ b/src/internet_identity/src/main.rs @@ -511,8 +511,7 @@ fn check_authentication(anchor_number: AnchorNumber) -> Result<(Anchor, DeviceKe /// New v2 API that aims to eventually replace the current API. /// The v2 API: /// * uses terminology more aligned with the front-end and is more consistent in its naming. -/// * uses opt variant return types consistently in order to by able to extend / change return types -/// in the future without breaking changes. +/// * uses [Result] return types consistently. /// /// TODO, API v2 rollout plan: /// 1. Develop API v2 far enough so that front-ends can switch to it. @@ -525,9 +524,9 @@ mod v2_api { #[update] #[candid_method] - async fn captcha_create() -> Option { + async fn captcha_create() -> Option> { let challenge = anchor_management::registration::create_challenge().await; - Some(CaptchaCreateResponse::Ok(challenge)) + Some(Ok(challenge)) } #[update] @@ -536,23 +535,25 @@ mod v2_api { authn_method: AuthnMethodData, challenge_result: ChallengeAttempt, temp_key: Option, - ) -> Option { - let result = match DeviceWithUsage::try_from(authn_method) - .map_err(|err| IdentityRegisterResponse::InvalidMetadata(err.to_string())) + ) -> Option> { + let device = match DeviceWithUsage::try_from(authn_method) + .map_err(|err| IdentityRegisterError::InvalidMetadata(err.to_string())) { - Ok(device) => IdentityRegisterResponse::from(register( - DeviceData::from(device), - challenge_result, - temp_key, - )), - Err(err) => err, + Ok(device) => device, + Err(err) => return Some(Err(err)), + }; + + let result = match register(DeviceData::from(device), challenge_result, temp_key) { + RegisterResponse::Registered { user_number } => Ok(user_number), + RegisterResponse::CanisterFull => Err(IdentityRegisterError::CanisterFull), + RegisterResponse::BadChallenge => Err(IdentityRegisterError::BadCaptcha), }; Some(result) } #[update] #[candid_method] - fn identity_info(identity_number: IdentityNumber) -> Option { + fn identity_info(identity_number: IdentityNumber) -> Option> { authenticate_and_record_activity(identity_number); let anchor_info = anchor_management::get_anchor_info(identity_number); let metadata = state::anchor(identity_number) @@ -571,7 +572,7 @@ mod v2_api { .map(AuthnMethodRegistration::from), metadata, }; - Some(IdentityInfoResponse::Ok(identity_info)) + Some(Ok(identity_info)) } #[update] @@ -579,16 +580,13 @@ mod v2_api { fn authn_method_add( identity_number: IdentityNumber, authn_method: AuthnMethodData, - ) -> Option { - let result = match DeviceWithUsage::try_from(authn_method) - .map_err(|err| AuthnMethodAddResponse::InvalidMetadata(err.to_string())) - { - Ok(device) => { + ) -> Option> { + let result = DeviceWithUsage::try_from(authn_method) + .map(|device| { add(identity_number, DeviceData::from(device)); - AuthnMethodAddResponse::Ok - } - Err(err) => err, - }; + () + }) + .map_err(|err| AuthnMethodAddError::InvalidMetadata(err.to_string())); Some(result) } @@ -597,9 +595,9 @@ mod v2_api { fn authn_method_remove( identity_number: IdentityNumber, public_key: PublicKey, - ) -> Option { + ) -> Option> { remove(identity_number, public_key); - Some(AuthnMethodRemoveResponse::Ok) + Some(Ok(())) } #[update] @@ -607,14 +605,14 @@ mod v2_api { fn identity_metadata_replace( identity_number: IdentityNumber, metadata: HashMap, - ) -> Option { + ) -> Option> { let result = authenticated_anchor_operation(identity_number, |anchor| { Ok(( - IdentityMetadataReplaceResponse::Ok, + (), anchor_management::identity_metadata_replace(anchor, metadata), )) }); - Some(result) + Some(Ok(result)) } } diff --git a/src/internet_identity/tests/integration/activity_stats/authn_methods.rs b/src/internet_identity/tests/integration/activity_stats/authn_methods.rs index 3178648c56..0d19f6e80e 100644 --- a/src/internet_identity/tests/integration/activity_stats/authn_methods.rs +++ b/src/internet_identity/tests/integration/activity_stats/authn_methods.rs @@ -47,12 +47,12 @@ fn should_report_daily_active_authn_methods() -> Result<(), CallError> { // repeated activity with the same authn_method on the same identity within the 24h // collection period should not increase the counter - api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?; + api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?.unwrap(); env.advance_time(Duration::from_secs(DAY_SECONDS)); // some activity is required to update the stats - api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?; + api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?.unwrap(); let metrics = get_metrics(&env, canister_id); assert_metric( @@ -103,12 +103,12 @@ fn should_report_monthly_active_authn_methods() -> Result<(), CallError> { // repeated activity with the same authn_method on the same identity within the 30-day // collection period should not increase the counter - api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?; + api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?.unwrap(); env.advance_time(Duration::from_secs(MONTH_SECONDS)); // some activity is required to update the stats - api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?; + api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?.unwrap(); let metrics = get_metrics(&env, canister_id); assert_metric( @@ -180,7 +180,8 @@ fn should_only_count_ii_domain_authn_methods() -> Result<(), CallError> { canister_id, non_ii_authn_method.principal(), identity_nr, - )?; + )? + .unwrap(); env.advance_time(Duration::from_secs(MONTH_SECONDS)); // some activity on an II domain is required to update the stats create_identity_with_authn_method(&env, canister_id, &ii_authn_method); @@ -223,7 +224,7 @@ fn should_keep_stats_across_upgrades() -> Result<(), CallError> { env.advance_time(Duration::from_secs(DAY_SECONDS)); // some activity is required to update the stats - api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?; + api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_nr)?.unwrap(); assert_metric( &get_metrics(&env, canister_id), diff --git a/src/internet_identity/tests/integration/archive_integration.rs b/src/internet_identity/tests/integration/archive_integration.rs index cce672b1c6..38368a6123 100644 --- a/src/internet_identity/tests/integration/archive_integration.rs +++ b/src/internet_identity/tests/integration/archive_integration.rs @@ -485,7 +485,8 @@ mod pull_entries_tests { device.principal(), anchor, &metadata, - )?; + )? + .unwrap(); // the archive polls for entries once per second env.advance_time(Duration::from_secs(2)); diff --git a/src/internet_identity/tests/integration/v2_api/authn_method_add.rs b/src/internet_identity/tests/integration/v2_api/authn_method_add.rs index b6f4b51bd1..b2270ed632 100644 --- a/src/internet_identity/tests/integration/v2_api/authn_method_add.rs +++ b/src/internet_identity/tests/integration/v2_api/authn_method_add.rs @@ -6,12 +6,9 @@ use canister_tests::api::internet_identity::api_v2; use canister_tests::framework::{ env, expect_user_error_with_message, install_ii_canister, II_WASM, }; -use canister_tests::match_value; use ic_test_state_machine_client::CallError; use ic_test_state_machine_client::ErrorCode::CanisterCalledTrap; -use internet_identity_interface::internet_identity::types::{ - AuthnMethodAddResponse, IdentityInfoResponse, MetadataEntry, -}; +use internet_identity_interface::internet_identity::types::{AuthnMethodAddError, MetadataEntry}; use regex::Regex; use serde_bytes::ByteBuf; @@ -24,21 +21,18 @@ fn should_add_authn_method() -> Result<(), CallError> { let authn_method_2 = sample_authn_method(2); let identity_number = create_identity_with_authn_method(&env, canister_id, &authn_method_1); - match_value!( - api_v2::authn_method_add( - &env, - canister_id, - principal, - identity_number, - &authn_method_2, - )?, - Some(AuthnMethodAddResponse::Ok) - ); - match_value!( - api_v2::identity_info(&env, canister_id, principal, identity_number)?, - Some(IdentityInfoResponse::Ok(identity_info)) - ); + api_v2::authn_method_add( + &env, + canister_id, + principal, + identity_number, + &authn_method_2, + )? + .expect("authn method add failed"); + + let identity_info = api_v2::identity_info(&env, canister_id, principal, identity_number)? + .expect("identity info failed"); assert!(eq_ignoring_last_authentication( &identity_info.authn_methods[1], @@ -84,16 +78,16 @@ fn should_report_error_on_failed_conversion() -> Result<(), CallError> { let identity_number = create_identity_with_authn_method(&env, canister_id, &authn_method_1); - match_value!( - api_v2::authn_method_add( - &env, - canister_id, - principal, - identity_number, - &authn_method_2, - )?, - Some(AuthnMethodAddResponse::InvalidMetadata(_)) - ); - + let result = api_v2::authn_method_add( + &env, + canister_id, + principal, + identity_number, + &authn_method_2, + )?; + assert!(matches!( + result, + Err(AuthnMethodAddError::InvalidMetadata(_)) + )); Ok(()) } diff --git a/src/internet_identity/tests/integration/v2_api/authn_method_remove.rs b/src/internet_identity/tests/integration/v2_api/authn_method_remove.rs index d61322cd01..449dafdda0 100644 --- a/src/internet_identity/tests/integration/v2_api/authn_method_remove.rs +++ b/src/internet_identity/tests/integration/v2_api/authn_method_remove.rs @@ -6,13 +6,8 @@ use canister_tests::api::internet_identity::api_v2; use canister_tests::framework::{ env, expect_user_error_with_message, install_ii_canister, II_WASM, }; -use canister_tests::match_value; use ic_test_state_machine_client::CallError; use ic_test_state_machine_client::ErrorCode::CanisterCalledTrap; -use internet_identity_interface::internet_identity::types::IdentityInfoResponse; -use internet_identity_interface::internet_identity::types::{ - AuthnMethodAddResponse, AuthnMethodRemoveResponse, -}; use regex::Regex; #[test] @@ -24,34 +19,28 @@ fn should_remove_authn_method() -> Result<(), CallError> { let authn_method_2 = sample_authn_method(2); let identity_number = create_identity_with_authn_method(&env, canister_id, &authn_method_1); - let result = api_v2::authn_method_add( + api_v2::authn_method_add( &env, canister_id, principal, identity_number, &authn_method_2, )? - .unwrap(); - - assert!(matches!(result, AuthnMethodAddResponse::Ok)); + .expect("authn method add failed"); - match_value!( - api_v2::identity_info(&env, canister_id, principal, identity_number)?, - Some(IdentityInfoResponse::Ok(identity_info)) - ); + let identity_info = api_v2::identity_info(&env, canister_id, principal, identity_number)? + .expect("identity info failed"); assert_eq!(identity_info.authn_methods.len(), 2); - match_value!( - api_v2::authn_method_remove( - &env, - canister_id, - principal, - identity_number, - &authn_method_2.public_key(), - )?, - Some(AuthnMethodRemoveResponse::Ok) - ); + api_v2::authn_method_remove( + &env, + canister_id, + principal, + identity_number, + &authn_method_2.public_key(), + )? + .expect("authn method remove failed"); Ok(()) } diff --git a/src/internet_identity/tests/integration/v2_api/authn_method_test_helpers.rs b/src/internet_identity/tests/integration/v2_api/authn_method_test_helpers.rs index fa8d624574..606295db83 100644 --- a/src/internet_identity/tests/integration/v2_api/authn_method_test_helpers.rs +++ b/src/internet_identity/tests/integration/v2_api/authn_method_test_helpers.rs @@ -1,10 +1,9 @@ use canister_tests::api::internet_identity::api_v2; -use canister_tests::match_value; use ic_cdk::api::management_canister::main::CanisterId; use ic_test_state_machine_client::StateMachine; use internet_identity_interface::internet_identity::types::{ - AuthnMethod, AuthnMethodData, AuthnMethodProtection, CaptchaCreateResponse, ChallengeAttempt, - IdentityNumber, IdentityRegisterResponse, PublicKeyAuthn, Purpose, + AuthnMethod, AuthnMethodData, AuthnMethodProtection, ChallengeAttempt, IdentityNumber, + PublicKeyAuthn, Purpose, }; use serde_bytes::ByteBuf; @@ -37,27 +36,22 @@ pub fn create_identity_with_authn_method( canister_id: CanisterId, authn_method: &AuthnMethodData, ) -> IdentityNumber { - match_value!( - api_v2::captcha_create(env, canister_id).unwrap(), - Some(CaptchaCreateResponse::Ok(challenge)) - ); + let challenge = api_v2::captcha_create(env, canister_id).unwrap().unwrap(); let challenge_attempt = ChallengeAttempt { chars: "a".to_string(), key: challenge.challenge_key, }; - match_value!( - api_v2::identity_register( - env, - canister_id, - authn_method.principal(), - authn_method, - &challenge_attempt, - None, - ), - Ok(Some(IdentityRegisterResponse::Ok(user_number))) - ); - user_number + api_v2::identity_register( + env, + canister_id, + authn_method.principal(), + authn_method, + &challenge_attempt, + None, + ) + .unwrap() + .unwrap() } pub fn sample_authn_method(i: u8) -> AuthnMethodData { diff --git a/src/internet_identity/tests/integration/v2_api/identity_info.rs b/src/internet_identity/tests/integration/v2_api/identity_info.rs index c0251e7ca8..d22d6126ac 100644 --- a/src/internet_identity/tests/integration/v2_api/identity_info.rs +++ b/src/internet_identity/tests/integration/v2_api/identity_info.rs @@ -3,16 +3,16 @@ use candid::Principal; use canister_tests::api::internet_identity as api; use canister_tests::api::internet_identity::api_v2; +use canister_tests::flows; use canister_tests::framework::{ env, expect_user_error_with_message, install_ii_canister, time, II_WASM, }; -use canister_tests::{flows, match_value}; use ic_cdk::api::management_canister::main::CanisterId; use ic_test_state_machine_client::ErrorCode::CanisterCalledTrap; use ic_test_state_machine_client::{CallError, StateMachine}; use internet_identity_interface::internet_identity::types::{ - AuthnMethodAddResponse, AuthnMethodData, AuthnMethodRegistration, DeviceData, - IdentityInfoResponse, IdentityNumber, KeyType, MetadataEntry, Purpose, + AuthnMethodData, AuthnMethodRegistration, DeviceData, IdentityNumber, KeyType, MetadataEntry, + Purpose, }; use regex::Regex; use serde_bytes::ByteBuf; @@ -26,10 +26,9 @@ fn should_get_identity_info() -> Result<(), CallError> { let devices = sample_devices(); let identity_number = create_identity_with_devices(&env, canister_id, &devices); - match_value!( - api_v2::identity_info(&env, canister_id, devices[0].principal(), identity_number)?, - Some(IdentityInfoResponse::Ok(identity_info)) - ); + let identity_info = + api_v2::identity_info(&env, canister_id, devices[0].principal(), identity_number)? + .expect("identity info failed"); assert_eq_ignoring_last_authentication(&identity_info.authn_methods, &devices); assert_eq!(identity_info.authn_method_registration, None); @@ -80,10 +79,9 @@ fn should_provide_authn_registration() -> Result<(), CallError> { api::enter_device_registration_mode(&env, canister_id, device1.principal(), identity_number)?; api::add_tentative_device(&env, canister_id, identity_number, &device2)?; - match_value!( - api_v2::identity_info(&env, canister_id, device1.principal(), identity_number)?, - Some(IdentityInfoResponse::Ok(identity_info)) - ); + let identity_info = + api_v2::identity_info(&env, canister_id, device1.principal(), identity_number)? + .expect("identity info failed"); assert_eq!( identity_info.authn_method_registration, @@ -125,17 +123,15 @@ fn create_identity_with_devices( let device1 = iter.next().unwrap(); let identity_number = flows::register_anchor_with_device(env, canister_id, device1); for (idx, device) in iter.enumerate() { - match_value!( - api_v2::authn_method_add( - env, - canister_id, - device1.principal(), - identity_number, - &AuthnMethodData::from(device.clone()), - ) - .unwrap_or_else(|_| panic!("could not add device {}", idx)), - Some(AuthnMethodAddResponse::Ok) - ); + api_v2::authn_method_add( + env, + canister_id, + device1.principal(), + identity_number, + &AuthnMethodData::from(device.clone()), + ) + .unwrap_or_else(|_| panic!("could not add device {}", idx)) + .expect("authn method add failed"); } identity_number } diff --git a/src/internet_identity/tests/integration/v2_api/identity_metadata.rs b/src/internet_identity/tests/integration/v2_api/identity_metadata.rs index abd5ca6027..855bb5c17e 100644 --- a/src/internet_identity/tests/integration/v2_api/identity_metadata.rs +++ b/src/internet_identity/tests/integration/v2_api/identity_metadata.rs @@ -6,10 +6,9 @@ use canister_tests::api::internet_identity::api_v2; use canister_tests::framework::{ env, expect_user_error_with_message, install_ii_canister, II_WASM, }; -use canister_tests::match_value; use ic_test_state_machine_client::CallError; use ic_test_state_machine_client::ErrorCode::CanisterCalledTrap; -use internet_identity_interface::internet_identity::types::{IdentityInfoResponse, MetadataEntry}; +use internet_identity_interface::internet_identity::types::MetadataEntry; use regex::Regex; use std::collections::HashMap; @@ -22,10 +21,9 @@ fn should_write_metadata() -> Result<(), CallError> { let authn_method = test_authn_method(); let identity_number = create_identity_with_authn_method(&env, canister_id, &authn_method); - match_value!( - api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_number)?, - Some(IdentityInfoResponse::Ok(identity_info)) - ); + let identity_info = + api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_number)? + .expect("identity info failed"); assert!(identity_info.metadata.is_empty()); let metadata = HashMap::from_iter(vec![( @@ -39,12 +37,12 @@ fn should_write_metadata() -> Result<(), CallError> { authn_method.principal(), identity_number, &metadata, - )?; + )? + .expect("identity metadata replace failed"); - match_value!( - api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_number)?, - Some(IdentityInfoResponse::Ok(identity_info)) - ); + let identity_info = + api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_number)? + .expect("identity info failed"); assert_eq!(identity_info.metadata, metadata); Ok(()) } @@ -86,10 +84,9 @@ fn should_not_write_too_large_identity_metadata_map() -> Result<(), CallError> { let authn_method = test_authn_method(); let identity_number = create_identity_with_authn_method(&env, canister_id, &authn_method); - match_value!( - api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_number)?, - Some(IdentityInfoResponse::Ok(identity_info)) - ); + let identity_info = + api_v2::identity_info(&env, canister_id, authn_method.principal(), identity_number)? + .expect("identity info failed"); assert!(identity_info.metadata.is_empty()); let metadata = HashMap::from_iter(vec![( diff --git a/src/internet_identity/tests/integration/v2_api/identity_register.rs b/src/internet_identity/tests/integration/v2_api/identity_register.rs index 0c62b9bf5c..35863e2642 100644 --- a/src/internet_identity/tests/integration/v2_api/identity_register.rs +++ b/src/internet_identity/tests/integration/v2_api/identity_register.rs @@ -7,10 +7,9 @@ use canister_tests::framework::{ arg_with_anchor_range, env, expect_user_error_with_message, install_ii_canister, install_ii_canister_with_arg, II_WASM, }; -use canister_tests::match_value; use ic_test_state_machine_client::ErrorCode::CanisterCalledTrap; use internet_identity_interface::internet_identity::types::{ - CaptchaCreateResponse, ChallengeAttempt, IdentityRegisterResponse, MetadataEntry, + ChallengeAttempt, IdentityRegisterError, MetadataEntry, }; use regex::Regex; use serde_bytes::ByteBuf; @@ -48,25 +47,21 @@ fn should_not_exceed_configured_identity_range() { create_identity_with_authn_method(&env, canister_id, &authn_method); create_identity_with_authn_method(&env, canister_id, &authn_method); - match_value!( - api_v2::captcha_create(&env, canister_id).unwrap(), - Some(CaptchaCreateResponse::Ok(challenge)) - ); + let challenge = api_v2::captcha_create(&env, canister_id).unwrap().unwrap(); - match_value!( - api_v2::identity_register( - &env, - canister_id, - authn_method.principal(), - &authn_method, - &ChallengeAttempt { - chars: "a".to_string(), - key: challenge.challenge_key, - }, - None, - ), - Ok(Some(IdentityRegisterResponse::CanisterFull)) - ); + let result = api_v2::identity_register( + &env, + canister_id, + authn_method.principal(), + &authn_method, + &ChallengeAttempt { + chars: "a".to_string(), + key: challenge.challenge_key, + }, + None, + ) + .unwrap(); + assert!(matches!(result, Err(IdentityRegisterError::CanisterFull))); } #[test] @@ -74,10 +69,7 @@ fn should_verify_sender_matches_authn_method() { let env = env(); let canister_id = install_ii_canister(&env, II_WASM.clone()); - match_value!( - api_v2::captcha_create(&env, canister_id).unwrap(), - Some(CaptchaCreateResponse::Ok(challenge)) - ); + let challenge = api_v2::captcha_create(&env, canister_id).unwrap().unwrap(); let result = api_v2::identity_register( &env, @@ -103,25 +95,21 @@ fn should_not_allow_wrong_captcha() { let canister_id = install_ii_canister(&env, II_WASM.clone()); let authn_method = test_authn_method(); - match_value!( - api_v2::captcha_create(&env, canister_id).unwrap(), - Some(CaptchaCreateResponse::Ok(challenge)) - ); + let challenge = api_v2::captcha_create(&env, canister_id).unwrap().unwrap(); - match_value!( - api_v2::identity_register( - &env, - canister_id, - authn_method.principal(), - &authn_method, - &ChallengeAttempt { - chars: "wrong solution".to_string(), - key: challenge.challenge_key, - }, - None, - ), - Ok(Some(IdentityRegisterResponse::BadCaptcha)) - ); + let result = api_v2::identity_register( + &env, + canister_id, + authn_method.principal(), + &authn_method, + &ChallengeAttempt { + chars: "a".to_string(), + key: challenge.challenge_key, + }, + None, + ) + .unwrap(); + assert!(matches!(result, Err(IdentityRegisterError::BadCaptcha))); } #[test] @@ -130,27 +118,23 @@ fn should_not_allow_expired_captcha() { let canister_id = install_ii_canister(&env, II_WASM.clone()); let authn_method = test_authn_method(); - match_value!( - api_v2::captcha_create(&env, canister_id).unwrap(), - Some(CaptchaCreateResponse::Ok(challenge)) - ); + let challenge = api_v2::captcha_create(&env, canister_id).unwrap().unwrap(); env.advance_time(Duration::from_secs(301)); // one second longer than captcha validity - match_value!( - api_v2::identity_register( - &env, - canister_id, - authn_method.principal(), - &authn_method, - &ChallengeAttempt { - chars: "wrong solution".to_string(), - key: challenge.challenge_key, - }, - None, - ), - Ok(Some(IdentityRegisterResponse::BadCaptcha)) - ); + let result = api_v2::identity_register( + &env, + canister_id, + authn_method.principal(), + &authn_method, + &ChallengeAttempt { + chars: "a".to_string(), + key: challenge.challenge_key, + }, + None, + ) + .unwrap(); + assert!(matches!(result, Err(IdentityRegisterError::BadCaptcha))); } #[test] @@ -163,23 +147,22 @@ fn should_fail_on_invalid_metadata() { MetadataEntry::Bytes(ByteBuf::from("invalid")), ); - match_value!( - api_v2::captcha_create(&env, canister_id).unwrap(), - Some(CaptchaCreateResponse::Ok(challenge)) - ); + let challenge = api_v2::captcha_create(&env, canister_id).unwrap().unwrap(); - match_value!( - api_v2::identity_register( - &env, - canister_id, - authn_method.principal(), - &authn_method, - &ChallengeAttempt { - chars: "a".to_string(), - key: challenge.challenge_key, - }, - None, - ), - Ok(Some(IdentityRegisterResponse::InvalidMetadata(_))) - ); + let result = api_v2::identity_register( + &env, + canister_id, + authn_method.principal(), + &authn_method, + &ChallengeAttempt { + chars: "a".to_string(), + key: challenge.challenge_key, + }, + None, + ) + .unwrap(); + assert!(matches!( + result, + Err(IdentityRegisterError::InvalidMetadata(_)) + )); } diff --git a/src/internet_identity_interface/src/internet_identity/conversions.rs b/src/internet_identity_interface/src/internet_identity/conversions.rs index ff98ecce93..3abbf1ebc6 100644 --- a/src/internet_identity_interface/src/internet_identity/conversions.rs +++ b/src/internet_identity_interface/src/internet_identity/conversions.rs @@ -250,15 +250,3 @@ impl TryFrom for DeviceWithUsage { }) } } - -impl From for IdentityRegisterResponse { - fn from(register_response: RegisterResponse) -> Self { - match register_response { - RegisterResponse::Registered { user_number } => { - IdentityRegisterResponse::Ok(user_number) - } - RegisterResponse::CanisterFull => IdentityRegisterResponse::CanisterFull, - RegisterResponse::BadChallenge => IdentityRegisterResponse::BadCaptcha, - } - } -} diff --git a/src/internet_identity_interface/src/internet_identity/types/api_v2.rs b/src/internet_identity_interface/src/internet_identity/types/api_v2.rs index a65090f78c..c4bc72cd23 100644 --- a/src/internet_identity_interface/src/internet_identity/types/api_v2.rs +++ b/src/internet_identity_interface/src/internet_identity/types/api_v2.rs @@ -1,6 +1,4 @@ -use crate::internet_identity::types::{ - Challenge, CredentialId, MetadataEntry, PublicKey, Purpose, Timestamp, -}; +use crate::internet_identity::types::{CredentialId, MetadataEntry, PublicKey, Purpose, Timestamp}; use candid::{CandidType, Deserialize}; use std::collections::HashMap; @@ -8,9 +6,7 @@ pub type IdentityNumber = u64; #[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)] pub enum AuthnMethodProtection { - #[serde(rename = "protected")] Protected, - #[serde(rename = "unprotected")] Unprotected, } @@ -28,9 +24,7 @@ pub struct WebAuthn { /// Supported authentication methods #[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)] pub enum AuthnMethod { - #[serde(rename = "webauthn")] WebAuthn(WebAuthn), - #[serde(rename = "pubkey")] PubKey(PublicKeyAuthn), } @@ -62,45 +56,13 @@ pub struct IdentityInfo { } #[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)] -pub enum CaptchaCreateResponse { - #[serde(rename = "ok")] - Ok(Challenge), -} - -#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)] -pub enum IdentityRegisterResponse { - #[serde(rename = "ok")] - Ok(IdentityNumber), - #[serde(rename = "canister_full")] +pub enum IdentityRegisterError { CanisterFull, - #[serde(rename = "bad_captcha")] BadCaptcha, - #[serde(rename = "invalid_metadata")] InvalidMetadata(String), } #[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)] -pub enum IdentityInfoResponse { - #[serde(rename = "ok")] - Ok(IdentityInfo), -} - -#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)] -pub enum AuthnMethodAddResponse { - #[serde(rename = "ok")] - Ok, - #[serde(rename = "invalid_metadata")] +pub enum AuthnMethodAddError { InvalidMetadata(String), } - -#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)] -pub enum AuthnMethodRemoveResponse { - #[serde(rename = "ok")] - Ok, -} - -#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)] -pub enum IdentityMetadataReplaceResponse { - #[serde(rename = "ok")] - Ok, -}