diff --git a/Cargo.lock b/Cargo.lock index be749ab9..f41be3aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,7 +167,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -216,7 +216,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -353,6 +353,7 @@ dependencies = [ "bitwarden-api-api", "bitwarden-api-identity", "bitwarden-crypto", + "bitwarden-error", "chrono", "getrandom", "hmac", @@ -413,6 +414,35 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bitwarden-error" +version = "1.0.0" +dependencies = [ + "bitwarden-error-macro", + "js-sys", + "serde", + "trybuild", + "tsify-next", + "wasm-bindgen", + "wasm-bindgen-test", +] + +[[package]] +name = "bitwarden-error-macro" +version = "1.0.0" +dependencies = [ + "bitwarden-error", + "darling", + "js-sys", + "proc-macro2", + "quote", + "serde", + "syn 2.0.87", + "thiserror", + "tsify-next", + "wasm-bindgen", +] + [[package]] name = "bitwarden-exporters" version = "1.0.0" @@ -567,6 +597,7 @@ version = "0.1.0" dependencies = [ "bitwarden-core", "bitwarden-crypto", + "bitwarden-error", "bitwarden-vault", "console_error_panic_hook", "console_log", @@ -792,7 +823,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1087,7 +1118,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1098,7 +1129,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1177,7 +1208,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1187,7 +1218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1407,7 +1438,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -1983,6 +2014,16 @@ dependencies = [ "unicase", ] +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2415,9 +2456,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -2818,9 +2859,15 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.82", + "syn 2.0.87", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -2844,7 +2891,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -2923,7 +2970,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -2934,7 +2981,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -2969,7 +3016,16 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", ] [[package]] @@ -3011,7 +3067,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3191,7 +3247,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3204,7 +3260,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3234,9 +3290,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.82" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -3252,6 +3308,12 @@ dependencies = [ "futures-core", ] +[[package]] +name = "target-triple" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" + [[package]] name = "tempfile" version = "3.13.0" @@ -3265,6 +3327,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "textwrap" version = "0.16.1" @@ -3291,7 +3362,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3384,7 +3455,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3420,6 +3491,40 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.3" @@ -3473,6 +3578,21 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "trybuild" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dcd332a5496c026f1e14b7f3d2b7bd98e509660c04239c58b0ba38a12daded4" +dependencies = [ + "glob", + "serde", + "serde_derive", + "serde_json", + "target-triple", + "termcolor", + "toml 0.8.19", +] + [[package]] name = "tsify-next" version = "0.5.4" @@ -3494,7 +3614,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3583,7 +3703,7 @@ dependencies = [ "paste", "serde", "textwrap", - "toml", + "toml 0.5.11", "uniffi_meta", "uniffi_udl", ] @@ -3606,7 +3726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2c801f0f05b06df456a2da4c41b9c2c4fdccc6b9916643c6c67275c4c9e4d07" dependencies = [ "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3638,8 +3758,8 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.82", - "toml", + "syn 2.0.87", + "toml 0.5.11", "uniffi_meta", ] @@ -3741,7 +3861,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -3805,7 +3925,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -3839,7 +3959,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3850,6 +3970,32 @@ version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +[[package]] +name = "wasm-bindgen-test" +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d381749acb0943d357dcbd8f0b100640679883fcdeeef04def49daf8d33a5426" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "minicov", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c97b2ef2c8d627381e51c071c2ab328eac606d3f69dd82bcbca20a9e389d95f0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "web-sys" version = "0.3.72" @@ -4096,6 +4242,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "wiremock" version = "0.6.2" @@ -4138,7 +4293,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] @@ -4159,7 +4314,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.87", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 485747ad..aa14ca88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,8 @@ bitwarden-generators = { path = "crates/bitwarden-generators", version = "=1.0.0 bitwarden-send = { path = "crates/bitwarden-send", version = "=1.0.0" } bitwarden-sm = { path = "bitwarden_license/bitwarden-sm", version = "=1.0.0" } bitwarden-vault = { path = "crates/bitwarden-vault", version = "=1.0.0" } +bitwarden-error = { path = "crates/bitwarden-error", version = "=1.0.0" } +bitwarden-error-macro = { path = "crates/bitwarden-error-macro", version = "=1.0.0" } # External crates that are expected to maintain a consistent version across all crates chrono = { version = ">=0.4.26, <0.5", features = [ @@ -56,6 +58,7 @@ uniffi = "=0.28.1" uuid = { version = ">=1.3.3, <2.0", features = ["serde", "v4"] } validator = { version = "0.18.1", features = ["derive"] } wasm-bindgen = { version = ">=0.2.91, <0.3", features = ["serde-serialize"] } +js-sys = { version = ">=0.3.72, <0.4" } wasm-bindgen-futures = "0.4.41" [workspace.lints.clippy] diff --git a/crates/bitwarden-core/Cargo.toml b/crates/bitwarden-core/Cargo.toml index d212afb7..fe1c6a1c 100644 --- a/crates/bitwarden-core/Cargo.toml +++ b/crates/bitwarden-core/Cargo.toml @@ -20,7 +20,11 @@ no-memory-hardening = [ ] # Disable memory hardening features uniffi = ["bitwarden-crypto/uniffi", "dep:uniffi"] # Uniffi bindings secrets = [] # Secrets manager API -wasm = ["dep:wasm-bindgen", "dep:tsify-next"] # WASM support +wasm = [ + "bitwarden-error/wasm", + "dep:wasm-bindgen", + "dep:tsify-next", +] # WASM support [dependencies] base64 = ">=0.22.1, <0.23" @@ -49,6 +53,7 @@ wasm-bindgen = { workspace = true, optional = true } zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } zxcvbn = { version = ">=3.0.1, <4.0", optional = true } tsify-next = { workspace = true, optional = true } +bitwarden-error = { workspace = true } [target.'cfg(not(target_arch="wasm32"))'.dependencies] # By default, we use rustls as the TLS stack and rust-platform-verifier to support user-installed root certificates diff --git a/crates/bitwarden-core/src/client/encryption_settings.rs b/crates/bitwarden-core/src/client/encryption_settings.rs index 9d954902..467ad61c 100644 --- a/crates/bitwarden-core/src/client/encryption_settings.rs +++ b/crates/bitwarden-core/src/client/encryption_settings.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use bitwarden_crypto::{AsymmetricCryptoKey, CryptoError, KeyContainer, SymmetricCryptoKey}; #[cfg(feature = "internal")] use bitwarden_crypto::{AsymmetricEncString, EncString, MasterKey}; +use bitwarden_error::prelude::*; use thiserror::Error; use uuid::Uuid; @@ -10,6 +11,7 @@ use uuid::Uuid; use crate::error::Result; use crate::VaultLocked; +#[bitwarden_error(flat)] #[derive(Debug, Error)] pub enum EncryptionSettingsError { #[error("Cryptography error, {0}")] diff --git a/crates/bitwarden-core/src/error.rs b/crates/bitwarden-core/src/error.rs index 697ca6c9..c627f374 100644 --- a/crates/bitwarden-core/src/error.rs +++ b/crates/bitwarden-core/src/error.rs @@ -4,6 +4,7 @@ use std::{borrow::Cow, fmt::Debug}; use bitwarden_api_api::apis::Error as ApiError; use bitwarden_api_identity::apis::Error as IdentityError; +use bitwarden_error::prelude::*; use log::debug; use reqwest::StatusCode; use thiserror::Error; @@ -12,6 +13,7 @@ use validator::ValidationErrors; #[cfg(feature = "internal")] use crate::client::encryption_settings::EncryptionSettingsError; +#[bitwarden_error(flat, export_as = "CoreError")] #[derive(Debug, Error)] pub enum Error { #[error(transparent)] diff --git a/crates/bitwarden-error-macro/Cargo.toml b/crates/bitwarden-error-macro/Cargo.toml new file mode 100644 index 00000000..2cdf79a5 --- /dev/null +++ b/crates/bitwarden-error-macro/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "bitwarden-error-macro" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true + +[features] +wasm = ["bitwarden-error/wasm"] + +[dependencies] +darling = "0.20.10" +proc-macro2 = "1.0.89" +quote = "1.0.37" +syn = "2.0.87" + +[lints] +workspace = true + +[lib] +proc-macro = true + +[dev-dependencies] +bitwarden-error.workspace = true +serde.workspace = true +thiserror.workspace = true +tsify-next.workspace = true +js-sys.workspace = true +wasm-bindgen.workspace = true diff --git a/crates/bitwarden-error-macro/src/args.rs b/crates/bitwarden-error-macro/src/args.rs new file mode 100644 index 00000000..aa70fbfa --- /dev/null +++ b/crates/bitwarden-error-macro/src/args.rs @@ -0,0 +1,23 @@ +use darling::FromMeta; + +#[derive(FromMeta)] +pub(crate) struct BitwardenErrorArgs { + #[darling(flatten)] + pub error_type: BitwardenErrorType, + + #[darling(default)] + pub export_as: Option, +} + +#[derive(FromMeta)] +#[darling(rename_all = "snake_case")] +pub(crate) enum BitwardenErrorType { + /// The error is going to be converted into a string using the `ToString` trait + Basic, + + /// The error is going to be converted into a flat error using the `FlatError` trait + Flat, + + /// The entire error stack is going to be made available using `serde` + Full, +} diff --git a/crates/bitwarden-error-macro/src/attribute.rs b/crates/bitwarden-error-macro/src/attribute.rs new file mode 100644 index 00000000..a62593af --- /dev/null +++ b/crates/bitwarden-error-macro/src/attribute.rs @@ -0,0 +1,49 @@ +use darling::{ast::NestedMeta, FromMeta}; +use quote::format_ident; + +use crate::args::{BitwardenErrorArgs, BitwardenErrorType}; + +pub(crate) fn bitwarden_error( + args: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let attr_args = match NestedMeta::parse_meta_list(args.into()) { + Ok(v) => v, + Err(e) => { + return proc_macro::TokenStream::from(darling::Error::from(e).write_errors()); + } + }; + + let args = match BitwardenErrorArgs::from_list(&attr_args) { + Ok(params) => params, + Err(error) => { + return proc_macro::TokenStream::from(error.write_errors()); + } + }; + + let input = syn::parse_macro_input!(item as syn::DeriveInput); + let type_identifier = &input.ident; + let export_as_identifier = &args + .export_as + .as_ref() + .map(|export_as| format_ident!("{}", export_as)) + .unwrap_or(input.ident.clone()); + + match args.error_type { + BitwardenErrorType::Basic => crate::basic::attribute::bitwarden_error_basic( + &input, + type_identifier, + export_as_identifier, + ), + BitwardenErrorType::Flat => crate::flat::attribute::bitwarden_error_flat( + &input, + type_identifier, + export_as_identifier, + ), + BitwardenErrorType::Full => crate::full::attribute::bitwarden_error_full( + &input, + type_identifier, + export_as_identifier, + ), + } +} diff --git a/crates/bitwarden-error-macro/src/basic/attribute.rs b/crates/bitwarden-error-macro/src/basic/attribute.rs new file mode 100644 index 00000000..a900bba2 --- /dev/null +++ b/crates/bitwarden-error-macro/src/basic/attribute.rs @@ -0,0 +1,61 @@ +use quote::quote; + +pub(crate) fn bitwarden_error_basic( + input: &syn::DeriveInput, + type_identifier: &proc_macro2::Ident, + export_as_identifier: &proc_macro2::Ident, +) -> proc_macro::TokenStream { + let wasm = + cfg!(feature = "wasm").then(|| basic_error_wasm(type_identifier, export_as_identifier)); + quote! { + #input + + #wasm + } + .into() +} + +fn basic_error_wasm( + type_identifier: &proc_macro2::Ident, + export_as_identifier: &proc_macro2::Ident, +) -> proc_macro2::TokenStream { + let export_as_identifier_str = export_as_identifier.to_string(); + let is_error_function_name = format!("is{}", export_as_identifier); + let ts_code_str = format!( + r##"r#" + export interface {export_as_identifier} extends Error {{ + name: "{export_as_identifier}"; + }}; + + export function {is_error_function_name}(error: any): error is {export_as_identifier}; + "#"## + ); + let ts_code: proc_macro2::TokenStream = ts_code_str + .parse() + .expect("Could not generate TypeScript code"); + + quote! { + const _: () = { + use bitwarden_error::wasm_bindgen::prelude::*; + + #[wasm_bindgen(typescript_custom_section)] + const TS_APPEND_CONTENT: &'static str = #ts_code; + + #[wasm_bindgen(js_name = #is_error_function_name, skip_typescript)] + pub fn is_error(error: &JsValue) -> bool { + let name_js_value = bitwarden_error::js_sys::Reflect::get(&error, &JsValue::from_str("name")).unwrap_or(JsValue::NULL); + let name = name_js_value.as_string().unwrap_or_default(); + name == #export_as_identifier_str + } + + #[automatically_derived] + impl From<#type_identifier> for JsValue { + fn from(error: #type_identifier) -> Self { + let js_error = SdkJsError::new(error.to_string()); + js_error.set_name(#export_as_identifier_str.to_owned()); + js_error.into() + } + } + }; + } +} diff --git a/crates/bitwarden-error-macro/src/basic/mod.rs b/crates/bitwarden-error-macro/src/basic/mod.rs new file mode 100644 index 00000000..8d46249f --- /dev/null +++ b/crates/bitwarden-error-macro/src/basic/mod.rs @@ -0,0 +1 @@ +pub mod attribute; diff --git a/crates/bitwarden-error-macro/src/flat/attribute.rs b/crates/bitwarden-error-macro/src/flat/attribute.rs new file mode 100644 index 00000000..9af2be59 --- /dev/null +++ b/crates/bitwarden-error-macro/src/flat/attribute.rs @@ -0,0 +1,115 @@ +use quote::quote; +use syn::Data; + +pub(crate) fn bitwarden_error_flat( + input: &syn::DeriveInput, + type_identifier: &proc_macro2::Ident, + export_as_identifier: &proc_macro2::Ident, +) -> proc_macro::TokenStream { + match &input.data { + Data::Enum(data) => { + let variant_names = data.variants.iter().map(|variant| &variant.ident); + let match_arms = data.variants.iter().map(|variant| { + let variant_ident = &variant.ident; + let variant_str = variant_ident.to_string(); + + match variant.fields { + syn::Fields::Unit => { + quote! { + #type_identifier::#variant_ident => #variant_str + } + } + syn::Fields::Named(_) => { + quote! { + #type_identifier::#variant_ident { .. } => #variant_str + } + } + syn::Fields::Unnamed(_) => { + quote! { + #type_identifier::#variant_ident(..) => #variant_str + } + } + } + }); + + let wasm = cfg!(feature = "wasm").then(|| { + flat_error_wasm( + type_identifier, + export_as_identifier, + &variant_names.collect::>(), + ) + }); + + quote! { + #input + #wasm + + #[automatically_derived] + impl ::bitwarden_error::prelude::FlatError for #type_identifier { + fn error_variant(&self) -> &'static str { + match &self { + #(#match_arms), * + } + } + } + } + .into() + } + _ => syn::Error::new_spanned(input, "bitwarden_error can only be used with enums") + .to_compile_error() + .into(), + } +} + +fn flat_error_wasm( + type_identifier: &proc_macro2::Ident, + export_as_identifier: &proc_macro2::Ident, + variant_names: &[&proc_macro2::Ident], +) -> proc_macro2::TokenStream { + let export_as_identifier_str = export_as_identifier.to_string(); + let is_error_function_name = format!("is{}", export_as_identifier); + let ts_variant_names = variant_names + .iter() + .map(|vn| format!(r#""{vn}""#)) + .collect::>() + .join("|"); + let ts_code_str = format!( + r##"r#" + export interface {export_as_identifier_str} extends Error {{ + name: "{export_as_identifier_str}"; + variant: {ts_variant_names}; + }}; + + export function {is_error_function_name}(error: any): error is {export_as_identifier_str}; + "#"##, + ); + let ts_code: proc_macro2::TokenStream = ts_code_str + .parse() + .expect("Could not generate TypeScript code"); + + quote! { + const _: () = { + use bitwarden_error::wasm_bindgen::prelude::*; + + #[wasm_bindgen(typescript_custom_section)] + const TS_APPEND_CONTENT: &'static str = #ts_code; + + #[wasm_bindgen(js_name = #is_error_function_name, skip_typescript)] + pub fn is_error(error: &JsValue) -> bool { + let name_js_value = bitwarden_error::js_sys::Reflect::get(&error, &JsValue::from_str("name")).unwrap_or(JsValue::NULL); + let name = name_js_value.as_string().unwrap_or_default(); + name == #export_as_identifier_str + } + + #[automatically_derived] + impl From<#type_identifier> for JsValue { + fn from(error: #type_identifier) -> Self { + let js_error = SdkJsError::new(error.to_string()); + js_error.set_name(#export_as_identifier_str.to_owned()); + js_error.set_variant(error.error_variant().to_owned()); + js_error.into() + } + } + }; + } +} diff --git a/crates/bitwarden-error-macro/src/flat/mod.rs b/crates/bitwarden-error-macro/src/flat/mod.rs new file mode 100644 index 00000000..8d46249f --- /dev/null +++ b/crates/bitwarden-error-macro/src/flat/mod.rs @@ -0,0 +1 @@ +pub mod attribute; diff --git a/crates/bitwarden-error-macro/src/full/attribute.rs b/crates/bitwarden-error-macro/src/full/attribute.rs new file mode 100644 index 00000000..88ad8d86 --- /dev/null +++ b/crates/bitwarden-error-macro/src/full/attribute.rs @@ -0,0 +1,28 @@ +use darling::Error; +use quote::quote; + +pub(crate) fn bitwarden_error_full( + input: &syn::DeriveInput, + type_identifier: &proc_macro2::Ident, + export_as_identifier: &proc_macro2::Ident, +) -> proc_macro::TokenStream { + if type_identifier != export_as_identifier { + return Error::custom("`bitwarden_error(full)` does not currently support `export_as`") + .write_errors() + .into(); + } + + let wasm_attributes = cfg!(feature = "wasm").then(|| { + quote! { + #[derive(bitwarden_error::tsify_next::Tsify)] + #[tsify(into_wasm_abi)] + } + }); + + quote! { + #[derive(serde::Serialize)] + #wasm_attributes + #input + } + .into() +} diff --git a/crates/bitwarden-error-macro/src/full/mod.rs b/crates/bitwarden-error-macro/src/full/mod.rs new file mode 100644 index 00000000..8d46249f --- /dev/null +++ b/crates/bitwarden-error-macro/src/full/mod.rs @@ -0,0 +1 @@ +pub mod attribute; diff --git a/crates/bitwarden-error-macro/src/lib.rs b/crates/bitwarden-error-macro/src/lib.rs new file mode 100644 index 00000000..01f8b887 --- /dev/null +++ b/crates/bitwarden-error-macro/src/lib.rs @@ -0,0 +1,120 @@ +mod args; +mod attribute; +mod basic; +mod flat; +mod full; + +/// A procedural macro for generating error types with customizable serialization behavior. +/// +/// # Attributes +/// +/// ## Error type + +/// - `basic`: The error is converted into a string using the `ToString` trait. +/// - `flat`: The error is converted into a flat structure using the `FlatError` trait. +/// - `full`: The entire error stack is made available using `serde`. +/// +/// ## Export as +/// +/// `export_as`: The name of the exported TypeScript type. If not provided, the name of the Rust +/// type is used. Note: This attribute is only available when using the `basic` and `flat` error +/// types. +/// +/// # Examples +/// +/// ## Basic +/// Using the `basic` error type: +/// +/// ```rust +/// use bitwarden_error::prelude::*; +/// use thiserror::Error; +/// +/// #[derive(Debug, Error)] +/// #[bitwarden_error(basic)] +/// enum MyError { +/// #[error("Not found")] +/// NotFound, +/// #[error("Permission denied")] +/// PermissionDenied, +/// } +/// ``` +/// +/// will generate the following TypeScript definition: +/// +/// ```typescript +/// export interface MyError extends Error { +/// name: "MyError"; +/// } +/// ``` +/// +/// ## Flat +/// +/// Using the `flat` error type: +/// +/// ```rust +/// use bitwarden_error::prelude::*; +/// use thiserror::Error; +/// +/// #[derive(Debug, Error)] +/// #[bitwarden_error(basic)] +/// enum MyError { +/// #[error("Not found")] +/// NotFound, +/// #[error("Permission denied")] +/// PermissionDenied, +/// } +/// ``` +/// +/// will generate the following TypeScript definition: +/// +/// ```typescript +/// export interface MyError extends Error { +/// name: "MyError"; +/// variant: "NotFound" | "PermissionDenied"; +/// } +/// ``` +/// +/// Using the `full` error type: +/// +/// ```rust +/// use bitwarden_error::prelude::*; +/// use serde::Serialize; +/// use thiserror::Error; +/// +/// #[bitwarden_error(full)] +/// #[derive(Debug, Error)] +/// #[error("Vault is locked")] +/// struct VaultLocked; +/// +/// #[derive(Debug, Serialize)] +/// struct ExternalError; +/// +/// #[bitwarden_error(full)] +/// #[derive(Debug, Error)] +/// enum MyError { +/// #[error(transparent)] +/// VaultLocked(#[from] VaultLocked), +/// #[error("External error")] +/// ExternalError(ExternalError), +/// } +/// ``` +/// +/// will use tsify_next::Tsify to generate roughly the following TypeScript definition: +/// +/// ```typescript +/// export type CryptoError = +/// | { MissingFieldError: MissingFieldError } +/// | { VaultLocked: VaultLocked }; +/// +/// export interface VaultLocked { } +/// ``` +/// +/// All the general interopability rules apply such as external types needing to be defined as +/// custom types. +#[proc_macro_attribute] +pub fn bitwarden_error( + args: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + attribute::bitwarden_error(args, item) +} diff --git a/crates/bitwarden-error/.cargo/config b/crates/bitwarden-error/.cargo/config new file mode 100644 index 00000000..4ec2f3b8 --- /dev/null +++ b/crates/bitwarden-error/.cargo/config @@ -0,0 +1,2 @@ +[target.wasm32-unknown-unknown] +runner = 'wasm-bindgen-test-runner' diff --git a/crates/bitwarden-error/Cargo.toml b/crates/bitwarden-error/Cargo.toml new file mode 100644 index 00000000..5c6aaa42 --- /dev/null +++ b/crates/bitwarden-error/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "bitwarden-error" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true + +[features] +wasm = [ + "bitwarden-error-macro/wasm", + "dep:js-sys", + "dep:tsify-next", + "dep:wasm-bindgen", +] + +[dependencies] +bitwarden-error-macro = { workspace = true } +js-sys = { workspace = true, optional = true } +tsify-next = { workspace = true, optional = true } +wasm-bindgen = { workspace = true, optional = true } + +[lints] +workspace = true + +[dev-dependencies] +serde.workspace = true +trybuild = "1.0.101" +wasm-bindgen-test = "0.3.45" diff --git a/crates/bitwarden-error/src/flat_error.rs b/crates/bitwarden-error/src/flat_error.rs new file mode 100644 index 00000000..78c19dc3 --- /dev/null +++ b/crates/bitwarden-error/src/flat_error.rs @@ -0,0 +1,3 @@ +pub trait FlatError { + fn error_variant(&self) -> &'static str; +} diff --git a/crates/bitwarden-error/src/lib.rs b/crates/bitwarden-error/src/lib.rs new file mode 100644 index 00000000..24e59ab5 --- /dev/null +++ b/crates/bitwarden-error/src/lib.rs @@ -0,0 +1,25 @@ +pub mod flat_error; + +#[cfg(feature = "wasm")] +pub mod wasm; + +/// Re-export the `js_sys` crate since the proc macro depends on it. +#[cfg(feature = "wasm")] +#[doc(hidden)] +pub use ::js_sys; +/// Re-export the `tsify_next` crate since the proc macro depends on it. +#[cfg(feature = "wasm")] +#[doc(hidden)] +pub use ::tsify_next; +/// Re-export the `wasm_bindgen` crate since the proc macro depends on it. +#[cfg(feature = "wasm")] +#[doc(hidden)] +pub use ::wasm_bindgen; + +pub mod prelude { + pub use bitwarden_error_macro::*; + + pub use crate::flat_error::FlatError; + #[cfg(feature = "wasm")] + pub use crate::wasm::SdkJsError; +} diff --git a/crates/bitwarden-error/src/wasm.rs b/crates/bitwarden-error/src/wasm.rs new file mode 100644 index 00000000..1489631f --- /dev/null +++ b/crates/bitwarden-error/src/wasm.rs @@ -0,0 +1,25 @@ +use wasm_bindgen::prelude::*; + +#[cfg_attr(feature = "wasm", wasm_bindgen)] +extern "C" { + #[wasm_bindgen(js_name = Error)] + pub type SdkJsError; + + #[wasm_bindgen(constructor, js_class = Error)] + pub fn new(message: String) -> SdkJsError; + + #[wasm_bindgen(method, getter, structural)] + pub fn message(this: &SdkJsError) -> String; + + #[wasm_bindgen(method, getter, structural)] + pub fn name(this: &SdkJsError) -> String; + + #[wasm_bindgen(method, setter, structural)] + pub fn set_name(this: &SdkJsError, name: String); + + #[wasm_bindgen(method, getter, structural)] + pub fn variant(this: &SdkJsError) -> String; + + #[wasm_bindgen(method, setter, structural)] + pub fn set_variant(this: &SdkJsError, variant: String); +} diff --git a/crates/bitwarden-error/tests/basic.rs b/crates/bitwarden-error/tests/basic.rs new file mode 100644 index 00000000..f029edd6 --- /dev/null +++ b/crates/bitwarden-error/tests/basic.rs @@ -0,0 +1,52 @@ +#[cfg(feature = "wasm")] +use wasm_bindgen_test::*; + +#[wasm_bindgen_test] +#[cfg(feature = "wasm")] +#[allow(dead_code)] // Not actually dead, but rust-analyzer doesn't understand `wasm_bindgen_test` +fn converts_to_js_error_using_to_string() { + use std::fmt::Display; + + use bitwarden_error::prelude::*; + use wasm_bindgen::JsValue; + + #[bitwarden_error(basic)] + struct SomeError; + impl Display for SomeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "This is an error") + } + } + + let simple = SomeError; + let js_value: JsValue = simple.into(); + + let js_error = SdkJsError::from(js_value); + assert_eq!(js_error.name(), "SomeError"); + assert_eq!(js_error.message(), "This is an error"); +} + +#[wasm_bindgen_test] +#[cfg(feature = "wasm")] +#[allow(dead_code)] // Not actually dead, but rust-analyzer doesn't understand `wasm_bindgen_test` +fn outputs_different_name_when_given_export_as() { + use std::fmt::Display; + + use bitwarden_error::prelude::*; + use wasm_bindgen::JsValue; + + #[bitwarden_error(basic, export_as = "SomeOtherError")] + struct SomeError; + impl Display for SomeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "This is an error") + } + } + + let simple = SomeError; + let js_value: JsValue = simple.into(); + + let js_error = SdkJsError::from(js_value); + assert_eq!(js_error.name(), "SomeOtherError"); + assert_eq!(js_error.message(), "This is an error"); +} diff --git a/crates/bitwarden-error/tests/compilation_tests/full.rs b/crates/bitwarden-error/tests/compilation_tests/full.rs new file mode 100644 index 00000000..9e8d3125 --- /dev/null +++ b/crates/bitwarden-error/tests/compilation_tests/full.rs @@ -0,0 +1,7 @@ +use bitwarden_error::prelude::*; + +/// Full errors do not support changing the name of the error in the generated JS +#[bitwarden_error(full, export_as = "SomeOtherError")] +struct SomeError; + +fn main() {} diff --git a/crates/bitwarden-error/tests/compilation_tests/full.stderr b/crates/bitwarden-error/tests/compilation_tests/full.stderr new file mode 100644 index 00000000..f25ad6ce --- /dev/null +++ b/crates/bitwarden-error/tests/compilation_tests/full.stderr @@ -0,0 +1,7 @@ +error: `bitwarden_error(full)` does not currently support `export_as` + --> tests/compilation_tests/full.rs:4:1 + | +4 | #[bitwarden_error(full, export_as = "SomeOtherError")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `bitwarden_error` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/bitwarden-error/tests/flat.rs b/crates/bitwarden-error/tests/flat.rs new file mode 100644 index 00000000..e9ed0146 --- /dev/null +++ b/crates/bitwarden-error/tests/flat.rs @@ -0,0 +1,133 @@ +use std::fmt::Display; + +use bitwarden_error::prelude::*; +#[cfg(feature = "wasm")] +use wasm_bindgen_test::*; + +#[test] +fn variant_for_basic_enum() { + #[bitwarden_error(flat)] + enum SimpleError { + Foo, + Bar, + Baz, + } + + impl Display for SimpleError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "This is an error") + } + } + + let foo = SimpleError::Foo; + let bar = SimpleError::Bar; + let baz = SimpleError::Baz; + + assert_eq!(foo.error_variant(), "Foo"); + assert_eq!(bar.error_variant(), "Bar"); + assert_eq!(baz.error_variant(), "Baz"); +} + +#[test] +fn variant_for_enum_with_fields() { + #[allow(dead_code)] + #[bitwarden_error(flat)] + enum ComplexError { + Foo(String), + Bar { x: i32, y: i32 }, + Baz(bool, bool), + } + impl Display for ComplexError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "This is an error") + } + } + + let foo = ComplexError::Foo("hello".to_string()); + let bar = ComplexError::Bar { x: 1, y: 2 }; + let baz = ComplexError::Baz(true, true); + + assert_eq!(foo.error_variant(), "Foo"); + assert_eq!(bar.error_variant(), "Bar"); + assert_eq!(baz.error_variant(), "Baz"); +} + +#[test] +#[cfg(feature = "wasm")] +fn variant_names_for_enum() { + #[allow(dead_code)] + #[bitwarden_error(flat)] + enum SimpleEnum { + Foo, + Bar, + Baz, + } + impl Display for SimpleEnum { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "This is an error") + } + } + + // TODO: Not sure how to test this yet + // let types = TS_TYPES_SimpleError; + // assert_eq!( + // types, + // r#" + // export const TS_TYPES_SimpleError = ""; + // "# + // ); +} + +#[wasm_bindgen_test] +#[cfg(feature = "wasm")] +#[allow(dead_code)] // Not actually dead, but rust-analyzer doesn't understand `wasm_bindgen_test` +fn converts_to_js_error() { + use wasm_bindgen::JsValue; + + #[bitwarden_error(flat)] + enum FlatEnum { + Foo, + Bar, + Baz, + } + impl Display for FlatEnum { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "This is an error") + } + } + + let simple = FlatEnum::Baz; + let js_value: JsValue = simple.into(); + + let js_error = SdkJsError::from(js_value); + assert_eq!(js_error.name(), "FlatEnum"); + assert_eq!(js_error.message(), "This is an error"); + assert_eq!(js_error.variant(), "Baz"); +} + +#[wasm_bindgen_test] +#[cfg(feature = "wasm")] +#[allow(dead_code)] // Not actually dead, but rust-analyzer doesn't understand `wasm_bindgen_test` +fn outputs_different_name_when_given_export_as() { + use wasm_bindgen::JsValue; + + #[bitwarden_error(flat, export_as = "SomeOtherEnum")] + enum FlatEnum { + Foo, + Bar, + Baz, + } + impl Display for FlatEnum { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "This is an error") + } + } + + let simple = FlatEnum::Baz; + let js_value: JsValue = simple.into(); + + let js_error = SdkJsError::from(js_value); + assert_eq!(js_error.name(), "SomeOtherEnum"); + assert_eq!(js_error.message(), "This is an error"); + assert_eq!(js_error.variant(), "Baz"); +} diff --git a/crates/bitwarden-error/tests/full.rs b/crates/bitwarden-error/tests/full.rs new file mode 100644 index 00000000..6b6598a6 --- /dev/null +++ b/crates/bitwarden-error/tests/full.rs @@ -0,0 +1,27 @@ +#[cfg(feature = "wasm")] +use wasm_bindgen_test::*; + +#[allow(dead_code)] +// Not actually dead, but rust-analyzer doesn't understand `wasm_bindgen_test` +#[wasm_bindgen_test] +#[cfg(feature = "wasm")] +// `full` errors are just forwarded to TSify and Serde so this is just a smoke test +fn converts_to_js() { + use bitwarden_error::prelude::*; + use wasm_bindgen::JsValue; + + #[bitwarden_error(full)] + enum SomeError { + Foo(String), + Bar(String), + Baz(String), + } + + let simple = SomeError::Baz("This is an error".to_string()); + let js_value: JsValue = simple.into(); + + // Errors only natively support rust -> js and so we use Reflect to get the value straight from + // the JSValue + let value = js_sys::Reflect::get(&js_value, &JsValue::from("Baz")).unwrap_or(JsValue::NULL); + assert_eq!(value.as_string().unwrap_or_default(), "This is an error"); +} diff --git a/crates/bitwarden-error/tests/mod.rs b/crates/bitwarden-error/tests/mod.rs new file mode 100644 index 00000000..b4c7c258 --- /dev/null +++ b/crates/bitwarden-error/tests/mod.rs @@ -0,0 +1,9 @@ +mod basic; +mod flat; +mod full; + +#[test] +fn compilation_tests() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/compilation_tests/*.rs"); +} diff --git a/crates/bitwarden-wasm-internal/Cargo.toml b/crates/bitwarden-wasm-internal/Cargo.toml index 33f8128e..41639d10 100644 --- a/crates/bitwarden-wasm-internal/Cargo.toml +++ b/crates/bitwarden-wasm-internal/Cargo.toml @@ -17,6 +17,7 @@ crate-type = ["cdylib"] [dependencies] bitwarden-core = { workspace = true, features = ["wasm", "internal"] } bitwarden-crypto = { workspace = true, features = ["wasm"] } +bitwarden-error = { version = "1.0.0", path = "../bitwarden-error" } bitwarden-vault = { workspace = true, features = ["wasm"] } console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } diff --git a/crates/bitwarden-wasm-internal/src/client.rs b/crates/bitwarden-wasm-internal/src/client.rs index a824b427..c42534df 100644 --- a/crates/bitwarden-wasm-internal/src/client.rs +++ b/crates/bitwarden-wasm-internal/src/client.rs @@ -1,7 +1,8 @@ extern crate console_error_panic_hook; -use std::rc::Rc; +use std::{fmt::Display, rc::Rc}; use bitwarden_core::{Client, ClientSettings}; +use bitwarden_error::prelude::*; use log::{set_max_level, Level}; use wasm_bindgen::prelude::*; @@ -53,8 +54,8 @@ impl BitwardenClient { env!("SDK_VERSION").to_owned() } - pub fn throw(&self, msg: String) -> Result<(), crate::error::GenericError> { - Err(crate::error::GenericError(msg)) + pub async fn throw(&self, msg: String) -> Result<(), TestError> { + Err(TestError(msg)) } /// Test method, calls http endpoint @@ -73,3 +74,12 @@ impl BitwardenClient { ClientVault::new(self.0.clone()) } } + +#[bitwarden_error(basic)] +pub struct TestError(String); + +impl Display for TestError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} diff --git a/crates/bitwarden-wasm-internal/src/crypto.rs b/crates/bitwarden-wasm-internal/src/crypto.rs index 9b89ffa7..1f9a3b48 100644 --- a/crates/bitwarden-wasm-internal/src/crypto.rs +++ b/crates/bitwarden-wasm-internal/src/crypto.rs @@ -1,6 +1,7 @@ use std::rc::Rc; use bitwarden_core::{ + client::encryption_settings::EncryptionSettingsError, mobile::crypto::{ InitOrgCryptoRequest, InitUserCryptoRequest, MakeKeyPairResponse, VerifyAsymmetricKeysRequest, VerifyAsymmetricKeysResponse, @@ -9,8 +10,6 @@ use bitwarden_core::{ }; use wasm_bindgen::prelude::*; -use crate::error::Result; - #[wasm_bindgen] pub struct ClientCrypto(Rc); @@ -24,20 +23,29 @@ impl ClientCrypto { impl ClientCrypto { /// Initialization method for the user crypto. Needs to be called before any other crypto /// operations. - pub async fn initialize_user_crypto(&self, req: InitUserCryptoRequest) -> Result<()> { - Ok(self.0.crypto().initialize_user_crypto(req).await?) + pub async fn initialize_user_crypto( + &self, + req: InitUserCryptoRequest, + ) -> Result<(), EncryptionSettingsError> { + self.0.crypto().initialize_user_crypto(req).await } /// Initialization method for the organization crypto. Needs to be called after /// `initialize_user_crypto` but before any other crypto operations. - pub async fn initialize_org_crypto(&self, req: InitOrgCryptoRequest) -> Result<()> { - Ok(self.0.crypto().initialize_org_crypto(req).await?) + pub async fn initialize_org_crypto( + &self, + req: InitOrgCryptoRequest, + ) -> Result<(), EncryptionSettingsError> { + self.0.crypto().initialize_org_crypto(req).await } /// Generates a new key pair and encrypts the private key with the provided user key. /// Crypto initialization not required. - pub fn make_key_pair(&self, user_key: String) -> Result { - Ok(self.0.crypto().make_key_pair(user_key)?) + pub fn make_key_pair( + &self, + user_key: String, + ) -> Result { + self.0.crypto().make_key_pair(user_key) } /// Verifies a user's asymmetric keys by decrypting the private key with the provided user @@ -46,7 +54,7 @@ impl ClientCrypto { pub fn verify_asymmetric_keys( &self, request: VerifyAsymmetricKeysRequest, - ) -> Result { - Ok(self.0.crypto().verify_asymmetric_keys(request)?) + ) -> Result { + self.0.crypto().verify_asymmetric_keys(request) } } diff --git a/crates/bitwarden-wasm-internal/src/error.rs b/crates/bitwarden-wasm-internal/src/error.rs deleted file mode 100644 index 237ee494..00000000 --- a/crates/bitwarden-wasm-internal/src/error.rs +++ /dev/null @@ -1,28 +0,0 @@ -use wasm_bindgen::prelude::*; - -// Importing an error class defined in JavaScript instead of defining it in Rust -// allows us to extend the `Error` class. It also provides much better console output. -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(js_name = Error)] - type JsError; - - #[wasm_bindgen(constructor, js_class = Error)] - fn new(message: String) -> JsError; -} - -pub type Result = std::result::Result; - -pub struct GenericError(pub String); - -impl From for GenericError { - fn from(error: T) -> Self { - GenericError(error.to_string()) - } -} - -impl From for JsValue { - fn from(error: GenericError) -> Self { - JsError::new(error.0).into() - } -} diff --git a/crates/bitwarden-wasm-internal/src/lib.rs b/crates/bitwarden-wasm-internal/src/lib.rs index 6367ff31..6f3516a9 100644 --- a/crates/bitwarden-wasm-internal/src/lib.rs +++ b/crates/bitwarden-wasm-internal/src/lib.rs @@ -1,7 +1,6 @@ mod client; mod crypto; mod custom_types; -mod error; mod vault; pub use client::BitwardenClient; diff --git a/crates/bitwarden-wasm-internal/src/vault/folders.rs b/crates/bitwarden-wasm-internal/src/vault/folders.rs index 65289269..8cb110a6 100644 --- a/crates/bitwarden-wasm-internal/src/vault/folders.rs +++ b/crates/bitwarden-wasm-internal/src/vault/folders.rs @@ -4,8 +4,6 @@ use bitwarden_core::Client; use bitwarden_vault::{ClientVaultExt, Folder, FolderView}; use wasm_bindgen::prelude::*; -use crate::error::Result; - #[wasm_bindgen] pub struct ClientFolders(Rc); @@ -18,7 +16,7 @@ impl ClientFolders { #[wasm_bindgen] impl ClientFolders { /// Decrypt folder - pub fn decrypt(&self, folder: Folder) -> Result { - Ok(self.0.vault().folders().decrypt(folder)?) + pub fn decrypt(&self, folder: Folder) -> Result { + self.0.vault().folders().decrypt(folder) } }