From e43e5ce74a85d87a625295b9b089a1b5b8e26fab Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Sun, 9 May 2021 20:11:17 +0100 Subject: Add logout, only login if not already logged in (#91) Also: - Ensures that a key is generated as soon as a user registers! - Ensures that "atuin key" will generate a key if needed, and doesn't double base64 encode data And a few other little fixes :) Resolves #85 Resolves #86 --- atuin-client/src/encryption.rs | 27 +++++++++++++++++---------- atuin-client/src/settings.rs | 4 +++- docs/sync.md | 6 ++++++ src/command/login.rs | 12 +++++++++++- src/command/logout.rs | 12 ++++++++++++ src/command/mod.rs | 12 ++++++++++-- src/command/register.rs | 3 +++ 7 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 src/command/logout.rs diff --git a/atuin-client/src/encryption.rs b/atuin-client/src/encryption.rs index 9cb8d3ea..ecb8a0c7 100644 --- a/atuin-client/src/encryption.rs +++ b/atuin-client/src/encryption.rs @@ -24,23 +24,30 @@ pub struct EncryptedHistory { pub nonce: secretbox::Nonce, } +pub fn new_key(settings: &Settings) -> Result { + let path = settings.key_path.as_str(); + + let key = secretbox::gen_key(); + let encoded = encode_key(key.clone())?; + + let mut file = File::create(path)?; + file.write_all(encoded.as_bytes())?; + + Ok(key) +} + // Loads the secret key, will create + save if it doesn't exist pub fn load_key(settings: &Settings) -> Result { let path = settings.key_path.as_str(); - if PathBuf::from(path).exists() { + let key = if PathBuf::from(path).exists() { let key = std::fs::read_to_string(path)?; - let key = decode_key(key)?; - Ok(key) + decode_key(key)? } else { - let key = secretbox::gen_key(); - let encoded = encode_key(key.clone())?; + new_key(settings)? + }; - let mut file = File::create(path)?; - file.write_all(encoded.as_bytes())?; - - Ok(key) - } + Ok(key) } pub fn load_encoded_key(settings: &Settings) -> Result { diff --git a/atuin-client/src/settings.rs b/atuin-client/src/settings.rs index 9057eca2..1d7e9a5f 100644 --- a/atuin-client/src/settings.rs +++ b/atuin-client/src/settings.rs @@ -83,7 +83,9 @@ impl Settings { } pub fn should_sync(&self) -> Result { - if !self.auto_sync { + let session_path = atuin_common::utils::data_dir().join("session"); + + if !self.auto_sync || !session_path.exists() { return Ok(false); } diff --git a/docs/sync.md b/docs/sync.md index 78510526..81e8b598 100644 --- a/docs/sync.md +++ b/docs/sync.md @@ -53,3 +53,9 @@ If you want to login to a new machine, you will require your encryption key ``` atuin login -u -p -k ``` + +## Logout + +``` +atuin logout +``` diff --git a/src/command/login.rs b/src/command/login.rs index eacb2105..9a144580 100644 --- a/src/command/login.rs +++ b/src/command/login.rs @@ -22,6 +22,16 @@ pub struct Cmd { impl Cmd { pub fn run(&self, settings: &Settings) -> Result<()> { + let session_path = atuin_common::utils::data_dir().join("session"); + + if session_path.exists() { + println!( + "You are already logged in! Please run 'atuin logout' if you wish to login again" + ); + + return Ok(()); + } + let session = api_client::login( settings.sync_address.as_str(), self.username.as_str(), @@ -34,7 +44,7 @@ impl Cmd { let key_path = settings.key_path.as_str(); let mut file = File::create(key_path)?; - file.write_all(&base64::decode(self.key.clone())?)?; + file.write_all(self.key.as_bytes())?; println!("Logged in!"); diff --git a/src/command/logout.rs b/src/command/logout.rs new file mode 100644 index 00000000..ec7d8dcb --- /dev/null +++ b/src/command/logout.rs @@ -0,0 +1,12 @@ +use std::fs::remove_file; + +pub fn run() { + let session_path = atuin_common::utils::data_dir().join("session"); + + if session_path.exists() { + remove_file(session_path.as_path()).expect("Failed to remove session file"); + println!("You have logged out!"); + } else { + println!("You are not logged in"); + } +} diff --git a/src/command/mod.rs b/src/command/mod.rs index 161c99d9..6050c4eb 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -13,6 +13,7 @@ mod history; mod import; mod init; mod login; +mod logout; mod register; mod search; mod server; @@ -83,6 +84,9 @@ pub enum AtuinCmd { #[structopt(about = "login to the configured server")] Login(login::Cmd), + #[structopt(about = "log out")] + Logout, + #[structopt(about = "register with the configured server")] Register(register::Cmd), @@ -136,6 +140,10 @@ impl AtuinCmd { Self::Sync { force } => sync::run(&client_settings, force, &mut db).await, Self::Login(l) => l.run(&client_settings), + Self::Logout => { + logout::run(); + Ok(()) + } Self::Register(r) => register::run( &client_settings, r.username.as_str(), @@ -143,8 +151,8 @@ impl AtuinCmd { r.password.as_str(), ), Self::Key => { - let key = std::fs::read(client_settings.key_path.as_str())?; - println!("{}", base64::encode(key)); + let key = atuin_client::encryption::load_key(&client_settings)?; + println!("{}", atuin_client::encryption::encode_key(key)?); Ok(()) } diff --git a/src/command/register.rs b/src/command/register.rs index acf9b1a3..7c38f483 100644 --- a/src/command/register.rs +++ b/src/command/register.rs @@ -27,5 +27,8 @@ pub fn run(settings: &Settings, username: &str, email: &str, password: &str) -> let mut file = File::create(path)?; file.write_all(session.session.as_bytes())?; + // Create a new key, and save it to disk + let _key = atuin_client::encryption::new_key(settings)?; + Ok(()) } -- cgit v1.2.3