steamguard-cli/src/commands/remove.rs
Carson McManus fe663cf43f
add HTTP proxy support (#264)
- allow extracting the http client from web api transport
- refactor most commands so that they can accept an external transport
- update confirmer to use transport's http client
- update remove command
- update TwoFactorClient so it doesn't need to be mutable
- update get_server_time so it requires a transport
- update remove_authenticator
- update login proceedure to use given transport
- update usages of do_login
- update setup
- update trade
- update code command
- update qr-login command
- make borrowcheck happy
- make WebApiTransport Clone and remove Default impl
- remove dead code
- fix lints

closes #177
2023-07-02 12:57:13 +00:00

102 lines
2.6 KiB
Rust

use std::sync::{Arc, Mutex};
use log::*;
use steamguard::{steamapi::TwoFactorClient, transport::TransportError, RemoveAuthenticatorError};
use crate::{errors::UserError, tui, AccountManager};
use super::*;
#[derive(Debug, Clone, Parser)]
#[clap(about = "Remove the authenticator from an account.")]
pub struct RemoveCommand;
impl<T> AccountCommand<T> for RemoveCommand
where
T: Transport + Clone,
{
fn execute(
&self,
transport: T,
manager: &mut AccountManager,
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
) -> anyhow::Result<()> {
eprintln!(
"This will remove the mobile authenticator from {} accounts: {}",
accounts.len(),
accounts
.iter()
.map(|a| a.lock().unwrap().account_name.clone())
.collect::<Vec<String>>()
.join(", ")
);
match tui::prompt_char("Do you want to continue?", "yN") {
'y' => {}
_ => {
info!("Aborting!");
return Err(UserError::Aborted.into());
}
}
let mut successful = vec![];
for a in accounts {
let mut account = a.lock().unwrap();
let client = TwoFactorClient::new(transport.clone());
let mut revocation: Option<String> = None;
loop {
match account.remove_authenticator(&client, revocation.as_ref()) {
Ok(_) => {
info!("Removed authenticator from {}", account.account_name);
successful.push(account.account_name.clone());
break;
}
Err(RemoveAuthenticatorError::TransportError(TransportError::Unauthorized)) => {
error!("Account {} is not logged in", account.account_name);
crate::do_login(transport.clone(), &mut account)?;
continue;
}
Err(RemoveAuthenticatorError::IncorrectRevocationCode {
attempts_remaining,
}) => {
error!(
"Revocation code was incorrect for {} ({} attempts remaining)",
account.account_name, attempts_remaining
);
if attempts_remaining == 0 {
error!("No attempts remaining, aborting!");
break;
}
eprint!("Enter the revocation code for {}: ", account.account_name);
let code = tui::prompt();
revocation = Some(code);
}
Err(RemoveAuthenticatorError::MissingRevocationCode) => {
error!(
"Account {} does not have a revocation code",
account.account_name
);
eprint!("Enter the revocation code for {}: ", account.account_name);
let code = tui::prompt();
revocation = Some(code);
}
Err(err) => {
error!(
"Unexpected error when removing authenticator from {}: {}",
account.account_name, err
);
break;
}
}
}
}
for account_name in successful {
manager.remove_account(account_name);
}
manager.save()?;
Ok(())
}
}