From b42278b1abd67a941782ce1a65d94808ba4c1631 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Tue, 7 Jul 2020 00:37:03 +0100 Subject: [PATCH] onep-api -> onep-backend-api & onep-api-op -> onep-backend-op --- Cargo.lock | 10 +++++----- Cargo.toml | 4 ++-- onep-api-op/Cargo.toml | 14 -------------- onep-api-op/src/lib.rs | 301 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- onep-api/Cargo.toml | 9 --------- onep-api/src/lib.rs | 58 ---------------------------------------------------------- onep-backend-api/Cargo.toml | 9 +++++++++ onep-backend-api/src/lib.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ onep-backend-op/Cargo.toml | 14 ++++++++++++++ onep-backend-op/src/lib.rs | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ onep-cli/Cargo.toml | 4 ++-- onep-cli/src/main.rs | 9 +++++---- 12 files changed, 397 insertions(+), 395 deletions(-) delete mode 100644 onep-api-op/Cargo.toml delete mode 100644 onep-api-op/src/lib.rs delete mode 100644 onep-api/Cargo.toml delete mode 100644 onep-api/src/lib.rs create mode 100644 onep-backend-api/Cargo.toml create mode 100644 onep-backend-api/src/lib.rs create mode 100644 onep-backend-op/Cargo.toml create mode 100644 onep-backend-op/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index cce23b2..1214001 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,14 +173,14 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "onep-api" +name = "onep-backend-api" version = "0.1.0" [[package]] -name = "onep-api-op" +name = "onep-backend-op" version = "0.1.0" dependencies = [ - "onep-api 0.1.0", + "onep-backend-api 0.1.0", "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)", "serde_with 1.5.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -195,8 +195,8 @@ dependencies = [ "clap 3.0.0-beta.1 (git+https://github.com/clap-rs/clap)", "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "onep-api 0.1.0", - "onep-api-op 0.1.0", + "onep-backend-api 0.1.0", + "onep-backend-op 0.1.0", "term-table 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 675a161..c376c6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = [ "onep-cli", - "onep-api", - "onep-api-op", + "onep-backend-api", + "onep-backend-op", ] \ No newline at end of file diff --git a/onep-api-op/Cargo.toml b/onep-api-op/Cargo.toml deleted file mode 100644 index f7a4e12..0000000 --- a/onep-api-op/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "onep-api-op" -version = "0.1.0" -authors = ["Jordan Doyle "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -onep-api = { path = "../onep-api" } -serde = { version = "1", features = ["derive"] } -serde_json = "1" -serde_with = "1.5.0-alpha.1" -thiserror = "1.0" \ No newline at end of file diff --git a/onep-api-op/src/lib.rs b/onep-api-op/src/lib.rs deleted file mode 100644 index 8dda8d6..0000000 --- a/onep-api-op/src/lib.rs +++ /dev/null @@ -1,301 +0,0 @@ -#![deny(clippy::pedantic)] - -use serde::Deserialize; -use serde_json::Value; -use std::borrow::Cow; -use std::process::Command; - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("op backend returned an error:\n{0}")] - Backend(String), - #[error("failed to exec backend:\n{0}")] - Exec(std::io::Error), - #[error("failed to parse json from op:\n{0}")] - Json(#[from] serde_json::error::Error), - #[error("failed to convert op response to utf-8:\n{0}")] - Utf8(#[from] std::str::Utf8Error), -} - -#[derive(Debug, Deserialize)] -struct GetAccount { - name: String, - domain: String, -} - -impl Into for GetAccount { - fn into(self) -> onep_api::AccountMetadata { - onep_api::AccountMetadata { - name: self.name, - domain: self.domain, - } - } -} - -#[derive(Debug, Deserialize)] -struct ListVault { - uuid: String, - name: String, -} - -impl Into for ListVault { - fn into(self) -> onep_api::VaultMetadata { - onep_api::VaultMetadata { - uuid: self.uuid, - name: self.name, - } - } -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct ListItem { - uuid: String, - vault_uuid: String, - created_at: String, - updated_at: String, - overview: ItemOverview, -} - -impl Into for ListItem { - fn into(self) -> onep_api::ItemMetadata { - onep_api::ItemMetadata { - title: self.overview.title, - account_info: self.overview.account_info, - uuid: self.uuid, - vault_uuid: self.vault_uuid, - } - } -} - -#[derive(Debug, Deserialize)] -struct ItemOverview { - #[serde(rename = "URLs", default)] - urls: Vec, - title: String, - url: Option, - #[serde(rename = "ainfo")] - account_info: String, - #[serde(default)] - tags: Vec, -} - -#[derive(Debug, Deserialize)] -struct ItemOverviewUrl { - #[serde(rename = "l")] - label: String, - #[serde(rename = "u")] - url: String, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct GetItem { - details: GetItemDetails, - overview: ItemOverview, -} - -impl Into for GetItem { - fn into(self) -> onep_api::Item { - onep_api::Item { - title: self.overview.title, - fields: self - .details - .fields - .into_iter() - .map(|f| f.into()) - .filter(|f: &onep_api::ItemField| !f.value.is_empty()) - .collect(), - sections: self - .details - .sections - .into_iter() - .map(|v| onep_api::ItemSection { - name: v.title, - fields: v - .fields - .into_iter() - .map(|f| f.into()) - .filter(|f: &onep_api::ItemField| !f.value.is_empty()) - .collect(), - }) - .collect(), - } - } -} - -#[derive(Debug, Deserialize)] -struct GetItemDetails { - #[serde(default)] - fields: Vec, - #[serde(default)] - sections: Vec, -} - -#[derive(Debug, Deserialize)] -struct GetItemDetailsField { - name: String, - #[serde(rename = "designation")] - field_type: String, - value: Value, -} - -impl Into for GetItemDetailsField { - fn into(self) -> onep_api::ItemField { - onep_api::ItemField { - name: self.field_type, - value: match self.value { - Value::Null => String::new(), - Value::String(v) => v, - Value::Number(v) => format!("{}", v), - Value::Bool(v) => if v { "true" } else { "false" }.to_string(), - _ => panic!("unknown item field type for {}", self.name), - }, - } - } -} - -#[derive(Debug, Deserialize)] -struct GetItemSection { - title: String, - #[serde(default)] - fields: Vec, -} - -#[derive(Debug, Deserialize)] -struct GetItemSectionField { - #[serde(rename = "k")] - kind: String, - #[serde(rename = "n")] - name: String, - #[serde(rename = "t")] - field_type: String, - #[serde(rename = "v", default)] - value: Value, -} - -impl Into for GetItemSectionField { - fn into(self) -> onep_api::ItemField { - onep_api::ItemField { - name: self.field_type, - value: match self.value { - Value::Null => String::new(), - Value::String(v) => v, - Value::Number(v) => format!("{}", v), - Value::Bool(v) => if v { "true" } else { "false" }.to_string(), - _ => panic!("unknown item field type for {}", self.name), - }, - } - } -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct CreateItem { - uuid: String, - vault_uuid: String, -} - -pub struct OnepasswordOp {} - -fn exec(args: I) -> Result, Error> -where - I: IntoIterator, - S: AsRef, -{ - let cmd = Command::new("op") - .args(args) - .output() - .map_err(Error::Exec)?; - - if cmd.status.success() { - Ok(cmd.stdout) - } else { - Err(Error::Backend( - std::str::from_utf8(&cmd.stderr)?.to_string(), - )) - } -} - -impl onep_api::OnePassword for OnepasswordOp { - type Error = Error; - - fn totp(&self, uuid: &str) -> Result { - Ok(std::str::from_utf8(&exec(&["get", "totp", uuid])?)?.to_string()) - } - - fn account(&self) -> Result { - let ret: GetAccount = serde_json::from_slice(&exec(&["get", "account"])?)?; - - Ok(ret.into()) - } - - fn vaults(&self) -> Result, Self::Error> { - let ret: Vec = serde_json::from_slice(&exec(&["list", "vaults"])?)?; - - Ok(ret.into_iter().map(|v| v.into()).collect()) - } - - #[allow(clippy::filter_map)] - fn search(&self, terms: Option<&str>) -> Result, Self::Error> { - let ret: Vec = serde_json::from_slice(&exec(&["list", "items"])?)?; - - Ok(ret - .into_iter() - .filter(|v| { - if let Some(terms) = terms { - v.uuid == terms - || v.vault_uuid == terms - || v.overview.urls.iter().any(|v| v.url.contains(terms)) - || v.overview.title.contains(terms) - || v.overview.account_info.contains(terms) - || v.overview.tags.iter().any(|v| v.contains(terms)) - } else { - true - } - }) - .map(|v| v.into()) - .collect()) - } - - fn get(&self, uuid: &str) -> Result, Self::Error> { - let ret: GetItem = serde_json::from_slice(&exec(&["get", "item", uuid])?)?; - - Ok(Some(ret.into())) - } - - fn generate( - &self, - name: &str, - username: Option<&str>, - url: Option<&str>, - tags: Option<&str>, - ) -> Result { - let mut args = Vec::with_capacity(12); - - args.push(Cow::Borrowed("create")); - args.push(Cow::Borrowed("item")); - args.push(Cow::Borrowed("Login")); - args.push(Cow::Borrowed("--generate-password")); - args.push(Cow::Borrowed("--title")); - args.push(Cow::Borrowed(name)); - - if let Some(url) = url { - args.push(Cow::Borrowed("--url")); - args.push(Cow::Borrowed(url)); - } - - if let Some(tags) = tags { - args.push(Cow::Borrowed("--tags")); - args.push(Cow::Borrowed(tags)); - } - - if let Some(username) = username { - args.push(Cow::Owned(format!("username={}", username))); - } - - let ret: CreateItem = serde_json::from_slice(&exec(args.iter().map(Cow::as_ref))?)?; - - Ok(self.get(&ret.uuid)?.unwrap_or_else(|| unreachable!())) - } -} diff --git a/onep-api/Cargo.toml b/onep-api/Cargo.toml deleted file mode 100644 index 09bee57..0000000 --- a/onep-api/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "onep-api" -version = "0.1.0" -authors = ["Jordan Doyle "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] \ No newline at end of file diff --git a/onep-api/src/lib.rs b/onep-api/src/lib.rs deleted file mode 100644 index 549fa50..0000000 --- a/onep-api/src/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -#![deny(clippy::pedantic)] -#![allow(clippy::missing_errors_doc)] - -#[derive(Debug)] -pub struct AccountMetadata { - pub name: String, - pub domain: String, -} - -#[derive(Debug)] -pub struct VaultMetadata { - pub uuid: String, - pub name: String, -} - -#[derive(Debug)] -pub struct ItemMetadata { - pub uuid: String, - pub vault_uuid: String, - pub title: String, - pub account_info: String, -} - -#[derive(Debug)] -pub struct Item { - pub title: String, - pub fields: Vec, - pub sections: Vec, -} - -#[derive(Debug)] -pub struct ItemField { - pub name: String, - pub value: String, -} - -#[derive(Debug)] -pub struct ItemSection { - pub name: String, - pub fields: Vec, -} - -pub trait OnePassword { - type Error; - - fn totp(&self, uuid: &str) -> Result; - fn account(&self) -> Result; - fn vaults(&self) -> Result, Self::Error>; - fn search(&self, terms: Option<&str>) -> Result, Self::Error>; - fn get(&self, uuid: &str) -> Result, Self::Error>; - fn generate( - &self, - name: &str, - username: Option<&str>, - url: Option<&str>, - tags: Option<&str>, - ) -> Result; -} diff --git a/onep-backend-api/Cargo.toml b/onep-backend-api/Cargo.toml new file mode 100644 index 0000000..bc6ab17 --- /dev/null +++ b/onep-backend-api/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "onep-backend-api" +version = "0.1.0" +authors = ["Jordan Doyle "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] \ No newline at end of file diff --git a/onep-backend-api/src/lib.rs b/onep-backend-api/src/lib.rs new file mode 100644 index 0000000..2c95300 --- /dev/null +++ b/onep-backend-api/src/lib.rs @@ -0,0 +1,58 @@ +#![deny(clippy::pedantic)] +#![allow(clippy::missing_errors_doc)] + +#[derive(Debug)] +pub struct AccountMetadata { + pub name: String, + pub domain: String, +} + +#[derive(Debug)] +pub struct VaultMetadata { + pub uuid: String, + pub name: String, +} + +#[derive(Debug)] +pub struct ItemMetadata { + pub uuid: String, + pub vault_uuid: String, + pub title: String, + pub account_info: String, +} + +#[derive(Debug)] +pub struct Item { + pub title: String, + pub fields: Vec, + pub sections: Vec, +} + +#[derive(Debug)] +pub struct ItemField { + pub name: String, + pub value: String, +} + +#[derive(Debug)] +pub struct ItemSection { + pub name: String, + pub fields: Vec, +} + +pub trait Backend { + type Error; + + fn totp(&self, uuid: &str) -> Result; + fn account(&self) -> Result; + fn vaults(&self) -> Result, Self::Error>; + fn search(&self, terms: Option<&str>) -> Result, Self::Error>; + fn get(&self, uuid: &str) -> Result, Self::Error>; + fn generate( + &self, + name: &str, + username: Option<&str>, + url: Option<&str>, + tags: Option<&str>, + ) -> Result; +} diff --git a/onep-backend-op/Cargo.toml b/onep-backend-op/Cargo.toml new file mode 100644 index 0000000..b47a10d --- /dev/null +++ b/onep-backend-op/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "onep-backend-op" +version = "0.1.0" +authors = ["Jordan Doyle "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +onep-backend-api = { path = "../onep-backend-api" } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +serde_with = "1.5.0-alpha.1" +thiserror = "1.0" \ No newline at end of file diff --git a/onep-backend-op/src/lib.rs b/onep-backend-op/src/lib.rs new file mode 100644 index 0000000..027998f --- /dev/null +++ b/onep-backend-op/src/lib.rs @@ -0,0 +1,302 @@ +#![deny(clippy::pedantic)] + +use onep_backend_api as api; +use serde::Deserialize; +use serde_json::Value; +use std::borrow::Cow; +use std::process::Command; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("op backend returned an error:\n{0}")] + Backend(String), + #[error("failed to exec backend:\n{0}")] + Exec(std::io::Error), + #[error("failed to parse json from op:\n{0}")] + Json(#[from] serde_json::error::Error), + #[error("failed to convert op response to utf-8:\n{0}")] + Utf8(#[from] std::str::Utf8Error), +} + +#[derive(Debug, Deserialize)] +struct GetAccount { + name: String, + domain: String, +} + +impl Into for GetAccount { + fn into(self) -> api::AccountMetadata { + api::AccountMetadata { + name: self.name, + domain: self.domain, + } + } +} + +#[derive(Debug, Deserialize)] +struct ListVault { + uuid: String, + name: String, +} + +impl Into for ListVault { + fn into(self) -> api::VaultMetadata { + api::VaultMetadata { + uuid: self.uuid, + name: self.name, + } + } +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct ListItem { + uuid: String, + vault_uuid: String, + created_at: String, + updated_at: String, + overview: ItemOverview, +} + +impl Into for ListItem { + fn into(self) -> api::ItemMetadata { + api::ItemMetadata { + title: self.overview.title, + account_info: self.overview.account_info, + uuid: self.uuid, + vault_uuid: self.vault_uuid, + } + } +} + +#[derive(Debug, Deserialize)] +struct ItemOverview { + #[serde(rename = "URLs", default)] + urls: Vec, + title: String, + url: Option, + #[serde(rename = "ainfo")] + account_info: String, + #[serde(default)] + tags: Vec, +} + +#[derive(Debug, Deserialize)] +struct ItemOverviewUrl { + #[serde(rename = "l")] + label: String, + #[serde(rename = "u")] + url: String, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct GetItem { + details: GetItemDetails, + overview: ItemOverview, +} + +impl Into for GetItem { + fn into(self) -> api::Item { + api::Item { + title: self.overview.title, + fields: self + .details + .fields + .into_iter() + .map(|f| f.into()) + .filter(|f: &api::ItemField| !f.value.is_empty()) + .collect(), + sections: self + .details + .sections + .into_iter() + .map(|v| api::ItemSection { + name: v.title, + fields: v + .fields + .into_iter() + .map(|f| f.into()) + .filter(|f: &api::ItemField| !f.value.is_empty()) + .collect(), + }) + .collect(), + } + } +} + +#[derive(Debug, Deserialize)] +struct GetItemDetails { + #[serde(default)] + fields: Vec, + #[serde(default)] + sections: Vec, +} + +#[derive(Debug, Deserialize)] +struct GetItemDetailsField { + name: String, + #[serde(rename = "designation")] + field_type: String, + value: Value, +} + +impl Into for GetItemDetailsField { + fn into(self) -> api::ItemField { + api::ItemField { + name: self.field_type, + value: match self.value { + Value::Null => String::new(), + Value::String(v) => v, + Value::Number(v) => format!("{}", v), + Value::Bool(v) => if v { "true" } else { "false" }.to_string(), + _ => panic!("unknown item field type for {}", self.name), + }, + } + } +} + +#[derive(Debug, Deserialize)] +struct GetItemSection { + title: String, + #[serde(default)] + fields: Vec, +} + +#[derive(Debug, Deserialize)] +struct GetItemSectionField { + #[serde(rename = "k")] + kind: String, + #[serde(rename = "n")] + name: String, + #[serde(rename = "t")] + field_type: String, + #[serde(rename = "v", default)] + value: Value, +} + +impl Into for GetItemSectionField { + fn into(self) -> api::ItemField { + api::ItemField { + name: self.field_type, + value: match self.value { + Value::Null => String::new(), + Value::String(v) => v, + Value::Number(v) => format!("{}", v), + Value::Bool(v) => if v { "true" } else { "false" }.to_string(), + _ => panic!("unknown item field type for {}", self.name), + }, + } + } +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct CreateItem { + uuid: String, + vault_uuid: String, +} + +pub struct OpBackend {} + +fn exec(args: I) -> Result, Error> +where + I: IntoIterator, + S: AsRef, +{ + let cmd = Command::new("op") + .args(args) + .output() + .map_err(Error::Exec)?; + + if cmd.status.success() { + Ok(cmd.stdout) + } else { + Err(Error::Backend( + std::str::from_utf8(&cmd.stderr)?.to_string(), + )) + } +} + +impl api::Backend for OpBackend { + type Error = Error; + + fn totp(&self, uuid: &str) -> Result { + Ok(std::str::from_utf8(&exec(&["get", "totp", uuid])?)?.to_string()) + } + + fn account(&self) -> Result { + let ret: GetAccount = serde_json::from_slice(&exec(&["get", "account"])?)?; + + Ok(ret.into()) + } + + fn vaults(&self) -> Result, Self::Error> { + let ret: Vec = serde_json::from_slice(&exec(&["list", "vaults"])?)?; + + Ok(ret.into_iter().map(|v| v.into()).collect()) + } + + #[allow(clippy::filter_map)] + fn search(&self, terms: Option<&str>) -> Result, Self::Error> { + let ret: Vec = serde_json::from_slice(&exec(&["list", "items"])?)?; + + Ok(ret + .into_iter() + .filter(|v| { + if let Some(terms) = terms { + v.uuid == terms + || v.vault_uuid == terms + || v.overview.urls.iter().any(|v| v.url.contains(terms)) + || v.overview.title.contains(terms) + || v.overview.account_info.contains(terms) + || v.overview.tags.iter().any(|v| v.contains(terms)) + } else { + true + } + }) + .map(|v| v.into()) + .collect()) + } + + fn get(&self, uuid: &str) -> Result, Self::Error> { + let ret: GetItem = serde_json::from_slice(&exec(&["get", "item", uuid])?)?; + + Ok(Some(ret.into())) + } + + fn generate( + &self, + name: &str, + username: Option<&str>, + url: Option<&str>, + tags: Option<&str>, + ) -> Result { + let mut args = Vec::with_capacity(12); + + args.push(Cow::Borrowed("create")); + args.push(Cow::Borrowed("item")); + args.push(Cow::Borrowed("Login")); + args.push(Cow::Borrowed("--generate-password")); + args.push(Cow::Borrowed("--title")); + args.push(Cow::Borrowed(name)); + + if let Some(url) = url { + args.push(Cow::Borrowed("--url")); + args.push(Cow::Borrowed(url)); + } + + if let Some(tags) = tags { + args.push(Cow::Borrowed("--tags")); + args.push(Cow::Borrowed(tags)); + } + + if let Some(username) = username { + args.push(Cow::Owned(format!("username={}", username))); + } + + let ret: CreateItem = serde_json::from_slice(&exec(args.iter().map(Cow::as_ref))?)?; + + Ok(self.get(&ret.uuid)?.unwrap_or_else(|| unreachable!())) + } +} diff --git a/onep-cli/Cargo.toml b/onep-cli/Cargo.toml index 64745e2..9546bce 100644 --- a/onep-cli/Cargo.toml +++ b/onep-cli/Cargo.toml @@ -11,8 +11,8 @@ path = "src/main.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -onep-api = { path = "../onep-api" } -onep-api-op = { path = "../onep-api-op" } +onep-backend-api = { path = "../onep-backend-api" } +onep-backend-op = { path = "../onep-backend-op" } clap = { git = "https://github.com/clap-rs/clap" } term-table = "1.3" diff --git a/onep-cli/src/main.rs b/onep-cli/src/main.rs index a0e07ed..c809d75 100644 --- a/onep-cli/src/main.rs +++ b/onep-cli/src/main.rs @@ -3,7 +3,8 @@ use clap::Clap; use colored::Colorize; use itertools::Itertools; -use onep_api::OnePassword; +use onep_backend_api as api; +use onep_backend_op as backend; use term_table::{ row::Row, table_cell::{Alignment, TableCell}, @@ -53,14 +54,14 @@ enum Opt { } fn main() { - if let Err(e) = run(&onep_api_op::OnepasswordOp {}) { + if let Err(e) = run(&backend::OpBackend {}) { eprintln!("{}", e); std::process::exit(1); } } #[allow(clippy::non_ascii_literal)] -fn run(imp: &T) -> anyhow::Result<()> +fn run(imp: &T) -> anyhow::Result<()> where T::Error: 'static + std::error::Error + Send + Sync, { @@ -167,7 +168,7 @@ where Ok(()) } -fn show(item: onep_api::Item) { +fn show(item: api::Item) { let mut table = Table::new(); table.style = TableStyle::extended(); -- libgit2 1.7.2