Skip to main content

matrix_sdk/encryption/secret_storage/
futures.rs

1// Copyright 2023 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{future::IntoFuture, pin::Pin};
16
17use futures_core::Future;
18use matrix_sdk_base::crypto::secret_storage::SecretStorageKey;
19use ruma::events::secret_storage::default_key::SecretStorageDefaultKeyEventContent;
20
21use super::{Result, SecretStorage, SecretStore};
22
23#[derive(Debug)]
24pub(crate) enum KeyOrPassphrase<'a> {
25    None,
26    Key(&'a SecretStorageKey),
27    Passphrase(&'a str),
28}
29
30/// Future returned by [`SecretStorage::create_secret_store()`].
31#[derive(Debug)]
32pub struct CreateStore<'a> {
33    pub(super) secret_storage: &'a SecretStorage,
34    pub(super) key: KeyOrPassphrase<'a>,
35}
36
37impl<'a> CreateStore<'a> {
38    /// Set the passphrase for the new [`SecretStore`].
39    ///
40    /// See the documentation for the [`SecretStorage::create_secret_store()`]
41    /// method for more info.
42    pub fn with_passphrase(mut self, passphrase: &'a str) -> Self {
43        self.key = KeyOrPassphrase::Passphrase(passphrase);
44
45        self
46    }
47
48    /// Set the key for the new [`SecretStore`].
49    ///
50    /// See the documentation for the [`SecretStorage::create_secret_store()`]
51    /// method for more info.
52    pub fn with_key(mut self, key: &'a SecretStorageKey) -> Self {
53        self.key = KeyOrPassphrase::Key(key);
54
55        self
56    }
57}
58
59impl<'a> IntoFuture for CreateStore<'a> {
60    type Output = Result<SecretStore>;
61    #[cfg(target_family = "wasm")]
62    type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 'a>>;
63    #[cfg(not(target_family = "wasm"))]
64    type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>;
65
66    fn into_future(self) -> Self::IntoFuture {
67        let Self { secret_storage, key } = self;
68
69        Box::pin(async move {
70            // Prevent multiple simultaneous calls to this method.
71            //
72            // See the documentation for the lock in the `store_secret` method
73            // for more info.
74            let client_copy = secret_storage.client.to_owned();
75            let _guard = client_copy.locks().open_secret_store_lock.lock().await;
76
77            let new_key = match key {
78                KeyOrPassphrase::None => SecretStorageKey::new(),
79                KeyOrPassphrase::Key(k) => k.clone(),
80                KeyOrPassphrase::Passphrase(p) => SecretStorageKey::new_from_passphrase(p),
81            };
82
83            let content = new_key.event_content().to_owned();
84
85            secret_storage.client.account().set_account_data(content).await?;
86
87            let store = SecretStore { client: secret_storage.client.to_owned(), key: new_key };
88            store.export_secrets().await?;
89
90            let default_key_content =
91                SecretStorageDefaultKeyEventContent::new(store.key.key_id().to_owned());
92
93            store.client.account().set_account_data(default_key_content).await?;
94
95            Ok(store)
96        })
97    }
98}