mirror of
https://github.com/atuinsh/atuin.git
synced 2024-11-08 01:15:04 +01:00
Allow using existing key file on login (#688)
* Allow logging in without overwriting existing key file If the given key on login in empty, keep the existing key file rather than overwriting it with an empty file. This is useful if you log out and want to log in again and still use the same key, or if you have copied over the key file rather than providing it as input. * Refuse logging in if key is empty Before the previous commit, an empty key file would be created if key wasn't specified, and after the previous commit, the key file would not be created if the key wasn't specified and stay empty if it was empty. Now the log command checks the key file if a key is not specified and exits with an error message if either the key file couldn't be opened or is empty. If a key is specified, the key file is just created with it as before. * Validate the key on login, create new if no exists After reading the key either from an existing key file, or from the user input, validate that the provided key is valid (rather than just checking that it isn't empty). If no key file exists, create a new key instead of erroring out.
This commit is contained in:
parent
78b54662cd
commit
2cec7ba677
@ -1,12 +1,12 @@
|
||||
use std::io;
|
||||
use std::{io, path::PathBuf};
|
||||
|
||||
use clap::Parser;
|
||||
use eyre::{bail, ContextCompat, Result};
|
||||
use eyre::{bail, Context, ContextCompat, Result};
|
||||
use tokio::{fs::File, io::AsyncWriteExt};
|
||||
|
||||
use atuin_client::{
|
||||
api_client,
|
||||
encryption::{encode_key, Key},
|
||||
encryption::{decode_key, encode_key, new_key, Key},
|
||||
settings::Settings,
|
||||
};
|
||||
use atuin_common::api::LoginRequest;
|
||||
@ -44,32 +44,36 @@ impl Cmd {
|
||||
}
|
||||
|
||||
let username = or_user_input(&self.username, "username");
|
||||
let key = or_user_input(&self.key, "encryption key");
|
||||
let key = or_user_input(&self.key, "encryption key [blank to use existing key file]");
|
||||
let password = self.password.clone().unwrap_or_else(read_user_password);
|
||||
let session = api_client::login(
|
||||
settings.sync_address.as_str(),
|
||||
LoginRequest { username, password },
|
||||
)
|
||||
.await?;
|
||||
|
||||
let session_path = settings.session_path.as_str();
|
||||
let mut file = File::create(session_path).await?;
|
||||
file.write_all(session.session.as_bytes()).await?;
|
||||
|
||||
let key_path = settings.key_path.as_str();
|
||||
let mut file = File::create(key_path).await?;
|
||||
|
||||
if key.is_empty() {
|
||||
if PathBuf::from(key_path).exists() {
|
||||
let bytes = fs_err::read_to_string(key_path)
|
||||
.context("existing key file couldn't be read")?;
|
||||
if decode_key(bytes).is_err() {
|
||||
bail!("the key in existing key file was invalid");
|
||||
}
|
||||
} else {
|
||||
println!("No key file exists, creating a new");
|
||||
let _key = new_key(settings)?;
|
||||
}
|
||||
} else {
|
||||
// try parse the key as a mnemonic...
|
||||
let key = match bip39::Mnemonic::from_phrase(&key, bip39::Language::English) {
|
||||
Ok(mnemonic) => encode_key(
|
||||
Key::from_slice(mnemonic.entropy()).context("key was not the correct length")?,
|
||||
Key::from_slice(mnemonic.entropy())
|
||||
.context("key was not the correct length")?,
|
||||
)?,
|
||||
Err(err) => {
|
||||
if let Some(err) = err.downcast_ref::<bip39::ErrorKind>() {
|
||||
match err {
|
||||
// assume they copied in the base64 key
|
||||
bip39::ErrorKind::InvalidWord => key,
|
||||
bip39::ErrorKind::InvalidChecksum => bail!("key mnemonic was not valid"),
|
||||
bip39::ErrorKind::InvalidChecksum => {
|
||||
bail!("key mnemonic was not valid")
|
||||
}
|
||||
bip39::ErrorKind::InvalidKeysize(_)
|
||||
| bip39::ErrorKind::InvalidWordLength(_)
|
||||
| bip39::ErrorKind::InvalidEntropyLength(_, _) => {
|
||||
@ -83,7 +87,23 @@ impl Cmd {
|
||||
}
|
||||
};
|
||||
|
||||
if decode_key(key.clone()).is_err() {
|
||||
bail!("the specified key was invalid");
|
||||
}
|
||||
|
||||
let mut file = File::create(key_path).await?;
|
||||
file.write_all(key.as_bytes()).await?;
|
||||
}
|
||||
|
||||
let session = api_client::login(
|
||||
settings.sync_address.as_str(),
|
||||
LoginRequest { username, password },
|
||||
)
|
||||
.await?;
|
||||
|
||||
let session_path = settings.session_path.as_str();
|
||||
let mut file = File::create(session_path).await?;
|
||||
file.write_all(session.session.as_bytes()).await?;
|
||||
|
||||
println!("Logged in!");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user