Skip to main content

bitwarden_pm/
lib.rs

1#![doc = include_str!("../README.md")]
2
3#[cfg(feature = "bitwarden-license")]
4mod commercial;
5
6use std::sync::Arc;
7
8use bitwarden_auth::AuthClientExt as _;
9use bitwarden_core::{
10    FromClient,
11    auth::{ClientManagedTokenHandler, ClientManagedTokens},
12};
13use bitwarden_crypto_cipher_suite::CryptoCipherSuiteClientExt as _;
14#[cfg(not(target_arch = "wasm32"))]
15use bitwarden_crypto_sync_handler::CryptoSyncHandler;
16use bitwarden_crypto_sync_handler::CryptoSyncHandlerClientExt as _;
17use bitwarden_exporters::ExporterClientExt as _;
18use bitwarden_generators::GeneratorClientsExt as _;
19use bitwarden_importers::ImporterClientExt as _;
20use bitwarden_organization_invite_link::InviteLinkClientExt as _;
21use bitwarden_policies::PoliciesClientExt as _;
22use bitwarden_send::SendClientExt as _;
23use bitwarden_sync::SyncClientExt as _;
24use bitwarden_unlock::UnlockClientExt as _;
25use bitwarden_user_crypto_management::UserCryptoManagementClientExt;
26use bitwarden_vault::{FolderSyncHandler, VaultClientExt as _};
27
28#[cfg(feature = "uniffi")]
29uniffi::setup_scaffolding!();
30
31/// Re-export subclients for easier access
32pub mod clients {
33    pub use bitwarden_auth::AuthClient;
34    pub use bitwarden_core::key_management::CryptoClient;
35    pub use bitwarden_crypto_cipher_suite::CryptoCipherSuiteClient;
36    pub use bitwarden_crypto_sync_handler::CryptoSyncHandlerClient;
37    pub use bitwarden_exporters::ExporterClient;
38    pub use bitwarden_generators::GeneratorClient;
39    pub use bitwarden_importers::ImporterClient;
40    pub use bitwarden_organization_invite_link::InviteLinkClient;
41    pub use bitwarden_policies::PolicyClient;
42    pub use bitwarden_send::SendClient;
43    pub use bitwarden_sync::SyncClient;
44    pub use bitwarden_unlock::UnlockClient;
45    pub use bitwarden_vault::VaultClient;
46}
47#[cfg(feature = "bitwarden-license")]
48pub use commercial::CommercialPasswordManagerClient;
49
50mod builder;
51pub mod migrations;
52pub use bitwarden_core::{RehydrationError, SaveStateData};
53pub use bitwarden_unlock::{SessionKey, UnlockError, UnlockMethod};
54pub use builder::PasswordManagerClientBuilder;
55
56/// The main entry point for the Bitwarden Password Manager SDK
57pub struct PasswordManagerClient(pub bitwarden_core::Client);
58
59impl PasswordManagerClient {
60    /// Initialize a new instance of the SDK client
61    pub fn new(settings: Option<bitwarden_core::ClientSettings>) -> Self {
62        let mut builder = PasswordManagerClientBuilder::new();
63        if let Some(s) = settings {
64            builder = builder.with_settings(s);
65        }
66        builder.build()
67    }
68
69    /// Returns a [`PasswordManagerClientBuilder`] for constructing a new [`PasswordManagerClient`].
70    pub fn builder() -> PasswordManagerClientBuilder {
71        PasswordManagerClientBuilder::new()
72    }
73
74    /// Initialize a new instance of the SDK client with client-managed tokens
75    pub fn new_with_client_tokens(
76        settings: Option<bitwarden_core::ClientSettings>,
77        tokens: Arc<dyn ClientManagedTokens>,
78    ) -> Self {
79        Self(bitwarden_core::Client::new_with_token_handler(
80            settings,
81            ClientManagedTokenHandler::new(tokens),
82        ))
83    }
84
85    /// Initialize a new instance of the SDK client with SDK managed state and sync handlers
86    /// registered
87    ///
88    /// This will eventually replace `new` when the SDK fully owns sync on all clients.
89    pub fn new_with_sync(settings: Option<bitwarden_core::ClientSettings>) -> Self {
90        let client = Self::new(settings);
91
92        let sync = client.sync();
93        #[cfg(not(target_arch = "wasm32"))]
94        sync.register_sync_handler(Arc::new(CryptoSyncHandler::new(client.0.clone())));
95        sync.register_sync_handler(Arc::new(FolderSyncHandler::from_client(&client.0)));
96
97        // TODO: Add more sync handlers here!
98
99        client
100    }
101
102    /// Platform operations
103    pub fn platform(&self) -> bitwarden_core::platform::PlatformClient {
104        self.0.platform()
105    }
106
107    /// Auth operations
108    pub fn auth(&self) -> bitwarden_auth::AuthClient {
109        self.0.auth_new()
110    }
111
112    /// Bitwarden licensed operations
113    #[cfg(feature = "bitwarden-license")]
114    pub fn commercial(&self) -> CommercialPasswordManagerClient {
115        CommercialPasswordManagerClient::new(self.0.clone())
116    }
117
118    /// Crypto operations
119    pub fn crypto(&self) -> bitwarden_core::key_management::CryptoClient {
120        self.0.crypto()
121    }
122
123    /// Crypto cipher suite operations
124    pub fn crypto_cipher_suite(&self) -> bitwarden_crypto_cipher_suite::CryptoCipherSuiteClient {
125        self.0.crypto_cipher_suite()
126    }
127
128    /// Feature flag operations
129    pub fn flags(&self) -> bitwarden_core::FlagsClient {
130        self.0.flags()
131    }
132
133    /// Key management operations that run on every sync
134    pub fn crypto_sync_handler(&self) -> bitwarden_crypto_sync_handler::CryptoSyncHandlerClient {
135        self.0.crypto_sync_handler()
136    }
137
138    /// Operations that manage the cryptographic machinery of a user account, including key-rotation
139    pub fn user_crypto_management(
140        &self,
141    ) -> bitwarden_user_crypto_management::UserCryptoManagementClient {
142        self.0.user_crypto_management()
143    }
144
145    /// Vault item operations
146    pub fn vault(&self) -> bitwarden_vault::VaultClient {
147        self.0.vault()
148    }
149
150    /// Exporter operations
151    pub fn exporters(&self) -> bitwarden_exporters::ExporterClient {
152        self.0.exporters()
153    }
154
155    /// Importer operations
156    pub fn importers(&self) -> bitwarden_importers::ImporterClient {
157        self.0.importers()
158    }
159
160    /// Generator operations
161    pub fn generator(&self) -> bitwarden_generators::GeneratorClient {
162        self.0.generator()
163    }
164
165    /// Send operations
166    pub fn sends(&self) -> bitwarden_send::SendClient {
167        self.0.sends()
168    }
169
170    /// Policy operations
171    pub fn policies(&self) -> bitwarden_policies::PolicyClient {
172        self.0.policies()
173    }
174
175    /// Organization invite link operations
176    pub fn invite_link(&self) -> bitwarden_organization_invite_link::InviteLinkClient {
177        self.0.invite_link()
178    }
179
180    /// Sync operations
181    pub fn sync(&self) -> bitwarden_sync::SyncClient {
182        self.0.sync()
183    }
184
185    /// Returns true when the user's symmetric key is loaded into the key store.
186    pub fn is_unlocked(&self) -> bool {
187        use bitwarden_core::key_management::SymmetricKeySlotId;
188        self.0
189            .internal
190            .get_key_store()
191            .context()
192            .has_symmetric_key(SymmetricKeySlotId::User)
193    }
194
195    /// Unlock operations
196    pub fn unlock(&self) -> bitwarden_unlock::UnlockClient {
197        self.0.unlock()
198    }
199
200    /// Write rehydration state to a StateRegistry.
201    ///
202    /// Delegates to [`Client::save_to_state`](bitwarden_core::Client::save_to_state).
203    pub async fn save_to_state(
204        data: SaveStateData,
205        reg: &bitwarden_state::registry::StateRegistry,
206    ) -> Result<(), RehydrationError> {
207        bitwarden_core::Client::save_to_state(data, reg).await
208    }
209
210    /// Reconstruct a locked PasswordManagerClient from a populated StateRegistry.
211    ///
212    /// Delegates to [`Client::load_from_state`](bitwarden_core::Client::load_from_state).
213    pub async fn load_from_state(
214        token_handler: std::sync::Arc<dyn bitwarden_core::auth::auth_tokens::TokenHandler>,
215        registry: bitwarden_state::registry::StateRegistry,
216    ) -> Result<Self, RehydrationError> {
217        let client = bitwarden_core::Client::load_from_state(token_handler, registry).await?;
218        Ok(PasswordManagerClient(client))
219    }
220}
221
222#[cfg(test)]
223mod tests {
224    use std::sync::Arc;
225
226    use super::*;
227
228    #[test]
229    fn new_with_server_communication_config_constructs() {
230        struct MockCookieProvider;
231
232        #[async_trait::async_trait]
233        impl bitwarden_server_communication_config::CookieProvider for MockCookieProvider {
234            async fn cookies(&self, _hostname: &str) -> Vec<(String, String)> {
235                vec![]
236            }
237
238            async fn acquire_cookie(
239                &self,
240                _hostname: &str,
241            ) -> Result<(), bitwarden_server_communication_config::AcquireCookieError> {
242                Ok(())
243            }
244
245            async fn needs_bootstrap(&self, _hostname: &str) -> bool {
246                false
247            }
248        }
249
250        let _client = PasswordManagerClient::builder()
251            .with_server_communication_config(Arc::new(MockCookieProvider))
252            .build();
253    }
254}