diff options
author | Jesse Luehrs <doy@tozt.net> | 2020-04-18 04:06:36 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2020-04-18 04:14:14 -0400 |
commit | b3c69bf88d973af04433d450a659ef1581d813e2 (patch) | |
tree | cb84d2671d2d365f025d8b9bbd714368ed88ce35 | |
parent | f2e12534b876e73a0c7c4593acb23ac200529309 (diff) | |
download | rbw-b3c69bf88d973af04433d450a659ef1581d813e2.tar.gz rbw-b3c69bf88d973af04433d450a659ef1581d813e2.zip |
stop using the api cipher struct publicly
-rw-r--r-- | src/actions.rs | 23 | ||||
-rw-r--r-- | src/api.rs | 47 | ||||
-rw-r--r-- | src/bin/rbw-agent/actions.rs | 4 | ||||
-rw-r--r-- | src/bin/rbw/commands.rs | 60 | ||||
-rw-r--r-- | src/db.rs | 10 |
5 files changed, 87 insertions, 57 deletions
diff --git a/src/actions.rs b/src/actions.rs index 71dd96a..ad99b5f 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -46,7 +46,7 @@ pub async fn unlock( pub async fn sync( access_token: &str, refresh_token: &str, -) -> Result<(Option<String>, String, Vec<crate::api::Cipher>)> { +) -> Result<(Option<String>, String, Vec<crate::db::Entry>)> { let res = sync_once(access_token).await; match res { Ok((protected_key, ciphers)) => Ok((None, protected_key, ciphers)), @@ -62,7 +62,7 @@ pub async fn sync( async fn sync_once( access_token: &str, -) -> Result<(String, Vec<crate::api::Cipher>)> { +) -> Result<(String, Vec<crate::db::Entry>)> { let config = crate::config::Config::load_async().await?; let client = crate::api::Client::new(&config.base_url(), &config.identity_url()); @@ -72,24 +72,33 @@ async fn sync_once( pub fn add( access_token: &str, refresh_token: &str, - cipher: &crate::api::Cipher, + name: &str, + username: Option<&str>, + password: Option<&str>, + notes: Option<&str>, ) -> Result<Option<String>> { - match add_once(access_token, cipher) { + match add_once(access_token, name, username, password, notes) { Ok(()) => Ok(None), Err(crate::error::Error::RequestUnauthorized) => { let access_token = exchange_refresh_token(refresh_token)?; - add_once(&access_token, cipher)?; + add_once(&access_token, name, username, password, notes)?; Ok(Some(access_token)) } Err(e) => Err(e), } } -fn add_once(access_token: &str, cipher: &crate::api::Cipher) -> Result<()> { +fn add_once( + access_token: &str, + name: &str, + username: Option<&str>, + password: Option<&str>, + notes: Option<&str>, +) -> Result<()> { let config = crate::config::Config::load()?; let client = crate::api::Client::new(&config.base_url(), &config.identity_url()); - client.add(access_token, cipher)?; + client.add(access_token, name, username, password, notes)?; Ok(()) } @@ -60,7 +60,7 @@ struct ConnectRefreshTokenRes { #[derive(serde::Deserialize, Debug)] struct SyncRes { #[serde(rename = "Ciphers")] - ciphers: Vec<Cipher>, + ciphers: Vec<SyncResCipher>, #[serde(rename = "Profile")] profile: Profile, } @@ -145,17 +145,30 @@ struct Profile { } #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] -pub struct Cipher { +struct SyncResCipher { + #[serde(rename = "Id")] + pub id: String, #[serde(rename = "Name")] pub name: String, #[serde(rename = "Login")] - pub login: Login, + pub login: SyncResLogin, #[serde(rename = "Notes")] pub notes: Option<String>, } +impl SyncResCipher { + fn to_entry(&self) -> crate::db::Entry { + crate::db::Entry { + name: self.name.clone(), + username: self.login.username.clone(), + password: self.login.password.clone(), + notes: self.notes.clone(), + } + } +} + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] -pub struct Login { +struct SyncResLogin { #[serde(rename = "Username")] pub username: Option<String>, #[serde(rename = "Password")] @@ -229,7 +242,7 @@ impl Client { pub async fn sync( &self, access_token: &str, - ) -> Result<(String, Vec<Cipher>)> { + ) -> Result<(String, Vec<crate::db::Entry>)> { let client = reqwest::Client::new(); let res = client .get(&self.api_url("/sync")) @@ -241,7 +254,12 @@ impl Client { reqwest::StatusCode::OK => { let sync_res: SyncRes = res.json().await.context(crate::error::Reqwest)?; - Ok((sync_res.profile.key, sync_res.ciphers)) + let ciphers = sync_res + .ciphers + .iter() + .map(SyncResCipher::to_entry) + .collect(); + Ok((sync_res.profile.key, ciphers)) } reqwest::StatusCode::UNAUTHORIZED => { Err(Error::RequestUnauthorized) @@ -252,18 +270,25 @@ impl Client { } } - pub fn add(&self, access_token: &str, cipher: &Cipher) -> Result<()> { + pub fn add( + &self, + access_token: &str, + name: &str, + username: Option<&str>, + password: Option<&str>, + notes: Option<&str>, + ) -> Result<()> { let req = CiphersPostReq { ty: 1, folder_id: None, organization_id: None, - name: cipher.name.clone(), - notes: cipher.notes.clone(), + name: name.to_string(), + notes: notes.map(std::string::ToString::to_string), favorite: false, login: CiphersPostReqLogin { uri: None, - username: cipher.login.username.clone(), - password: cipher.login.password.clone(), + username: username.map(std::string::ToString::to_string), + password: password.map(std::string::ToString::to_string), totp: None, }, }; diff --git a/src/bin/rbw-agent/actions.rs b/src/bin/rbw-agent/actions.rs index 75c1c25..9875d5c 100644 --- a/src/bin/rbw-agent/actions.rs +++ b/src/bin/rbw-agent/actions.rs @@ -137,7 +137,7 @@ pub async fn sync(sock: &mut crate::sock::Sock) -> anyhow::Result<()> { } else { return Err(anyhow::anyhow!("failed to find refresh token in db")); }; - let (access_token, protected_key, ciphers) = + let (access_token, protected_key, entries) = rbw::actions::sync(&access_token, &refresh_token) .await .context("failed to sync database from server")?; @@ -145,7 +145,7 @@ pub async fn sync(sock: &mut crate::sock::Sock) -> anyhow::Result<()> { db.access_token = Some(access_token); } db.protected_key = Some(protected_key); - db.ciphers = ciphers; + db.entries = entries; db.save_async(&email) .await .context("failed to save database")?; diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs index 253ce5d..30c5d1e 100644 --- a/src/bin/rbw/commands.rs +++ b/src/bin/rbw/commands.rs @@ -72,10 +72,10 @@ pub fn list() -> anyhow::Result<()> { let email = config_email()?; let db = rbw::db::Db::load(&email) .context("failed to load password database")?; - for cipher in db.ciphers { + for entry in db.entries { println!( "{}", - crate::actions::decrypt(&cipher.name) + crate::actions::decrypt(&entry.name) .context("failed to decrypt entry name")? ); } @@ -145,18 +145,14 @@ pub fn add(name: &str, username: Option<&str>) -> anyhow::Result<()> { Some(crate::actions::encrypt(¬es)?) }; - let cipher = rbw::api::Cipher { - name, - login: rbw::api::Login { - username, - password: Some(password), - }, - notes, - }; - - if let Some(access_token) = - rbw::actions::add(&access_token, &refresh_token, &cipher)? - { + if let Some(access_token) = rbw::actions::add( + &access_token, + &refresh_token, + &name, + username.as_deref(), + Some(&password), + notes.as_deref(), + )? { db.access_token = Some(access_token); db.save(&email).context("failed to save database")?; } @@ -191,18 +187,14 @@ pub fn generate( .transpose()?; let password = crate::actions::encrypt(&password)?; - let cipher = rbw::api::Cipher { - name, - login: rbw::api::Login { - username, - password: Some(password), - }, - notes: None, - }; - - if let Some(access_token) = - rbw::actions::add(&access_token, &refresh_token, &cipher)? - { + if let Some(access_token) = rbw::actions::add( + &access_token, + &refresh_token, + &name, + username.as_deref(), + Some(&password), + None, + )? { db.access_token = Some(access_token); db.save(&email).context("failed to save database")?; } @@ -276,7 +268,7 @@ fn find_entry( username: Option<&str>, ) -> anyhow::Result<DecryptedCipher> { let ciphers: anyhow::Result<Vec<DecryptedCipher>> = db - .ciphers + .entries .iter() .cloned() .map(decrypt_cipher) @@ -314,24 +306,20 @@ fn find_entry( } } -fn decrypt_cipher( - cipher: rbw::api::Cipher, -) -> anyhow::Result<DecryptedCipher> { +fn decrypt_cipher(entry: rbw::db::Entry) -> anyhow::Result<DecryptedCipher> { Ok(DecryptedCipher { - name: crate::actions::decrypt(&cipher.name)?, - username: cipher - .login + name: crate::actions::decrypt(&entry.name)?, + username: entry .username .as_ref() .map(|username| crate::actions::decrypt(username)) .transpose()?, - password: cipher - .login + password: entry .password .as_ref() .map(|password| crate::actions::decrypt(password)) .transpose()?, - notes: cipher + notes: entry .notes .as_ref() .map(|notes| crate::actions::decrypt(notes)) @@ -3,6 +3,14 @@ use crate::prelude::*; use std::io::{Read as _, Write as _}; use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _}; +#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] +pub struct Entry { + pub name: String, + pub username: Option<String>, + pub password: Option<String>, + pub notes: Option<String>, +} + #[derive(serde::Serialize, serde::Deserialize, Default, Debug)] pub struct Db { pub access_token: Option<String>, @@ -11,7 +19,7 @@ pub struct Db { pub iterations: Option<u32>, pub protected_key: Option<String>, - pub ciphers: Vec<crate::api::Cipher>, + pub entries: Vec<Entry>, } impl Db { |