diff --git a/matrix_sdk_crypto/src/identities/user.rs b/matrix_sdk_crypto/src/identities/user.rs index f50e02cd..a10cde4d 100644 --- a/matrix_sdk_crypto/src/identities/user.rs +++ b/matrix_sdk_crypto/src/identities/user.rs @@ -651,7 +651,7 @@ impl OwnUserIdentity { #[cfg(test)] pub(crate) mod test { use serde_json::json; - use std::{convert::TryFrom, sync::Arc}; + use std::convert::TryFrom; use matrix_sdk_common::{ api::r0::keys::get_keys::Response as KeyQueryResponse, identifiers::user_id, @@ -661,7 +661,7 @@ pub(crate) mod test { identities::{Device, ReadOnlyDevice}, machine::test::response_from_file, olm::Account, - store::MemoryStore, + store::{MemoryStore, Store}, verification::VerificationMachine, }; @@ -884,7 +884,7 @@ pub(crate) mod test { let verification_machine = VerificationMachine::new( Account::new(second.user_id(), second.device_id()), - Arc::new(Box::new(MemoryStore::new())), + Store::new(Box::new(MemoryStore::new())), ); let first = Device { diff --git a/matrix_sdk_crypto/src/machine.rs b/matrix_sdk_crypto/src/machine.rs index 945ecb49..e3298909 100644 --- a/matrix_sdk_crypto/src/machine.rs +++ b/matrix_sdk_crypto/src/machine.rs @@ -62,7 +62,7 @@ use super::{ InboundGroupSession, OlmMessage, OutboundGroupSession, }, requests::{IncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest}, - store::{CryptoStore, MemoryStore, Result as StoreResult}, + store::{CryptoStore, MemoryStore, Result as StoreResult, Store}, verification::{Sas, VerificationMachine}, }; @@ -79,7 +79,7 @@ pub struct OlmMachine { /// Store for the encryption keys. /// Persists all the encryption keys so a client can resume the session /// without the need to create new keys. - store: Arc>, + store: Store, /// The currently active outbound group sessions. outbound_group_sessions: Arc>, /// A state machine that is responsible to handle and keep track of SAS @@ -113,7 +113,7 @@ impl OlmMachine { /// * `device_id` - The unique id of the device that owns this machine. pub fn new(user_id: &UserId, device_id: &DeviceId) -> Self { let store: Box = Box::new(MemoryStore::new()); - let store = Arc::new(store); + let store = Store::new(store); let account = Account::new(user_id, device_id); OlmMachine { @@ -161,7 +161,7 @@ impl OlmMachine { } }; - let store = Arc::new(store); + let store = Store::new(store); let verification_machine = VerificationMachine::new(account.clone(), store.clone()); Ok(OlmMachine { diff --git a/matrix_sdk_crypto/src/store/memorystore.rs b/matrix_sdk_crypto/src/store/memorystore.rs index 4de015bf..acd6f704 100644 --- a/matrix_sdk_crypto/src/store/memorystore.rs +++ b/matrix_sdk_crypto/src/store/memorystore.rs @@ -36,6 +36,7 @@ pub struct MemoryStore { users_for_key_query: Arc>, devices: DeviceStore, identities: Arc>, + values: Arc>, } impl Default for MemoryStore { @@ -47,6 +48,7 @@ impl Default for MemoryStore { users_for_key_query: Arc::new(DashSet::new()), devices: DeviceStore::new(), identities: Arc::new(DashMap::new()), + values: Arc::new(DashMap::new()), } } } @@ -164,6 +166,15 @@ impl CryptoStore for MemoryStore { } Ok(()) } + + async fn save_value(&self, key: String, value: String) -> Result<()> { + self.values.insert(key, value); + Ok(()) + } + + async fn get_value(&self, key: &str) -> Result> { + Ok(self.values.get(key).map(|v| v.to_owned())) + } } #[cfg(test)] diff --git a/matrix_sdk_crypto/src/store/mod.rs b/matrix_sdk_crypto/src/store/mod.rs index 88d2ec90..31e3e9ea 100644 --- a/matrix_sdk_crypto/src/store/mod.rs +++ b/matrix_sdk_crypto/src/store/mod.rs @@ -49,9 +49,10 @@ pub use memorystore::MemoryStore; #[cfg(feature = "sqlite_cryptostore")] pub use sqlite::SqliteStore; -use std::{collections::HashSet, fmt::Debug, io::Error as IoError, sync::Arc}; +use std::{collections::HashSet, fmt::Debug, io::Error as IoError, ops::Deref, sync::Arc}; use olm_rs::errors::{OlmAccountError, OlmGroupSessionError, OlmSessionError}; +use serde::{Deserialize, Serialize}; use serde_json::Error as SerdeError; use thiserror::Error; use url::ParseError; @@ -76,6 +77,44 @@ use super::{ use crate::error::SessionUnpicklingError; +/// A wrapper for our CryptoStore trait object. +/// +/// This is needed because we want to have a generic interface so we can +/// store/restore objects that we can serialize. Since trait objects and +/// generics don't mix let the CryptoStore store strings and this wrapper +/// adds the generic interface on top. +#[derive(Debug, Clone)] +pub(crate) struct Store(Arc>); + +impl Store { + pub fn new(store: Box) -> Self { + Self(Arc::new(store)) + } + + #[allow(dead_code)] + pub async fn get_object Deserialize<'b>>(&self, key: &str) -> Result> { + if let Some(value) = self.get_value(key).await? { + Ok(Some(serde_json::from_str(&value)?)) + } else { + Ok(None) + } + } + + #[allow(dead_code)] + pub async fn save_object(&self, key: &str, value: &impl Serialize) -> Result<()> { + let value = serde_json::to_string(value)?; + self.save_value(key.to_owned(), value).await + } +} + +impl Deref for Store { + type Target = dyn CryptoStore; + + fn deref(&self) -> &Self::Target { + &**self.0 + } +} + /// A `CryptoStore` specific result type. pub type Result = std::result::Result; @@ -250,4 +289,10 @@ pub trait CryptoStore: Debug { /// /// * `user_id` - The user for which we should get the identity. async fn get_user_identity(&self, user_id: &UserId) -> Result>; + + /// Save a serializeable object in the store. + async fn save_value(&self, key: String, value: String) -> Result<()>; + + /// Load a serializeable object from the store. + async fn get_value(&self, key: &str) -> Result>; } diff --git a/matrix_sdk_crypto/src/store/sqlite.rs b/matrix_sdk_crypto/src/store/sqlite.rs index 91b2a339..0072b476 100644 --- a/matrix_sdk_crypto/src/store/sqlite.rs +++ b/matrix_sdk_crypto/src/store/sqlite.rs @@ -1371,6 +1371,14 @@ impl CryptoStore for SqliteStore { Ok(()) } + + async fn save_value(&self, _key: String, _value: String) -> Result<()> { + todo!() + } + + async fn get_value(&self, _key: &str) -> Result> { + todo!() + } } #[cfg(not(tarpaulin_include))] diff --git a/matrix_sdk_crypto/src/verification/machine.rs b/matrix_sdk_crypto/src/verification/machine.rs index 9dbaca6c..03a36909 100644 --- a/matrix_sdk_crypto/src/verification/machine.rs +++ b/matrix_sdk_crypto/src/verification/machine.rs @@ -27,20 +27,20 @@ use matrix_sdk_common::{ use super::sas::{content_to_request, Sas}; use crate::{ requests::{OutgoingRequest, ToDeviceRequest}, - store::{CryptoStore, CryptoStoreError}, + store::{CryptoStoreError, Store}, Account, ReadOnlyDevice, }; #[derive(Clone, Debug)] pub struct VerificationMachine { account: Account, - pub(crate) store: Arc>, + pub(crate) store: Store, verifications: Arc>, outgoing_to_device_messages: Arc>, } impl VerificationMachine { - pub(crate) fn new(account: Account, store: Arc>) -> Self { + pub(crate) fn new(account: Account, store: Store) -> Self { Self { account, store, @@ -221,7 +221,6 @@ mod test { use std::{ convert::TryFrom, - sync::Arc, time::{Duration, Instant}, }; @@ -233,7 +232,7 @@ mod test { use super::{Sas, VerificationMachine}; use crate::{ requests::OutgoingRequests, - store::{CryptoStore, MemoryStore}, + store::{CryptoStore, MemoryStore, Store}, verification::test::{get_content_from_request, wrap_any_to_device_content}, Account, ReadOnlyDevice, }; @@ -258,7 +257,7 @@ mod test { let alice = Account::new(&alice_id(), &alice_device_id()); let bob = Account::new(&bob_id(), &bob_device_id()); let store = MemoryStore::new(); - let bob_store: Arc> = Arc::new(Box::new(MemoryStore::new())); + let bob_store = Store::new(Box::new(MemoryStore::new())); let bob_device = ReadOnlyDevice::from_account(&bob).await; let alice_device = ReadOnlyDevice::from_account(&alice).await; @@ -269,7 +268,7 @@ mod test { .await .unwrap(); - let machine = VerificationMachine::new(alice, Arc::new(Box::new(store))); + let machine = VerificationMachine::new(alice, Store::new(Box::new(store))); let (bob_sas, start_content) = Sas::start(bob, alice_device, bob_store, None); machine .receive_event(&mut wrap_any_to_device_content( @@ -286,7 +285,7 @@ mod test { fn create() { let alice = Account::new(&alice_id(), &alice_device_id()); let store = MemoryStore::new(); - let _ = VerificationMachine::new(alice, Arc::new(Box::new(store))); + let _ = VerificationMachine::new(alice, Store::new(Box::new(store))); } #[tokio::test] diff --git a/matrix_sdk_crypto/src/verification/sas/mod.rs b/matrix_sdk_crypto/src/verification/sas/mod.rs index 61724ed5..82af6692 100644 --- a/matrix_sdk_crypto/src/verification/sas/mod.rs +++ b/matrix_sdk_crypto/src/verification/sas/mod.rs @@ -34,7 +34,7 @@ use matrix_sdk_common::{ use crate::{ identities::{LocalTrust, ReadOnlyDevice, UserIdentities}, - store::{CryptoStore, CryptoStoreError}, + store::{CryptoStoreError, Store}, Account, ToDeviceRequest, }; @@ -47,7 +47,7 @@ use sas_state::{ /// Short authentication string object. pub struct Sas { inner: Arc>, - store: Arc>, + store: Store, account: Account, other_device: ReadOnlyDevice, other_identity: Option, @@ -104,7 +104,7 @@ impl Sas { pub(crate) fn start( account: Account, other_device: ReadOnlyDevice, - store: Arc>, + store: Store, other_identity: Option, ) -> (Sas, StartEventContent) { let (inner, content) = InnerSas::start( @@ -139,7 +139,7 @@ impl Sas { pub(crate) fn from_start_event( account: Account, other_device: ReadOnlyDevice, - store: Arc>, + store: Store, event: &ToDeviceEvent, other_identity: Option, ) -> Result { @@ -646,7 +646,7 @@ impl InnerSas { #[cfg(test)] mod test { - use std::{convert::TryFrom, sync::Arc}; + use std::convert::TryFrom; use matrix_sdk_common::{ events::{EventContent, ToDeviceEvent}, @@ -654,7 +654,7 @@ mod test { }; use crate::{ - store::{CryptoStore, MemoryStore}, + store::{MemoryStore, Store}, verification::test::{get_content_from_request, wrap_any_to_device_content}, Account, ReadOnlyDevice, }; @@ -776,8 +776,8 @@ mod test { let bob = Account::new(&bob_id(), &bob_device_id()); let bob_device = ReadOnlyDevice::from_account(&bob).await; - let alice_store: Arc> = Arc::new(Box::new(MemoryStore::new())); - let bob_store: Arc> = Arc::new(Box::new(MemoryStore::new())); + let alice_store = Store::new(Box::new(MemoryStore::new())); + let bob_store = Store::new(Box::new(MemoryStore::new())); bob_store .save_devices(&[alice_device.clone()])