Skip to content

Commit 5e9d57a

Browse files
committed
Implement SDK managed state
# Conflicts: # Cargo.lock # crates/bitwarden-state/Cargo.toml # crates/bitwarden-state/src/registry.rs # crates/bitwarden-state/src/repository.rs # crates/bitwarden-vault/src/cipher/cipher.rs # Conflicts: # crates/bitwarden-vault/src/vault_client.rs # Conflicts: # Cargo.lock # crates/bitwarden-state/Cargo.toml Use bundled sqlite to solve compile issues Update readme Don't stringify the data in indexeddb Remove the comment Update readme
1 parent a3d748a commit 5e9d57a

File tree

16 files changed

+712
-17
lines changed

16 files changed

+712
-17
lines changed

Cargo.lock

Lines changed: 95 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bitwarden-core/src/platform/state_client.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::sync::Arc;
22

3-
use bitwarden_state::repository::{Repository, RepositoryItem};
3+
use bitwarden_state::{
4+
registry::StateRegistryError,
5+
repository::{Repository, RepositoryItem, RepositoryItemData},
6+
};
47

58
use crate::Client;
69

@@ -25,4 +28,25 @@ impl StateClient {
2528
pub fn get_client_managed<T: RepositoryItem>(&self) -> Option<Arc<dyn Repository<T>>> {
2629
self.client.internal.repository_map.get_client_managed()
2730
}
31+
32+
/// Initialize the database for SDK managed repositories.
33+
pub async fn initialize_database(
34+
&self,
35+
repositories: Vec<RepositoryItemData>,
36+
) -> Result<(), StateRegistryError> {
37+
self.client
38+
.internal
39+
.repository_map
40+
.initialize_database(repositories)
41+
.await
42+
}
43+
44+
/// Get a SDK managed state repository for a specific type, if it exists.
45+
pub fn get_sdk_managed<
46+
T: RepositoryItem + serde::ser::Serialize + serde::de::DeserializeOwned,
47+
>(
48+
&self,
49+
) -> Result<impl Repository<T>, StateRegistryError> {
50+
self.client.internal.repository_map.get_sdk_managed()
51+
}
2852
}

crates/bitwarden-state/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,20 @@ wasm = []
1515

1616
[dependencies]
1717
async-trait = { workspace = true }
18+
bitwarden-error = { workspace = true }
19+
bitwarden-threading = { workspace = true }
20+
serde = { workspace = true }
21+
serde_json = { workspace = true }
1822
thiserror = { workspace = true }
23+
tokio = { workspace = true }
24+
25+
[target.'cfg(target_arch="wasm32")'.dependencies]
26+
indexed-db = ">=0.4.2, <0.5"
27+
js-sys = { workspace = true }
28+
tsify-next = { workspace = true }
29+
30+
[target.'cfg(not(target_arch="wasm32"))'.dependencies]
31+
rusqlite = { version = ">=0.36.0, <0.37", features = ["bundled"] }
1932

2033
[dev-dependencies]
2134
tokio = { workspace = true, features = ["rt"] }

crates/bitwarden-state/README.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct Cipher {
1414

1515
// Register `Cipher` for use with a `Repository`.
1616
// This should be done in the crate where `Cipher` is defined.
17-
bitwarden_state::register_repository_item!(Cipher, "Cipher");
17+
bitwarden_state::register_repository_item!(Cipher, "Cipher", version: 1);
1818
```
1919

2020
With the registration complete, the next important decision is to select where will the data be
@@ -173,3 +173,64 @@ class CipherStoreImpl: CipherStore {
173173

174174
getClient(userId = userId).platform().store().registerCipherStore(CipherStoreImpl());
175175
```
176+
177+
## SDK-Managed State
178+
179+
With `SDK-Managed State`, the SDK will be exclusively responsible for the data storage. This means
180+
that the clients don't need to make any changes themselves, as the implementation is internal to the
181+
SDK. To add support for an SDK managed `Repository`, it needs to be added to the initialization code
182+
for WASM and UniFFI. This example shows how to add support for `Cipher`s.
183+
184+
### WASM
185+
186+
Go to `crates/bitwarden-wasm-internal/src/platform/mod.rs` and add a line with your type, as shown:
187+
188+
```rust,ignore
189+
pub async fn initialize_state(
190+
&self,
191+
cipher_repository: CipherRepository,
192+
) -> Result<(), bitwarden_state::registry::StateRegistryError> {
193+
let cipher = cipher_repository.into_channel_impl();
194+
self.0.platform().state().register_client_managed(cipher);
195+
196+
let sdk_managed_repositories = vec![
197+
// This should list all the SDK-managed repositories
198+
<Cipher as RepositoryItem>::data(),
199+
// Add your type here
200+
];
201+
202+
self.0
203+
.platform()
204+
.state()
205+
.initialize_database(sdk_managed_repositories)
206+
.await
207+
}
208+
```
209+
210+
### UniFFI
211+
212+
Go to `crates/bitwarden-uniffi/src/platform/mod.rs` and add a line with your type, as shown:
213+
214+
```rust,ignore
215+
pub async fn initialize_state(
216+
&self,
217+
cipher_repository: Arc<dyn CipherRepository>,
218+
) -> Result<()> {
219+
let cipher = UniffiRepositoryBridge::new(cipher_repository);
220+
self.0.platform().state().register_client_managed(cipher);
221+
222+
let sdk_managed_repositories = vec![
223+
// This should list all the SDK-managed repositories
224+
<Cipher as RepositoryItem>::data(),
225+
// Add your type here
226+
];
227+
228+
self.0
229+
.platform()
230+
.state()
231+
.initialize_database(sdk_managed_repositories)
232+
.await
233+
.map_err(Error::StateRegistry)?;
234+
Ok(())
235+
}
236+
```

crates/bitwarden-state/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ pub mod repository;
55

66
/// This module provides a registry for managing repositories of different types.
77
pub mod registry;
8+
9+
pub(crate) mod sdk_managed;

0 commit comments

Comments
 (0)