Skip to main content

bitwarden_pm/
lib.rs

1#![doc = include_str!("../README.md")]
2
3#[cfg(feature = "bitwarden-license")]
4mod commercial;
5
6/// Dev-only debug-capability tree rooted on the top-level client. Compiled only
7/// under the `debug-capabilities` feature.
8#[cfg(feature = "debug-capabilities")]
9pub mod debug;
10
11use std::sync::Arc;
12
13use bitwarden_auth::AuthClientExt as _;
14use bitwarden_core::{
15    ClientBuilder, FromClient,
16    auth::{ClientManagedTokenHandler, ClientManagedTokens},
17    client::tracing_middleware::ReqwestTracingMiddleware,
18};
19use bitwarden_crypto_cipher_suite::CryptoCipherSuiteClientExt as _;
20#[cfg(not(target_arch = "wasm32"))]
21use bitwarden_crypto_sync_handler::CryptoSyncHandler;
22use bitwarden_crypto_sync_handler::CryptoSyncHandlerClientExt as _;
23use bitwarden_emergency_access::EmergencyAccessClientExt as _;
24use bitwarden_exporters::ExporterClientExt as _;
25use bitwarden_generators::GeneratorClientsExt as _;
26use bitwarden_importers::ImporterClientExt as _;
27use bitwarden_managed_settings::{ManagedSettingsClient, ManagedSettingsClientExt as _};
28use bitwarden_member_administration::OrganizationUsersManagementClientExt as _;
29use bitwarden_organization_domains::OrganizationDomainsClientExt as _;
30use bitwarden_organization_invite_link::InviteLinkClientExt as _;
31use bitwarden_organizations::OrganizationsClientExt as _;
32use bitwarden_policies::{PoliciesClientExt as _, PolicySyncHandler};
33use bitwarden_send::{SendClientExt as _, SendSyncHandler, SendSyncHandlerClientExt as _};
34use bitwarden_sync::SyncClientExt as _;
35use bitwarden_unlock::UnlockClientExt as _;
36use bitwarden_user_crypto_management::UserCryptoManagementClientExt;
37use bitwarden_vault::{FolderSyncHandler, VaultClientExt as _};
38
39#[cfg(feature = "uniffi")]
40uniffi::setup_scaffolding!();
41
42/// Re-export subclients for easier access
43pub mod clients {
44    pub use bitwarden_auth::AuthClient;
45    pub use bitwarden_collections::collection_client::CollectionsClient;
46    pub use bitwarden_core::key_management::CryptoClient;
47    pub use bitwarden_crypto_cipher_suite::CryptoCipherSuiteClient;
48    pub use bitwarden_crypto_sync_handler::CryptoSyncHandlerClient;
49    pub use bitwarden_emergency_access::EmergencyAccessClient;
50    pub use bitwarden_exporters::ExporterClient;
51    pub use bitwarden_generators::GeneratorClient;
52    pub use bitwarden_importers::ImporterClient;
53    pub use bitwarden_member_administration::OrganizationUsersManagementClient;
54    pub use bitwarden_organization_domains::OrganizationDomainsClient;
55    pub use bitwarden_organization_invite_link::InviteLinkClient;
56    pub use bitwarden_organizations::OrganizationsClient;
57    pub use bitwarden_policies::PolicyClient;
58    pub use bitwarden_send::{SendClient, SendSyncHandlerClient};
59    pub use bitwarden_sync::SyncClient;
60    pub use bitwarden_unlock::UnlockClient;
61    pub use bitwarden_vault::VaultClient;
62}
63#[cfg(feature = "bitwarden-license")]
64pub use commercial::CommercialPasswordManagerClient;
65
66mod builder;
67pub mod migrations;
68pub use bitwarden_core::{RehydrationError, SaveStateData};
69pub use bitwarden_unlock::{SessionKey, UnlockError, UnlockMethod};
70pub use builder::PasswordManagerClientBuilder;
71
72/// The main entry point for the Bitwarden Password Manager SDK
73#[derive(Clone)]
74pub struct PasswordManagerClient(pub bitwarden_core::Client);
75
76impl PasswordManagerClient {
77    /// Initialize a new instance of the SDK client
78    pub fn new(settings: Option<bitwarden_core::ClientSettings>) -> Self {
79        let mut builder = PasswordManagerClientBuilder::new();
80        if let Some(s) = settings {
81            builder = builder.with_settings(s);
82        }
83        builder.build()
84    }
85
86    /// Returns a [`PasswordManagerClientBuilder`] for constructing a new [`PasswordManagerClient`].
87    pub fn builder() -> PasswordManagerClientBuilder {
88        PasswordManagerClientBuilder::new()
89    }
90
91    /// Initialize a new instance of the SDK client with client-managed tokens and a shared
92    /// managed-settings handle.
93    ///
94    /// `managed_settings` is owned by the host application, which acquires a management profile
95    /// from the operating system's device-management channel and pushes it in. Only its cell is
96    /// captured, so profiles the host pushes later are visible to this client.
97    pub fn new_with_client_tokens(
98        settings: Option<bitwarden_core::ClientSettings>,
99        tokens: Arc<dyn ClientManagedTokens>,
100        managed_settings: &ManagedSettingsClient,
101    ) -> Self {
102        let mut builder = ClientBuilder::new()
103            .with_token_handler(ClientManagedTokenHandler::new(tokens))
104            .with_middleware(vec![Arc::new(ReqwestTracingMiddleware)])
105            .with_managed_profile(managed_settings.cell());
106        if let Some(s) = settings {
107            builder = builder.with_settings(s);
108        }
109        Self(builder.build())
110    }
111
112    /// Initialize a new instance of the SDK client with SDK managed state and sync handlers
113    /// registered
114    ///
115    /// This will eventually replace `new` when the SDK fully owns sync on all clients.
116    pub fn new_with_sync(settings: Option<bitwarden_core::ClientSettings>) -> Self {
117        let client = Self::new(settings);
118
119        let sync = client.sync();
120        #[cfg(not(target_arch = "wasm32"))]
121        sync.register_sync_handler(Arc::new(CryptoSyncHandler::new(client.0.clone())));
122        sync.register_sync_handler(Arc::new(FolderSyncHandler::from_client(&client.0)));
123        sync.register_sync_handler(Arc::new(SendSyncHandler::from_client(&client.0)));
124        sync.register_sync_handler(Arc::new(PolicySyncHandler::from_client(&client.0)));
125
126        // TODO: Add more sync handlers here!
127
128        client
129    }
130
131    /// Platform operations
132    pub fn platform(&self) -> bitwarden_core::platform::PlatformClient {
133        self.0.platform()
134    }
135
136    /// Administrator-enforced settings operations.
137    pub fn managed_settings(&self) -> ManagedSettingsClient {
138        self.0.managed_settings()
139    }
140
141    /// Auth operations
142    pub fn auth(&self) -> bitwarden_auth::AuthClient {
143        self.0.auth_new()
144    }
145
146    /// Bitwarden licensed operations
147    #[cfg(feature = "bitwarden-license")]
148    pub fn commercial(&self) -> CommercialPasswordManagerClient {
149        CommercialPasswordManagerClient::new(self.0.clone())
150    }
151
152    /// Crypto operations
153    pub fn crypto(&self) -> bitwarden_core::key_management::CryptoClient {
154        self.0.crypto()
155    }
156
157    /// Crypto cipher suite operations
158    pub fn crypto_cipher_suite(&self) -> bitwarden_crypto_cipher_suite::CryptoCipherSuiteClient {
159        self.0.crypto_cipher_suite()
160    }
161
162    /// Feature flag operations
163    pub fn flags(&self) -> bitwarden_core::FlagsClient {
164        self.0.flags()
165    }
166
167    /// Key management operations that run on every sync
168    pub fn crypto_sync_handler(&self) -> bitwarden_crypto_sync_handler::CryptoSyncHandlerClient {
169        self.0.crypto_sync_handler()
170    }
171
172    /// Operations that manage the cryptographic machinery of a user account, including key-rotation
173    pub fn user_crypto_management(
174        &self,
175    ) -> bitwarden_user_crypto_management::UserCryptoManagementClient {
176        self.0.user_crypto_management()
177    }
178
179    /// Vault item operations
180    pub fn vault(&self) -> bitwarden_vault::VaultClient {
181        self.0.vault()
182    }
183
184    /// Collection related operations.
185    ///
186    /// This is registered directly on the top-level client in addition to being nested under
187    /// [`vault`](Self::vault); once all consumers have migrated to this accessor, the nested one
188    /// will be removed.
189    pub fn collections(&self) -> bitwarden_collections::collection_client::CollectionsClient {
190        bitwarden_collections::collection_client::CollectionsClient::from_client(&self.0)
191    }
192
193    /// Exporter operations
194    pub fn exporters(&self) -> bitwarden_exporters::ExporterClient {
195        self.0.exporters()
196    }
197
198    /// Importer operations
199    pub fn importers(&self) -> bitwarden_importers::ImporterClient {
200        self.0.importers()
201    }
202
203    /// Generator operations
204    pub fn generator(&self) -> bitwarden_generators::GeneratorClient {
205        self.0.generator()
206    }
207
208    /// Send operations
209    pub fn sends(&self) -> bitwarden_send::SendClient {
210        self.0.sends()
211    }
212
213    /// Send sync handler operations
214    pub fn send_sync_handler(&self) -> bitwarden_send::SendSyncHandlerClient {
215        self.0.send_sync_handler()
216    }
217
218    /// Policy operations
219    pub fn policies(&self) -> bitwarden_policies::PolicyClient {
220        self.0.policies()
221    }
222
223    /// Operations on the current user's organizations
224    pub fn organizations(&self) -> bitwarden_organizations::OrganizationsClient {
225        self.0.organizations()
226    }
227
228    /// Organization invite link operations
229    pub fn invite_link(&self) -> bitwarden_organization_invite_link::InviteLinkClient {
230        self.0.invite_link()
231    }
232
233    /// Organization verified domain operations.
234    pub fn organization_domains(
235        &self,
236    ) -> bitwarden_organization_domains::OrganizationDomainsClient {
237        self.0.organization_domains()
238    }
239
240    /// Emergency access operations, performed as the grantee.
241    pub fn emergency_access(&self) -> bitwarden_emergency_access::EmergencyAccessClient {
242        self.0.emergency_access()
243    }
244
245    /// Organization member administration operations.
246    pub fn organization_users_management(
247        &self,
248    ) -> bitwarden_member_administration::OrganizationUsersManagementClient {
249        self.0.organization_users_management()
250    }
251
252    /// Sync operations
253    pub fn sync(&self) -> bitwarden_sync::SyncClient {
254        self.0.sync()
255    }
256
257    /// Returns true when the user's symmetric key is loaded into the key store.
258    pub fn is_unlocked(&self) -> bool {
259        use bitwarden_core::key_management::SymmetricKeySlotId;
260        self.0
261            .internal
262            .get_key_store()
263            .context()
264            .has_symmetric_key(SymmetricKeySlotId::User)
265    }
266
267    /// Unlock operations
268    pub fn unlock(&self) -> bitwarden_unlock::UnlockClient {
269        self.0.unlock()
270    }
271
272    /// Write rehydration state to a StateRegistry.
273    ///
274    /// Delegates to [`Client::save_to_state`](bitwarden_core::Client::save_to_state).
275    pub async fn save_to_state(
276        data: SaveStateData,
277        reg: &bitwarden_state::registry::StateRegistry,
278    ) -> Result<(), RehydrationError> {
279        bitwarden_core::Client::save_to_state(data, reg).await
280    }
281
282    /// Reconstruct a locked PasswordManagerClient from a populated StateRegistry.
283    ///
284    /// Delegates to [`Client::load_from_state`](bitwarden_core::Client::load_from_state).
285    pub async fn load_from_state(
286        token_handler: std::sync::Arc<dyn bitwarden_core::auth::auth_tokens::TokenHandler>,
287        registry: bitwarden_state::registry::StateRegistry,
288    ) -> Result<Self, RehydrationError> {
289        let client = bitwarden_core::Client::load_from_state(token_handler, registry).await?;
290        Ok(PasswordManagerClient(client))
291    }
292}
293
294#[cfg(test)]
295mod tests {
296    use std::sync::Arc;
297
298    use super::*;
299
300    #[test]
301    fn new_with_server_communication_config_constructs() {
302        struct MockCookieProvider;
303
304        #[async_trait::async_trait]
305        impl bitwarden_server_communication_config::CookieProvider for MockCookieProvider {
306            async fn cookies(&self, _hostname: &str) -> Vec<(String, String)> {
307                vec![]
308            }
309
310            async fn acquire_cookie(
311                &self,
312                _hostname: &str,
313            ) -> Result<(), bitwarden_server_communication_config::AcquireCookieError> {
314                Ok(())
315            }
316
317            async fn needs_bootstrap(&self, _hostname: &str) -> bool {
318                false
319            }
320        }
321
322        let _client = PasswordManagerClient::builder()
323            .with_server_communication_config(Arc::new(MockCookieProvider))
324            .build();
325    }
326}