diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs index 2ba66c426d3..8b3d097a737 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs @@ -18,10 +18,7 @@ use indexed_db_futures::{prelude::*, web_sys::DomException}; use tracing::info; use wasm_bindgen::JsValue; -use crate::{ - crypto_store::{indexeddb_serializer::IndexeddbSerializer, Result}, - IndexeddbCryptoStoreError, -}; +use crate::{crypto_store::Result, serializer::IndexeddbSerializer, IndexeddbCryptoStoreError}; mod old_keys; mod v0_to_v5; diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v10_to_v11.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v10_to_v11.rs index 11de8b32a90..2e6c1bb2297 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v10_to_v11.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v10_to_v11.rs @@ -19,10 +19,12 @@ use indexed_db_futures::IdbQuerySource; use wasm_bindgen::JsValue; use web_sys::{DomException, IdbTransactionMode}; -use crate::crypto_store::{ - indexeddb_serializer::IndexeddbSerializer, - keys, - migrations::{do_schema_upgrade, old_keys, MigrationDb}, +use crate::{ + crypto_store::{ + keys, + migrations::{do_schema_upgrade, old_keys, MigrationDb}, + }, + serializer::IndexeddbSerializer, }; /// Migrate data from `backup_keys.backup_key_v1` to diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v5_to_v7.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v5_to_v7.rs index 473960b3ff4..dd54665f6a2 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v5_to_v7.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v5_to_v7.rs @@ -26,11 +26,11 @@ use web_sys::{DomException, IdbTransactionMode}; use crate::{ crypto_store::{ - indexeddb_serializer::IndexeddbSerializer, keys, migrations::{add_nonunique_index, do_schema_upgrade, old_keys, v7, MigrationDb}, Result, }, + serializer::IndexeddbSerializer, IndexeddbCryptoStoreError, }; diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7_to_v8.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7_to_v8.rs index 9cba57a7b1f..f6092da2101 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7_to_v8.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7_to_v8.rs @@ -22,10 +22,10 @@ use web_sys::{DomException, IdbTransactionMode}; use crate::{ crypto_store::{ - indexeddb_serializer::IndexeddbSerializer, migrations::{do_schema_upgrade, old_keys, v7, MigrationDb}, Result, }, + serializer::IndexeddbSerializer, IndexeddbCryptoStoreError, }; diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v8_to_v10.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v8_to_v10.rs index e180b56492b..61a8f58da3e 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v8_to_v10.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v8_to_v10.rs @@ -22,7 +22,6 @@ use web_sys::{DomException, IdbTransactionMode}; use crate::{ crypto_store::{ - indexeddb_serializer::IndexeddbSerializer, keys, migrations::{ add_nonunique_index, do_schema_upgrade, old_keys, @@ -30,6 +29,7 @@ use crate::{ }, InboundGroupSessionIndexedDbObject, Result, }, + serializer::IndexeddbSerializer, IndexeddbCryptoStoreError, }; diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs index 520c3d03839..7ffcafa2a20 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs @@ -47,12 +47,11 @@ use tracing::{debug, warn}; use wasm_bindgen::JsValue; use web_sys::IdbKeyRange; -use self::indexeddb_serializer::MaybeEncrypted; -use crate::crypto_store::{ - indexeddb_serializer::IndexeddbSerializer, migrations::open_and_upgrade_db, +use crate::{ + crypto_store::migrations::open_and_upgrade_db, + serializer::{IndexeddbSerializer, IndexeddbSerializerError, MaybeEncrypted}, }; -mod indexeddb_serializer; mod migrations; mod keys { @@ -148,6 +147,20 @@ pub enum IndexeddbCryptoStoreError { SchemaTooNewError { max_supported_version: u32, current_version: u32 }, } +impl From for IndexeddbCryptoStoreError { + fn from(value: IndexeddbSerializerError) -> Self { + match value { + IndexeddbSerializerError::Serialization(error) => Self::Serialization(error), + IndexeddbSerializerError::DomException { code, name, message } => { + Self::DomException { code, name, message } + } + IndexeddbSerializerError::CryptoStoreError(crypto_store_error) => { + Self::CryptoStoreError(crypto_store_error) + } + } + } +} + impl From for IndexeddbCryptoStoreError { fn from(frm: web_sys::DomException) -> IndexeddbCryptoStoreError { IndexeddbCryptoStoreError::DomException { @@ -1141,7 +1154,7 @@ impl_crypto_store! { .object_store(keys::DEVICES)? .get(&key)? .await? - .map(|i| self.serializer.deserialize_value(i)) + .map(|i| self.serializer.deserialize_value(i).map_err(Into::into)) .transpose() } @@ -1178,7 +1191,7 @@ impl_crypto_store! { .object_store(keys::IDENTITIES)? .get(&self.serializer.encode_key(keys::IDENTITIES, user_id))? .await? - .map(|i| self.serializer.deserialize_value(i)) + .map(|i| self.serializer.deserialize_value(i).map_err(Into::into)) .transpose() } @@ -1355,7 +1368,7 @@ impl_crypto_store! { .object_store(keys::ROOM_SETTINGS)? .get(&key)? .await? - .map(|v| self.serializer.deserialize_value(v)) + .map(|v| self.serializer.deserialize_value(v).map_err(Into::into)) .transpose() } @@ -1372,7 +1385,7 @@ impl_crypto_store! { .object_store(keys::CORE)? .get(&JsValue::from_str(key))? .await? - .map(|v| self.serializer.deserialize_value(v)) + .map(|v| self.serializer.deserialize_value(v).map_err(Into::into)) .transpose() } @@ -1769,7 +1782,7 @@ mod unit_tests { use ruma::{device_id, room_id, user_id}; use super::InboundGroupSessionIndexedDbObject; - use crate::crypto_store::indexeddb_serializer::{IndexeddbSerializer, MaybeEncrypted}; + use crate::serializer::{IndexeddbSerializer, MaybeEncrypted}; #[test] fn needs_backup_is_serialized_as_a_u8_in_json() { diff --git a/crates/matrix-sdk-indexeddb/src/lib.rs b/crates/matrix-sdk-indexeddb/src/lib.rs index a828ac6755c..94b2c5b5315 100644 --- a/crates/matrix-sdk-indexeddb/src/lib.rs +++ b/crates/matrix-sdk-indexeddb/src/lib.rs @@ -9,6 +9,8 @@ mod crypto_store; mod safe_encode; #[cfg(feature = "e2e-encryption")] mod serialize_bool_for_indexeddb; +#[cfg(feature = "e2e-encryption")] +mod serializer; #[cfg(feature = "state-store")] mod state_store; diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/indexeddb_serializer.rs b/crates/matrix-sdk-indexeddb/src/serializer.rs similarity index 93% rename from crates/matrix-sdk-indexeddb/src/crypto_store/indexeddb_serializer.rs rename to crates/matrix-sdk-indexeddb/src/serializer.rs index 6237403bba9..0cecf36c05f 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/indexeddb_serializer.rs +++ b/crates/matrix-sdk-indexeddb/src/serializer.rs @@ -27,9 +27,9 @@ use wasm_bindgen::JsValue; use web_sys::IdbKeyRange; use zeroize::Zeroizing; -use crate::{safe_encode::SafeEncode, IndexeddbCryptoStoreError}; +use crate::safe_encode::SafeEncode; -type Result = std::result::Result; +type Result = std::result::Result; const BASE64: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, general_purpose::NO_PAD); @@ -39,6 +39,35 @@ pub struct IndexeddbSerializer { store_cipher: Option>, } +#[derive(Debug, thiserror::Error)] +pub enum IndexeddbSerializerError { + #[error(transparent)] + Serialization(#[from] serde_json::Error), + #[error("DomException {name} ({code}): {message}")] + DomException { + /// DomException code + code: u16, + /// Specific name of the DomException + name: String, + /// Message given to the DomException + message: String, + }, + #[error(transparent)] + CryptoStoreError(#[from] CryptoStoreError), +} + +impl From for IndexeddbSerializerError { + fn from(frm: web_sys::DomException) -> Self { + Self::DomException { name: frm.name(), message: frm.message(), code: frm.code() } + } +} + +impl From for IndexeddbSerializerError { + fn from(e: serde_wasm_bindgen::Error) -> Self { + Self::Serialization(serde::de::Error::custom(e.to_string())) + } +} + #[derive(Debug, Deserialize, Serialize)] #[serde(untagged)] pub enum MaybeEncrypted { @@ -90,7 +119,7 @@ impl IndexeddbSerializer { &self, table_name: &str, key: T, - ) -> Result + ) -> Result where T: SafeEncode, { @@ -98,7 +127,7 @@ impl IndexeddbSerializer { Some(cipher) => key.encode_to_range_secure(table_name, cipher), None => key.encode_to_range(), } - .map_err(|e| IndexeddbCryptoStoreError::DomException { + .map_err(|e| IndexeddbSerializerError::DomException { code: 0, name: "IdbKeyRangeMakeError".to_owned(), message: e, @@ -113,7 +142,7 @@ impl IndexeddbSerializer { pub fn serialize_value( &self, value: &impl Serialize, - ) -> Result { + ) -> Result { let serialized = self.maybe_encrypt_value(value)?; Ok(serde_wasm_bindgen::to_value(&serialized)?) } @@ -167,7 +196,7 @@ impl IndexeddbSerializer { pub fn deserialize_value( &self, value: JsValue, - ) -> Result { + ) -> Result { // Objects which are serialized nowadays should be represented as a // `MaybeEncrypted`. However, `serialize_value` previously used a // different format, so we need to handle that in case we have old data. @@ -221,11 +250,11 @@ impl IndexeddbSerializer { pub fn deserialize_legacy_value( &self, value: JsValue, - ) -> Result { + ) -> Result { match &self.store_cipher { Some(cipher) => { if !value.is_array() { - return Err(IndexeddbCryptoStoreError::CryptoStoreError( + return Err(IndexeddbSerializerError::CryptoStoreError( CryptoStoreError::UnpicklingError, )); }