diff --git a/demos/vc_issuer/app/generated/vc_issuer_idl.js b/demos/vc_issuer/app/generated/vc_issuer_idl.js index 64bf91a5a9..a39b387ab9 100644 --- a/demos/vc_issuer/app/generated/vc_issuer_idl.js +++ b/demos/vc_issuer/app/generated/vc_issuer_idl.js @@ -108,6 +108,7 @@ export const idlFactory = ({ IDL }) => { [], ), 'set_alternative_origins' : IDL.Func([IDL.Text], [], []), + 'set_derivation_origin' : IDL.Func([IDL.Text, IDL.Text], [], []), 'vc_consent_message' : IDL.Func( [Icrc21VcConsentMessageRequest], [IDL.Variant({ 'Ok' : Icrc21ConsentInfo, 'Err' : Icrc21Error })], diff --git a/demos/vc_issuer/app/generated/vc_issuer_types.d.ts b/demos/vc_issuer/app/generated/vc_issuer_types.d.ts index 07f4fe3eff..64f056a427 100644 --- a/demos/vc_issuer/app/generated/vc_issuer_types.d.ts +++ b/demos/vc_issuer/app/generated/vc_issuer_types.d.ts @@ -88,6 +88,7 @@ export interface _SERVICE { { 'Err' : IssueCredentialError } >, 'set_alternative_origins' : ActorMethod<[string], undefined>, + 'set_derivation_origin' : ActorMethod<[string, string], undefined>, 'vc_consent_message' : ActorMethod< [Icrc21VcConsentMessageRequest], { 'Ok' : Icrc21ConsentInfo } | diff --git a/demos/vc_issuer/src/main.rs b/demos/vc_issuer/src/main.rs index d338b8f81e..794f7c680b 100644 --- a/demos/vc_issuer/src/main.rs +++ b/demos/vc_issuer/src/main.rs @@ -77,7 +77,7 @@ fn config_memory() -> Memory { #[cfg(target_arch = "wasm32")] use ic_cdk::println; -#[derive(CandidType, Deserialize)] +#[derive(CandidType, Deserialize, Clone)] struct IssuerConfig { /// Root of trust for checking canister signatures. ic_root_key_raw: Vec, @@ -143,7 +143,7 @@ struct IssuerInit { #[candid_method(init)] fn init(init_arg: Option) { if let Some(init) = init_arg { - apply_config(init); + apply_config(IssuerConfig::from(init)); }; init_assets(); @@ -156,17 +156,21 @@ fn post_upgrade(init_arg: Option) { #[update] #[candid_method] -fn configure(config: IssuerInit) { - if ic_cdk::api::is_controller(&caller()) { - apply_config(config); - } else { - panic!("Only a controller can call configure()."); - } +fn configure(init: IssuerInit) { + apply_config(IssuerConfig::from(init)); +} + +#[update] +fn set_derivation_origin(frontend_hostname: String, derivation_origin: String) { + let mut config: IssuerConfig = CONFIG.with_borrow(|config| config.get().clone()); + config.derivation_origin = derivation_origin; + config.frontend_hostname = frontend_hostname; + apply_config(config); } -fn apply_config(init: IssuerInit) { +fn apply_config(config: IssuerConfig) { CONFIG - .with_borrow_mut(|config_cell| config_cell.set(IssuerConfig::from(init))) + .with_borrow_mut(|config_cell| config_cell.set(config)) .expect("failed to apply issuer config"); } diff --git a/demos/vc_issuer/tests/issue_credential.rs b/demos/vc_issuer/tests/issue_credential.rs index bccaab2293..bd4f31bd4a 100644 --- a/demos/vc_issuer/tests/issue_credential.rs +++ b/demos/vc_issuer/tests/issue_credential.rs @@ -6,9 +6,7 @@ use canister_sig_util::{extract_raw_root_pk_from_der, CanisterSigPublicKey}; use canister_tests::api::http_request; use canister_tests::api::internet_identity::vc_mvp as ii_api; use canister_tests::flows; -use canister_tests::framework::{ - env, get_wasm_path, principal_1, principal_2, test_principal, time, II_WASM, -}; +use canister_tests::framework::{env, get_wasm_path, principal_1, test_principal, time, II_WASM}; use ic_cdk::api::management_canister::provisional::CanisterId; use ic_response_verification::types::VerificationInfo; use ic_response_verification::verify_request_response_pair; @@ -113,10 +111,9 @@ mod api { pub fn configure( env: &StateMachine, canister_id: CanisterId, - sender: Principal, config: &IssuerInit, ) -> Result<(), CallError> { - call_candid_as(env, canister_id, sender, "configure", (config,)) + call_candid(env, canister_id, "configure", (config,)) } pub fn vc_consent_message( @@ -138,19 +135,31 @@ mod api { pub fn derivation_origin( env: &StateMachine, canister_id: CanisterId, - sender: Principal, derivation_origin_req: &DerivationOriginRequest, ) -> Result, CallError> { - call_candid_as( + call_candid( env, canister_id, - sender, "derivation_origin", (derivation_origin_req,), ) .map(|(x,)| x) } + pub fn set_derivation_origin( + env: &StateMachine, + canister_id: CanisterId, + frontend_hostname: &str, + derivation_origin: &str, + ) -> Result<(), CallError> { + call_candid( + env, + canister_id, + "set_derivation_origin", + (frontend_hostname, derivation_origin), + ) + } + pub fn set_alternative_origins( env: &StateMachine, canister_id: CanisterId, @@ -366,12 +375,41 @@ fn should_return_derivation_origin() { let canister_id = install_canister(&env, VC_ISSUER_WASM.clone()); let frontend_hostname = format!("https://{}.icp0.io", canister_id.to_text()); let req = DerivationOriginRequest { frontend_hostname }; - let response = api::derivation_origin(&env, canister_id, principal_1(), &req) + let response = api::derivation_origin(&env, canister_id, &req) .expect("API call failed") .expect("derivation_origin error"); assert_eq!(response.origin, req.frontend_hostname); } +#[test] +fn should_set_derivation_origin() { + let env = env(); + let canister_id = install_canister(&env, VC_ISSUER_WASM.clone()); + let req = DerivationOriginRequest { + frontend_hostname: "frontend_hostname.com".to_string(), + }; + + let response = api::derivation_origin(&env, canister_id, &req) + .expect("API call failed") + .expect("derivation_origin error"); + let default_derivation_origin = format!("https://{}.icp0.io", canister_id.to_text()); + assert_eq!(response.origin, default_derivation_origin); + + let derivation_origin = "https://derivation.origin"; + api::set_derivation_origin( + &env, + canister_id, + "frontend_hostname.com".to_string().as_str(), + derivation_origin, + ) + .expect("failed to set derivation_origin"); + + let response = api::derivation_origin(&env, canister_id, &req) + .expect("API call failed") + .expect("derivation_origin error"); + assert_eq!(response.origin, derivation_origin); +} + #[test] fn should_return_derivation_origin_with_custom_init() { let env = env(); @@ -385,7 +423,6 @@ fn should_return_derivation_origin_with_custom_init() { let response = api::derivation_origin( &env, issuer_id, - principal_1(), &DerivationOriginRequest { frontend_hostname: custom_init.frontend_hostname.clone(), }, @@ -730,19 +767,8 @@ fn should_issue_credential_e2e() -> Result<(), CallError> { #[test] fn should_configure() { let env = env(); - let controller = principal_1(); - let issuer_id = install_canister_as(&env, VC_ISSUER_WASM.clone(), Some(controller)); - api::configure(&env, issuer_id, controller, &DUMMY_ISSUER_INIT).expect("API call failed"); -} - -#[test] -fn should_fail_configure_if_not_controller() { - let env = env(); - let controller = principal_1(); - let not_controller = principal_2(); - let issuer_id = install_canister_as(&env, VC_ISSUER_WASM.clone(), Some(controller)); - let result = api::configure(&env, issuer_id, not_controller, &DUMMY_ISSUER_INIT); - assert_matches!(result, Err(e) if format!("{:?}", e).contains("Only a controller can call configure")); + let issuer_id = install_canister(&env, VC_ISSUER_WASM.clone()); + api::configure(&env, issuer_id, &DUMMY_ISSUER_INIT).expect("API call failed"); } #[test] diff --git a/demos/vc_issuer/vc_demo_issuer.did b/demos/vc_issuer/vc_demo_issuer.did index e4c945d276..1e8227317c 100644 --- a/demos/vc_issuer/vc_demo_issuer.did +++ b/demos/vc_issuer/vc_demo_issuer.did @@ -120,6 +120,7 @@ service: (opt IssuerConfig) -> { /// Configure the issuer (e.g. set the root key), used for deployment/testing. configure: (IssuerConfig) -> (); + set_derivation_origin: (frontend_hostname: text, derivation_origin: text) -> (); // Sets the content of the alternative origins file. set_alternative_origins: (alternative_origins: text) -> (); diff --git a/src/frontend/generated/vc_issuer_idl.js b/src/frontend/generated/vc_issuer_idl.js index 64bf91a5a9..a39b387ab9 100644 --- a/src/frontend/generated/vc_issuer_idl.js +++ b/src/frontend/generated/vc_issuer_idl.js @@ -108,6 +108,7 @@ export const idlFactory = ({ IDL }) => { [], ), 'set_alternative_origins' : IDL.Func([IDL.Text], [], []), + 'set_derivation_origin' : IDL.Func([IDL.Text, IDL.Text], [], []), 'vc_consent_message' : IDL.Func( [Icrc21VcConsentMessageRequest], [IDL.Variant({ 'Ok' : Icrc21ConsentInfo, 'Err' : Icrc21Error })], diff --git a/src/vc-api/src/generated/vc_issuer_types.ts b/src/vc-api/src/generated/vc_issuer_types.ts index 07f4fe3eff..6fbe791dbb 100644 --- a/src/vc-api/src/generated/vc_issuer_types.ts +++ b/src/vc-api/src/generated/vc_issuer_types.ts @@ -87,6 +87,7 @@ export interface _SERVICE { { 'Ok' : PreparedCredentialData } | { 'Err' : IssueCredentialError } >, + 'set_derivation_origin' : ActorMethod<[string, string], undefined>, 'set_alternative_origins' : ActorMethod<[string], undefined>, 'vc_consent_message' : ActorMethod< [Icrc21VcConsentMessageRequest],