add --password
argument and STEAMGUARD_CLI_STEAM_PASSWORD
environment variable (#326)
closes #324
This commit is contained in:
parent
04295dc742
commit
0c256a0e05
12 changed files with 63 additions and 15 deletions
|
@ -44,7 +44,12 @@ pub(crate) trait ManifestCommand<T>
|
||||||
where
|
where
|
||||||
T: Transport,
|
T: Transport,
|
||||||
{
|
{
|
||||||
fn execute(&self, transport: T, manager: &mut AccountManager) -> anyhow::Result<()>;
|
fn execute(
|
||||||
|
&self,
|
||||||
|
transport: T,
|
||||||
|
manager: &mut AccountManager,
|
||||||
|
args: &GlobalArgs,
|
||||||
|
) -> anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A command that operates on individual accounts.
|
/// A command that operates on individual accounts.
|
||||||
|
@ -57,6 +62,7 @@ where
|
||||||
transport: T,
|
transport: T,
|
||||||
manager: &mut AccountManager,
|
manager: &mut AccountManager,
|
||||||
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
||||||
|
args: &GlobalArgs,
|
||||||
) -> anyhow::Result<()>;
|
) -> anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +98,13 @@ pub(crate) struct GlobalArgs {
|
||||||
long_help = "Select the account you want by steam username. Case-sensitive. By default, the first account in the manifest is selected."
|
long_help = "Select the account you want by steam username. Case-sensitive. By default, the first account in the manifest is selected."
|
||||||
)]
|
)]
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
|
#[clap(
|
||||||
|
long,
|
||||||
|
conflicts_with = "all",
|
||||||
|
help = "Steam account password. You really shouldn't use this if you can avoid it.",
|
||||||
|
env = "STEAMGUARD_CLI_STEAM_PASSWORD"
|
||||||
|
)]
|
||||||
|
pub password: Option<SecretString>,
|
||||||
#[clap(
|
#[clap(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
|
|
|
@ -29,6 +29,7 @@ where
|
||||||
transport: T,
|
transport: T,
|
||||||
_manager: &mut AccountManager,
|
_manager: &mut AccountManager,
|
||||||
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
||||||
|
_args: &GlobalArgs,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let server_time = if self.offline {
|
let server_time = if self.offline {
|
||||||
SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs()
|
SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs()
|
||||||
|
|
|
@ -12,7 +12,12 @@ impl<T> ManifestCommand<T> for DecryptCommand
|
||||||
where
|
where
|
||||||
T: Transport,
|
T: Transport,
|
||||||
{
|
{
|
||||||
fn execute(&self, _transport: T, manager: &mut AccountManager) -> anyhow::Result<()> {
|
fn execute(
|
||||||
|
&self,
|
||||||
|
_transport: T,
|
||||||
|
manager: &mut AccountManager,
|
||||||
|
_args: &GlobalArgs,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
load_accounts_with_prompts(manager)?;
|
load_accounts_with_prompts(manager)?;
|
||||||
|
|
||||||
#[cfg(feature = "keyring")]
|
#[cfg(feature = "keyring")]
|
||||||
|
|
|
@ -16,7 +16,12 @@ impl<T> ManifestCommand<T> for EncryptCommand
|
||||||
where
|
where
|
||||||
T: Transport,
|
T: Transport,
|
||||||
{
|
{
|
||||||
fn execute(&self, _transport: T, manager: &mut AccountManager) -> anyhow::Result<()> {
|
fn execute(
|
||||||
|
&self,
|
||||||
|
_transport: T,
|
||||||
|
manager: &mut AccountManager,
|
||||||
|
_args: &GlobalArgs,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
if !manager.has_passkey() {
|
if !manager.has_passkey() {
|
||||||
let passkey: Option<SecretString>;
|
let passkey: Option<SecretString>;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -19,7 +19,12 @@ impl<T> ManifestCommand<T> for ImportCommand
|
||||||
where
|
where
|
||||||
T: Transport,
|
T: Transport,
|
||||||
{
|
{
|
||||||
fn execute(&self, _transport: T, manager: &mut AccountManager) -> anyhow::Result<()> {
|
fn execute(
|
||||||
|
&self,
|
||||||
|
_transport: T,
|
||||||
|
manager: &mut AccountManager,
|
||||||
|
_args: &GlobalArgs,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
for file_path in self.files.iter() {
|
for file_path in self.files.iter() {
|
||||||
debug!("loading entry: {:?}", file_path);
|
debug!("loading entry: {:?}", file_path);
|
||||||
match manager.import_account(file_path) {
|
match manager.import_account(file_path) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ where
|
||||||
_transport: T,
|
_transport: T,
|
||||||
_manager: &mut AccountManager,
|
_manager: &mut AccountManager,
|
||||||
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
||||||
|
_args: &GlobalArgs,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ where
|
||||||
transport: T,
|
transport: T,
|
||||||
_manager: &mut AccountManager,
|
_manager: &mut AccountManager,
|
||||||
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
||||||
|
args: &GlobalArgs,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
ensure!(
|
ensure!(
|
||||||
accounts.len() == 1,
|
accounts.len() == 1,
|
||||||
|
@ -37,7 +38,7 @@ where
|
||||||
info!("Approving login to {}", account.account_name);
|
info!("Approving login to {}", account.account_name);
|
||||||
|
|
||||||
if account.tokens.is_none() {
|
if account.tokens.is_none() {
|
||||||
crate::do_login(transport.clone(), &mut account)?;
|
crate::do_login(transport.clone(), &mut account, args.password.clone())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -57,7 +58,7 @@ where
|
||||||
}
|
}
|
||||||
Err(QrApproverError::Unauthorized) => {
|
Err(QrApproverError::Unauthorized) => {
|
||||||
warn!("tokens are invalid. Attempting to log in again.");
|
warn!("tokens are invalid. Attempting to log in again.");
|
||||||
crate::do_login(transport.clone(), &mut account)?;
|
crate::do_login(transport.clone(), &mut account, args.password.clone())?;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Failed to approve login: {}", e);
|
error!("Failed to approve login: {}", e);
|
||||||
|
|
|
@ -20,6 +20,7 @@ where
|
||||||
transport: T,
|
transport: T,
|
||||||
manager: &mut AccountManager,
|
manager: &mut AccountManager,
|
||||||
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
||||||
|
args: &GlobalArgs,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"This will remove the mobile authenticator from {} accounts: {}",
|
"This will remove the mobile authenticator from {} accounts: {}",
|
||||||
|
@ -54,7 +55,7 @@ where
|
||||||
}
|
}
|
||||||
Err(RemoveAuthenticatorError::TransportError(TransportError::Unauthorized)) => {
|
Err(RemoveAuthenticatorError::TransportError(TransportError::Unauthorized)) => {
|
||||||
error!("Account {} is not logged in", account.account_name);
|
error!("Account {} is not logged in", account.account_name);
|
||||||
crate::do_login(transport.clone(), &mut account)?;
|
crate::do_login(transport.clone(), &mut account, args.password.clone())?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(RemoveAuthenticatorError::IncorrectRevocationCode {
|
Err(RemoveAuthenticatorError::IncorrectRevocationCode {
|
||||||
|
|
|
@ -18,7 +18,12 @@ impl<T> ManifestCommand<T> for SetupCommand
|
||||||
where
|
where
|
||||||
T: Transport + Clone,
|
T: Transport + Clone,
|
||||||
{
|
{
|
||||||
fn execute(&self, transport: T, manager: &mut AccountManager) -> anyhow::Result<()> {
|
fn execute(
|
||||||
|
&self,
|
||||||
|
transport: T,
|
||||||
|
manager: &mut AccountManager,
|
||||||
|
args: &GlobalArgs,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
eprintln!("Log in to the account that you want to link to steamguard-cli");
|
eprintln!("Log in to the account that you want to link to steamguard-cli");
|
||||||
eprint!("Username: ");
|
eprint!("Username: ");
|
||||||
let username = tui::prompt().to_lowercase();
|
let username = tui::prompt().to_lowercase();
|
||||||
|
@ -30,7 +35,7 @@ where
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
info!("Logging in to {}", username);
|
info!("Logging in to {}", username);
|
||||||
let tokens = crate::do_login_raw(transport.clone(), username)
|
let tokens = crate::do_login_raw(transport.clone(), username, args.password.clone())
|
||||||
.expect("Failed to log in. Account has not been linked.");
|
.expect("Failed to log in. Account has not been linked.");
|
||||||
|
|
||||||
info!("Adding authenticator...");
|
info!("Adding authenticator...");
|
||||||
|
|
|
@ -34,13 +34,14 @@ where
|
||||||
transport: T,
|
transport: T,
|
||||||
manager: &mut AccountManager,
|
manager: &mut AccountManager,
|
||||||
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
accounts: Vec<Arc<Mutex<SteamGuardAccount>>>,
|
||||||
|
args: &GlobalArgs,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
for a in accounts {
|
for a in accounts {
|
||||||
let mut account = a.lock().unwrap();
|
let mut account = a.lock().unwrap();
|
||||||
|
|
||||||
if !account.is_logged_in() {
|
if !account.is_logged_in() {
|
||||||
info!("Account does not have tokens, logging in");
|
info!("Account does not have tokens, logging in");
|
||||||
crate::do_login(transport.clone(), &mut account)?;
|
crate::do_login(transport.clone(), &mut account, args.password.clone())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("{}: Checking for trade confirmations", account.account_name);
|
info!("{}: Checking for trade confirmations", account.account_name);
|
||||||
|
@ -55,7 +56,7 @@ where
|
||||||
}
|
}
|
||||||
Err(ConfirmerError::InvalidTokens) => {
|
Err(ConfirmerError::InvalidTokens) => {
|
||||||
info!("obtaining new tokens");
|
info!("obtaining new tokens");
|
||||||
crate::do_login(transport.clone(), &mut account)?;
|
crate::do_login(transport.clone(), &mut account, args.password.clone())?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to get trade confirmations: {}", err);
|
error!("Failed to get trade confirmations: {}", err);
|
||||||
|
|
14
src/login.rs
14
src/login.rs
|
@ -17,6 +17,7 @@ use crate::tui;
|
||||||
pub fn do_login<T: Transport + Clone>(
|
pub fn do_login<T: Transport + Clone>(
|
||||||
transport: T,
|
transport: T,
|
||||||
account: &mut SteamGuardAccount,
|
account: &mut SteamGuardAccount,
|
||||||
|
password: Option<SecretString>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if let Some(tokens) = account.tokens.as_mut() {
|
if let Some(tokens) = account.tokens.as_mut() {
|
||||||
info!("Refreshing access token...");
|
info!("Refreshing access token...");
|
||||||
|
@ -44,7 +45,11 @@ pub fn do_login<T: Transport + Clone>(
|
||||||
account.account_name = tui::prompt();
|
account.account_name = tui::prompt();
|
||||||
}
|
}
|
||||||
let _ = std::io::stdout().flush();
|
let _ = std::io::stdout().flush();
|
||||||
let password = tui::prompt_password()?;
|
let password = if let Some(p) = password {
|
||||||
|
p
|
||||||
|
} else {
|
||||||
|
tui::prompt_password()?
|
||||||
|
};
|
||||||
if !password.expose_secret().is_empty() {
|
if !password.expose_secret().is_empty() {
|
||||||
debug!("password is present");
|
debug!("password is present");
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,9 +70,14 @@ pub fn do_login<T: Transport + Clone>(
|
||||||
pub fn do_login_raw<T: Transport + Clone>(
|
pub fn do_login_raw<T: Transport + Clone>(
|
||||||
transport: T,
|
transport: T,
|
||||||
username: String,
|
username: String,
|
||||||
|
password: Option<SecretString>,
|
||||||
) -> anyhow::Result<Tokens> {
|
) -> anyhow::Result<Tokens> {
|
||||||
let _ = std::io::stdout().flush();
|
let _ = std::io::stdout().flush();
|
||||||
let password = tui::prompt_password()?;
|
let password = if let Some(p) = password {
|
||||||
|
p
|
||||||
|
} else {
|
||||||
|
tui::prompt_password()?
|
||||||
|
};
|
||||||
if !password.expose_secret().is_empty() {
|
if !password.expose_secret().is_empty() {
|
||||||
debug!("password is present");
|
debug!("password is present");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -232,7 +232,7 @@ fn run(args: commands::Args) -> anyhow::Result<()> {
|
||||||
let transport = WebApiTransport::new(http_client);
|
let transport = WebApiTransport::new(http_client);
|
||||||
|
|
||||||
if let CommandType::Manifest(cmd) = cmd {
|
if let CommandType::Manifest(cmd) = cmd {
|
||||||
cmd.execute(transport, &mut manager)?;
|
cmd.execute(transport, &mut manager, &globalargs)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ fn run(args: commands::Args) -> anyhow::Result<()> {
|
||||||
);
|
);
|
||||||
|
|
||||||
if let CommandType::Account(cmd) = cmd {
|
if let CommandType::Account(cmd) = cmd {
|
||||||
return cmd.execute(transport, &mut manager, selected_accounts);
|
return cmd.execute(transport, &mut manager, selected_accounts, &globalargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in a new issue