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