diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2020-09-09 21:37:19 +0200 |
---|---|---|
committer | Robin Krahl <robin.krahl@ireas.org> | 2020-09-11 11:03:32 +0200 |
commit | ef7b6b03355b82621d16f4f02a5a1a4558ae64cc (patch) | |
tree | 97b505e2e74a4b9e8aacb6c530fd23d7244a37c2 /src | |
parent | 70b9a1f0287f2aeda9677110106f43d1048306f3 (diff) | |
download | nitrocli-ef7b6b03355b82621d16f4f02a5a1a4558ae64cc.tar.gz nitrocli-ef7b6b03355b82621d16f4f02a5a1a4558ae64cc.tar.bz2 |
List all matching devices in status commmand
Previously, the status command would fail if more than one Nitrokey
device is connected. With this patch, we list all attached devices that
match the specified filter (model, serial number, USB path).
This also casues some changes in the test cases: Previously, we assumed
that status fails for multiple attached devices. We now use the lock
command to produce this behavior.
Diffstat (limited to 'src')
-rw-r--r-- | src/commands.rs | 31 | ||||
-rw-r--r-- | src/tests/run.rs | 16 | ||||
-rw-r--r-- | src/tests/status.rs | 20 |
3 files changed, 52 insertions, 15 deletions
diff --git a/src/commands.rs b/src/commands.rs index 597fcd8..a4e805e 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -363,19 +363,24 @@ fn print_storage_status( } /// Query and pretty print the status that is common to all Nitrokey devices. -fn print_status(ctx: &mut Context<'_>, device: &nitrokey::DeviceWrapper<'_>) -> anyhow::Result<()> { +fn print_status( + ctx: &mut Context<'_>, + idx: usize, + device: &nitrokey::DeviceWrapper<'_>, +) -> anyhow::Result<()> { let serial_number = device .get_serial_number() .context("Could not query the serial number")?; println!( ctx, - r#"Status: + r#"Device #{idx}: model: {model} serial number: {id} firmware version: {fwv} user retry count: {urc} admin retry count: {arc}"#, + idx = idx, model = args::DeviceModel::from(device.get_model()).as_user_facing_str(), id = serial_number, fwv = device @@ -402,7 +407,27 @@ fn print_status(ctx: &mut Context<'_>, device: &nitrokey::DeviceWrapper<'_>) -> /// Inquire the status of the nitrokey. pub fn status(ctx: &mut Context<'_>) -> anyhow::Result<()> { - with_device(ctx, |ctx, device| print_status(ctx, &device)) + let device_infos = find_devices(&ctx.config)?; + anyhow::ensure!( + !device_infos.is_empty(), + "Nitrokey device not found{}", + format_filter(&ctx.config) + ); + + let mut manager = + nitrokey::take().context("Failed to acquire access to Nitrokey device manager")?; + for (idx, device_info) in device_infos.iter().enumerate() { + let device = manager + .connect_path(device_info.path.deref()) + .with_context(|| { + format!( + "Failed to connect to Nitrokey device at path {}", + device_info.path + ) + })?; + print_status(ctx, idx, &device)?; + } + Ok(()) } /// List the attached Nitrokey devices. diff --git a/src/tests/run.rs b/src/tests/run.rs index b39b1da..3dd4c98 100644 --- a/src/tests/run.rs +++ b/src/tests/run.rs @@ -113,7 +113,7 @@ fn config_file() { fn connect_multiple(_model: nitrokey::Model) -> anyhow::Result<()> { let devices = nitrokey::list_devices()?; if devices.len() > 1 { - let res = Nitrocli::new().handle(&["status"]); + let res = Nitrocli::new().handle(&["lock"]); let err = res.unwrap_err().to_string(); assert_eq!( err, @@ -190,16 +190,12 @@ fn connect_model(_model: nitrokey::Model) -> anyhow::Result<()> { model.to_lowercase() ) ); - } else if count == 1 { - assert!(res?.contains(&format!("model: {}\n", model))); } else { - let err = res.unwrap_err().to_string(); assert_eq!( - err, - format!( - "Multiple Nitrokey devices found (filter: model={}). ", - model.to_lowercase() - ) + "Use the --model, --serial-number, and --usb-path options to select one" + count, + res? + .matches(&format!("model: {}\n", model)) + .count() ); } } @@ -213,7 +209,7 @@ fn connect_usb_path_model_serial(_model: nitrokey::Model) -> anyhow::Result<()> for device in devices { let mut args = Vec::new(); args.push("status".to_owned()); - args.push(format!("--usb-path={}", device.path)); + args.push(format!("--usb-path={}", &device.path)); if let Some(model) = device.model { args.push(format!("--model={}", model.to_string().to_lowercase())); } diff --git a/src/tests/status.rs b/src/tests/status.rs index fe69d78..1f5bbf7 100644 --- a/src/tests/status.rs +++ b/src/tests/status.rs @@ -24,7 +24,7 @@ fn not_found() { #[test_device(pro)] fn output_pro(model: nitrokey::Model) -> anyhow::Result<()> { let re = regex::Regex::new( - r#"^Status: + r#"^Device #0: model: Pro serial number: 0x[[:xdigit:]]{8} firmware version: v\d+\.\d+ @@ -42,7 +42,7 @@ $"#, #[test_device(storage)] fn output_storage(model: nitrokey::Model) -> anyhow::Result<()> { let re = regex::Regex::new( - r#"^Status: + r#"^Device #0: model: Storage serial number: 0x[[:xdigit:]]{8} firmware version: v\d+\.\d+ @@ -64,3 +64,19 @@ $"#, assert!(re.is_match(&out), out); Ok(()) } + +#[test_device] +fn output_multiple(_model: nitrokey::Model) -> anyhow::Result<()> { + let devices = nitrokey::list_devices()?; + let out = Nitrocli::new().handle(&["status"])?; + for (idx, device) in devices.iter().enumerate() { + assert!(out.contains(&format!("Device #{}:\n", idx)), out); + if let Some(model) = device.model { + assert!(out.contains(&format!("model: {}\n", model)), out); + } + if let Some(sn) = device.serial_number { + assert!(out.contains(&format!("serial number: {}\n", sn)), out); + } + } + Ok(()) +} |