Skip to content
Snippets Groups Projects
Commit cf7a4292 authored by Nicolas80's avatar Nicolas80
Browse files

* Adapted to have more coherent commands descriptions and added `long_about`...

* Adapted to have more coherent commands descriptions and added `long_about` more detailed description for `import` and `derivation`
* Added the `vault list for` command
* Added display of "format" of <Root> derivations in all `vault list` commands
* Only allowing derivations for format "substrate" and "seed"
parent 747e02da
No related branches found
No related tags found
1 merge request!41Adding db persistence for all SecretFormat of vault keys as well as supporting derivations
...@@ -13,10 +13,10 @@ use std::path::PathBuf; ...@@ -13,10 +13,10 @@ use std::path::PathBuf;
/// define universal dividends subcommands /// define universal dividends subcommands
#[derive(Clone, Debug, clap::Parser)] #[derive(Clone, Debug, clap::Parser)]
pub enum Subcommand { pub enum Subcommand {
/// List available keys /// List available derivations
#[clap(subcommand)] #[clap(subcommand)]
List(ListChoice), List(ListChoice),
/// Use specific vault key (changes the config address) /// Use specific derivation (changes the config Address)
Use { Use {
#[clap(flatten)] #[clap(flatten)]
address_or_vault_name: AddressOrVaultNameGroup, address_or_vault_name: AddressOrVaultNameGroup,
...@@ -24,29 +24,40 @@ pub enum Subcommand { ...@@ -24,29 +24,40 @@ pub enum Subcommand {
/// Generate a mnemonic /// Generate a mnemonic
Generate, Generate,
/// Import key from (substrate)mnemonic or other format with interactive prompt /// Import key from (substrate)mnemonic or other format with interactive prompt
#[clap(
long_about = "Import key from (substrate)mnemonic or other format with interactive prompt\n\
\n\
If a (substrate)mnemonic is provided with a derivation path, it will ensure the <Root> derivation\n\
and associated key exists before creating the new derivation; but please use command \n\
`vault derivation|derive|deriv` to add a derivation to an existing <Root> derivation instead."
)]
Import { Import {
/// Secret key format (substrate, seed, cesium) /// Secret key format (substrate, seed, cesium)
#[clap(short = 'S', long, required = false, default_value = SecretFormat::Substrate)] #[clap(short = 'S', long, required = false, default_value = SecretFormat::Substrate)]
secret_format: SecretFormat, secret_format: SecretFormat,
}, },
/// Add a derivation to an existing (root) vault key /// Add a derivation to an existing <Root> derivation
#[clap(long_about = "Add a derivation to an existing <Root> derivation\n\
\n\
Only \"substrate\" and \"seed\" format are supported for derivations\n\
Use command `vault list root` to see available <Root> derivations and their format")]
#[clap(alias = "deriv")] #[clap(alias = "deriv")]
#[clap(alias = "derive")] #[clap(alias = "derive")]
Derivation { Derivation {
#[clap(flatten)] #[clap(flatten)]
address_or_vault_name: AddressOrVaultNameGroup, address_or_vault_name: AddressOrVaultNameGroup,
}, },
/// Give a meaningful vault name to a vault key or derivation /// Give a meaningful derivation name to a key derivation (can be for a <Root> derivation)
Rename { Rename {
/// key SS58 Address /// SS58 Address
address: AccountId, address: AccountId,
}, },
/// Remove a vault key (and potential derivations if it's a root key) /// Remove a derivation (and all linked derivations along with the key if a <Root> derivation is given)
Remove { Remove {
#[clap(flatten)] #[clap(flatten)]
address_or_vault_name: AddressOrVaultNameGroup, address_or_vault_name: AddressOrVaultNameGroup,
}, },
/// (deprecated)List available key files (needs to be migrated with command "vault migrate" in order to use them) /// (deprecated)List available key files (needs to be migrated with command `vault migrate` in order to use them)
ListFiles, ListFiles,
/// (deprecated)Migrate old key files into db (will have to provide password for each key) /// (deprecated)Migrate old key files into db (will have to provide password for each key)
Migrate, Migrate,
...@@ -56,10 +67,15 @@ pub enum Subcommand { ...@@ -56,10 +67,15 @@ pub enum Subcommand {
#[derive(Clone, Default, Debug, clap::Parser)] #[derive(Clone, Default, Debug, clap::Parser)]
pub enum ListChoice { pub enum ListChoice {
/// List all keys and derivations in the vault /// List all <Root> derivations and their linked derivations in the vault
#[default] #[default]
All, All,
/// List only root keys /// List all derivations linked to the one selected
For {
#[clap(flatten)]
address_or_vault_name: AddressOrVaultNameGroup,
},
/// List only <Root> derivations in the vault
Root, Root,
} }
...@@ -107,9 +123,13 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -107,9 +123,13 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
) )
.await?; .await?;
let table = compute_vault_derivations_table(&derivations).await?; let table = compute_vault_derivations_table(
data.connection.as_ref().unwrap(),
&derivations,
)
.await?;
println!("available keys:"); println!("available derivations:");
println!("{table}"); println!("{table}");
} }
ListChoice::Root => { ListChoice::Root => {
...@@ -118,9 +138,34 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -118,9 +138,34 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
) )
.await?; .await?;
let table = compute_vault_derivations_table(&derivations).await?; let table = compute_vault_derivations_table(
data.connection.as_ref().unwrap(),
&derivations,
)
.await?;
println!("available <Root> derivations:");
println!("{table}");
}
ListChoice::For {
address_or_vault_name,
} => {
let root_derivation =
retrieve_vault_derivation(&data, address_or_vault_name).await?;
let linked_derivations = vault_derivation::fetch_all_linked_derivations_in_order(
data.connection.as_ref().unwrap(),
&root_derivation.root_address,
)
.await?;
let table = compute_vault_derivations_table(
data.connection.as_ref().unwrap(),
&linked_derivations,
)
.await?;
println!("available root keys:"); println!("available derivations linked to {root_derivation}:");
println!("{table}"); println!("{table}");
} }
}, },
...@@ -176,7 +221,11 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -176,7 +221,11 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
.await?; .await?;
println!("Here are all the linked derivations already present in the vault:"); println!("Here are all the linked derivations already present in the vault:");
let table = compute_vault_derivations_table(&linked_derivations).await?; let table = compute_vault_derivations_table(
data.connection.as_ref().unwrap(),
&linked_derivations,
)
.await?;
println!("{table}"); println!("{table}");
return Ok(()); return Ok(());
...@@ -225,6 +274,16 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -225,6 +274,16 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
root_derivation.address root_derivation.address
)))?; )))?;
if vault_account.crypto_type == CryptoType::Ed25519Seed {
println!(
"Only \"{}\" and \"{}\" format are supported for derivations",
Into::<&str>::into(SecretFormat::Substrate),
Into::<&str>::into(SecretFormat::Seed)
);
println!("Use command `vault list root` to see available <Root> derivations and their format");
return Ok(());
}
println!("Adding derivation to root key: {root_derivation}"); println!("Adding derivation to root key: {root_derivation}");
println!("Enter password to decrypt the root key"); println!("Enter password to decrypt the root key");
...@@ -308,7 +367,8 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -308,7 +367,8 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
) )
.await?; .await?;
let table = compute_vault_derivations_table(&all_derivations_to_delete).await?; let table =
compute_vault_derivations_table(&txn, &all_derivations_to_delete).await?;
println!("All derivations linked to the root derivation:"); println!("All derivations linked to the root derivation:");
println!("{table}"); println!("{table}");
...@@ -468,17 +528,22 @@ async fn compute_vault_key_files_table(vault_key_addresses: &[String]) -> Result ...@@ -468,17 +528,22 @@ async fn compute_vault_key_files_table(vault_key_addresses: &[String]) -> Result
Ok(table) Ok(table)
} }
async fn compute_vault_derivations_table( async fn compute_vault_derivations_table<C>(
db: &C,
derivations_ordered: &[vault_derivation::Model], derivations_ordered: &[vault_derivation::Model],
) -> Result<Table, GcliError> { ) -> Result<Table, GcliError>
where
C: ConnectionTrait,
{
let mut table = Table::new(); let mut table = Table::new();
table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY); table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY);
table.set_header(vec!["SS58 Address", "Path", "Vault Name"]); table.set_header(vec!["SS58 Address", "Format", "Path", "Derivation Name"]);
let empty_name = "".to_string(); let empty_string = "".to_string();
let root_path = "<Root>".to_string(); let root_path = "<Root>".to_string();
let mut current_root_address = "".to_string(); let mut current_root_address = "".to_string();
let mut current_root_name: Option<String> = None; let mut current_root_name: Option<String> = None;
let mut current_vault_format: Option<&str> = None;
for derivation in derivations_ordered { for derivation in derivations_ordered {
if derivation.root_address != current_root_address { if derivation.root_address != current_root_address {
...@@ -490,6 +555,19 @@ async fn compute_vault_derivations_table( ...@@ -490,6 +555,19 @@ async fn compute_vault_derivations_table(
} }
current_root_address = derivation.root_address.clone(); current_root_address = derivation.root_address.clone();
current_root_name = derivation.name.clone(); current_root_name = derivation.name.clone();
let vault_account = vault_account::Entity::find_by_id(current_root_address.clone())
.one(db)
.await?
.ok_or(GcliError::Input(format!(
"No vault account found with address:'{current_root_address}'"
)))?;
current_vault_format = match vault_account.crypto_type {
CryptoType::Sr25519Mnemonic => Some(SecretFormat::Substrate.into()),
CryptoType::Sr25519Seed => Some(SecretFormat::Seed.into()),
CryptoType::Ed25519Seed => Some(SecretFormat::Cesium.into()),
};
} else { } else {
// Validate that the RootAddress is the same as current_root_address // Validate that the RootAddress is the same as current_root_address
if derivation.root_address != current_root_address { if derivation.root_address != current_root_address {
...@@ -505,15 +583,15 @@ async fn compute_vault_derivations_table( ...@@ -505,15 +583,15 @@ async fn compute_vault_derivations_table(
" ".to_string() + &derivation.address " ".to_string() + &derivation.address
}; };
let path = if derivation.path.is_none() { let (path, format) = if derivation.path.is_none() {
root_path.clone() (root_path.clone(), current_vault_format.unwrap())
} else { } else {
derivation.path.clone().unwrap() (derivation.path.clone().unwrap(), empty_string.as_str())
}; };
let name = if derivation.name.is_none() { let name = if derivation.name.is_none() {
if derivation.path.is_none() { if derivation.path.is_none() {
empty_name.clone() empty_string.clone()
} else if let Some(current_root_name) = &current_root_name { } else if let Some(current_root_name) = &current_root_name {
format!( format!(
"<{}{}>", "<{}{}>",
...@@ -521,7 +599,7 @@ async fn compute_vault_derivations_table( ...@@ -521,7 +599,7 @@ async fn compute_vault_derivations_table(
derivation.path.clone().unwrap() derivation.path.clone().unwrap()
) )
} else { } else {
empty_name.clone() empty_string.clone()
} }
} else { } else {
derivation.name.clone().unwrap() derivation.name.clone().unwrap()
...@@ -529,6 +607,7 @@ async fn compute_vault_derivations_table( ...@@ -529,6 +607,7 @@ async fn compute_vault_derivations_table(
table.add_row(vec![ table.add_row(vec![
Cell::new(&address), Cell::new(&address),
Cell::new(format),
Cell::new(&path), Cell::new(&path),
Cell::new(&name), Cell::new(&name),
]); ]);
......
...@@ -91,7 +91,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -91,7 +91,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
) )
.await? .await?
{ {
println!("(Vault entry: {})", derivation); println!("(Vault derivation: {})", derivation);
} }
} }
} }
......
...@@ -78,11 +78,11 @@ trait AddressOrVaultName { ...@@ -78,11 +78,11 @@ trait AddressOrVaultName {
#[derive(Debug, clap::Args, Clone)] #[derive(Debug, clap::Args, Clone)]
#[group(required = false, multiple = false)] #[group(required = false, multiple = false)]
pub struct AddressOrVaultNameGroupOptional { pub struct AddressOrVaultNameGroupOptional {
/// key SS58 Address /// SS58 Address
#[clap(short)] #[clap(short)]
address: Option<AccountId>, address: Option<AccountId>,
/// Vault name for a key /// Derivation name for a SS58 Address (can be a <Root> derivation name)
#[clap(short = 'v')] #[clap(short = 'd')]
name: Option<String>, name: Option<String>,
} }
...@@ -98,11 +98,11 @@ impl AddressOrVaultName for AddressOrVaultNameGroupOptional { ...@@ -98,11 +98,11 @@ impl AddressOrVaultName for AddressOrVaultNameGroupOptional {
#[derive(Debug, clap::Args, Clone)] #[derive(Debug, clap::Args, Clone)]
#[group(required = true, multiple = false)] #[group(required = true, multiple = false)]
pub struct AddressOrVaultNameGroup { pub struct AddressOrVaultNameGroup {
/// key SS58 Address /// SS58 Address
#[clap(short)] #[clap(short)]
address: Option<AccountId>, address: Option<AccountId>,
/// Vault name for a key /// Derivation name for a SS58 Address (can be a <Root> derivation name)
#[clap(short = 'v')] #[clap(short = 'd')]
name: Option<String>, name: Option<String>,
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment