From 80791860fea475c9e2dae6153b8a31e87c1c8fe8 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 19 Apr 2022 09:23:29 +0200 Subject: [PATCH] fixing style and typos --- .../src/store/integration_tests.rs | 2 +- .../matrix-sdk-indexeddb/src/safe_encode.rs | 58 +++--- .../matrix-sdk-indexeddb/src/state_store.rs | 162 +++++++++++------ crates/matrix-sdk-sled/src/cryptostore.rs | 1 - crates/matrix-sdk-sled/src/encode_key.rs | 50 ++---- crates/matrix-sdk-sled/src/state_store.rs | 167 +++++++++++++----- crates/matrix-sdk-store-encryption/src/lib.rs | 19 +- 7 files changed, 286 insertions(+), 173 deletions(-) diff --git a/crates/matrix-sdk-base/src/store/integration_tests.rs b/crates/matrix-sdk-base/src/store/integration_tests.rs index ee3811ec2..a885d6a63 100644 --- a/crates/matrix-sdk-base/src/store/integration_tests.rs +++ b/crates/matrix-sdk-base/src/store/integration_tests.rs @@ -468,7 +468,7 @@ macro_rules! statestore_integration_tests { }), }; - assert!(store.get_media_content(&request_file).await.unwrap().is_none(), "unexpectd media found"); + assert!(store.get_media_content(&request_file).await.unwrap().is_none(), "unexpected media found"); assert!(store.get_media_content(&request_thumbnail).await.unwrap().is_none(), "media not found"); store.add_media_content(&request_file, content.clone()).await.expect("adding media failed"); diff --git a/crates/matrix-sdk-indexeddb/src/safe_encode.rs b/crates/matrix-sdk-indexeddb/src/safe_encode.rs index 4a2503639..94f33891f 100644 --- a/crates/matrix-sdk-indexeddb/src/safe_encode.rs +++ b/crates/matrix-sdk-indexeddb/src/safe_encode.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] +use base64::{encode_config as base64_encode, STANDARD_NO_PAD}; use matrix_sdk_base::ruma::events::{ GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, }; @@ -8,7 +9,6 @@ use matrix_sdk_common::ruma::{ use matrix_sdk_store_encryption::StoreCipher; use wasm_bindgen::JsValue; use web_sys::IdbKeyRange; -use base64::{STANDARD_NO_PAD, encode_config as base64_encode}; /// Helpers for wasm32/browser environments @@ -47,29 +47,32 @@ pub trait SafeEncode { JsValue::from(self.as_secure_string(table_name, store_cipher)) } - /// encode self securely for the given tablename with the given `store_cipher` hash_key, - /// returns the value as a base64 encoded string without any padding. + /// encode self securely for the given tablename with the given + /// `store_cipher` hash_key, returns the value as a base64 encoded + /// string without any padding. fn as_secure_string(&self, table_name: &str, store_cipher: &StoreCipher) -> String { base64_encode( store_cipher.hash_key(table_name, self.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ) } /// encode self into a JsValue, internally using `as_encoded_string` /// to escape the value of self, and append the given counter fn encode_with_counter(&self, i: usize) -> JsValue { - JsValue::from(format!("{}{}{:0000000x}", - self.as_encoded_string(), - KEY_SEPARATOR, - i - )) + JsValue::from(format!("{}{}{:0000000x}", self.as_encoded_string(), KEY_SEPARATOR, i)) } /// encode self into a JsValue, internally using `as_secure_string` /// to escape the value of self, and append the given counter - fn encode_with_counter_secure(&self, table_name: &str, store_cipher: &StoreCipher, i: usize) -> JsValue { - JsValue::from(format!("{}{}{:0000000x}", + fn encode_with_counter_secure( + &self, + table_name: &str, + store_cipher: &StoreCipher, + i: usize, + ) -> JsValue { + JsValue::from(format!( + "{}{}{:0000000x}", self.as_secure_string(table_name, store_cipher), KEY_SEPARATOR, i @@ -88,7 +91,11 @@ pub trait SafeEncode { .map_err(|e| e.as_string().unwrap_or_else(|| "Creating key range failed".to_owned())) } - fn encode_to_range_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Result { + fn encode_to_range_secure( + &self, + table_name: &str, + store_cipher: &StoreCipher, + ) -> Result { let key = self.as_secure_string(table_name, store_cipher); IdbKeyRange::bound( &JsValue::from([&key, KEY_SEPARATOR].concat()), @@ -113,14 +120,15 @@ where [ &base64_encode( store_cipher.hash_key(table_name, self.0.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), KEY_SEPARATOR, &base64_encode( store_cipher.hash_key(table_name, self.1.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), - ].concat() + ] + .concat() } } @@ -147,19 +155,20 @@ where [ &base64_encode( store_cipher.hash_key(table_name, self.0.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), KEY_SEPARATOR, &base64_encode( store_cipher.hash_key(table_name, self.1.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), KEY_SEPARATOR, &base64_encode( store_cipher.hash_key(table_name, self.2.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), - ].concat() + ] + .concat() } } @@ -189,24 +198,25 @@ where [ &base64_encode( store_cipher.hash_key(table_name, self.0.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), KEY_SEPARATOR, &base64_encode( store_cipher.hash_key(table_name, self.1.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), KEY_SEPARATOR, &base64_encode( store_cipher.hash_key(table_name, self.2.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), KEY_SEPARATOR, &base64_encode( store_cipher.hash_key(table_name, self.3.as_encoded_string().as_bytes()), - STANDARD_NO_PAD + STANDARD_NO_PAD, ), - ].concat() + ] + .concat() } } diff --git a/crates/matrix-sdk-indexeddb/src/state_store.rs b/crates/matrix-sdk-indexeddb/src/state_store.rs index 40f6303e1..f6e64e647 100644 --- a/crates/matrix-sdk-indexeddb/src/state_store.rs +++ b/crates/matrix-sdk-indexeddb/src/state_store.rs @@ -20,13 +20,9 @@ use indexed_db_futures::prelude::*; use matrix_sdk_base::{ deserialized_responses::{MemberEvent, SyncRoomEvent}, media::{MediaRequest, UniqueKey}, - store::{ - BoxStream, Result as StoreResult, StateChanges, StateStore, StoreError, - }, + store::{BoxStream, Result as StoreResult, StateChanges, StateStore, StoreError}, RoomInfo, }; -use matrix_sdk_store_encryption::{StoreCipher, Error as EncryptionError}; - use matrix_sdk_common::{ async_trait, ruma::{ @@ -44,6 +40,7 @@ use matrix_sdk_common::{ EventId, MxcUri, RoomId, RoomVersionId, UserId, }, }; +use matrix_sdk_store_encryption::{Error as EncryptionError, StoreCipher}; use serde::{Deserialize, Serialize}; use tracing::{info, warn}; use wasm_bindgen::JsValue; @@ -85,8 +82,14 @@ impl From for StoreError { EncryptionError::Random(e) => StoreError::Encryption(e.to_string()), EncryptionError::Serialization(e) => StoreError::Json(e), EncryptionError::Encryption(e) => StoreError::Encryption(e.to_string()), - EncryptionError::Version(found, expected) => StoreError::Encryption(format!("Bad Database Encryption Version: expected {} found {}", expected, found)), - EncryptionError::Length(found, expected) => StoreError::Encryption(format!("The database key an invalid length: expected {} found {}", expected, found)), + EncryptionError::Version(found, expected) => StoreError::Encryption(format!( + "Bad Database Encryption Version: expected {} found {}", + expected, found + )), + EncryptionError::Length(found, expected) => StoreError::Encryption(format!( + "The database key an invalid length: expected {} found {}", + expected, found + )), }, _ => StoreError::Backend(anyhow!(e)), } @@ -231,12 +234,12 @@ impl IndexeddbStore { { StoreCipher::import(passphrase, &inner)? } else { - let ciph = StoreCipher::new()?; + let cipher = StoreCipher::new()?; ob.put_key_val( &JsValue::from_str(KEYS::STORE_KEY), - &JsValue::from_serde(&StoreKeyWrapper(ciph.export(passphrase)?))?, + &JsValue::from_serde(&StoreKeyWrapper(cipher.export(passphrase)?))?, )?; - ciph + cipher }; tx.await.into_result()?; @@ -269,7 +272,8 @@ impl IndexeddbStore { } fn encode_key(&self, table_name: &str, key: T) -> JsValue - where T: SafeEncode + where + T: SafeEncode, { match self.store_cipher { Some(ref cipher) => key.encode_secure(table_name, cipher), @@ -277,26 +281,31 @@ impl IndexeddbStore { } } - fn encode_to_range(&self, table_name: &str, key: T) -> Result - where T: SafeEncode + fn encode_to_range( + &self, + table_name: &str, + key: T, + ) -> Result + where + T: SafeEncode, { match self.store_cipher { Some(ref cipher) => key.encode_to_range_secure(table_name, cipher), - None => key.encode_to_range() - }.map_err(|e| SerializationError::StoreError(StoreError::Backend(anyhow!(e)))) + None => key.encode_to_range(), + } + .map_err(|e| SerializationError::StoreError(StoreError::Backend(anyhow!(e)))) } - fn encode_key_with_counter(&self, table_name: &str, key: &T, i: usize) -> JsValue - where T: SafeEncode + where + T: SafeEncode, { match self.store_cipher { Some(ref cipher) => key.encode_with_counter_secure(table_name, cipher, i), - None => key.encode_with_counter(i) + None => key.encode_with_counter(i), } } - pub async fn save_filter(&self, filter_name: &str, filter_id: &str) -> Result<()> { let tx = self .inner @@ -304,7 +313,10 @@ impl IndexeddbStore { let obj = tx.object_store(KEYS::SESSION)?; - obj.put_key_val(&self.encode_key(KEYS::FILTER, (KEYS::FILTER, filter_name)), &JsValue::from_str(filter_id))?; + obj.put_key_val( + &self.encode_key(KEYS::FILTER, (KEYS::FILTER, filter_name)), + &JsValue::from_str(filter_id), + )?; tx.await.into_result()?; @@ -401,7 +413,8 @@ impl IndexeddbStore { for (event_type, event) in &changes.account_data { store.put_key_val( &self.encode_key(KEYS::ACCOUNT_DATA, event_type), - &self.serialize_event(&event)?)?; + &self.serialize_event(&event)?, + )?; } } @@ -431,8 +444,9 @@ impl IndexeddbStore { let store = tx.object_store(KEYS::ROOM_INFOS)?; for (room_id, room_info) in &changes.room_infos { store.put_key_val( - &self.encode_key(KEYS::ROOM_INFOS, room_id), - &self.serialize_event(&room_info)?)?; + &self.encode_key(KEYS::ROOM_INFOS, room_id), + &self.serialize_event(&room_info)?, + )?; } } @@ -441,7 +455,7 @@ impl IndexeddbStore { for (sender, event) in &changes.presence { store.put_key_val( &self.encode_key(KEYS::PRESENCE, sender), - &self.serialize_event(&event)? + &self.serialize_event(&event)?, )?; } } @@ -451,7 +465,7 @@ impl IndexeddbStore { for (room_id, info) in &changes.stripped_room_infos { store.put_key_val( &self.encode_key(KEYS::STRIPPED_ROOM_INFOS, room_id), - &self.serialize_event(&info)? + &self.serialize_event(&info)?, )?; } } @@ -471,7 +485,8 @@ impl IndexeddbStore { for (room, event_types) in &changes.stripped_state { for (event_type, events) in event_types { for (state_key, event) in events { - let key = self.encode_key(KEYS::STRIPPED_ROOM_STATE, (room, event_type, state_key)); + let key = self + .encode_key(KEYS::STRIPPED_ROOM_STATE, (room, event_type, state_key)); store.put_key_val(&key, &self.serialize_event(&event)?)?; } } @@ -494,14 +509,14 @@ impl IndexeddbStore { MembershipState::Join => { joined.put_key_val_owned( &self.encode_key(KEYS::JOINED_USER_IDS, key), - &self.serialize_event(&event.state_key)? + &self.serialize_event(&event.state_key)?, )?; invited.delete(&self.encode_key(KEYS::INVITED_USER_IDS, key))?; } MembershipState::Invite => { invited.put_key_val_owned( &self.encode_key(KEYS::INVITED_USER_IDS, key), - &self.serialize_event(&event.state_key)? + &self.serialize_event(&event.state_key)?, )?; joined.delete(&self.encode_key(KEYS::JOINED_USER_IDS, key))?; } @@ -511,10 +526,16 @@ impl IndexeddbStore { } } - members.put_key_val_owned(&self.encode_key(KEYS::MEMBERS, key), &self.serialize_event(&event)?)?; + members.put_key_val_owned( + &self.encode_key(KEYS::MEMBERS, key), + &self.serialize_event(&event)?, + )?; if let Some(profile) = profile_changes.and_then(|p| p.get(&event.state_key)) { - profiles_store.put_key_val_owned(&self.encode_key(KEYS::PROFILES, key), &self.serialize_event(&profile)?)?; + profiles_store.put_key_val_owned( + &self.encode_key(KEYS::PROFILES, key), + &self.serialize_event(&profile)?, + )?; } } } @@ -528,15 +549,20 @@ impl IndexeddbStore { for (event_id, receipts) in &content.0 { for (receipt_type, receipts) in receipts { for (user_id, receipt) in receipts { - let key = self.encode_key(KEYS::ROOM_USER_RECEIPTS, (room, receipt_type, user_id)); + let key = self.encode_key( + KEYS::ROOM_USER_RECEIPTS, + (room, receipt_type, user_id), + ); if let Some((old_event, _)) = room_user_receipts.get(&key)?.await?.and_then(|f| { self.deserialize_event::<(Box, Receipt)>(f).ok() }) { - room_event_receipts - .delete(&self.encode_key(KEYS::ROOM_EVENT_RECEIPTS, (room, receipt_type, &old_event, user_id)))?; + room_event_receipts.delete(&self.encode_key( + KEYS::ROOM_EVENT_RECEIPTS, + (room, receipt_type, &old_event, user_id), + ))?; } room_user_receipts @@ -544,7 +570,10 @@ impl IndexeddbStore { // Add the receipt to the room event receipts room_event_receipts.put_key_val( - &self.encode_key(KEYS::ROOM_EVENT_RECEIPTS, (room, receipt_type, event_id, user_id)), + &self.encode_key( + KEYS::ROOM_EVENT_RECEIPTS, + (room, receipt_type, event_id, user_id), + ), &self.serialize_event(&(user_id, receipt))?, )?; } @@ -574,7 +603,7 @@ impl IndexeddbStore { let stores = &[ (KEYS::ROOM_TIMELINE, &timeline_store), (KEYS::ROOM_TIMELINE_METADATA, &timeline_metadata_store), - (KEYS::ROOM_EVENT_ID_TO_POSITION, &event_id_to_position_store) + (KEYS::ROOM_EVENT_ID_TO_POSITION, &event_id_to_position_store), ]; for (table_name, store) in stores { let range = self.encode_to_range(table_name, room_id)?; @@ -603,7 +632,10 @@ impl IndexeddbStore { let mut delete_timeline = false; for event in &timeline.events { if let Some(event_id) = event.event_id() { - let event_key = self.encode_key(KEYS::ROOM_EVENT_ID_TO_POSITION, (room_id, event_id)); + let event_key = self.encode_key( + KEYS::ROOM_EVENT_ID_TO_POSITION, + (room_id, event_id), + ); if event_id_to_position_store .count_with_key_owned(event_key)? .await? @@ -621,11 +653,10 @@ impl IndexeddbStore { room_id ); - let stores = &[ (KEYS::ROOM_TIMELINE, &timeline_store), (KEYS::ROOM_TIMELINE_METADATA, &timeline_metadata_store), - (KEYS::ROOM_EVENT_ID_TO_POSITION, &event_id_to_position_store) + (KEYS::ROOM_EVENT_ID_TO_POSITION, &event_id_to_position_store), ]; for (table_name, store) in stores { let range = self.encode_to_range(table_name, room_id)?; @@ -678,7 +709,10 @@ impl IndexeddbStore { AnySyncMessageLikeEvent::RoomRedaction(redaction), )) = event.event.deserialize() { - let redacts_key = self.encode_key(KEYS::ROOM_EVENT_ID_TO_POSITION, (room_id, &redaction.redacts)); + let redacts_key = self.encode_key( + KEYS::ROOM_EVENT_ID_TO_POSITION, + (room_id, &redaction.redacts), + ); if let Some(position_key) = event_id_to_position_store.get_owned(redacts_key)?.await? { @@ -705,10 +739,15 @@ impl IndexeddbStore { } metadata.start_position -= 1; - let key = self.encode_key_with_counter(KEYS::ROOM_TIMELINE, room_id, metadata.start_position); + let key = self.encode_key_with_counter( + KEYS::ROOM_TIMELINE, + room_id, + metadata.start_position, + ); // Only add event with id to the position map if let Some(event_id) = event.event_id() { - let event_key = self.encode_key(KEYS::ROOM_EVENT_ID_TO_POSITION, (room_id, event_id)); + let event_key = self + .encode_key(KEYS::ROOM_EVENT_ID_TO_POSITION, (room_id, event_id)); event_id_to_position_store.put_key_val(&event_key, &key)?; } @@ -717,10 +756,15 @@ impl IndexeddbStore { } else { for event in &timeline.events { metadata.end_position += 1; - let key = self.encode_key_with_counter(KEYS::ROOM_TIMELINE, room_id, metadata.end_position); + let key = self.encode_key_with_counter( + KEYS::ROOM_TIMELINE, + room_id, + metadata.end_position, + ); // Only add event with id to the position map if let Some(event_id) = event.event_id() { - let event_key = self.encode_key(KEYS::ROOM_EVENT_ID_TO_POSITION, (room_id, event_id)); + let event_key = self + .encode_key(KEYS::ROOM_EVENT_ID_TO_POSITION, (room_id, event_id)); event_id_to_position_store.put_key_val(&event_key, &key)?; } @@ -728,8 +772,10 @@ impl IndexeddbStore { } } - timeline_metadata_store - .put_key_val_owned(&self.encode_key(KEYS::ROOM_TIMELINE_METADATA, room_id), &JsValue::from_serde(&metadata)?)?; + timeline_metadata_store.put_key_val_owned( + &self.encode_key(KEYS::ROOM_TIMELINE_METADATA, room_id), + &JsValue::from_serde(&metadata)?, + )?; } } @@ -807,10 +853,8 @@ impl IndexeddbStore { } pub async fn get_user_ids_stream(&self, room_id: &RoomId) -> Result>> { - Ok([ - self.get_invited_user_ids(room_id).await?, - self.get_joined_user_ids(room_id).await? - ].concat()) + Ok([self.get_invited_user_ids(room_id).await?, self.get_joined_user_ids(room_id).await?] + .concat()) } pub async fn get_invited_user_ids(&self, room_id: &RoomId) -> Result>> { @@ -934,7 +978,8 @@ impl IndexeddbStore { receipt_type: ReceiptType, event_id: &EventId, ) -> Result, Receipt)>> { - let range = self.encode_to_range(KEYS::ROOM_EVENT_RECEIPTS, (room_id, &receipt_type, event_id))?; + let range = + self.encode_to_range(KEYS::ROOM_EVENT_RECEIPTS, (room_id, &receipt_type, event_id))?; let tx = self.inner.transaction_on_one_with_mode( KEYS::ROOM_EVENT_RECEIPTS, IdbTransactionMode::Readonly, @@ -950,7 +995,8 @@ impl IndexeddbStore { } async fn add_media_content(&self, request: &MediaRequest, data: Vec) -> Result<()> { - let key = self.encode_key(KEYS::MEDIA, (request.source.unique_key(), request.format.unique_key())); + let key = self + .encode_key(KEYS::MEDIA, (request.source.unique_key(), request.format.unique_key())); let tx = self.inner.transaction_on_one_with_mode(KEYS::MEDIA, IdbTransactionMode::Readwrite)?; @@ -960,7 +1006,8 @@ impl IndexeddbStore { } async fn get_media_content(&self, request: &MediaRequest) -> Result>> { - let key = self.encode_key(KEYS::MEDIA, (request.source.unique_key(), request.format.unique_key())); + let key = self + .encode_key(KEYS::MEDIA, (request.source.unique_key(), request.format.unique_key())); self.inner .transaction_on_one_with_mode(KEYS::MEDIA, IdbTransactionMode::Readonly)? .object_store(KEYS::MEDIA)? @@ -1004,7 +1051,8 @@ impl IndexeddbStore { } async fn remove_media_content(&self, request: &MediaRequest) -> Result<()> { - let key = self.encode_key(KEYS::MEDIA, (request.source.unique_key(), request.format.unique_key())); + let key = self + .encode_key(KEYS::MEDIA, (request.source.unique_key(), request.format.unique_key())); let tx = self.inner.transaction_on_one_with_mode(KEYS::MEDIA, IdbTransactionMode::Readwrite)?; @@ -1299,16 +1347,16 @@ mod encrypted_tests { wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); use matrix_sdk_base::statestore_integration_tests; - - use super::{IndexeddbStore, Result, StoreCipher}; use uuid::Uuid; + use super::{IndexeddbStore, Result, StoreCipher}; + async fn get_store() -> Result { - let db_name = format!("test-state-encrypted-{}", Uuid::new_v4().to_hyphenated().to_string()); + let db_name = + format!("test-state-encrypted-{}", Uuid::new_v4().to_hyphenated().to_string()); let key = StoreCipher::new()?; Ok(IndexeddbStore::open_helper(db_name, Some(key)).await?) } statestore_integration_tests! { integration } } - diff --git a/crates/matrix-sdk-sled/src/cryptostore.rs b/crates/matrix-sdk-sled/src/cryptostore.rs index c8afd2fd8..2c30c638a 100644 --- a/crates/matrix-sdk-sled/src/cryptostore.rs +++ b/crates/matrix-sdk-sled/src/cryptostore.rs @@ -186,7 +186,6 @@ impl EncodeSecureKey for Session { } } - #[derive(Clone, Debug)] pub struct AccountInfo { user_id: Arc, diff --git a/crates/matrix-sdk-sled/src/encode_key.rs b/crates/matrix-sdk-sled/src/encode_key.rs index 097c4dc0b..8ae46ea40 100644 --- a/crates/matrix-sdk-sled/src/encode_key.rs +++ b/crates/matrix-sdk-sled/src/encode_key.rs @@ -1,12 +1,13 @@ use matrix_sdk_common::ruma::{ - events::{secret::request::SecretName, GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType}, + events::{ + secret::request::SecretName, GlobalAccountDataEventType, RoomAccountDataEventType, + StateEventType, + }, receipt::ReceiptType, - EventEncryptionAlgorithm, - DeviceId, EventId, MxcUri, RoomId, TransactionId, UserId, + DeviceId, EventEncryptionAlgorithm, EventId, MxcUri, RoomId, TransactionId, UserId, }; use matrix_sdk_store_encryption::StoreCipher; - pub const ENCODE_SEPARATOR: u8 = 0xff; pub trait EncodeKey { @@ -107,11 +108,7 @@ where B: EncodeKey, { fn encode(&self) -> Vec { - [ - self.0.encode(), - self.1.encode(), - ] - .concat() + [self.0.encode(), self.1.encode()].concat() } } @@ -122,12 +119,7 @@ where C: EncodeKey, { fn encode(&self) -> Vec { - [ - self.0.encode(), - self.1.encode(), - self.2.encode(), - ] - .concat() + [self.0.encode(), self.1.encode(), self.2.encode()].concat() } } @@ -139,13 +131,7 @@ where D: EncodeKey, { fn encode(&self) -> Vec { - [ - self.0.encode(), - self.1.encode(), - self.2.encode(), - self.3.encode(), - ] - .concat() + [self.0.encode(), self.1.encode(), self.2.encode(), self.3.encode()].concat() } } @@ -161,12 +147,10 @@ impl EncodeKey for GlobalAccountDataEventType { } } - pub trait EncodeSecureKey { fn encode_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Vec; } - impl EncodeSecureKey for &T { fn encode_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Vec { T::encode_secure(self, table_name, store_cipher) @@ -179,7 +163,6 @@ impl EncodeSecureKey for Box { } } - impl EncodeSecureKey for UserId { fn encode_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Vec { let user_id = store_cipher.hash_key(table_name, self.as_bytes()); @@ -221,10 +204,7 @@ impl EncodeSecureKey for EventId { impl EncodeSecureKey for MxcUri { fn encode_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Vec { let s: &str = self.as_ref(); - [ - store_cipher.hash_key(table_name, s.as_bytes()).as_slice(), - &[ENCODE_SEPARATOR], - ].concat() + [store_cipher.hash_key(table_name, s.as_bytes()).as_slice(), &[ENCODE_SEPARATOR]].concat() } } @@ -241,7 +221,8 @@ impl EncodeSecureKey for GlobalAccountDataEventType { [ store_cipher.hash_key(table_name, self.to_string().as_bytes()).as_slice(), &[ENCODE_SEPARATOR], - ].concat() + ] + .concat() } } @@ -250,7 +231,8 @@ impl EncodeSecureKey for StateEventType { [ store_cipher.hash_key(table_name, self.to_string().as_bytes()).as_slice(), &[ENCODE_SEPARATOR], - ].concat() + ] + .concat() } } @@ -259,11 +241,11 @@ impl EncodeSecureKey for RoomAccountDataEventType { [ store_cipher.hash_key(table_name, self.to_string().as_bytes()).as_slice(), &[ENCODE_SEPARATOR], - ].concat() + ] + .concat() } } - impl EncodeSecureKey for (A, B) where A: EncodeSecureKey, @@ -310,4 +292,4 @@ where ] .concat() } -} \ No newline at end of file +} diff --git a/crates/matrix-sdk-sled/src/state_store.rs b/crates/matrix-sdk-sled/src/state_store.rs index 92d7d57bd..2dc161e65 100644 --- a/crates/matrix-sdk-sled/src/state_store.rs +++ b/crates/matrix-sdk-sled/src/state_store.rs @@ -23,13 +23,10 @@ use anyhow::anyhow; use async_stream::stream; use futures_core::stream::Stream; use futures_util::stream::{self, StreamExt, TryStreamExt}; -use matrix_sdk_store_encryption::{StoreCipher, Error as KeyEncryptionError}; use matrix_sdk_base::{ deserialized_responses::{MemberEvent, SyncRoomEvent}, media::{MediaRequest, UniqueKey}, - store::{ - BoxStream, Result as StoreResult, StateChanges, StateStore, StoreError, - }, + store::{BoxStream, Result as StoreResult, StateChanges, StateStore, StoreError}, RoomInfo, }; use matrix_sdk_common::{ @@ -50,6 +47,7 @@ use matrix_sdk_common::{ EventId, MxcUri, RoomId, RoomVersionId, UserId, }, }; +use matrix_sdk_store_encryption::{Error as KeyEncryptionError, StoreCipher}; use serde::{Deserialize, Serialize}; use sled::{ transaction::{ConflictableTransactionError, TransactionError}, @@ -60,7 +58,7 @@ use tracing::{info, warn}; #[cfg(feature = "crypto-store")] use super::OpenStoreError; -use crate::encode_key::{EncodeSecureKey, EncodeKey, ENCODE_SEPARATOR}; +use crate::encode_key::{EncodeKey, EncodeSecureKey, ENCODE_SEPARATOR}; #[cfg(feature = "crypto-store")] pub use crate::CryptoStore; @@ -99,8 +97,14 @@ impl Into for SledStoreError { KeyEncryptionError::Random(e) => StoreError::Encryption(e.to_string()), KeyEncryptionError::Serialization(e) => StoreError::Json(e), KeyEncryptionError::Encryption(e) => StoreError::Encryption(e.to_string()), - KeyEncryptionError::Version(found, expected) => StoreError::Encryption(format!("Bad Database Encryption Version: expected {} found {}", expected, found)), - KeyEncryptionError::Length(found, expected) => StoreError::Encryption(format!("The database key an invalid length: expected {} found {}", expected, found)), + KeyEncryptionError::Version(found, expected) => StoreError::Encryption(format!( + "Bad Database Encryption Version: expected {} found {}", + expected, found + )), + KeyEncryptionError::Length(found, expected) => StoreError::Encryption(format!( + "The database key an invalid length: expected {} found {}", + expected, found + )), }, SledStoreError::StoreError(e) => e, _ => StoreError::Backend(anyhow!(self)), @@ -108,7 +112,6 @@ impl Into for SledStoreError { } } - const SESSION: &str = "session"; const ACCOUNT_DATA: &str = "account-data"; const MEMBER: &str = "member"; @@ -173,7 +176,11 @@ impl std::fmt::Debug for SledStore { } impl SledStore { - fn open_helper(db: Db, path: Option, store_cipher: Option) -> Result { + fn open_helper( + db: Db, + path: Option, + store_cipher: Option, + ) -> Result { let session = db.open_tree(SESSION)?; let account_data = db.open_tree(ACCOUNT_DATA)?; @@ -244,10 +251,14 @@ impl SledStore { let db = Config::new().temporary(true).open().map_err(|e| StoreError::Backend(anyhow!(e)))?; - SledStore::open_helper(db, None, Some(StoreCipher::new().expect("can't create store cipher"))).map_err(|e| e.into()) + SledStore::open_helper( + db, + None, + Some(StoreCipher::new().expect("can't create store cipher")), + ) + .map_err(|e| e.into()) } - pub fn open_with_passphrase(path: impl AsRef, passphrase: &str) -> StoreResult { Self::inner_open_with_passphrase(path, passphrase).map_err(|e| e.into()) } @@ -259,9 +270,9 @@ impl SledStore { let store_cipher = if let Some(inner) = db.get("store_cipher".encode())? { StoreCipher::import(passphrase, &inner)? } else { - let ciph = StoreCipher::new()?; - db.insert("store_cipher".encode(), ciph.export(passphrase)?)?; - ciph + let cipher = StoreCipher::new()?; + db.insert("store_cipher".encode(), cipher.export(passphrase)?)?; + cipher }; SledStore::open_helper(db, Some(path), Some(store_cipher)) @@ -307,7 +318,7 @@ impl SledStore { Ok(serde_json::from_slice(event)?) } } - + fn encode_key( &self, table_name: &str, @@ -324,14 +335,15 @@ impl SledStore { &self, tablename: &str, s: &A, - i: usize + i: usize, ) -> Vec { [ &self.encode_key(tablename, s), [ENCODE_SEPARATOR].as_slice(), i.to_be_bytes().as_ref(), [ENCODE_SEPARATOR].as_slice(), - ].concat() + ] + .concat() } pub async fn save_filter(&self, filter_name: &str, filter_id: &str) -> Result<()> { @@ -401,11 +413,17 @@ impl SledStore { match event.content.membership { MembershipState::Join => { - joined.insert(self.encode_key(JOINED_USER_ID, &key), event.state_key.as_str())?; + joined.insert( + self.encode_key(JOINED_USER_ID, &key), + event.state_key.as_str(), + )?; invited.remove(self.encode_key(INVITED_USER_ID, &key))?; } MembershipState::Invite => { - invited.insert(self.encode_key(INVITED_USER_ID, &key), event.state_key.as_str())?; + invited.insert( + self.encode_key(INVITED_USER_ID, &key), + event.state_key.as_str(), + )?; joined.remove(self.encode_key(JOINED_USER_ID, &key))?; } _ => { @@ -499,7 +517,10 @@ impl SledStore { for (room, events) in &changes.stripped_members { for event in events.values() { stripped_members.insert( - self.encode_key(STRIPPED_ROOM_MEMBER, &(room, event.state_key.to_string())), + self.encode_key( + STRIPPED_ROOM_MEMBER, + &(room, event.state_key.to_string()), + ), self.serialize_event(&event) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -510,7 +531,10 @@ impl SledStore { for (event_type, events) in event_types { for (state_key, event) in events { stripped_state.insert( - self.encode_key(STRIPPED_ROOM_STATE, &(room, event_type.to_string(), state_key)), + self.encode_key( + STRIPPED_ROOM_STATE, + &(room, event_type.to_string(), state_key), + ), self.serialize_event(&event) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -533,7 +557,10 @@ impl SledStore { for (user_id, receipt) in receipts { // Add the receipt to the room user receipts if let Some(old) = room_user_receipts.insert( - self.encode_key(ROOM_USER_RECEIPT, &(room, receipt_type, user_id)), + self.encode_key( + ROOM_USER_RECEIPT, + &(room, receipt_type, user_id), + ), self.serialize_event(&(event_id, receipt)) .map_err(ConflictableTransactionError::Abort)?, )? { @@ -541,14 +568,18 @@ impl SledStore { let (old_event, _): (Box, Receipt) = self .deserialize_event(&old) .map_err(ConflictableTransactionError::Abort)?; - room_event_receipts.remove( - self.encode_key(ROOM_EVENT_RECEIPT, &(room, receipt_type, old_event, user_id)), - )?; + room_event_receipts.remove(self.encode_key( + ROOM_EVENT_RECEIPT, + &(room, receipt_type, old_event, user_id), + ))?; } // Add the receipt to the room event receipts room_event_receipts.insert( - self.encode_key(ROOM_EVENT_RECEIPT, &(room, receipt_type, event_id, user_id)), + self.encode_key( + ROOM_EVENT_RECEIPT, + &(room, receipt_type, event_id, user_id), + ), self.serialize_event(&(user_id, receipt)) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -635,7 +666,10 @@ impl SledStore { &self, room_id: &RoomId, ) -> StoreResult>>> { - Ok(self.get_joined_user_ids(room_id).await?.chain(self.get_invited_user_ids(room_id).await?)) + Ok(self + .get_joined_user_ids(room_id) + .await? + .chain(self.get_invited_user_ids(room_id).await?)) } pub async fn get_invited_user_ids( @@ -780,8 +814,10 @@ impl SledStore { } async fn add_media_content(&self, request: &MediaRequest, data: Vec) -> Result<()> { - self.media - .insert(self.encode_key(MEDIA, &(request.source.unique_key(), request.format.unique_key())), data)?; + self.media.insert( + self.encode_key(MEDIA, &(request.source.unique_key(), request.format.unique_key())), + data, + )?; self.inner.flush_async().await?; @@ -790,7 +826,8 @@ impl SledStore { async fn get_media_content(&self, request: &MediaRequest) -> Result>> { let db = self.clone(); - let key = self.encode_key(MEDIA, &(request.source.unique_key(), request.format.unique_key())); + let key = + self.encode_key(MEDIA, &(request.source.unique_key(), request.format.unique_key())); spawn_blocking(move || Ok(db.media.get(key)?.map(|m| m.to_vec()))).await? } @@ -809,7 +846,9 @@ impl SledStore { } async fn remove_media_content(&self, request: &MediaRequest) -> Result<()> { - self.media.remove(self.encode_key(MEDIA, &(request.source.unique_key(), request.format.unique_key())))?; + self.media.remove( + self.encode_key(MEDIA, &(request.source.unique_key(), request.format.unique_key())), + )?; Ok(()) } @@ -826,8 +865,7 @@ impl SledStore { } async fn remove_room(&self, room_id: &RoomId) -> Result<()> { - - let mut members_batch = sled::Batch::default(); + let mut members_batch = sled::Batch::default(); for key in self.members.scan_prefix(self.encode_key(MEMBER, room_id)).keys() { members_batch.remove(key?) } @@ -843,12 +881,15 @@ impl SledStore { } let mut joined_user_ids_batch = sled::Batch::default(); - for key in self.joined_user_ids.scan_prefix(self.encode_key(JOINED_USER_ID, room_id)).keys() { + for key in self.joined_user_ids.scan_prefix(self.encode_key(JOINED_USER_ID, room_id)).keys() + { joined_user_ids_batch.remove(key?) } let mut invited_user_ids_batch = sled::Batch::default(); - for key in self.invited_user_ids.scan_prefix(self.encode_key(INVITED_USER_ID, room_id)).keys() { + for key in + self.invited_user_ids.scan_prefix(self.encode_key(INVITED_USER_ID, room_id)).keys() + { invited_user_ids_batch.remove(key?) } @@ -858,27 +899,41 @@ impl SledStore { } let mut room_account_data_batch = sled::Batch::default(); - for key in self.room_account_data.scan_prefix(self.encode_key(ROOM_ACCOUNT_DATA, room_id)).keys() { + for key in + self.room_account_data.scan_prefix(self.encode_key(ROOM_ACCOUNT_DATA, room_id)).keys() + { room_account_data_batch.remove(key?) } let mut stripped_members_batch = sled::Batch::default(); - for key in self.stripped_members.scan_prefix(self.encode_key(STRIPPED_ROOM_MEMBER, room_id)).keys() { + for key in + self.stripped_members.scan_prefix(self.encode_key(STRIPPED_ROOM_MEMBER, room_id)).keys() + { stripped_members_batch.remove(key?) } let mut stripped_room_state_batch = sled::Batch::default(); - for key in self.stripped_room_state.scan_prefix(self.encode_key(STRIPPED_ROOM_STATE, room_id)).keys() { + for key in self + .stripped_room_state + .scan_prefix(self.encode_key(STRIPPED_ROOM_STATE, room_id)) + .keys() + { stripped_room_state_batch.remove(key?) } let mut room_user_receipts_batch = sled::Batch::default(); - for key in self.room_user_receipts.scan_prefix(self.encode_key(ROOM_USER_RECEIPT, room_id)).keys() { + for key in + self.room_user_receipts.scan_prefix(self.encode_key(ROOM_USER_RECEIPT, room_id)).keys() + { room_user_receipts_batch.remove(key?) } let mut room_event_receipts_batch = sled::Batch::default(); - for key in self.room_event_receipts.scan_prefix(self.encode_key(ROOM_EVENT_RECEIPT, room_id)).keys() { + for key in self + .room_event_receipts + .scan_prefix(self.encode_key(ROOM_EVENT_RECEIPT, room_id)) + .keys() + { room_event_receipts_batch.remove(key?) } @@ -985,7 +1040,11 @@ impl SledStore { } let mut event_id_to_position_batch = sled::Batch::default(); - for key in self.room_event_id_to_position.scan_prefix(self.encode_key(ROOM_EVENT_ID_POSITION, &room_id)).keys() { + for key in self + .room_event_id_to_position + .scan_prefix(self.encode_key(ROOM_EVENT_ID_POSITION, &room_id)) + .keys() + { event_id_to_position_batch.remove(key?) } @@ -993,7 +1052,8 @@ impl SledStore { (&self.room_timeline, &self.room_timeline_metadata, &self.room_event_id_to_position) .transaction( |(room_timeline, room_timeline_metadata, room_event_id_to_position)| { - room_timeline_metadata.remove(self.encode_key(TIMELINE_METADATA, &room_id))?; + room_timeline_metadata + .remove(self.encode_key(TIMELINE_METADATA, &room_id))?; room_timeline.apply_batch(&timeline_batch)?; room_event_id_to_position.apply_batch(&event_id_to_position_batch)?; @@ -1045,7 +1105,8 @@ impl SledStore { let mut delete_timeline = false; for event in &timeline.events { if let Some(event_id) = event.event_id() { - let event_key = self.encode_key(ROOM_EVENT_ID_POSITION, &(room_id, event_id)); + let event_key = + self.encode_key(ROOM_EVENT_ID_POSITION, &(room_id, event_id)); if self.room_event_id_to_position.contains_key(event_key)? { delete_timeline = true; break; @@ -1100,7 +1161,8 @@ impl SledStore { AnySyncMessageLikeEvent::RoomRedaction(redaction), )) = event.event.deserialize() { - let redacts_key = self.encode_key(ROOM_EVENT_ID_POSITION, &(room_id, redaction.redacts)); + let redacts_key = + self.encode_key(ROOM_EVENT_ID_POSITION, &(room_id, redaction.redacts)); if let Some(position_key) = self.room_event_id_to_position.get(redacts_key)? { @@ -1125,28 +1187,35 @@ impl SledStore { } metadata.start_position -= 1; - let key = self.encode_key_with_counter(TIMELINE, room_id, metadata.start_position); + let key = + self.encode_key_with_counter(TIMELINE, room_id, metadata.start_position); timeline_batch.insert(key.as_slice(), self.serialize_event(&event)?); // Only add event with id to the position map if let Some(event_id) = event.event_id() { - let event_key = self.encode_key(ROOM_EVENT_ID_POSITION, &(room_id, event_id)); + let event_key = + self.encode_key(ROOM_EVENT_ID_POSITION, &(room_id, event_id)); event_id_to_position_batch.insert(event_key.as_slice(), key.as_slice()); } } } else { for event in &timeline.events { metadata.end_position += 1; - let key = self.encode_key_with_counter(TIMELINE, room_id, metadata.end_position); + let key = + self.encode_key_with_counter(TIMELINE, room_id, metadata.end_position); timeline_batch.insert(key.as_slice(), self.serialize_event(&event)?); // Only add event with id to the position map if let Some(event_id) = event.event_id() { - let event_key = self.encode_key(ROOM_EVENT_ID_POSITION, &(room_id, event_id)); + let event_key = + self.encode_key(ROOM_EVENT_ID_POSITION, &(room_id, event_id)); event_id_to_position_batch.insert(event_key.as_slice(), key.as_slice()); } } } - timeline_metadata_batch.insert(self.encode_key(TIMELINE_METADATA, &room_id), serde_json::to_vec(&metadata)?); + timeline_metadata_batch.insert( + self.encode_key(TIMELINE_METADATA, &room_id), + serde_json::to_vec(&metadata)?, + ); } let ret: Result<(), TransactionError> = diff --git a/crates/matrix-sdk-store-encryption/src/lib.rs b/crates/matrix-sdk-store-encryption/src/lib.rs index 1adeb33a3..4ff7b6d4a 100644 --- a/crates/matrix-sdk-store-encryption/src/lib.rs +++ b/crates/matrix-sdk-store-encryption/src/lib.rs @@ -289,8 +289,9 @@ impl StoreCipher { /// Encrypt a value before it is inserted into the key/value store. /// - /// A value can be decrypted using the [`StoreCipher::decrypt_value_typed()`] - /// method. This is the lower level function to `encrypt_value`, but returns the + /// A value can be decrypted using the + /// [`StoreCipher::decrypt_value_typed()`] method. This is the lower + /// level function to `encrypt_value`, but returns the /// full `EncryptdValue`-type /// /// # Arguments @@ -399,8 +400,9 @@ impl StoreCipher { /// Decrypt a value after it was fetchetd from the key/value store. /// - /// A value can be encrypted using the [`StoreCipher::encrypt_value_typed()`] - /// method. Lower level method to [`StoreCipher::decrypt_value_typed()`] + /// A value can be encrypted using the + /// [`StoreCipher::encrypt_value_typed()`] method. Lower level method to + /// [`StoreCipher::decrypt_value_typed()`] /// /// # Arguments /// @@ -427,14 +429,16 @@ impl StoreCipher { /// assert_eq!(value, decrypted); /// # Result::<_, anyhow::Error>::Ok(()) }; /// ``` - pub fn decrypt_value_typed Deserialize<'b>>(&self, value: EncryptedValue) -> Result { + pub fn decrypt_value_typed Deserialize<'b>>( + &self, + value: EncryptedValue, + ) -> Result { let mut plaintext = self.decrypt_value_data(value)?; let ret = serde_json::from_slice(&plaintext); plaintext.zeroize(); Ok(ret?) } - /// Decrypt a value after it was fetchetd from the key/value store. /// /// A value can be encrypted using the [`StoreCipher::encrypt_value_data()`] @@ -494,7 +498,8 @@ impl MacKey { } } -/// Encrypted value, ready for storage, as created by the [`StoreCipher::encrypt_value_data()`] +/// Encrypted value, ready for storage, as created by the +/// [`StoreCipher::encrypt_value_data()`] #[derive(Debug, Serialize, Deserialize, PartialEq)] pub struct EncryptedValue { version: u8,