aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-04-18 04:06:36 -0400
committerJesse Luehrs <doy@tozt.net>2020-04-18 04:14:14 -0400
commitb3c69bf88d973af04433d450a659ef1581d813e2 (patch)
treecb84d2671d2d365f025d8b9bbd714368ed88ce35
parentf2e12534b876e73a0c7c4593acb23ac200529309 (diff)
downloadrbw-b3c69bf88d973af04433d450a659ef1581d813e2.tar.gz
rbw-b3c69bf88d973af04433d450a659ef1581d813e2.zip
stop using the api cipher struct publicly
-rw-r--r--src/actions.rs23
-rw-r--r--src/api.rs47
-rw-r--r--src/bin/rbw-agent/actions.rs4
-rw-r--r--src/bin/rbw/commands.rs60
-rw-r--r--src/db.rs10
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(())
}
diff --git a/src/api.rs b/src/api.rs
index 76aca76..9588b4c 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -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(&notes)?)
};
- 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))
diff --git a/src/db.rs b/src/db.rs
index 95da739..6e73852 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -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 {