1use std::{
16 collections::{BTreeMap, HashMap, HashSet},
17 convert::Infallible,
18 sync::Arc,
19};
20
21use async_trait::async_trait;
22use matrix_sdk_common::{
23 cross_process_lock::memory_store_helper::try_take_leased_lock, locks::RwLock as StdRwLock,
24};
25use ruma::{
26 events::secret::request::SecretName, time::Instant, DeviceId, OwnedDeviceId, OwnedRoomId,
27 OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UserId,
28};
29use tokio::sync::{Mutex, RwLock};
30use tracing::warn;
31use vodozemac::Curve25519PublicKey;
32
33use super::{
34 caches::DeviceStore,
35 types::{
36 BackupKeys, Changes, DehydratedDeviceKey, PendingChanges, RoomKeyCounts, RoomSettings,
37 StoredRoomKeyBundleData, TrackedUser,
38 },
39 Account, CryptoStore, InboundGroupSession, Session,
40};
41use crate::{
42 gossiping::{GossipRequest, GossippedSecret, SecretInfo},
43 identities::{DeviceData, UserIdentityData},
44 olm::{
45 OutboundGroupSession, PickledAccount, PickledInboundGroupSession, PickledSession,
46 PrivateCrossSigningIdentity, SenderDataType, StaticAccountData,
47 },
48 types::events::room_key_withheld::RoomKeyWithheldEvent,
49};
50
51fn encode_key_info(info: &SecretInfo) -> String {
52 match info {
53 SecretInfo::KeyRequest(info) => {
54 format!("{}{}{}", info.room_id(), info.algorithm(), info.session_id())
55 }
56 SecretInfo::SecretRequest(i) => i.as_ref().to_owned(),
57 }
58}
59
60type SessionId = String;
61
62#[derive(Clone, Debug, PartialEq)]
64struct BackupVersion(String);
65
66impl BackupVersion {
67 fn from(s: &str) -> Self {
68 Self(s.to_owned())
69 }
70
71 fn as_str(&self) -> &str {
72 &self.0
73 }
74}
75
76#[derive(Default, Debug)]
78pub struct MemoryStore {
79 static_account: Arc<StdRwLock<Option<StaticAccountData>>>,
80
81 account: StdRwLock<Option<String>>,
82 sessions: StdRwLock<BTreeMap<String, BTreeMap<String, String>>>,
84 inbound_group_sessions: StdRwLock<BTreeMap<OwnedRoomId, HashMap<String, String>>>,
85
86 inbound_group_sessions_backed_up_to:
90 StdRwLock<HashMap<OwnedRoomId, HashMap<SessionId, BackupVersion>>>,
91
92 outbound_group_sessions: StdRwLock<BTreeMap<OwnedRoomId, OutboundGroupSession>>,
93 private_identity: StdRwLock<Option<PrivateCrossSigningIdentity>>,
94 tracked_users: StdRwLock<HashMap<OwnedUserId, TrackedUser>>,
95 olm_hashes: StdRwLock<HashMap<String, HashSet<String>>>,
96 devices: DeviceStore,
97 identities: StdRwLock<HashMap<OwnedUserId, String>>,
98 outgoing_key_requests: StdRwLock<HashMap<OwnedTransactionId, GossipRequest>>,
99 key_requests_by_info: StdRwLock<HashMap<String, OwnedTransactionId>>,
100 direct_withheld_info: StdRwLock<HashMap<OwnedRoomId, HashMap<String, RoomKeyWithheldEvent>>>,
101 custom_values: StdRwLock<HashMap<String, Vec<u8>>>,
102 leases: StdRwLock<HashMap<String, (String, Instant)>>,
103 secret_inbox: StdRwLock<HashMap<String, Vec<GossippedSecret>>>,
104 backup_keys: RwLock<BackupKeys>,
105 dehydrated_device_pickle_key: RwLock<Option<DehydratedDeviceKey>>,
106 next_batch_token: RwLock<Option<String>>,
107 room_settings: StdRwLock<HashMap<OwnedRoomId, RoomSettings>>,
108 room_key_bundles:
109 StdRwLock<HashMap<OwnedRoomId, HashMap<OwnedUserId, StoredRoomKeyBundleData>>>,
110
111 save_changes_lock: Arc<Mutex<()>>,
112}
113
114impl MemoryStore {
115 pub fn new() -> Self {
117 Self::default()
118 }
119
120 fn get_static_account(&self) -> Option<StaticAccountData> {
121 self.static_account.read().clone()
122 }
123
124 pub(crate) fn save_devices(&self, devices: Vec<DeviceData>) {
125 for device in devices {
126 let _ = self.devices.add(device);
127 }
128 }
129
130 fn delete_devices(&self, devices: Vec<DeviceData>) {
131 for device in devices {
132 let _ = self.devices.remove(device.user_id(), device.device_id());
133 }
134 }
135
136 fn save_sessions(&self, sessions: Vec<(String, PickledSession)>) {
137 let mut session_store = self.sessions.write();
138
139 for (session_id, pickle) in sessions {
140 let entry = session_store.entry(pickle.sender_key.to_base64()).or_default();
141
142 entry.insert(
144 session_id,
145 serde_json::to_string(&pickle).expect("Failed to serialize olm session"),
146 );
147 }
148 }
149
150 fn save_outbound_group_sessions(&self, sessions: Vec<OutboundGroupSession>) {
151 self.outbound_group_sessions
152 .write()
153 .extend(sessions.into_iter().map(|s| (s.room_id().to_owned(), s)));
154 }
155
156 fn save_private_identity(&self, private_identity: Option<PrivateCrossSigningIdentity>) {
157 *self.private_identity.write() = private_identity;
158 }
159
160 async fn get_inbound_group_sessions_and_backed_up_to(
164 &self,
165 ) -> Result<Vec<(InboundGroupSession, Option<BackupVersion>)>> {
166 let lookup = |s: &InboundGroupSession| {
167 self.inbound_group_sessions_backed_up_to
168 .read()
169 .get(&s.room_id)?
170 .get(s.session_id())
171 .cloned()
172 };
173
174 Ok(self
175 .get_inbound_group_sessions()
176 .await?
177 .into_iter()
178 .map(|s| {
179 let v = lookup(&s);
180 (s, v)
181 })
182 .collect())
183 }
184}
185
186type Result<T> = std::result::Result<T, Infallible>;
187
188#[cfg_attr(target_family = "wasm", async_trait(?Send))]
189#[cfg_attr(not(target_family = "wasm"), async_trait)]
190impl CryptoStore for MemoryStore {
191 type Error = Infallible;
192
193 async fn load_account(&self) -> Result<Option<Account>> {
194 let pickled_account: Option<PickledAccount> = self.account.read().as_ref().map(|acc| {
195 serde_json::from_str(acc)
196 .expect("Deserialization failed: invalid pickled account JSON format")
197 });
198
199 if let Some(pickle) = pickled_account {
200 let account =
201 Account::from_pickle(pickle).expect("From pickle failed: invalid pickle format");
202
203 *self.static_account.write() = Some(account.static_data().clone());
204
205 Ok(Some(account))
206 } else {
207 Ok(None)
208 }
209 }
210
211 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
212 Ok(self.private_identity.read().clone())
213 }
214
215 async fn next_batch_token(&self) -> Result<Option<String>> {
216 Ok(self.next_batch_token.read().await.clone())
217 }
218
219 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
220 let _guard = self.save_changes_lock.lock().await;
221
222 let pickled_account = if let Some(account) = changes.account {
223 *self.static_account.write() = Some(account.static_data().clone());
224 Some(account.pickle())
225 } else {
226 None
227 };
228
229 *self.account.write() = pickled_account.map(|pickle| {
230 serde_json::to_string(&pickle)
231 .expect("Serialization failed: invalid pickled account JSON format")
232 });
233
234 Ok(())
235 }
236
237 async fn save_changes(&self, changes: Changes) -> Result<()> {
238 let _guard = self.save_changes_lock.lock().await;
239
240 let mut pickled_session: Vec<(String, PickledSession)> = Vec::new();
241 for session in changes.sessions {
242 let session_id = session.session_id().to_owned();
243 let pickle = session.pickle().await;
244 pickled_session.push((session_id.clone(), pickle));
245 }
246 self.save_sessions(pickled_session);
247
248 self.save_inbound_group_sessions(changes.inbound_group_sessions, None).await?;
249 self.save_outbound_group_sessions(changes.outbound_group_sessions);
250 self.save_private_identity(changes.private_identity);
251
252 self.save_devices(changes.devices.new);
253 self.save_devices(changes.devices.changed);
254 self.delete_devices(changes.devices.deleted);
255
256 {
257 let mut identities = self.identities.write();
258 for identity in changes.identities.new.into_iter().chain(changes.identities.changed) {
259 identities.insert(
260 identity.user_id().to_owned(),
261 serde_json::to_string(&identity)
262 .expect("UserIdentityData should always serialize to json"),
263 );
264 }
265 }
266
267 {
268 let mut olm_hashes = self.olm_hashes.write();
269 for hash in changes.message_hashes {
270 olm_hashes.entry(hash.sender_key.to_owned()).or_default().insert(hash.hash.clone());
271 }
272 }
273
274 {
275 let mut outgoing_key_requests = self.outgoing_key_requests.write();
276 let mut key_requests_by_info = self.key_requests_by_info.write();
277
278 for key_request in changes.key_requests {
279 let id = key_request.request_id.clone();
280 let info_string = encode_key_info(&key_request.info);
281
282 outgoing_key_requests.insert(id.clone(), key_request);
283 key_requests_by_info.insert(info_string, id);
284 }
285 }
286
287 if let Some(key) = changes.backup_decryption_key {
288 self.backup_keys.write().await.decryption_key = Some(key);
289 }
290
291 if let Some(version) = changes.backup_version {
292 self.backup_keys.write().await.backup_version = Some(version);
293 }
294
295 if let Some(pickle_key) = changes.dehydrated_device_pickle_key {
296 let mut lock = self.dehydrated_device_pickle_key.write().await;
297 *lock = Some(pickle_key);
298 }
299
300 {
301 let mut secret_inbox = self.secret_inbox.write();
302 for secret in changes.secrets {
303 secret_inbox.entry(secret.secret_name.to_string()).or_default().push(secret);
304 }
305 }
306
307 {
308 let mut direct_withheld_info = self.direct_withheld_info.write();
309 for (room_id, data) in changes.withheld_session_info {
310 for (session_id, event) in data {
311 direct_withheld_info
312 .entry(room_id.to_owned())
313 .or_default()
314 .insert(session_id, event);
315 }
316 }
317 }
318
319 if let Some(next_batch_token) = changes.next_batch_token {
320 *self.next_batch_token.write().await = Some(next_batch_token);
321 }
322
323 if !changes.room_settings.is_empty() {
324 let mut settings = self.room_settings.write();
325 settings.extend(changes.room_settings);
326 }
327
328 if !changes.received_room_key_bundles.is_empty() {
329 let mut room_key_bundles = self.room_key_bundles.write();
330 for bundle in changes.received_room_key_bundles {
331 room_key_bundles
332 .entry(bundle.bundle_data.room_id.clone())
333 .or_default()
334 .insert(bundle.sender_user.clone(), bundle);
335 }
336 }
337
338 Ok(())
339 }
340
341 async fn save_inbound_group_sessions(
342 &self,
343 sessions: Vec<InboundGroupSession>,
344 backed_up_to_version: Option<&str>,
345 ) -> Result<()> {
346 for session in sessions {
347 let room_id = session.room_id();
348 let session_id = session.session_id();
349
350 let backed_up = session.backed_up();
352 if backed_up != backed_up_to_version.is_some() {
353 warn!(
354 backed_up,
355 backed_up_to_version,
356 "Session backed-up flag does not correspond to backup version setting",
357 );
358 }
359
360 if let Some(backup_version) = backed_up_to_version {
361 self.inbound_group_sessions_backed_up_to
362 .write()
363 .entry(room_id.to_owned())
364 .or_default()
365 .insert(session_id.to_owned(), BackupVersion::from(backup_version));
366 }
367
368 let pickle = session.pickle().await;
369 self.inbound_group_sessions
370 .write()
371 .entry(session.room_id().to_owned())
372 .or_default()
373 .insert(
374 session.session_id().to_owned(),
375 serde_json::to_string(&pickle)
376 .expect("Pickle pickle data should serialize to json"),
377 );
378 }
379 Ok(())
380 }
381
382 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
383 let device_keys = self.get_own_device().await?.as_device_keys().clone();
384
385 if let Some(pickles) = self.sessions.read().get(sender_key) {
386 let mut sessions: Vec<Session> = Vec::new();
387 for serialized_pickle in pickles.values() {
388 let pickle: PickledSession = serde_json::from_str(serialized_pickle.as_str())
389 .expect("Pickle pickle deserialization should work");
390 let session = Session::from_pickle(device_keys.clone(), pickle)
391 .expect("Expect from pickle to always work");
392 sessions.push(session);
393 }
394 Ok(Some(sessions))
395 } else {
396 Ok(None)
397 }
398 }
399
400 async fn get_inbound_group_session(
401 &self,
402 room_id: &RoomId,
403 session_id: &str,
404 ) -> Result<Option<InboundGroupSession>> {
405 let pickle: Option<PickledInboundGroupSession> = self
406 .inbound_group_sessions
407 .read()
408 .get(room_id)
409 .and_then(|m| m.get(session_id))
410 .and_then(|ser| {
411 serde_json::from_str(ser).expect("Pickle pickle deserialization should work")
412 });
413
414 Ok(pickle.map(|p| {
415 InboundGroupSession::from_pickle(p).expect("Expect from pickle to always work")
416 }))
417 }
418
419 async fn get_withheld_info(
420 &self,
421 room_id: &RoomId,
422 session_id: &str,
423 ) -> Result<Option<RoomKeyWithheldEvent>> {
424 Ok(self
425 .direct_withheld_info
426 .read()
427 .get(room_id)
428 .and_then(|e| Some(e.get(session_id)?.to_owned())))
429 }
430
431 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
432 let inbounds = self
433 .inbound_group_sessions
434 .read()
435 .values()
436 .flat_map(HashMap::values)
437 .map(|ser| {
438 let pickle: PickledInboundGroupSession =
439 serde_json::from_str(ser).expect("Pickle deserialization should work");
440 InboundGroupSession::from_pickle(pickle).expect("Expect from pickle to always work")
441 })
442 .collect();
443 Ok(inbounds)
444 }
445
446 async fn inbound_group_session_counts(
447 &self,
448 backup_version: Option<&str>,
449 ) -> Result<RoomKeyCounts> {
450 let backed_up = if let Some(backup_version) = backup_version {
451 self.get_inbound_group_sessions_and_backed_up_to()
452 .await?
453 .into_iter()
454 .filter(|(_, o)| o.as_ref().is_some_and(|o| o.as_str() == backup_version))
456 .count()
457 } else {
458 0
462 };
463
464 let total = self.inbound_group_sessions.read().values().map(HashMap::len).sum();
465 Ok(RoomKeyCounts { total, backed_up })
466 }
467
468 async fn get_inbound_group_sessions_by_room_id(
469 &self,
470 room_id: &RoomId,
471 ) -> Result<Vec<InboundGroupSession>> {
472 let inbounds = match self.inbound_group_sessions.read().get(room_id) {
473 None => Vec::new(),
474 Some(v) => v
475 .values()
476 .map(|ser| {
477 let pickle: PickledInboundGroupSession =
478 serde_json::from_str(ser).expect("Pickle deserialization should work");
479 InboundGroupSession::from_pickle(pickle)
480 .expect("Expect from pickle to always work")
481 })
482 .collect(),
483 };
484 Ok(inbounds)
485 }
486
487 async fn get_inbound_group_sessions_for_device_batch(
488 &self,
489 sender_key: Curve25519PublicKey,
490 sender_data_type: SenderDataType,
491 after_session_id: Option<String>,
492 limit: usize,
493 ) -> Result<Vec<InboundGroupSession>> {
494 let mut sessions: Vec<_> = self
497 .get_inbound_group_sessions()
498 .await?
499 .into_iter()
500 .filter(|session: &InboundGroupSession| {
501 session.creator_info.curve25519_key == sender_key
502 && session.sender_data.to_type() == sender_data_type
503 })
504 .collect();
505
506 sessions.sort_by_key(|s| s.session_id().to_owned());
508
509 let start_index = {
511 match after_session_id {
512 None => 0,
513 Some(id) => {
514 sessions
517 .iter()
518 .position(|session| session.session_id() > id.as_str())
519 .unwrap_or(sessions.len())
520 }
521 }
522 };
523
524 Ok(sessions.drain(start_index..).take(limit).collect())
526 }
527
528 async fn inbound_group_sessions_for_backup(
529 &self,
530 backup_version: &str,
531 limit: usize,
532 ) -> Result<Vec<InboundGroupSession>> {
533 Ok(self
534 .get_inbound_group_sessions_and_backed_up_to()
535 .await?
536 .into_iter()
537 .filter_map(|(session, backed_up_to)| {
538 if let Some(ref existing_version) = backed_up_to {
539 if existing_version.as_str() == backup_version {
540 return None;
542 }
543 }
544 Some(session)
546 })
547 .take(limit)
548 .collect())
549 }
550
551 async fn mark_inbound_group_sessions_as_backed_up(
552 &self,
553 backup_version: &str,
554 room_and_session_ids: &[(&RoomId, &str)],
555 ) -> Result<()> {
556 for &(room_id, session_id) in room_and_session_ids {
557 let session = self.get_inbound_group_session(room_id, session_id).await?;
558
559 if let Some(session) = session {
560 session.mark_as_backed_up();
561
562 self.inbound_group_sessions_backed_up_to
563 .write()
564 .entry(room_id.to_owned())
565 .or_default()
566 .insert(session_id.to_owned(), BackupVersion::from(backup_version));
567
568 let updated_pickle = session.pickle().await;
570
571 self.inbound_group_sessions.write().entry(room_id.to_owned()).or_default().insert(
572 session_id.to_owned(),
573 serde_json::to_string(&updated_pickle)
574 .expect("Pickle serialization should work"),
575 );
576 }
577 }
578
579 Ok(())
580 }
581
582 async fn reset_backup_state(&self) -> Result<()> {
583 Ok(())
590 }
591
592 async fn load_backup_keys(&self) -> Result<BackupKeys> {
593 Ok(self.backup_keys.read().await.to_owned())
594 }
595
596 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
597 Ok(self.dehydrated_device_pickle_key.read().await.to_owned())
598 }
599
600 async fn delete_dehydrated_device_pickle_key(&self) -> Result<()> {
601 let mut lock = self.dehydrated_device_pickle_key.write().await;
602 *lock = None;
603 Ok(())
604 }
605
606 async fn get_outbound_group_session(
607 &self,
608 room_id: &RoomId,
609 ) -> Result<Option<OutboundGroupSession>> {
610 Ok(self.outbound_group_sessions.read().get(room_id).cloned())
611 }
612
613 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
614 Ok(self.tracked_users.read().values().cloned().collect())
615 }
616
617 async fn save_tracked_users(&self, tracked_users: &[(&UserId, bool)]) -> Result<()> {
618 self.tracked_users.write().extend(tracked_users.iter().map(|(user_id, dirty)| {
619 let user_id: OwnedUserId = user_id.to_owned().into();
620 (user_id.clone(), TrackedUser { user_id, dirty: *dirty })
621 }));
622 Ok(())
623 }
624
625 async fn get_device(
626 &self,
627 user_id: &UserId,
628 device_id: &DeviceId,
629 ) -> Result<Option<DeviceData>> {
630 Ok(self.devices.get(user_id, device_id))
631 }
632
633 async fn get_user_devices(
634 &self,
635 user_id: &UserId,
636 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
637 Ok(self.devices.user_devices(user_id))
638 }
639
640 async fn get_own_device(&self) -> Result<DeviceData> {
641 let account =
642 self.get_static_account().expect("Expect account to exist when getting own device");
643
644 Ok(self
645 .devices
646 .get(&account.user_id, &account.device_id)
647 .expect("Invalid state: Should always have a own device"))
648 }
649
650 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
651 let serialized = self.identities.read().get(user_id).cloned();
652 match serialized {
653 None => Ok(None),
654 Some(serialized) => {
655 let id: UserIdentityData = serde_json::from_str(serialized.as_str())
656 .expect("Only valid serialized identity are saved");
657 Ok(Some(id))
658 }
659 }
660 }
661
662 async fn is_message_known(&self, message_hash: &crate::olm::OlmMessageHash) -> Result<bool> {
663 Ok(self
664 .olm_hashes
665 .write()
666 .entry(message_hash.sender_key.to_owned())
667 .or_default()
668 .contains(&message_hash.hash))
669 }
670
671 async fn get_outgoing_secret_requests(
672 &self,
673 request_id: &TransactionId,
674 ) -> Result<Option<GossipRequest>> {
675 Ok(self.outgoing_key_requests.read().get(request_id).cloned())
676 }
677
678 async fn get_secret_request_by_info(
679 &self,
680 key_info: &SecretInfo,
681 ) -> Result<Option<GossipRequest>> {
682 let key_info_string = encode_key_info(key_info);
683
684 Ok(self
685 .key_requests_by_info
686 .read()
687 .get(&key_info_string)
688 .and_then(|i| self.outgoing_key_requests.read().get(i).cloned()))
689 }
690
691 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
692 Ok(self
693 .outgoing_key_requests
694 .read()
695 .values()
696 .filter(|req| !req.sent_out)
697 .cloned()
698 .collect())
699 }
700
701 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
702 let req = self.outgoing_key_requests.write().remove(request_id);
703 if let Some(i) = req {
704 let key_info_string = encode_key_info(&i.info);
705 self.key_requests_by_info.write().remove(&key_info_string);
706 }
707
708 Ok(())
709 }
710
711 async fn get_secrets_from_inbox(
712 &self,
713 secret_name: &SecretName,
714 ) -> Result<Vec<GossippedSecret>> {
715 Ok(self.secret_inbox.write().entry(secret_name.to_string()).or_default().to_owned())
716 }
717
718 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
719 self.secret_inbox.write().remove(secret_name.as_str());
720
721 Ok(())
722 }
723
724 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
725 Ok(self.room_settings.read().get(room_id).cloned())
726 }
727
728 async fn get_received_room_key_bundle_data(
729 &self,
730 room_id: &RoomId,
731 user_id: &UserId,
732 ) -> Result<Option<StoredRoomKeyBundleData>> {
733 let guard = self.room_key_bundles.read();
734
735 let result = guard.get(room_id).and_then(|bundles| bundles.get(user_id).cloned());
736
737 Ok(result)
738 }
739
740 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>> {
741 Ok(self.custom_values.read().get(key).cloned())
742 }
743
744 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<()> {
745 self.custom_values.write().insert(key.to_owned(), value);
746 Ok(())
747 }
748
749 async fn remove_custom_value(&self, key: &str) -> Result<()> {
750 self.custom_values.write().remove(key);
751 Ok(())
752 }
753
754 async fn try_take_leased_lock(
755 &self,
756 lease_duration_ms: u32,
757 key: &str,
758 holder: &str,
759 ) -> Result<bool> {
760 Ok(try_take_leased_lock(&mut self.leases.write(), lease_duration_ms, key, holder))
761 }
762}
763
764#[cfg(test)]
765mod tests {
766 use std::collections::HashMap;
767
768 use matrix_sdk_test::async_test;
769 use ruma::{room_id, user_id, RoomId};
770 use vodozemac::{Curve25519PublicKey, Ed25519PublicKey};
771
772 use super::SessionId;
773 use crate::{
774 identities::device::testing::get_device,
775 olm::{
776 tests::get_account_and_session_test_helper, Account, InboundGroupSession,
777 OlmMessageHash, PrivateCrossSigningIdentity, SenderData,
778 },
779 store::{
780 memorystore::MemoryStore,
781 types::{Changes, DeviceChanges, PendingChanges},
782 CryptoStore,
783 },
784 DeviceData,
785 };
786
787 #[async_test]
788 async fn test_session_store() {
789 let (account, session) = get_account_and_session_test_helper();
790 let own_device = DeviceData::from_account(&account);
791 let store = MemoryStore::new();
792
793 assert!(store.load_account().await.unwrap().is_none());
794
795 store
796 .save_changes(Changes {
797 devices: DeviceChanges { new: vec![own_device], ..Default::default() },
798 ..Default::default()
799 })
800 .await
801 .unwrap();
802 store.save_pending_changes(PendingChanges { account: Some(account) }).await.unwrap();
803
804 store
805 .save_changes(Changes { sessions: (vec![session.clone()]), ..Default::default() })
806 .await
807 .unwrap();
808
809 let sessions = store.get_sessions(&session.sender_key.to_base64()).await.unwrap().unwrap();
810
811 let loaded_session = &sessions[0];
812
813 assert_eq!(&session, loaded_session);
814 }
815
816 #[async_test]
817 async fn test_inbound_group_session_store() {
818 let (account, _) = get_account_and_session_test_helper();
819 let room_id = room_id!("!test:localhost");
820 let curve_key = "Nn0L2hkcCMFKqynTjyGsJbth7QrVmX3lbrksMkrGOAw";
821
822 let (outbound, _) = account.create_group_session_pair_with_defaults(room_id).await;
823 let inbound = InboundGroupSession::new(
824 Curve25519PublicKey::from_base64(curve_key).unwrap(),
825 Ed25519PublicKey::from_base64("ee3Ek+J2LkkPmjGPGLhMxiKnhiX//xcqaVL4RP6EypE").unwrap(),
826 room_id,
827 &outbound.session_key().await,
828 SenderData::unknown(),
829 outbound.settings().algorithm.to_owned(),
830 None,
831 false,
832 )
833 .unwrap();
834
835 let store = MemoryStore::new();
836 store.save_inbound_group_sessions(vec![inbound.clone()], None).await.unwrap();
837
838 let loaded_session =
839 store.get_inbound_group_session(room_id, outbound.session_id()).await.unwrap().unwrap();
840 assert_eq!(inbound, loaded_session);
841 }
842
843 #[async_test]
844 async fn test_backing_up_marks_sessions_as_backed_up() {
845 let room_id = room_id!("!test:localhost");
847 let (store, sessions) = store_with_sessions(2, room_id).await;
848
849 mark_backed_up(&store, room_id, "bkp1", &sessions).await;
851
852 let but = backed_up_tos(&store).await;
854 assert_eq!(but[sessions[0].session_id()], "bkp1");
855 assert_eq!(but[sessions[1].session_id()], "bkp1");
856 }
857
858 #[async_test]
859 async fn test_backing_up_a_second_set_of_sessions_updates_their_backup_order() {
860 let room_id = room_id!("!test:localhost");
862 let (store, sessions) = store_with_sessions(3, room_id).await;
863
864 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
866
867 mark_backed_up(&store, room_id, "bkp2", &sessions[1..]).await;
869
870 let but = backed_up_tos(&store).await;
872 assert_eq!(but[sessions[0].session_id()], "bkp1");
873 assert_eq!(but[sessions[1].session_id()], "bkp2");
874 assert_eq!(but[sessions[2].session_id()], "bkp2");
875 }
876
877 #[async_test]
878 async fn test_backing_up_again_to_the_same_version_has_no_effect() {
879 let room_id = room_id!("!test:localhost");
881 let (store, sessions) = store_with_sessions(3, room_id).await;
882
883 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
885
886 mark_backed_up(&store, room_id, "bkp1", &sessions[1..]).await;
888
889 let but = backed_up_tos(&store).await;
891 assert_eq!(but[sessions[0].session_id()], "bkp1");
892 assert_eq!(but[sessions[1].session_id()], "bkp1");
893 assert_eq!(but[sessions[2].session_id()], "bkp1");
894 }
895
896 #[async_test]
897 async fn test_backing_up_to_an_old_backup_version_can_increase_backed_up_to() {
898 let room_id = room_id!("!test:localhost");
901 let (store, sessions) = store_with_sessions(4, room_id).await;
902 mark_backed_up(&store, room_id, "older_bkp", &sessions[..2]).await;
903 mark_backed_up(&store, room_id, "newer_bkp", &sessions[1..2]).await;
904
905 mark_backed_up(&store, room_id, "older_bkp", &sessions[2..]).await;
907
908 let but = backed_up_tos(&store).await;
910 assert_eq!(but[sessions[0].session_id()], "older_bkp");
911 assert_eq!(but[sessions[1].session_id()], "newer_bkp");
912 assert_eq!(but[sessions[2].session_id()], "older_bkp");
913 assert_eq!(but[sessions[3].session_id()], "older_bkp");
914 }
915
916 #[async_test]
917 async fn test_backing_up_to_an_old_backup_version_overwrites_a_newer_one() {
918 let room_id = room_id!("!test:localhost");
920 let (store, sessions) = store_with_sessions(4, room_id).await;
921 mark_backed_up(&store, room_id, "older_bkp", &sessions).await;
922 assert_eq!(backed_up_tos(&store).await[sessions[0].session_id()], "older_bkp");
924 mark_backed_up(&store, room_id, "newer_bkp", &sessions).await;
925 assert_eq!(backed_up_tos(&store).await[sessions[0].session_id()], "newer_bkp");
927
928 mark_backed_up(&store, room_id, "older_bkp", &sessions[..2]).await;
930
931 let but = backed_up_tos(&store).await;
933 assert_eq!(but[sessions[0].session_id()], "older_bkp");
934 assert_eq!(but[sessions[1].session_id()], "older_bkp");
935 assert_eq!(but[sessions[2].session_id()], "newer_bkp");
936 assert_eq!(but[sessions[3].session_id()], "newer_bkp");
937 }
938
939 #[async_test]
940 async fn test_not_backed_up_sessions_are_eligible_for_backup() {
941 let room_id = room_id!("!test:localhost");
943 let (store, sessions) = store_with_sessions(4, room_id).await;
944 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
945
946 let mut to_backup = store
948 .inbound_group_sessions_for_backup("bkp1", 10)
949 .await
950 .expect("Failed to ask for sessions to backup");
951 to_backup.sort_by_key(|s| s.session_id().to_owned());
952
953 assert_eq!(to_backup, &[sessions[2].clone(), sessions[3].clone()]);
955 }
956
957 #[async_test]
958 async fn test_all_sessions_are_eligible_for_backup_if_version_is_unknown() {
959 let room_id = room_id!("!test:localhost");
961 let (store, sessions) = store_with_sessions(4, room_id).await;
962 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
963
964 let mut to_backup = store
966 .inbound_group_sessions_for_backup("unknown_bkp", 10)
967 .await
968 .expect("Failed to ask for sessions to backup");
969 to_backup.sort_by_key(|s| s.session_id().to_owned());
970
971 assert_eq!(
973 to_backup,
974 &[sessions[0].clone(), sessions[1].clone(), sessions[2].clone(), sessions[3].clone()]
975 );
976 }
977
978 #[async_test]
979 async fn test_sessions_backed_up_to_a_later_version_are_eligible_for_backup() {
980 let room_id = room_id!("!test:localhost");
982 let (store, sessions) = store_with_sessions(4, room_id).await;
983 mark_backed_up(&store, room_id, "bkp0", &sessions[..1]).await;
984 mark_backed_up(&store, room_id, "bkp1", &sessions[1..2]).await;
985 mark_backed_up(&store, room_id, "bkp2", &sessions[2..3]).await;
986
987 let mut to_backup = store
989 .inbound_group_sessions_for_backup("bkp1", 10)
990 .await
991 .expect("Failed to ask for sessions to backup");
992 to_backup.sort_by_key(|s| s.session_id().to_owned());
993
994 assert_eq!(
996 to_backup,
997 &[
998 sessions[0].clone(), sessions[2].clone(), sessions[3].clone(), ]
1003 );
1004 }
1005
1006 #[async_test]
1007 async fn test_outbound_group_session_store() {
1008 let (account, _) = get_account_and_session_test_helper();
1010 let room_id = room_id!("!test:localhost");
1011 let (outbound, _) = account.create_group_session_pair_with_defaults(room_id).await;
1012
1013 let store = MemoryStore::new();
1015 store.save_outbound_group_sessions(vec![outbound.clone()]);
1016
1017 let loaded_session = store.get_outbound_group_session(room_id).await.unwrap().unwrap();
1019 assert_eq!(
1020 serde_json::to_string(&outbound.pickle().await).unwrap(),
1021 serde_json::to_string(&loaded_session.pickle().await).unwrap()
1022 );
1023 }
1024
1025 #[async_test]
1026 async fn test_tracked_users_are_stored_once_per_user_id() {
1027 let user1 = user_id!("@user1:s");
1029 let user2 = user_id!("@user2:s");
1030 let user3 = user_id!("@user3:s");
1031 let store = MemoryStore::new();
1032 store.save_tracked_users(&[(user1, true), (user2, true)]).await.unwrap();
1033
1034 store.save_tracked_users(&[(user2, false), (user3, false)]).await.unwrap();
1036
1037 let loaded_tracked_users =
1039 store.load_tracked_users().await.expect("failed to load tracked users");
1040
1041 let tracked_contains = |user_id, dirty| {
1042 loaded_tracked_users.iter().any(|u| u.user_id == user_id && u.dirty == dirty)
1043 };
1044
1045 assert!(tracked_contains(user1, true));
1046 assert!(tracked_contains(user2, false));
1047 assert!(tracked_contains(user3, false));
1048 assert_eq!(loaded_tracked_users.len(), 3);
1049 }
1050
1051 #[async_test]
1052 async fn test_private_identity_store() {
1053 let private_identity = PrivateCrossSigningIdentity::empty(user_id!("@u:s"));
1055
1056 let store = MemoryStore::new();
1058 store.save_private_identity(Some(private_identity.clone()));
1059
1060 let loaded_identity =
1062 store.load_identity().await.expect("failed to load private identity").unwrap();
1063
1064 assert_eq!(loaded_identity.user_id(), user_id!("@u:s"));
1065 }
1066
1067 #[async_test]
1068 async fn test_device_store() {
1069 let device = get_device();
1070 let store = MemoryStore::new();
1071
1072 store.save_devices(vec![device.clone()]);
1073
1074 let loaded_device =
1075 store.get_device(device.user_id(), device.device_id()).await.unwrap().unwrap();
1076
1077 assert_eq!(device, loaded_device);
1078
1079 let user_devices = store.get_user_devices(device.user_id()).await.unwrap();
1080
1081 assert_eq!(&**user_devices.keys().next().unwrap(), device.device_id());
1082 assert_eq!(user_devices.values().next().unwrap(), &device);
1083
1084 let loaded_device = user_devices.get(device.device_id()).unwrap();
1085
1086 assert_eq!(&device, loaded_device);
1087
1088 store.delete_devices(vec![device.clone()]);
1089 assert!(store.get_device(device.user_id(), device.device_id()).await.unwrap().is_none());
1090 }
1091
1092 #[async_test]
1093 async fn test_message_hash() {
1094 let store = MemoryStore::new();
1095
1096 let hash =
1097 OlmMessageHash { sender_key: "test_sender".to_owned(), hash: "test_hash".to_owned() };
1098
1099 let mut changes = Changes::default();
1100 changes.message_hashes.push(hash.clone());
1101
1102 assert!(!store.is_message_known(&hash).await.unwrap());
1103 store.save_changes(changes).await.unwrap();
1104 assert!(store.is_message_known(&hash).await.unwrap());
1105 }
1106
1107 #[async_test]
1108 async fn test_key_counts_of_empty_store_are_zero() {
1109 let store = MemoryStore::new();
1111
1112 let key_counts = store.inbound_group_session_counts(Some("")).await.unwrap();
1114
1115 assert_eq!(key_counts.total, 0);
1117 assert_eq!(key_counts.backed_up, 0);
1118 }
1119
1120 #[async_test]
1121 async fn test_counting_sessions_reports_the_number_of_sessions() {
1122 let room_id = room_id!("!test:localhost");
1124 let (store, _) = store_with_sessions(4, room_id).await;
1125
1126 let key_counts = store.inbound_group_session_counts(Some("bkp")).await.unwrap();
1128
1129 assert_eq!(key_counts.total, 4);
1131 assert_eq!(key_counts.backed_up, 0);
1133 }
1134
1135 #[async_test]
1136 async fn test_counting_backed_up_sessions_reports_the_number_backed_up_in_this_backup() {
1137 let room_id = room_id!("!test:localhost");
1139 let (store, sessions) = store_with_sessions(5, room_id).await;
1140 mark_backed_up(&store, room_id, "bkp", &sessions[..2]).await;
1141
1142 let key_counts = store.inbound_group_session_counts(Some("bkp")).await.unwrap();
1144
1145 assert_eq!(key_counts.total, 5);
1147 assert_eq!(key_counts.backed_up, 2);
1149 }
1150
1151 #[async_test]
1152 async fn test_counting_backed_up_sessions_for_null_backup_reports_zero() {
1153 let room_id = room_id!("!test:localhost");
1155 let (store, sessions) = store_with_sessions(4, room_id).await;
1156 mark_backed_up(&store, room_id, "bkp", &sessions[..2]).await;
1157
1158 let key_counts = store.inbound_group_session_counts(None).await.unwrap();
1160
1161 assert_eq!(key_counts.backed_up, 0);
1163 }
1164
1165 #[async_test]
1166 async fn test_counting_backed_up_sessions_only_reports_sessions_in_the_version_specified() {
1167 let room_id = room_id!("!test:localhost");
1169 let (store, sessions) = store_with_sessions(4, room_id).await;
1170 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
1171 mark_backed_up(&store, room_id, "bkp2", &sessions[3..]).await;
1172
1173 let key_counts = store.inbound_group_session_counts(Some("bkp2")).await.unwrap();
1175
1176 assert_eq!(key_counts.backed_up, 1);
1178 }
1179
1180 async fn mark_backed_up(
1182 store: &MemoryStore,
1183 room_id: &RoomId,
1184 backup_version: &str,
1185 sessions: &[InboundGroupSession],
1186 ) {
1187 let rooms_and_ids: Vec<_> = sessions.iter().map(|s| (room_id, s.session_id())).collect();
1188
1189 store
1190 .mark_inbound_group_sessions_as_backed_up(backup_version, &rooms_and_ids)
1191 .await
1192 .expect("Failed to mark sessions as backed up");
1193 }
1194
1195 async fn store_with_sessions(
1199 num_sessions: usize,
1200 room_id: &RoomId,
1201 ) -> (MemoryStore, Vec<InboundGroupSession>) {
1202 let (account, _) = get_account_and_session_test_helper();
1203
1204 let mut sessions = Vec::with_capacity(num_sessions);
1205 for _ in 0..num_sessions {
1206 sessions.push(new_session(&account, room_id).await);
1207 }
1208 sessions.sort_by_key(|s| s.session_id().to_owned());
1209
1210 let store = MemoryStore::new();
1211 store.save_inbound_group_sessions(sessions.clone(), None).await.unwrap();
1212
1213 (store, sessions)
1214 }
1215
1216 async fn new_session(account: &Account, room_id: &RoomId) -> InboundGroupSession {
1218 let curve_key = "Nn0L2hkcCMFKqynTjyGsJbth7QrVmX3lbrksMkrGOAw";
1219 let (outbound, _) = account.create_group_session_pair_with_defaults(room_id).await;
1220
1221 InboundGroupSession::new(
1222 Curve25519PublicKey::from_base64(curve_key).unwrap(),
1223 Ed25519PublicKey::from_base64("ee3Ek+J2LkkPmjGPGLhMxiKnhiX//xcqaVL4RP6EypE").unwrap(),
1224 room_id,
1225 &outbound.session_key().await,
1226 SenderData::unknown(),
1227 outbound.settings().algorithm.to_owned(),
1228 None,
1229 false,
1230 )
1231 .unwrap()
1232 }
1233
1234 async fn backed_up_tos(store: &MemoryStore) -> HashMap<SessionId, String> {
1237 store
1238 .get_inbound_group_sessions_and_backed_up_to()
1239 .await
1240 .expect("Unable to get inbound group sessions and backup order")
1241 .iter()
1242 .map(|(s, o)| {
1243 (
1244 s.session_id().to_owned(),
1245 o.as_ref().map(|v| v.as_str().to_owned()).unwrap_or("".to_owned()),
1246 )
1247 })
1248 .collect()
1249 }
1250}
1251
1252#[cfg(test)]
1253mod integration_tests {
1254 use std::{
1255 collections::HashMap,
1256 sync::{Arc, Mutex, OnceLock},
1257 };
1258
1259 use async_trait::async_trait;
1260 use ruma::{
1261 events::secret::request::SecretName, DeviceId, OwnedDeviceId, RoomId, TransactionId, UserId,
1262 };
1263 use vodozemac::Curve25519PublicKey;
1264
1265 use super::MemoryStore;
1266 use crate::{
1267 cryptostore_integration_tests, cryptostore_integration_tests_time,
1268 olm::{
1269 InboundGroupSession, OlmMessageHash, OutboundGroupSession, PrivateCrossSigningIdentity,
1270 SenderDataType, StaticAccountData,
1271 },
1272 store::{
1273 types::{
1274 BackupKeys, Changes, DehydratedDeviceKey, PendingChanges, RoomKeyCounts,
1275 RoomSettings, StoredRoomKeyBundleData, TrackedUser,
1276 },
1277 CryptoStore,
1278 },
1279 types::events::room_key_withheld::RoomKeyWithheldEvent,
1280 Account, DeviceData, GossipRequest, GossippedSecret, SecretInfo, Session, UserIdentityData,
1281 };
1282
1283 #[derive(Clone, Debug)]
1286 struct PersistentMemoryStore(Arc<MemoryStore>);
1287
1288 impl PersistentMemoryStore {
1289 fn new() -> Self {
1290 Self(Arc::new(MemoryStore::new()))
1291 }
1292
1293 fn get_static_account(&self) -> Option<StaticAccountData> {
1294 self.0.get_static_account()
1295 }
1296 }
1297
1298 async fn get_store(
1303 name: &str,
1304 _passphrase: Option<&str>,
1305 clear_data: bool,
1306 ) -> PersistentMemoryStore {
1307 static STORES: OnceLock<Mutex<HashMap<String, PersistentMemoryStore>>> = OnceLock::new();
1312 let stores = STORES.get_or_init(|| Mutex::new(HashMap::new()));
1313
1314 let mut stores = stores.lock().unwrap();
1315
1316 if clear_data {
1317 let new_store = PersistentMemoryStore::new();
1319 stores.insert(name.to_owned(), new_store.clone());
1320 new_store
1321 } else {
1322 stores.entry(name.to_owned()).or_insert_with(PersistentMemoryStore::new).clone()
1323 }
1324 }
1325
1326 #[cfg_attr(target_family = "wasm", async_trait(?Send))]
1328 #[cfg_attr(not(target_family = "wasm"), async_trait)]
1329 impl CryptoStore for PersistentMemoryStore {
1330 type Error = <MemoryStore as CryptoStore>::Error;
1331
1332 async fn load_account(&self) -> Result<Option<Account>, Self::Error> {
1333 self.0.load_account().await
1334 }
1335
1336 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>, Self::Error> {
1337 self.0.load_identity().await
1338 }
1339
1340 async fn save_changes(&self, changes: Changes) -> Result<(), Self::Error> {
1341 self.0.save_changes(changes).await
1342 }
1343
1344 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<(), Self::Error> {
1345 self.0.save_pending_changes(changes).await
1346 }
1347
1348 async fn save_inbound_group_sessions(
1349 &self,
1350 sessions: Vec<InboundGroupSession>,
1351 backed_up_to_version: Option<&str>,
1352 ) -> Result<(), Self::Error> {
1353 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await
1354 }
1355
1356 async fn get_sessions(
1357 &self,
1358 sender_key: &str,
1359 ) -> Result<Option<Vec<Session>>, Self::Error> {
1360 self.0.get_sessions(sender_key).await
1361 }
1362
1363 async fn get_inbound_group_session(
1364 &self,
1365 room_id: &RoomId,
1366 session_id: &str,
1367 ) -> Result<Option<InboundGroupSession>, Self::Error> {
1368 self.0.get_inbound_group_session(room_id, session_id).await
1369 }
1370
1371 async fn get_withheld_info(
1372 &self,
1373 room_id: &RoomId,
1374 session_id: &str,
1375 ) -> Result<Option<RoomKeyWithheldEvent>, Self::Error> {
1376 self.0.get_withheld_info(room_id, session_id).await
1377 }
1378
1379 async fn get_inbound_group_sessions(
1380 &self,
1381 ) -> Result<Vec<InboundGroupSession>, Self::Error> {
1382 self.0.get_inbound_group_sessions().await
1383 }
1384
1385 async fn inbound_group_session_counts(
1386 &self,
1387 backup_version: Option<&str>,
1388 ) -> Result<RoomKeyCounts, Self::Error> {
1389 self.0.inbound_group_session_counts(backup_version).await
1390 }
1391
1392 async fn get_inbound_group_sessions_by_room_id(
1393 &self,
1394 room_id: &RoomId,
1395 ) -> Result<Vec<InboundGroupSession>, Self::Error> {
1396 self.0.get_inbound_group_sessions_by_room_id(room_id).await
1397 }
1398
1399 async fn get_inbound_group_sessions_for_device_batch(
1400 &self,
1401 sender_key: Curve25519PublicKey,
1402 sender_data_type: SenderDataType,
1403 after_session_id: Option<String>,
1404 limit: usize,
1405 ) -> Result<Vec<InboundGroupSession>, Self::Error> {
1406 self.0
1407 .get_inbound_group_sessions_for_device_batch(
1408 sender_key,
1409 sender_data_type,
1410 after_session_id,
1411 limit,
1412 )
1413 .await
1414 }
1415
1416 async fn inbound_group_sessions_for_backup(
1417 &self,
1418 backup_version: &str,
1419 limit: usize,
1420 ) -> Result<Vec<InboundGroupSession>, Self::Error> {
1421 self.0.inbound_group_sessions_for_backup(backup_version, limit).await
1422 }
1423
1424 async fn mark_inbound_group_sessions_as_backed_up(
1425 &self,
1426 backup_version: &str,
1427 room_and_session_ids: &[(&RoomId, &str)],
1428 ) -> Result<(), Self::Error> {
1429 self.0
1430 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
1431 .await
1432 }
1433
1434 async fn reset_backup_state(&self) -> Result<(), Self::Error> {
1435 self.0.reset_backup_state().await
1436 }
1437
1438 async fn load_backup_keys(&self) -> Result<BackupKeys, Self::Error> {
1439 self.0.load_backup_keys().await
1440 }
1441
1442 async fn load_dehydrated_device_pickle_key(
1443 &self,
1444 ) -> Result<Option<DehydratedDeviceKey>, Self::Error> {
1445 self.0.load_dehydrated_device_pickle_key().await
1446 }
1447
1448 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
1449 self.0.delete_dehydrated_device_pickle_key().await
1450 }
1451
1452 async fn get_outbound_group_session(
1453 &self,
1454 room_id: &RoomId,
1455 ) -> Result<Option<OutboundGroupSession>, Self::Error> {
1456 self.0.get_outbound_group_session(room_id).await
1457 }
1458
1459 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error> {
1460 self.0.load_tracked_users().await
1461 }
1462
1463 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error> {
1464 self.0.save_tracked_users(users).await
1465 }
1466
1467 async fn get_device(
1468 &self,
1469 user_id: &UserId,
1470 device_id: &DeviceId,
1471 ) -> Result<Option<DeviceData>, Self::Error> {
1472 self.0.get_device(user_id, device_id).await
1473 }
1474
1475 async fn get_user_devices(
1476 &self,
1477 user_id: &UserId,
1478 ) -> Result<HashMap<OwnedDeviceId, DeviceData>, Self::Error> {
1479 self.0.get_user_devices(user_id).await
1480 }
1481
1482 async fn get_own_device(&self) -> Result<DeviceData, Self::Error> {
1483 self.0.get_own_device().await
1484 }
1485
1486 async fn get_user_identity(
1487 &self,
1488 user_id: &UserId,
1489 ) -> Result<Option<UserIdentityData>, Self::Error> {
1490 self.0.get_user_identity(user_id).await
1491 }
1492
1493 async fn is_message_known(
1494 &self,
1495 message_hash: &OlmMessageHash,
1496 ) -> Result<bool, Self::Error> {
1497 self.0.is_message_known(message_hash).await
1498 }
1499
1500 async fn get_outgoing_secret_requests(
1501 &self,
1502 request_id: &TransactionId,
1503 ) -> Result<Option<GossipRequest>, Self::Error> {
1504 self.0.get_outgoing_secret_requests(request_id).await
1505 }
1506
1507 async fn get_secret_request_by_info(
1508 &self,
1509 secret_info: &SecretInfo,
1510 ) -> Result<Option<GossipRequest>, Self::Error> {
1511 self.0.get_secret_request_by_info(secret_info).await
1512 }
1513
1514 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>, Self::Error> {
1515 self.0.get_unsent_secret_requests().await
1516 }
1517
1518 async fn delete_outgoing_secret_requests(
1519 &self,
1520 request_id: &TransactionId,
1521 ) -> Result<(), Self::Error> {
1522 self.0.delete_outgoing_secret_requests(request_id).await
1523 }
1524
1525 async fn get_secrets_from_inbox(
1526 &self,
1527 secret_name: &SecretName,
1528 ) -> Result<Vec<GossippedSecret>, Self::Error> {
1529 self.0.get_secrets_from_inbox(secret_name).await
1530 }
1531
1532 async fn delete_secrets_from_inbox(
1533 &self,
1534 secret_name: &SecretName,
1535 ) -> Result<(), Self::Error> {
1536 self.0.delete_secrets_from_inbox(secret_name).await
1537 }
1538
1539 async fn get_room_settings(
1540 &self,
1541 room_id: &RoomId,
1542 ) -> Result<Option<RoomSettings>, Self::Error> {
1543 self.0.get_room_settings(room_id).await
1544 }
1545
1546 async fn get_received_room_key_bundle_data(
1547 &self,
1548 room_id: &RoomId,
1549 user_id: &UserId,
1550 ) -> crate::store::Result<Option<StoredRoomKeyBundleData>, Self::Error> {
1551 self.0.get_received_room_key_bundle_data(room_id, user_id).await
1552 }
1553
1554 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
1555 self.0.get_custom_value(key).await
1556 }
1557
1558 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
1559 self.0.set_custom_value(key, value).await
1560 }
1561
1562 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
1563 self.0.remove_custom_value(key).await
1564 }
1565
1566 async fn try_take_leased_lock(
1567 &self,
1568 lease_duration_ms: u32,
1569 key: &str,
1570 holder: &str,
1571 ) -> Result<bool, Self::Error> {
1572 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await
1573 }
1574
1575 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
1576 self.0.next_batch_token().await
1577 }
1578 }
1579
1580 cryptostore_integration_tests!();
1581 cryptostore_integration_tests_time!();
1582}