diff --git a/Cargo.lock b/Cargo.lock index 5682d5bd1..04b614b68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -169,6 +169,48 @@ dependencies = [ "zeroize", ] +[[package]] +name = "askama" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" +dependencies = [ + "askama_parser", + "basic-toml", + "memchr", + "proc-macro2", + "quote", + "rustc-hash", + "serde", + "serde_derive", + "syn", +] + +[[package]] +name = "askama_parser" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f" +dependencies = [ + "memchr", + "serde", + "serde_derive", + "winnow", +] + [[package]] name = "assert-json-diff" version = "2.0.2" @@ -357,7 +399,6 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tsify", - "uniffi", "wasm-bindgen", "wasm-bindgen-futures", "wiremock", @@ -619,7 +660,6 @@ dependencies = [ "bitwarden-generators", "bitwarden-send", "bitwarden-vault", - "thiserror 1.0.69", "tsify", "uniffi", "wasm-bindgen", @@ -698,6 +738,7 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tsify", + "uniffi", ] [[package]] @@ -947,16 +988,16 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", "semver", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.12", ] [[package]] @@ -1329,7 +1370,7 @@ dependencies = [ "bitflags 2.9.1", "crossterm_winapi", "parking_lot", - "rustix", + "rustix 0.38.44", "winapi", ] @@ -1751,6 +1792,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "ff" version = "0.13.1" @@ -2587,6 +2634,12 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "litemap" version = "0.8.0" @@ -2955,12 +3008,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "pbkdf2" version = "0.12.2" @@ -3453,45 +3500,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rinja" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dc4940d00595430b3d7d5a01f6222b5e5b51395d1120bdb28d854bb8abb17a5" -dependencies = [ - "itoa", - "rinja_derive", -] - -[[package]] -name = "rinja_derive" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d9ed0146aef6e2825f1b1515f074510549efba38d71f4554eec32eb36ba18b" -dependencies = [ - "basic-toml", - "memchr", - "mime", - "mime_guess", - "proc-macro2", - "quote", - "rinja_parser", - "rustc-hash", - "serde", - "syn", -] - -[[package]] -name = "rinja_parser" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f9a866e2e00a7a1fb27e46e9e324a6f7c0e7edc4543cae1d38f4e4a100c610" -dependencies = [ - "memchr", - "nom", - "serde", -] - [[package]] name = "rsa" version = "0.9.8" @@ -3557,10 +3565,23 @@ dependencies = [ "bitflags 2.9.1", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.15", "windows-sys 0.59.0", ] +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.60.2", +] + [[package]] name = "rustls" version = "0.23.28" @@ -4217,6 +4238,19 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" +[[package]] +name = "tempfile" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix 1.0.8", + "windows-sys 0.60.2", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -4424,15 +4458,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.8.23" @@ -4578,7 +4603,7 @@ dependencies = [ "serde_json", "target-triple", "termcolor", - "toml 0.8.23", + "toml", ] [[package]] @@ -4664,9 +4689,8 @@ checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "uniffi" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe34585ac0275accf6c284d0080cc2840f3898c551cda869ec291b5a4218712c" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "anyhow", "camino", @@ -4676,6 +4700,7 @@ dependencies = [ "uniffi_build", "uniffi_core", "uniffi_macros", + "uniffi_pipeline", ] [[package]] @@ -4687,32 +4712,33 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a792af1424cc8b3c43b44c1a6cb7935ed1fbe5584a74f70e8bab9799740266d" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "anyhow", + "askama", "camino", "cargo_metadata", "fs-err", "glob", "goblin", "heck 0.5.0", + "indexmap 2.9.0", "once_cell", - "paste", - "rinja", "serde", + "tempfile", "textwrap", - "toml 0.5.11", + "toml", + "uniffi_internal_macros", "uniffi_meta", + "uniffi_pipeline", "uniffi_udl", ] [[package]] name = "uniffi_build" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c4138211f2ae951018fcce6a978e1fcd1a47c3fd0bc0d5472a520520060db1" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "anyhow", "camino", @@ -4721,9 +4747,8 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c18baace68a52666d33d12d73ca335ecf27a302202cefb53b1f974512bb72417" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "anyhow", "async-compat", @@ -4734,9 +4759,8 @@ dependencies = [ [[package]] name = "uniffi_internal_macros" -version = "0.29.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64bec2f3a33f2f08df8150e67fa45ba59a2ca740bf20c1beb010d4d791f9a1b" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "anyhow", "indexmap 2.9.0", @@ -4747,9 +4771,8 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d82c82ef945c51082d8763635334b994e63e77650f09d0fae6d28dd08b1de83" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "camino", "fs-err", @@ -4758,26 +4781,37 @@ dependencies = [ "quote", "serde", "syn", - "toml 0.5.11", + "toml", "uniffi_meta", ] [[package]] name = "uniffi_meta" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6027b971c2aa86350dd180aee9819729c7b99bacd381534511ff29d2c09cea" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "anyhow", "siphasher", "uniffi_internal_macros", + "uniffi_pipeline", +] + +[[package]] +name = "uniffi_pipeline" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.9.0", + "tempfile", + "uniffi_internal_macros", ] [[package]] name = "uniffi_udl" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52300b7a4ab02dc159a038a13d5bfe27aefbad300d91b0b501b3dda094c1e0a2" +version = "0.29.4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "anyhow", "textwrap", @@ -5047,8 +5081,7 @@ dependencies = [ [[package]] name = "weedle2" version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" +source = "git+https://github.com/mozilla/uniffi-rs?rev=6d46b3f756dde3213357c477d86771a0fc5da7b4#6d46b3f756dde3213357c477d86771a0fc5da7b4" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index b0e39ca59..32c2ac9ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ tokio = { version = "1.36.0", features = ["macros"] } tsify = { version = ">=0.5.5, <0.6", features = [ "js", ], default-features = false } -uniffi = "=0.29.1" +uniffi = "=0.29.4" uuid = { version = ">=1.3.3, <2.0", features = ["serde", "v4", "js"] } validator = { version = ">=0.18.1, <0.21", features = ["derive"] } wasm-bindgen = { version = ">=0.2.91, <0.3", features = ["serde-serialize"] } @@ -92,6 +92,13 @@ wiremock = ">=0.6.0, <0.7" [patch.crates-io] pkcs5 = { git = "https://github.com/bitwarden/rustcrypto-formats.git", rev = "2b27c63034217dd126bbf5ed874da51b84f8c705" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "6d46b3f756dde3213357c477d86771a0fc5da7b4" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "6d46b3f756dde3213357c477d86771a0fc5da7b4" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "6d46b3f756dde3213357c477d86771a0fc5da7b4" } +uniffi_internal_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "6d46b3f756dde3213357c477d86771a0fc5da7b4" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "6d46b3f756dde3213357c477d86771a0fc5da7b4" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "6d46b3f756dde3213357c477d86771a0fc5da7b4" } + [workspace.lints.clippy] unused_async = "deny" unwrap_used = "deny" @@ -99,6 +106,9 @@ string_slice = "warn" [workspace.lints.rust] missing_docs = "warn" +unexpected_cfgs = { level = "warn", check-cfg = [ + 'cfg(feature, values("uniffi", "wasm"))', +] } [workspace.metadata.dylint] libraries = [{ path = "support/lints" }] diff --git a/crates/bitwarden-auth/Cargo.toml b/crates/bitwarden-auth/Cargo.toml index a287bbeb3..416b18449 100644 --- a/crates/bitwarden-auth/Cargo.toml +++ b/crates/bitwarden-auth/Cargo.toml @@ -15,7 +15,6 @@ license-file.workspace = true keywords.workspace = true [features] -uniffi = ["bitwarden-core/uniffi", "dep:uniffi"] # Uniffi bindings wasm = [ "bitwarden-core/wasm", "dep:tsify", @@ -32,7 +31,6 @@ reqwest = { workspace = true } serde = { workspace = true } thiserror = { workspace = true } tsify = { workspace = true, optional = true } -uniffi = { workspace = true, optional = true } wasm-bindgen = { workspace = true, optional = true } wasm-bindgen-futures = { workspace = true, optional = true } diff --git a/crates/bitwarden-core/src/auth/auth_client.rs b/crates/bitwarden-core/src/auth/auth_client.rs index dd5f68ae3..a033b1536 100644 --- a/crates/bitwarden-core/src/auth/auth_client.rs +++ b/crates/bitwarden-core/src/auth/auth_client.rs @@ -206,6 +206,7 @@ impl AuthClient { #[allow(missing_docs)] #[cfg(feature = "internal")] #[derive(Debug, thiserror::Error)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Error), uniffi(flat_error))] pub enum TrustDeviceError { #[error(transparent)] Crypto(#[from] bitwarden_crypto::CryptoError), diff --git a/crates/bitwarden-core/src/auth/auth_request.rs b/crates/bitwarden-core/src/auth/auth_request.rs index 0a9eb8425..098b9d10c 100644 --- a/crates/bitwarden-core/src/auth/auth_request.rs +++ b/crates/bitwarden-core/src/auth/auth_request.rs @@ -75,6 +75,7 @@ pub(crate) fn auth_request_decrypt_master_key( #[allow(missing_docs)] #[derive(Debug, Error)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Error), uniffi(flat_error))] pub enum ApproveAuthRequestError { #[error(transparent)] Crypto(#[from] CryptoError), diff --git a/crates/bitwarden-core/src/auth/mod.rs b/crates/bitwarden-core/src/auth/mod.rs index ab2d7619d..4c9f7ef0a 100644 --- a/crates/bitwarden-core/src/auth/mod.rs +++ b/crates/bitwarden-core/src/auth/mod.rs @@ -51,6 +51,7 @@ pub use key_connector::KeyConnectorResponse; /// Error for authentication related operations #[allow(missing_docs)] #[derive(Debug, Error)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Error), uniffi(flat_error))] pub enum AuthValidateError { #[error(transparent)] NotAuthenticated(#[from] NotAuthenticatedError), diff --git a/crates/bitwarden-core/src/error.rs b/crates/bitwarden-core/src/error.rs index 43c8ae853..9c6c9ba6f 100644 --- a/crates/bitwarden-core/src/error.rs +++ b/crates/bitwarden-core/src/error.rs @@ -30,6 +30,7 @@ macro_rules! impl_bitwarden_error { /// Errors from performing network requests. #[allow(missing_docs)] #[derive(Debug, Error)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Error), uniffi(flat_error))] pub enum ApiError { #[error(transparent)] Reqwest(#[from] reqwest::Error), diff --git a/crates/bitwarden-core/src/platform/generate_fingerprint.rs b/crates/bitwarden-core/src/platform/generate_fingerprint.rs index c17a91fe8..98764b207 100644 --- a/crates/bitwarden-core/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden-core/src/platform/generate_fingerprint.rs @@ -33,6 +33,7 @@ pub struct FingerprintResponse { /// Errors that can occur when computing a fingerprint. #[allow(missing_docs)] #[derive(Debug, Error)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Error))] pub enum FingerprintError { #[error(transparent)] Crypto(#[from] bitwarden_crypto::CryptoError), @@ -48,6 +49,7 @@ pub(crate) fn generate_fingerprint(input: &FingerprintRequest) -> Result Result { - Ok(self - .0 - .auth() - .make_register_keys(email, password, kdf) - .map_err(Error::Crypto)?) + Ok(self.0.auth().make_register_keys(email, password, kdf)?) } /// Generate keys needed for TDE process @@ -74,17 +69,12 @@ impl AuthClient { Ok(self .0 .auth() - .make_register_tde_keys(email, org_public_key, remember_device) - .map_err(Error::EncryptionSettings)?) + .make_register_tde_keys(email, org_public_key, remember_device)?) } /// Generate keys needed to onboard a new user without master key to key connector pub fn make_key_connector_keys(&self) -> Result { - Ok(self - .0 - .auth() - .make_key_connector_keys() - .map_err(Error::Crypto)?) + Ok(self.0.auth().make_key_connector_keys()?) } /// Validate the user password @@ -93,11 +83,7 @@ impl AuthClient { /// `HashPurpose::LocalAuthentication` during login and persist it. If the login method has no /// password, use the email OTP. pub fn validate_password(&self, password: String, password_hash: B64) -> Result { - Ok(self - .0 - .auth() - .validate_password(password, password_hash) - .map_err(Error::AuthValidate)?) + Ok(self.0.auth().validate_password(password, password_hash)?) } /// Validate the user password without knowing the password hash @@ -114,8 +100,7 @@ impl AuthClient { Ok(self .0 .auth() - .validate_password_user_key(password, encrypted_user_key) - .map_err(Error::AuthValidate)?) + .validate_password_user_key(password, encrypted_user_key)?) } /// Validate the user PIN @@ -126,33 +111,21 @@ impl AuthClient { /// This works by comparing the decrypted user key with the current user key, so the client must /// be unlocked. pub fn validate_pin(&self, pin: String, pin_protected_user_key: EncString) -> Result { - Ok(self - .0 - .auth() - .validate_pin(pin, pin_protected_user_key) - .map_err(Error::AuthValidate)?) + Ok(self.0.auth().validate_pin(pin, pin_protected_user_key)?) } /// Initialize a new auth request pub fn new_auth_request(&self, email: String) -> Result { - Ok(self - .0 - .auth() - .new_auth_request(&email) - .map_err(Error::Crypto)?) + Ok(self.0.auth().new_auth_request(&email)?) } /// Approve an auth request pub fn approve_auth_request(&self, public_key: B64) -> Result { - Ok(self - .0 - .auth() - .approve_auth_request(public_key) - .map_err(Error::ApproveAuthRequest)?) + Ok(self.0.auth().approve_auth_request(public_key)?) } /// Trust the current device pub fn trust_device(&self) -> Result { - Ok(self.0.auth().trust_device().map_err(Error::TrustDevice)?) + Ok(self.0.auth().trust_device()?) } } diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 76ae12230..d43881ed0 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -5,7 +5,7 @@ use bitwarden_core::key_management::crypto::{ use bitwarden_crypto::{EncString, Kdf, UnsignedSharedKey}; use bitwarden_encoding::B64; -use crate::error::{Error, Result}; +use crate::error::Result; #[allow(missing_docs)] #[derive(uniffi::Object)] @@ -16,31 +16,19 @@ impl CryptoClient { /// 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 - .initialize_user_crypto(req) - .await - .map_err(Error::EncryptionSettings)?) + Ok(self.0.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 - .initialize_org_crypto(req) - .await - .map_err(Error::EncryptionSettings)?) + Ok(self.0.initialize_org_crypto(req).await?) } /// Get the uses's decrypted encryption key. Note: It's very important /// to keep this key safe, as it can be used to decrypt all of the user's data pub async fn get_user_encryption_key(&self) -> Result { - Ok(self - .0 - .get_user_encryption_key() - .await - .map_err(Error::MobileCrypto)?) + Ok(self.0.get_user_encryption_key().await?) } /// Create the data necessary to update the user's password. The user's encryption key is @@ -56,33 +44,27 @@ impl CryptoClient { /// re-encrypted with the new password. This returns the new encrypted user key and the new /// password hash but does not update sdk state. pub fn make_update_password(&self, new_password: String) -> Result { - Ok(self - .0 - .make_update_password(new_password) - .map_err(Error::MobileCrypto)?) + Ok(self.0.make_update_password(new_password)?) } /// Generates a PIN protected user key from the provided PIN. The result can be stored and later /// used to initialize another client instance by using the PIN and the PIN key with /// `initialize_user_crypto`. pub fn derive_pin_key(&self, pin: String) -> Result { - Ok(self.0.derive_pin_key(pin).map_err(Error::MobileCrypto)?) + Ok(self.0.derive_pin_key(pin)?) } /// Derives the pin protected user key from encrypted pin. Used when pin requires master /// password on first unlock. pub fn derive_pin_user_key(&self, encrypted_pin: EncString) -> Result { - Ok(self - .0 - .derive_pin_user_key(encrypted_pin) - .map_err(Error::MobileCrypto)?) + Ok(self.0.derive_pin_user_key(encrypted_pin)?) } /// Protects the current user key with the provided PIN. The result can be stored and later /// used to initialize another client instance by using the PIN and the PIN key with /// `initialize_user_crypto`. pub fn enroll_pin(&self, pin: String) -> Result { - Ok(self.0.enroll_pin(pin).map_err(Error::MobileCrypto)?) + Ok(self.0.enroll_pin(pin)?) } /// Protects the current user key with the provided PIN. The result can be stored and later @@ -94,32 +76,22 @@ impl CryptoClient { ) -> Result { Ok(self .0 - .enroll_pin_with_encrypted_pin(encrypted_pin.to_string()) - .map_err(Error::MobileCrypto)?) + .enroll_pin_with_encrypted_pin(encrypted_pin.to_string())?) } pub fn enroll_admin_password_reset(&self, public_key: B64) -> Result { - Ok(self - .0 - .enroll_admin_password_reset(public_key) - .map_err(Error::EnrollAdminPasswordReset)?) + Ok(self.0.enroll_admin_password_reset(public_key)?) } /// Derive the master key for migrating to the key connector pub fn derive_key_connector(&self, request: DeriveKeyConnectorRequest) -> Result { - Ok(self - .0 - .derive_key_connector(request) - .map_err(Error::DeriveKeyConnector)?) + Ok(self.0.derive_key_connector(request)?) } /// Create the data necessary to update the user's kdf settings. The user's encryption key is /// re-encrypted for the password under the new kdf settings. This returns the new encrypted /// user key and the new password hash but does not update sdk state. pub fn make_update_kdf(&self, password: String, kdf: Kdf) -> Result { - Ok(self - .0 - .make_update_kdf(password, kdf) - .map_err(Error::MobileCrypto)?) + Ok(self.0.make_update_kdf(password, kdf)?) } } diff --git a/crates/bitwarden-uniffi/src/error.rs b/crates/bitwarden-uniffi/src/error.rs index edf50c31a..23fe3835d 100644 --- a/crates/bitwarden-uniffi/src/error.rs +++ b/crates/bitwarden-uniffi/src/error.rs @@ -1,45 +1,13 @@ -use std::fmt::{Display, Formatter}; - use bitwarden_exporters::ExportError; use bitwarden_generators::{PassphraseError, PasswordError, UsernameError}; +pub type Result = std::result::Result; +pub type Error = BitwardenError; + // Name is converted from *Error to *Exception, so we can't just name the enum Error because // Exception already exists -#[derive(uniffi::Error, Debug)] -#[uniffi(flat_error)] +#[derive(uniffi::Error, thiserror::Error, Debug)] pub enum BitwardenError { - E(Error), - Conversion(Box), -} - -impl From for BitwardenError { - fn from(e: Error) -> Self { - Self::E(e) - } -} - -impl Display for BitwardenError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - Self::E(e) => Display::fmt(e, f), - Self::Conversion(e) => Display::fmt(e, f), - } - } -} - -impl std::error::Error for BitwardenError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - BitwardenError::E(e) => Some(e), - BitwardenError::Conversion(e) => Some(e.as_ref()), - } - } -} - -pub type Result = std::result::Result; - -#[derive(thiserror::Error, Debug)] -pub enum Error { #[error(transparent)] Api(#[from] bitwarden_core::ApiError), #[error(transparent)] @@ -125,4 +93,7 @@ pub enum Error { SshGeneration(#[from] bitwarden_ssh::error::KeyGenerationError), #[error(transparent)] SshImport(#[from] bitwarden_ssh::error::SshKeyImportError), + + #[error("A conversion error occurred: {0}")] + Conversion(String), } diff --git a/crates/bitwarden-uniffi/src/lib.rs b/crates/bitwarden-uniffi/src/lib.rs index 6490e7505..af6322d72 100644 --- a/crates/bitwarden-uniffi/src/lib.rs +++ b/crates/bitwarden-uniffi/src/lib.rs @@ -99,7 +99,7 @@ impl Client { .await .map_err(|e| Error::Api(e.into()))?; - Ok(res.text().await.map_err(|e| Error::Api(e.into()))?) + res.text().await.map_err(|e| Error::Api(e.into())) } } @@ -125,6 +125,6 @@ fn init_logger() { /// Check [`bitwarden_uniffi_error`] for more details fn setup_error_converter() { bitwarden_uniffi_error::set_error_to_uniffi_error(|e| { - crate::error::BitwardenError::Conversion(e).into() + crate::error::BitwardenError::Conversion(e.to_string()).into() }); } diff --git a/crates/bitwarden-uniffi/src/platform/mod.rs b/crates/bitwarden-uniffi/src/platform/mod.rs index bcf4d4a35..f17f91019 100644 --- a/crates/bitwarden-uniffi/src/platform/mod.rs +++ b/crates/bitwarden-uniffi/src/platform/mod.rs @@ -6,7 +6,7 @@ use bitwarden_state::DatabaseConfiguration; use bitwarden_vault::Cipher; use repository::UniffiRepositoryBridge; -use crate::error::{Error, Result}; +use crate::error::Result; mod fido2; mod repository; @@ -18,20 +18,12 @@ pub struct PlatformClient(pub(crate) bitwarden_core::Client); impl PlatformClient { /// Fingerprint (public key) pub fn fingerprint(&self, req: FingerprintRequest) -> Result { - Ok(self - .0 - .platform() - .fingerprint(&req) - .map_err(Error::Fingerprint)?) + Ok(self.0.platform().fingerprint(&req)?) } /// Fingerprint using logged in user's public key pub fn user_fingerprint(&self, fingerprint_material: String) -> Result { - Ok(self - .0 - .platform() - .user_fingerprint(fingerprint_material) - .map_err(Error::UserFingerprint)?) + Ok(self.0.platform().user_fingerprint(fingerprint_material)?) } /// Load feature flags into the client @@ -76,8 +68,8 @@ impl StateClient { .platform() .state() .initialize_database(configuration.into(), migrations) - .await - .map_err(Error::StateRegistry)?; + .await?; + Ok(()) } } diff --git a/crates/bitwarden-uniffi/src/platform/repository.rs b/crates/bitwarden-uniffi/src/platform/repository.rs index 73036fe75..cfe93726d 100644 --- a/crates/bitwarden-uniffi/src/platform/repository.rs +++ b/crates/bitwarden-uniffi/src/platform/repository.rs @@ -15,7 +15,6 @@ impl std::fmt::Debug for UniffiRepositoryBridge { } #[derive(uniffi::Error, thiserror::Error, Debug)] -#[uniffi(flat_error)] pub enum RepositoryError { #[error("Internal error: {0}")] Internal(String), @@ -64,12 +63,7 @@ macro_rules! create_uniffi_repository { async fn has( &self, id: String, - ) -> Result { - match self.get(id).await { - Ok(x) => Ok(x.is_some()), - Err(e) => Err(e), - } - } + ) -> Result; } #[async_trait::async_trait] diff --git a/crates/bitwarden-uniffi/src/tool/mod.rs b/crates/bitwarden-uniffi/src/tool/mod.rs index dc6a168b1..fcd0906c7 100644 --- a/crates/bitwarden-uniffi/src/tool/mod.rs +++ b/crates/bitwarden-uniffi/src/tool/mod.rs @@ -5,7 +5,7 @@ use bitwarden_generators::{ }; use bitwarden_vault::{Cipher, Folder}; -use crate::error::{Error, Result}; +use crate::error::Result; mod sends; pub use sends::SendClient; @@ -20,17 +20,17 @@ pub struct GeneratorClients(pub(crate) bitwarden_generators::GeneratorClient); impl GeneratorClients { /// Generate Password pub fn password(&self, settings: PasswordGeneratorRequest) -> Result { - Ok(self.0.password(settings).map_err(Error::Password)?) + Ok(self.0.password(settings)?) } /// Generate Passphrase pub fn passphrase(&self, settings: PassphraseGeneratorRequest) -> Result { - Ok(self.0.passphrase(settings).map_err(Error::Passphrase)?) + Ok(self.0.passphrase(settings)?) } /// Generate Username pub async fn username(&self, settings: UsernameGeneratorRequest) -> Result { - Ok(self.0.username(settings).await.map_err(Error::Username)?) + Ok(self.0.username(settings).await?) } } @@ -46,10 +46,7 @@ impl ExporterClient { ciphers: Vec, format: ExportFormat, ) -> Result { - Ok(self - .0 - .export_vault(folders, ciphers, format) - .map_err(Error::Export)?) + Ok(self.0.export_vault(folders, ciphers, format)?) } /// Export organization vault @@ -61,8 +58,7 @@ impl ExporterClient { ) -> Result { Ok(self .0 - .export_organization_vault(collections, ciphers, format) - .map_err(Error::Export)?) + .export_organization_vault(collections, ciphers, format)?) } /// Credential Exchange Format (CXF) @@ -72,7 +68,7 @@ impl ExporterClient { /// For use with Apple using [ASCredentialExportManager](https://developer.apple.com/documentation/authenticationservices/ascredentialexportmanager). /// Ideally the output should be immediately deserialized to [ASImportableAccount](https://developer.apple.com/documentation/authenticationservices/asimportableaccount). pub fn export_cxf(&self, account: Account, ciphers: Vec) -> Result { - Ok(self.0.export_cxf(account, ciphers).map_err(Error::Export)?) + Ok(self.0.export_cxf(account, ciphers)?) } /// Credential Exchange Format (CXF) @@ -82,6 +78,6 @@ impl ExporterClient { /// For use with Apple using [ASCredentialExportManager](https://developer.apple.com/documentation/authenticationservices/ascredentialexportmanager). /// Ideally the input should be immediately serialized from [ASImportableAccount](https://developer.apple.com/documentation/authenticationservices/asimportableaccount). pub fn import_cxf(&self, payload: String) -> Result> { - Ok(self.0.import_cxf(payload).map_err(Error::Export)?) + Ok(self.0.import_cxf(payload)?) } } diff --git a/crates/bitwarden-uniffi/src/tool/sends.rs b/crates/bitwarden-uniffi/src/tool/sends.rs index b2e104243..6be523ea5 100644 --- a/crates/bitwarden-uniffi/src/tool/sends.rs +++ b/crates/bitwarden-uniffi/src/tool/sends.rs @@ -2,7 +2,7 @@ use std::path::Path; use bitwarden_send::{Send, SendListView, SendView}; -use crate::{error::Error, Result}; +use crate::Result; #[derive(uniffi::Object)] pub struct SendClient(pub(crate) bitwarden_send::SendClient); @@ -11,15 +11,12 @@ pub struct SendClient(pub(crate) bitwarden_send::SendClient); impl SendClient { /// Encrypt send pub fn encrypt(&self, send: SendView) -> Result { - Ok(self.0.encrypt(send).map_err(Error::SendEncrypt)?) + Ok(self.0.encrypt(send)?) } /// Encrypt a send file in memory pub fn encrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { - Ok(self - .0 - .encrypt_buffer(send, &buffer) - .map_err(Error::SendEncrypt)?) + Ok(self.0.encrypt_buffer(send, &buffer)?) } /// Encrypt a send file located in the file system @@ -29,32 +26,26 @@ impl SendClient { decrypted_file_path: String, encrypted_file_path: String, ) -> Result<()> { - Ok(self - .0 - .encrypt_file( - send, - Path::new(&decrypted_file_path), - Path::new(&encrypted_file_path), - ) - .map_err(Error::SendEncryptFile)?) + Ok(self.0.encrypt_file( + send, + Path::new(&decrypted_file_path), + Path::new(&encrypted_file_path), + )?) } /// Decrypt send pub fn decrypt(&self, send: Send) -> Result { - Ok(self.0.decrypt(send).map_err(Error::SendDecrypt)?) + Ok(self.0.decrypt(send)?) } /// Decrypt send list pub fn decrypt_list(&self, sends: Vec) -> Result> { - Ok(self.0.decrypt_list(sends).map_err(Error::SendDecrypt)?) + Ok(self.0.decrypt_list(sends)?) } /// Decrypt a send file in memory pub fn decrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { - Ok(self - .0 - .decrypt_buffer(send, &buffer) - .map_err(Error::SendDecrypt)?) + Ok(self.0.decrypt_buffer(send, &buffer)?) } /// Decrypt a send file located in the file system @@ -64,13 +55,10 @@ impl SendClient { encrypted_file_path: String, decrypted_file_path: String, ) -> Result<()> { - Ok(self - .0 - .decrypt_file( - send, - Path::new(&encrypted_file_path), - Path::new(&decrypted_file_path), - ) - .map_err(Error::SendDecryptFile)?) + Ok(self.0.decrypt_file( + send, + Path::new(&encrypted_file_path), + Path::new(&decrypted_file_path), + )?) } } diff --git a/crates/bitwarden-uniffi/src/tool/ssh.rs b/crates/bitwarden-uniffi/src/tool/ssh.rs index fdb188e62..42a71011c 100644 --- a/crates/bitwarden-uniffi/src/tool/ssh.rs +++ b/crates/bitwarden-uniffi/src/tool/ssh.rs @@ -1,9 +1,6 @@ use bitwarden_vault::SshKeyView; -use crate::{ - error::{BitwardenError, Error}, - Result, -}; +use crate::Result; #[derive(uniffi::Object)] pub struct SshClient(); @@ -14,8 +11,7 @@ impl SshClient { &self, key_algorithm: bitwarden_ssh::generator::KeyAlgorithm, ) -> Result { - bitwarden_ssh::generator::generate_sshkey(key_algorithm) - .map_err(|e| BitwardenError::E(Error::SshGeneration(e))) + bitwarden_ssh::generator::generate_sshkey(key_algorithm).map_err(Into::into) } pub fn import_ssh_key( @@ -23,7 +19,6 @@ impl SshClient { imported_key: String, password: Option, ) -> Result { - bitwarden_ssh::import::import_key(imported_key, password) - .map_err(|e| BitwardenError::E(Error::SshImport(e))) + bitwarden_ssh::import::import_key(imported_key, password).map_err(Into::into) } } diff --git a/crates/bitwarden-uniffi/src/vault/attachments.rs b/crates/bitwarden-uniffi/src/vault/attachments.rs index 98ffc1a67..095809c80 100644 --- a/crates/bitwarden-uniffi/src/vault/attachments.rs +++ b/crates/bitwarden-uniffi/src/vault/attachments.rs @@ -2,7 +2,7 @@ use std::path::Path; use bitwarden_vault::{Attachment, AttachmentEncryptResult, AttachmentView, Cipher}; -use crate::{error::Error, Result}; +use crate::Result; #[derive(uniffi::Object)] pub struct AttachmentsClient(pub(crate) bitwarden_vault::AttachmentsClient); @@ -16,10 +16,7 @@ impl AttachmentsClient { attachment: AttachmentView, buffer: Vec, ) -> Result { - Ok(self - .0 - .encrypt_buffer(cipher, attachment, &buffer) - .map_err(Error::Encrypt)?) + Ok(self.0.encrypt_buffer(cipher, attachment, &buffer)?) } /// Encrypt an attachment file located in the file system @@ -30,15 +27,12 @@ impl AttachmentsClient { decrypted_file_path: String, encrypted_file_path: String, ) -> Result { - Ok(self - .0 - .encrypt_file( - cipher, - attachment, - Path::new(&decrypted_file_path), - Path::new(&encrypted_file_path), - ) - .map_err(Error::EncryptFile)?) + Ok(self.0.encrypt_file( + cipher, + attachment, + Path::new(&decrypted_file_path), + Path::new(&encrypted_file_path), + )?) } /// Decrypt an attachment file in memory pub fn decrypt_buffer( @@ -47,10 +41,7 @@ impl AttachmentsClient { attachment: AttachmentView, buffer: Vec, ) -> Result> { - Ok(self - .0 - .decrypt_buffer(cipher, attachment, &buffer) - .map_err(Error::Decrypt)?) + Ok(self.0.decrypt_buffer(cipher, attachment, &buffer)?) } /// Decrypt an attachment file located in the file system @@ -61,14 +52,11 @@ impl AttachmentsClient { encrypted_file_path: String, decrypted_file_path: String, ) -> Result<()> { - Ok(self - .0 - .decrypt_file( - cipher, - attachment, - Path::new(&encrypted_file_path), - Path::new(&decrypted_file_path), - ) - .map_err(Error::DecryptFile)?) + Ok(self.0.decrypt_file( + cipher, + attachment, + Path::new(&encrypted_file_path), + Path::new(&decrypted_file_path), + )?) } } diff --git a/crates/bitwarden-uniffi/src/vault/ciphers.rs b/crates/bitwarden-uniffi/src/vault/ciphers.rs index ee55302a0..6508558eb 100644 --- a/crates/bitwarden-uniffi/src/vault/ciphers.rs +++ b/crates/bitwarden-uniffi/src/vault/ciphers.rs @@ -4,7 +4,7 @@ use bitwarden_vault::{ Fido2CredentialView, }; -use crate::{error::Error, Result}; +use crate::Result; #[allow(missing_docs)] #[derive(uniffi::Object)] @@ -14,17 +14,17 @@ pub struct CiphersClient(pub(crate) bitwarden_vault::CiphersClient); impl CiphersClient { /// Encrypt cipher pub fn encrypt(&self, cipher_view: CipherView) -> Result { - Ok(self.0.encrypt(cipher_view).map_err(Error::Encrypt)?) + Ok(self.0.encrypt(cipher_view)?) } /// Decrypt cipher pub fn decrypt(&self, cipher: Cipher) -> Result { - Ok(self.0.decrypt(cipher).map_err(Error::Decrypt)?) + Ok(self.0.decrypt(cipher)?) } /// Decrypt cipher list pub fn decrypt_list(&self, ciphers: Vec) -> Result> { - Ok(self.0.decrypt_list(ciphers).map_err(Error::Decrypt)?) + Ok(self.0.decrypt_list(ciphers)?) } /// Decrypt cipher list with failures @@ -42,10 +42,7 @@ impl CiphersClient { &self, cipher_view: CipherView, ) -> Result> { - Ok(self - .0 - .decrypt_fido2_credentials(cipher_view) - .map_err(Error::Decrypt)?) + Ok(self.0.decrypt_fido2_credentials(cipher_view)?) } /// Move a cipher to an organization, reencrypting the cipher key if necessary @@ -54,9 +51,6 @@ impl CiphersClient { cipher: CipherView, organization_id: OrganizationId, ) -> Result { - Ok(self - .0 - .move_to_organization(cipher, organization_id) - .map_err(Error::Cipher)?) + Ok(self.0.move_to_organization(cipher, organization_id)?) } } diff --git a/crates/bitwarden-uniffi/src/vault/collections.rs b/crates/bitwarden-uniffi/src/vault/collections.rs index 77eb381f6..26e307ffc 100644 --- a/crates/bitwarden-uniffi/src/vault/collections.rs +++ b/crates/bitwarden-uniffi/src/vault/collections.rs @@ -6,7 +6,7 @@ use bitwarden_collections::{ }; use uuid::Uuid; -use crate::{error::Error, Result}; +use crate::Result; #[allow(missing_docs)] #[derive(uniffi::Object)] @@ -16,12 +16,12 @@ pub struct CollectionsClient(pub(crate) bitwarden_vault::collection_client::Coll impl CollectionsClient { /// Decrypt collection pub fn decrypt(&self, collection: Collection) -> Result { - Ok(self.0.decrypt(collection).map_err(Error::Decrypt)?) + Ok(self.0.decrypt(collection)?) } /// Decrypt collection list pub fn decrypt_list(&self, collections: Vec) -> Result> { - Ok(self.0.decrypt_list(collections).map_err(Error::Decrypt)?) + Ok(self.0.decrypt_list(collections)?) } /// diff --git a/crates/bitwarden-uniffi/src/vault/folders.rs b/crates/bitwarden-uniffi/src/vault/folders.rs index 18a108cfd..1273e06bb 100644 --- a/crates/bitwarden-uniffi/src/vault/folders.rs +++ b/crates/bitwarden-uniffi/src/vault/folders.rs @@ -1,6 +1,6 @@ use bitwarden_vault::{Folder, FolderView}; -use crate::{error::Error, Result}; +use crate::Result; #[allow(missing_docs)] #[derive(uniffi::Object)] @@ -10,16 +10,16 @@ pub struct FoldersClient(pub(crate) bitwarden_vault::FoldersClient); impl FoldersClient { /// Encrypt folder pub fn encrypt(&self, folder: FolderView) -> Result { - Ok(self.0.encrypt(folder).map_err(Error::Encrypt)?) + Ok(self.0.encrypt(folder)?) } /// Decrypt folder pub fn decrypt(&self, folder: Folder) -> Result { - Ok(self.0.decrypt(folder).map_err(Error::Decrypt)?) + Ok(self.0.decrypt(folder)?) } /// Decrypt folder list pub fn decrypt_list(&self, folders: Vec) -> Result> { - Ok(self.0.decrypt_list(folders).map_err(Error::Decrypt)?) + Ok(self.0.decrypt_list(folders)?) } } diff --git a/crates/bitwarden-uniffi/src/vault/mod.rs b/crates/bitwarden-uniffi/src/vault/mod.rs index ba7c5b1e5..ec5d83187 100644 --- a/crates/bitwarden-uniffi/src/vault/mod.rs +++ b/crates/bitwarden-uniffi/src/vault/mod.rs @@ -1,7 +1,7 @@ use bitwarden_vault::{CipherListView, TotpResponse}; use chrono::{DateTime, Utc}; -use crate::error::{Error, Result}; +use crate::error::Result; #[allow(missing_docs)] pub mod attachments; @@ -52,11 +52,7 @@ impl VaultClient { /// - OTP Auth URI /// - Steam URI pub fn generate_totp(&self, key: String, time: Option>) -> Result { - Ok(self - .0 - .totp() - .generate_totp(key, time) - .map_err(Error::Totp)?) + Ok(self.0.totp().generate_totp(key, time)?) } /// Generate a TOTP code from a provided cipher list view. @@ -65,10 +61,6 @@ impl VaultClient { view: CipherListView, time: Option>, ) -> Result { - Ok(self - .0 - .totp() - .generate_totp_cipher_view(view, time) - .map_err(Error::Totp)?) + Ok(self.0.totp().generate_totp_cipher_view(view, time)?) } } diff --git a/crates/bitwarden-uniffi/src/vault/password_history.rs b/crates/bitwarden-uniffi/src/vault/password_history.rs index 4aeece64a..61f533b51 100644 --- a/crates/bitwarden-uniffi/src/vault/password_history.rs +++ b/crates/bitwarden-uniffi/src/vault/password_history.rs @@ -1,6 +1,6 @@ use bitwarden_vault::{PasswordHistory, PasswordHistoryView}; -use crate::{error::Error, Result}; +use crate::Result; #[allow(missing_docs)] #[derive(uniffi::Object)] @@ -10,11 +10,11 @@ pub struct PasswordHistoryClient(pub(crate) bitwarden_vault::PasswordHistoryClie impl PasswordHistoryClient { /// Encrypt password history pub fn encrypt(&self, password_history: PasswordHistoryView) -> Result { - Ok(self.0.encrypt(password_history).map_err(Error::Encrypt)?) + Ok(self.0.encrypt(password_history)?) } /// Decrypt password history pub fn decrypt_list(&self, list: Vec) -> Result> { - Ok(self.0.decrypt_list(list).map_err(Error::Decrypt)?) + Ok(self.0.decrypt_list(list)?) } }