Skip to content

Commit

Permalink
Merge pull request #729 from gnunicorn/gnunicorn/issue609
Browse files Browse the repository at this point in the history
Ensure all data state stores save is encrypted
  • Loading branch information
gnunicorn authored Jun 7, 2022
2 parents d4f49ca + a308771 commit 7f49618
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 85 deletions.
38 changes: 30 additions & 8 deletions crates/matrix-sdk-base/src/store/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,28 @@ macro_rules! statestore_integration_tests {
assert!(!members.is_empty(), "We expected to find members for the room")
}

#[async_test]
async fn test_filter_saving() {
let store = get_store().await.unwrap();
let test_name = "filter_name";
let filter_id = "filter_id_1234";
assert_eq!(store.get_filter(test_name).await.unwrap(), None);
store.save_filter(test_name, filter_id).await.unwrap();
assert_eq!(store.get_filter(test_name).await.unwrap(), Some(filter_id.to_owned()));
}

#[async_test]
async fn test_sync_token_saving() {
let mut changes = StateChanges::default();
let store = get_store().await.unwrap();
let sync_token = "t392-516_47314_0_7_1".to_owned();

changes.sync_token = Some(sync_token.clone());
assert_eq!(store.get_sync_token().await.unwrap(), None);
store.save_changes(&changes).await.unwrap();
assert_eq!(store.get_sync_token().await.unwrap(), Some(sync_token));
}

#[async_test]
async fn test_stripped_member_saving() {
let store = get_store().await.unwrap();
Expand Down Expand Up @@ -625,7 +647,7 @@ macro_rules! statestore_integration_tests {

// Add sync response
let sync = SyncResponse::try_from_http_response(
Response::builder().body(serde_json::to_vec(&*test_json::MORE_SYNC).unwrap()).unwrap(),
Response::builder().body(serde_json::to_vec(&*test_json::MORE_SYNC).expect("Parsing MORE_SYNC failed")).unwrap(),
)
.unwrap();

Expand All @@ -643,15 +665,15 @@ macro_rules! statestore_integration_tests {
);
let mut changes = StateChanges::new(sync.next_batch.clone());
changes.add_timeline(room_id, timeline_slice);
store.save_changes(&changes).await.unwrap();
store.save_changes(&changes).await.expect("Saving room timeline failed");

check_timeline_events(room_id, &store, &stored_events, timeline.prev_batch.as_deref())
.await;

// Add message response
let messages = MessageResponse::try_from_http_response(
Response::builder()
.body(serde_json::to_vec(&*test_json::SYNC_ROOM_MESSAGES_BATCH_1).unwrap())
.body(serde_json::to_vec(&*test_json::SYNC_ROOM_MESSAGES_BATCH_1).expect("Parsing SYNC_ROOM_MESSAGES_BATCH_1 failed"))
.unwrap(),
)
.unwrap();
Expand All @@ -669,14 +691,14 @@ macro_rules! statestore_integration_tests {
TimelineSlice::new(events, messages.start.clone(), messages.end.clone(), false, false);
let mut changes = StateChanges::default();
changes.add_timeline(room_id, timeline_slice);
store.save_changes(&changes).await.unwrap();
store.save_changes(&changes).await.expect("Saving room update timeline failed");

check_timeline_events(room_id, &store, &stored_events, messages.end.as_deref()).await;

// Add second message response
let messages = MessageResponse::try_from_http_response(
Response::builder()
.body(serde_json::to_vec(&*test_json::SYNC_ROOM_MESSAGES_BATCH_2).unwrap())
.body(serde_json::to_vec(&*test_json::SYNC_ROOM_MESSAGES_BATCH_2).expect("Parsing SYNC_ROOM_MESSAGES_BATCH_2 failed"))
.unwrap(),
)
.unwrap();
Expand All @@ -694,7 +716,7 @@ macro_rules! statestore_integration_tests {
TimelineSlice::new(events, messages.start.clone(), messages.end.clone(), false, false);
let mut changes = StateChanges::default();
changes.add_timeline(room_id, timeline_slice);
store.save_changes(&changes).await.unwrap();
store.save_changes(&changes).await.expect("Saving room update timeline 2 failed");

check_timeline_events(room_id, &store, &stored_events, messages.end.as_deref()).await;

Expand Down Expand Up @@ -722,7 +744,7 @@ macro_rules! statestore_integration_tests {
);
let mut changes = StateChanges::new(sync.next_batch.clone());
changes.add_timeline(room_id, timeline_slice);
store.save_changes(&changes).await.unwrap();
store.save_changes(&changes).await.expect("Saving room update timeline 3 failed");

check_timeline_events(room_id, &store, &stored_events, messages.end.as_deref()).await;

Expand All @@ -737,7 +759,7 @@ macro_rules! statestore_integration_tests {
);
let mut changes = StateChanges::default();
changes.add_timeline(room_id, timeline_slice);
store.save_changes(&changes).await.unwrap();
store.save_changes(&changes).await.expect("Saving room update timeline 4 failed");

check_timeline_events(room_id, &store, &Vec::new(), end_token.as_deref()).await;
}
Expand Down
16 changes: 9 additions & 7 deletions crates/matrix-sdk-indexeddb/src/state_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ impl IndexeddbStore {

obj.put_key_val(
&self.encode_key(KEYS::FILTER, (KEYS::FILTER, filter_name)),
&JsValue::from_str(filter_id),
&self.serialize_event(&filter_id)?,
)?;

tx.await.into_result()?;
Expand All @@ -339,13 +339,13 @@ impl IndexeddbStore {
}

pub async fn get_filter(&self, filter_name: &str) -> Result<Option<String>> {
Ok(self
.inner
self.inner
.transaction_on_one_with_mode(KEYS::SESSION, IdbTransactionMode::Readonly)?
.object_store(KEYS::SESSION)?
.get(&self.encode_key(KEYS::FILTER, (KEYS::FILTER, filter_name)))?
.await?
.and_then(|f| f.as_string()))
.map(|f| self.deserialize_event(f))
.transpose()
}

pub async fn get_sync_token(&self) -> Result<Option<String>> {
Expand Down Expand Up @@ -675,7 +675,7 @@ impl IndexeddbStore {
let metadata: Option<TimelineMetadata> = timeline_metadata_store
.get(&self.encode_key(KEYS::ROOM_TIMELINE_METADATA, room_id))?
.await?
.map(|v| v.into_serde())
.map(|v| self.deserialize_event(&v))
.transpose()?;
if let Some(mut metadata) = metadata {
if !timeline.sync && Some(&timeline.start) != metadata.end.as_ref() {
Expand Down Expand Up @@ -834,7 +834,7 @@ impl IndexeddbStore {

timeline_metadata_store.put_key_val_owned(
&self.encode_key(KEYS::ROOM_TIMELINE_METADATA, room_id),
&JsValue::from_serde(&metadata)?,
&self.serialize_event(&metadata)?,
)?;
}
}
Expand Down Expand Up @@ -1474,11 +1474,13 @@ mod tests {
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

use matrix_sdk_base::statestore_integration_tests;
use uuid::Uuid;

use super::{IndexeddbStore, Result};

async fn get_store() -> Result<IndexeddbStore> {
Ok(IndexeddbStore::open().await?)
let db_name = format!("test-state-plain-{}", Uuid::new_v4().as_hyphenated().to_string());
Ok(IndexeddbStore::open_helper(db_name, None).await?)
}

statestore_integration_tests! { integration }
Expand Down
17 changes: 17 additions & 0 deletions crates/matrix-sdk-sled/src/encode_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@ use ruma::{
RoomId, TransactionId, UserId,
};

/// Hold any data to be used as an encoding key
/// without checking for the existence of `ENCODE_SEPARATOR` within
pub struct EncodeUnchecked<'a>(&'a [u8]);

impl<'a> EncodeUnchecked<'a> {
/// Wrap any `[u8]`
pub fn from(bytes: &'a [u8]) -> Self {
EncodeUnchecked(bytes)
}
}

impl<'a> EncodeKey for EncodeUnchecked<'a> {
fn encode_as_bytes(&self) -> Cow<'a, [u8]> {
(self.0).into()
}
}

pub const ENCODE_SEPARATOR: u8 = 0xff;

pub trait EncodeKey {
Expand Down
Loading

0 comments on commit 7f49618

Please sign in to comment.