WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crates/matrix-sdk-indexeddb/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file.

## [Unreleased] - ReleaseDate

### Features

- Expose implementations of `EventCacheStore` and `MediaStore` and add a
composite type for initializing all stores with a single function - i.e.,
`IndexeddbStores::open`. Additionally, allow feature flags for each of the
stores to be used independent of and in combination with the others.
([#5946](https://github.com/matrix-org/matrix-rust-sdk/pull/5946))

### Bug Fixes

- Ensure that encrypted tests are run with a `StoreCipher`. This happened to reveal tests which fail in an
Expand Down
13 changes: 8 additions & 5 deletions crates/matrix-sdk-indexeddb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ default-target = "wasm32-unknown-unknown"
rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]

[features]
default = ["e2e-encryption", "state-store", "event-cache-store"]
event-cache-store = ["dep:matrix-sdk-base", "media-store"]
media-store = ["dep:matrix-sdk-base"]
state-store = ["dep:matrix-sdk-base", "growable-bloom-filter"]
e2e-encryption = ["dep:matrix-sdk-base", "dep:matrix-sdk-crypto"]
default = ["e2e-encryption", "state-store", "event-cache-store", "media-store"]
event-cache-store = ["dep:matrix-sdk-base", "media-store", "indexed-type-serializer"]
media-store = ["dep:matrix-sdk-base", "indexed-type-serializer"]
state-store = ["dep:matrix-sdk-base", "growable-bloom-filter", "safe-encode-traits"]
e2e-encryption = ["dep:matrix-sdk-base", "dep:matrix-sdk-crypto", "safe-encode-serializer"]
safe-encode-traits = []
safe-encode-serializer = ["dep:matrix-sdk-crypto", "safe-encode-traits"]
Comment on lines +22 to +23
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What safe means here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safe is part of the name of an encoder and serializer - i.e., trait SafeEncode.

I agree that this isn't a good name for a feature, but it helps a lot to have more granular feature flags when adding [#cfg(feature = ...)] statements in the code. I thought about prefixing it with _ or internal- to show that it really isn't for an end user, but for internal organization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open to other directions with this!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep as they are, and see how it goes in the future.

indexed-type-serializer = ["safe-encode-serializer"]
testing = ["matrix-sdk-crypto?/testing"]
experimental-encrypted-state-events = [
"matrix-sdk-crypto?/experimental-encrypted-state-events"
Expand Down
12 changes: 11 additions & 1 deletion crates/matrix-sdk-indexeddb/src/event_cache_store/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
error::IndexeddbEventCacheStoreError, migrations::open_and_upgrade_db,
IndexeddbEventCacheStore,
},
serializer::{IndexedTypeSerializer, SafeEncodeSerializer},
serializer::{indexed_type::IndexedTypeSerializer, safe_encode::types::SafeEncodeSerializer},
};

/// A type for conveniently building an [`IndexeddbEventCacheStore`]
Expand Down Expand Up @@ -56,6 +56,16 @@ impl IndexeddbEventCacheStoreBuilder {
self
}

/// Create a new [`IndexeddbEventCacheStoreBuilder`] where the database name
/// is constructed by joining the given prefix with
/// [`Self::DEFAULT_DATABASE_NAME`] and separated by `::`.
pub fn with_prefix(prefix: &str) -> Self {
Self {
database_name: format!("{}::{}", prefix, Self::DEFAULT_DATABASE_NAME),
store_cipher: None,
}
}

/// Sets the store cipher to use when encrypting data before it is persisted
/// to the IndexedDB database. By default, no store cipher is used -
/// i.e., data is not encrypted before it is persisted.
Expand Down
2 changes: 1 addition & 1 deletion crates/matrix-sdk-indexeddb/src/event_cache_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use crate::{
transaction::IndexeddbEventCacheStoreTransaction,
types::{ChunkType, InBandEvent, Lease, OutOfBandEvent},
},
serializer::{Indexed, IndexedTypeSerializer},
serializer::indexed_type::{traits::Indexed, IndexedTypeSerializer},
transaction::TransactionError,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,17 @@ use crate::{
types::{Chunk, Event, Gap, Lease, Position},
},
serializer::{
Indexed, IndexedKey, IndexedKeyComponentBounds, IndexedPrefixKeyBounds,
IndexedPrefixKeyComponentBounds, MaybeEncrypted, SafeEncodeSerializer,
INDEXED_KEY_LOWER_CHARACTER, INDEXED_KEY_LOWER_STRING, INDEXED_KEY_UPPER_CHARACTER,
INDEXED_KEY_UPPER_STRING,
indexed_type::{
constants::{
INDEXED_KEY_LOWER_CHARACTER, INDEXED_KEY_LOWER_STRING, INDEXED_KEY_UPPER_CHARACTER,
INDEXED_KEY_UPPER_STRING,
},
traits::{
Indexed, IndexedKey, IndexedKeyComponentBounds, IndexedPrefixKeyBounds,
IndexedPrefixKeyComponentBounds,
},
},
safe_encode::types::{MaybeEncrypted, SafeEncodeSerializer},
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ use crate::{
},
types::{Chunk, ChunkType, Event, Gap, Lease, Position},
},
serializer::{
Indexed, IndexedKeyRange, IndexedPrefixKeyBounds, IndexedPrefixKeyComponentBounds,
serializer::indexed_type::{
range::IndexedKeyRange,
traits::{Indexed, IndexedPrefixKeyBounds, IndexedPrefixKeyComponentBounds},
IndexedTypeSerializer,
},
transaction::{Transaction, TransactionError},
Expand Down
166 changes: 166 additions & 0 deletions crates/matrix-sdk-indexeddb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,156 @@ pub use state_store::{
MigrationConflictStrategy,
};

#[cfg(feature = "event-cache-store")]
pub use crate::event_cache_store::{
IndexeddbEventCacheStore, IndexeddbEventCacheStoreBuilder, IndexeddbEventCacheStoreError,
};
#[cfg(feature = "media-store")]
pub use crate::media_store::{
IndexeddbMediaStore, IndexeddbMediaStoreBuilder, IndexeddbMediaStoreError,
};

/// Structure containing implementations of every type
/// of store using IndexedDB for persistent storage.
///
/// Note that each of the stores is behind a feature flag and will
/// only be available when its corresponding flag is set.
pub struct IndexeddbStores {
/// An IndexedDB-backed implementation of [`CryptoStore`][1]
///
/// [1]: matrix_sdk_crypto::store::CryptoStore
#[cfg(feature = "e2e-encryption")]
pub crypto: IndexeddbCryptoStore,
/// An IndexedDB-backed implementation of [`StateStore`][1]
///
/// [1]: matrix_sdk_base::store::StateStore
#[cfg(feature = "state-store")]
pub state: IndexeddbStateStore,
/// An IndexedDB-backed implementation of [`EventCacheStore`][1]
///
/// [1]: matrix_sdk_base::event_cache::store::EventCacheStore
#[cfg(feature = "event-cache-store")]
pub event_cache: IndexeddbEventCacheStore,
/// An IndexedDB-backed implementation of [`MediaStore`][1]
///
/// [1]: matrix_sdk_base::media::store::MediaStore
#[cfg(feature = "media-store")]
pub media: IndexeddbMediaStore,
}

impl IndexeddbStores {
/// Opens and returns all stores using the given database name and,
/// optionally, a passphrase.
///
/// If `e2e-encryption` and `state-store` features are not enabled,
/// `passphrase` is ignored. Otherwise `passphrase` is used to import or
/// create a [`StoreCipher`][1] which encrypts contents of all stores.
///
/// Note that each of the stores is behind a feature flag and will only be
/// opened when the corresponding flag is set.
///
/// [1]: matrix_sdk_store_encryption::StoreCipher
pub async fn open(
name: &str,
#[allow(unused_variables)] passphrase: Option<&str>,
) -> Result<Self, OpenStoreError> {
#[cfg(all(feature = "e2e-encryption", feature = "state-store"))]
if let Some(passphrase) = passphrase {
return Self::open_with_passphrase(name, passphrase).await;
}

Self::open_without_passphrase(name).await
}

/// Opens and returns all stores using the given database name. Contents of
/// the stores are NOT encrypted.
///
/// Note that each of the stores is behind a feature flag and will only be
/// opened when the corresponding flag is set.
#[allow(clippy::unused_async)]
pub async fn open_without_passphrase(name: &str) -> Result<Self, OpenStoreError> {
#[cfg(feature = "state-store")]
let state = IndexeddbStateStore::builder()
.name(name.to_owned())
.build()
.await
.map_err(StoreError::from)?;

#[cfg(feature = "e2e-encryption")]
let crypto = IndexeddbCryptoStore::open_with_name(name).await?;

#[cfg(feature = "event-cache-store")]
let event_cache = IndexeddbEventCacheStoreBuilder::with_prefix(name).build().await?;

#[cfg(feature = "media-store")]
let media = IndexeddbMediaStoreBuilder::with_prefix(name).build().await?;

Ok(Self {
#[cfg(feature = "state-store")]
state,
#[cfg(feature = "e2e-encryption")]
crypto,
#[cfg(feature = "event-cache-store")]
event_cache,
#[cfg(feature = "media-store")]
media,
})
}

/// Opens and returns all stores using the given database name and
/// passphrase. Passphrase is used to import or create a [`StoreCipher`][1]
/// which encrypts contents of all stores.
///
/// Note that [`IndexeddbEventCacheStore`] and [`IndexeddbMediaStore`] are
/// behind feature flags and will only be opened when their
/// corresponding flags are set.
///
/// [1]: matrix_sdk_store_encryption::StoreCipher
#[cfg(all(feature = "e2e-encryption", feature = "state-store"))]
pub async fn open_with_passphrase(
name: &str,
passphrase: &str,
) -> Result<Self, OpenStoreError> {
let state = IndexeddbStateStore::builder()
.name(name.to_owned())
.passphrase(passphrase.to_owned())
.build()
.await
.map_err(StoreError::from)?;
let store_cipher =
state.store_cipher.clone().ok_or(OpenStoreError::FailedToLoadStoreCipher)?;

let crypto =
IndexeddbCryptoStore::open_with_store_cipher(name, Some(store_cipher.clone())).await?;

#[cfg(feature = "event-cache-store")]
let event_cache = IndexeddbEventCacheStoreBuilder::with_prefix(name)
.store_cipher(store_cipher.clone())
.build()
.await?;

#[cfg(feature = "media-store")]
let media = IndexeddbMediaStoreBuilder::with_prefix(name)
.store_cipher(store_cipher.clone())
.build()
.await?;

Ok(Self {
state,
crypto,
#[cfg(feature = "event-cache-store")]
event_cache,
#[cfg(feature = "media-store")]
media,
})
}
}

/// Create a [`IndexeddbStateStore`] and a [`IndexeddbCryptoStore`] that use the
/// same name and passphrase.
#[deprecated(
note = "this function only opens state and crypto stores, use `IndexeddbStores::open()` instead."
)]
#[cfg(all(feature = "e2e-encryption", feature = "state-store"))]
pub async fn open_stores_with_name(
name: &str,
Expand Down Expand Up @@ -75,4 +223,22 @@ pub enum OpenStoreError {
#[cfg(feature = "e2e-encryption")]
#[error(transparent)]
Crypto(#[from] IndexeddbCryptoStoreError),

/// An error occurred while trying to load a [`StoreCipher`][1] from a
/// passphrase
///
/// [1]: matrix_sdk_store_encryption::StoreCipher
#[cfg(feature = "e2e-encryption")]
#[error("failed to load store cipher")]
FailedToLoadStoreCipher,

/// An error occurred with the event cache store implementation.
#[cfg(feature = "event-cache-store")]
#[error(transparent)]
Event(#[from] IndexeddbEventCacheStoreError),

/// An error occurred with the media store implementation.
#[cfg(feature = "media-store")]
#[error(transparent)]
Media(#[from] IndexeddbMediaStoreError),
}
12 changes: 11 additions & 1 deletion crates/matrix-sdk-indexeddb/src/media_store/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
media_store::{
error::IndexeddbMediaStoreError, migrations::open_and_upgrade_db, IndexeddbMediaStore,
},
serializer::{IndexedTypeSerializer, SafeEncodeSerializer},
serializer::{indexed_type::IndexedTypeSerializer, safe_encode::types::SafeEncodeSerializer},
};

/// A type for conveniently building an [`IndexeddbMediaStore`]
Expand All @@ -44,6 +44,16 @@ impl IndexeddbMediaStoreBuilder {
/// [`IndexeddbMediaStore`]
pub const DEFAULT_DATABASE_NAME: &'static str = "media";

/// Create a new [`IndexeddbMediaStoreBuilder`] where the database name is
/// constructed by joining the given prefix with
/// [`Self::DEFAULT_DATABASE_NAME`] and separated by `::`.
pub fn with_prefix(prefix: &str) -> Self {
Self {
database_name: format!("{}::{}", prefix, Self::DEFAULT_DATABASE_NAME),
store_cipher: None,
}
}

/// Sets the name of the IndexedDB database which will be opened. This
/// defaults to [`Self::DEFAULT_DATABASE_NAME`].
pub fn database_name(mut self, name: String) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion crates/matrix-sdk-indexeddb/src/media_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use crate::{
transaction::IndexeddbMediaStoreTransaction,
types::{Lease, Media, MediaCleanupTime, MediaContent, MediaMetadata, UnixTime},
},
serializer::{Indexed, IndexedTypeSerializer},
serializer::indexed_type::{traits::Indexed, IndexedTypeSerializer},
transaction::TransactionError,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ use crate::{
serializer::indexed_types::{IndexedMediaContentId, IndexedMediaContentSize},
types::UnixTime,
},
serializer::{
indexed_type::constants::{INDEXED_KEY_LOWER_UUID, INDEXED_KEY_UPPER_UUID},
INDEXED_KEY_UPPER_DURATION_SECONDS,
serializer::indexed_type::constants::{
INDEXED_KEY_LOWER_UUID, INDEXED_KEY_UPPER_DURATION_SECONDS, INDEXED_KEY_UPPER_UUID,
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,13 @@ use crate::{
types::{Lease, MediaCleanupTime, MediaContent, MediaMetadata, UnixTime},
},
serializer::{
Indexed, IndexedKey, IndexedKeyComponentBounds, IndexedPrefixKeyComponentBounds,
MaybeEncrypted, SafeEncodeSerializer, INDEXED_KEY_LOWER_STRING, INDEXED_KEY_UPPER_STRING,
indexed_type::{
constants::{INDEXED_KEY_LOWER_STRING, INDEXED_KEY_UPPER_STRING},
traits::{
Indexed, IndexedKey, IndexedKeyComponentBounds, IndexedPrefixKeyComponentBounds,
},
},
safe_encode::types::{MaybeEncrypted, SafeEncodeSerializer},
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ use crate::{
},
types::{Lease, Media, MediaCleanupTime, MediaContent, MediaMetadata, UnixTime},
},
serializer::{IndexedKeyRange, IndexedPrefixKeyComponentBounds, IndexedTypeSerializer},
serializer::indexed_type::{
range::IndexedKeyRange, traits::IndexedPrefixKeyComponentBounds, IndexedTypeSerializer,
},
transaction::{Transaction, TransactionError},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use thiserror::Error;
use traits::{Indexed, IndexedKey};
use wasm_bindgen::JsValue;

use crate::serializer::SafeEncodeSerializer;
use crate::serializer::safe_encode::types::SafeEncodeSerializer;

#[derive(Debug, Error)]
pub enum IndexedTypeSerializerError<IndexingError> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
// limitations under the License

use crate::serializer::{
Indexed, IndexedKey, IndexedKeyBounds, IndexedPrefixKeyBounds, SafeEncodeSerializer,
indexed_type::traits::{Indexed, IndexedKey, IndexedKeyBounds, IndexedPrefixKeyBounds},
safe_encode::types::SafeEncodeSerializer,
};

/// Representation of a range of keys of type `K`. This is loosely
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License

use crate::serializer::SafeEncodeSerializer;
use crate::serializer::safe_encode::types::SafeEncodeSerializer;

/// A conversion trait for preparing high-level types into indexed types
/// which are better suited for storage in IndexedDB.
Expand Down
Loading
Loading