diff --git a/src/commands/identity.rs b/src/commands/identity.rs index 708c9c5cad81bb2367be4ce3279ad0bf3c3adf58..7ae600e0adb29078dfb303f937505edcc7374596 100644 --- a/src/commands/identity.rs +++ b/src/commands/identity.rs @@ -63,10 +63,15 @@ pub enum Subcommand { GenRevocDoc, /// Display member count MemberCount, - /// Link an account to the identity + /// Link an account to the [target] identity + #[clap(long_about = "Link an account to the [target] identity.\n\ + \n\ + The target identity can be passed as argument using any of the suggested options.")] LinkAccount(SecretProvider), - /// Migrate identity to another account - /// Change Owner Key + /// Migrate identity to another [target] account + #[clap(long_about = "Migrate identity to another [target] account.\n\ + \n\ + The target account can be passed as argument using any of the suggested options.")] ChangeOwnerKey(SecretProvider), } @@ -89,6 +94,41 @@ pub struct SecretProvider { crypto_scheme: CryptoScheme, } +impl SecretProvider { + /// Analyses the SecretProvider data and tries to retrieve a keypair. + /// + /// Will potentially request a password to decrypt the secret in keystore if it was asked to use a vault account. + /// + /// Or it could request the `secret` if using `secret-format` without also providing the `secret`. + /// + /// Will return an error if no data was provided or if it encountered another issue in the process. + async fn get_keypair(&self, data: &Data) -> Result<KeyPair, GcliError> { + let key_pair = if let Some(address) = self.address.clone() { + commands::vault::fetch_vault_keypair_for_address(data, address).await? + } else if let Some(vault_name) = self.vault_name.clone() { + let account_tree_node = + retrieve_account_tree_node_for_name(data.connect_db(), &vault_name).await?; + let address = account_tree_node.borrow().account.address.0.clone(); + + commands::vault::fetch_vault_keypair_for_address(data, address).await? + } else if let Some(secret_format) = self.secret_format { + let keypair = get_keypair(secret_format, self.secret.as_deref(), self.crypto_scheme)?; + println!( + "target address:'{}' (using crypto-scheme:{})", + keypair.address(), + <&'static str>::from(self.crypto_scheme) + ); + keypair + } else { + return Err(GcliError::Input( + "One of `address`/`vault_name`/`secret_format`(and optional `secret` & `crypto_scheme`) must be provided".to_string(), + )); + }; + + Ok(key_pair) + } +} + /// handle identity commands pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError> { let mut data = data.build_client().await?; @@ -154,16 +194,16 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE .unwrap() ) } - Subcommand::LinkAccount(params) => { - let target_keypair = get_keypair_from_secret_provider(&data, params).await?; + Subcommand::LinkAccount(secret_provider) => { + let target_keypair = secret_provider.get_keypair(&data).await?; println!("Trying to make the link"); let address = target_keypair.address(); let data = data.fetch_idty_index().await?; // idty index required for payload link_account(&data, address, target_keypair).await?; } - Subcommand::ChangeOwnerKey(params) => { - let target_keypair = get_keypair_from_secret_provider(&data, params).await?; + Subcommand::ChangeOwnerKey(secret_provider) => { + let target_keypair = secret_provider.get_keypair(&data).await?; println!("Trying to change owner key"); let address = target_keypair.address(); @@ -175,39 +215,6 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE Ok(()) } -async fn get_keypair_from_secret_provider( - data: &Data, - secret_provider: SecretProvider, -) -> Result<KeyPair, GcliError> { - let key_pair = if let Some(address) = secret_provider.address { - commands::vault::fetch_vault_keypair_for_address(data, address).await? - } else if let Some(vault_name) = secret_provider.vault_name { - let account_tree_node = - retrieve_account_tree_node_for_name(data.connect_db(), &vault_name).await?; - let address = account_tree_node.borrow().account.address.0.clone(); - - commands::vault::fetch_vault_keypair_for_address(data, address).await? - } else if let Some(secret_format) = secret_provider.secret_format { - let keypair = get_keypair( - secret_format, - secret_provider.secret.as_deref(), - secret_provider.crypto_scheme, - )?; - println!( - "target address:'{}' (using crypto-scheme:{})", - keypair.address(), - <&'static str>::from(secret_provider.crypto_scheme) - ); - keypair - } else { - return Err(GcliError::Input( - "One of `address`/`vault_name`/`secret_format`(and optional `secret` & `crypto_scheme`) must be provided".to_string(), - )); - }; - - Ok(key_pair) -} - // ====================== // TODO derive this automatically diff --git a/src/commands/vault.rs b/src/commands/vault.rs index f6941cf268202ebf5ae160919f9bcd82be0d4fe1..e6cf88bd29e15edd1f4cddbaac2d081e6fad9e23 100644 --- a/src/commands/vault.rs +++ b/src/commands/vault.rs @@ -1196,7 +1196,7 @@ fn find_substrate_vault_key_file(data: &Data, address: &str) -> Result<Option<Pa } /// Gets secret in keystore, prompt for the password and compute the keypair associated to `address` -/// +/// /// Returns an error if no entry was found in the keystore or if another error occurred during the process pub async fn fetch_vault_keypair_for_address( data: &Data, @@ -1208,7 +1208,6 @@ pub async fn fetch_vault_keypair_for_address( .ok_or_else(|| GcliError::Input("vault account not found".to_string())) } - /// try to get secret in keystore, prompt for the password and compute the keypair associated to `address` pub async fn try_fetch_key_pair( data: &Data,