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 ClientBuilder, FromClient,
11 auth::{ClientManagedTokenHandler, ClientManagedTokens},
12 client::tracing_middleware::ReqwestTracingMiddleware,
13};
14use bitwarden_crypto_cipher_suite::CryptoCipherSuiteClientExt as _;
15#[cfg(not(target_arch = "wasm32"))]
16use bitwarden_crypto_sync_handler::CryptoSyncHandler;
17use bitwarden_crypto_sync_handler::CryptoSyncHandlerClientExt as _;
18use bitwarden_exporters::ExporterClientExt as _;
19use bitwarden_generators::GeneratorClientsExt as _;
20use bitwarden_importers::ImporterClientExt as _;
21use bitwarden_managed_settings::{ManagedSettingsClient, ManagedSettingsClientExt as _};
22use bitwarden_organization_invite_link::InviteLinkClientExt as _;
23use bitwarden_policies::PoliciesClientExt as _;
24use bitwarden_send::{SendClientExt as _, SendSyncHandler, SendSyncHandlerClientExt as _};
25use bitwarden_sync::SyncClientExt as _;
26use bitwarden_unlock::UnlockClientExt as _;
27use bitwarden_user_crypto_management::UserCryptoManagementClientExt;
28use bitwarden_vault::{FolderSyncHandler, VaultClientExt as _};
29
30#[cfg(feature = "uniffi")]
31uniffi::setup_scaffolding!();
32
33pub mod clients {
35 pub use bitwarden_auth::AuthClient;
36 pub use bitwarden_collections::collection_client::CollectionsClient;
37 pub use bitwarden_core::key_management::CryptoClient;
38 pub use bitwarden_crypto_cipher_suite::CryptoCipherSuiteClient;
39 pub use bitwarden_crypto_sync_handler::CryptoSyncHandlerClient;
40 pub use bitwarden_exporters::ExporterClient;
41 pub use bitwarden_generators::GeneratorClient;
42 pub use bitwarden_importers::ImporterClient;
43 pub use bitwarden_organization_invite_link::InviteLinkClient;
44 pub use bitwarden_policies::PolicyClient;
45 pub use bitwarden_send::{SendClient, SendSyncHandlerClient};
46 pub use bitwarden_sync::SyncClient;
47 pub use bitwarden_unlock::UnlockClient;
48 pub use bitwarden_vault::VaultClient;
49}
50#[cfg(feature = "bitwarden-license")]
51pub use commercial::CommercialPasswordManagerClient;
52
53mod builder;
54pub mod migrations;
55pub use bitwarden_core::{RehydrationError, SaveStateData};
56pub use bitwarden_unlock::{SessionKey, UnlockError, UnlockMethod};
57pub use builder::PasswordManagerClientBuilder;
58
59pub struct PasswordManagerClient(pub bitwarden_core::Client);
61
62impl PasswordManagerClient {
63 pub fn new(settings: Option<bitwarden_core::ClientSettings>) -> Self {
65 let mut builder = PasswordManagerClientBuilder::new();
66 if let Some(s) = settings {
67 builder = builder.with_settings(s);
68 }
69 builder.build()
70 }
71
72 pub fn builder() -> PasswordManagerClientBuilder {
74 PasswordManagerClientBuilder::new()
75 }
76
77 pub fn new_with_client_tokens(
84 settings: Option<bitwarden_core::ClientSettings>,
85 tokens: Arc<dyn ClientManagedTokens>,
86 managed_settings: &ManagedSettingsClient,
87 ) -> Self {
88 let mut builder = ClientBuilder::new()
89 .with_token_handler(ClientManagedTokenHandler::new(tokens))
90 .with_middleware(vec![Arc::new(ReqwestTracingMiddleware)])
91 .with_managed_profile(managed_settings.cell());
92 if let Some(s) = settings {
93 builder = builder.with_settings(s);
94 }
95 Self(builder.build())
96 }
97
98 pub fn new_with_sync(settings: Option<bitwarden_core::ClientSettings>) -> Self {
103 let client = Self::new(settings);
104
105 let sync = client.sync();
106 #[cfg(not(target_arch = "wasm32"))]
107 sync.register_sync_handler(Arc::new(CryptoSyncHandler::new(client.0.clone())));
108 sync.register_sync_handler(Arc::new(FolderSyncHandler::from_client(&client.0)));
109 sync.register_sync_handler(Arc::new(SendSyncHandler::from_client(&client.0)));
110
111 client
114 }
115
116 pub fn platform(&self) -> bitwarden_core::platform::PlatformClient {
118 self.0.platform()
119 }
120
121 pub fn managed_settings(&self) -> ManagedSettingsClient {
123 self.0.managed_settings()
124 }
125
126 pub fn auth(&self) -> bitwarden_auth::AuthClient {
128 self.0.auth_new()
129 }
130
131 #[cfg(feature = "bitwarden-license")]
133 pub fn commercial(&self) -> CommercialPasswordManagerClient {
134 CommercialPasswordManagerClient::new(self.0.clone())
135 }
136
137 pub fn crypto(&self) -> bitwarden_core::key_management::CryptoClient {
139 self.0.crypto()
140 }
141
142 pub fn crypto_cipher_suite(&self) -> bitwarden_crypto_cipher_suite::CryptoCipherSuiteClient {
144 self.0.crypto_cipher_suite()
145 }
146
147 pub fn flags(&self) -> bitwarden_core::FlagsClient {
149 self.0.flags()
150 }
151
152 pub fn crypto_sync_handler(&self) -> bitwarden_crypto_sync_handler::CryptoSyncHandlerClient {
154 self.0.crypto_sync_handler()
155 }
156
157 pub fn user_crypto_management(
159 &self,
160 ) -> bitwarden_user_crypto_management::UserCryptoManagementClient {
161 self.0.user_crypto_management()
162 }
163
164 pub fn vault(&self) -> bitwarden_vault::VaultClient {
166 self.0.vault()
167 }
168
169 pub fn collections(&self) -> bitwarden_collections::collection_client::CollectionsClient {
175 bitwarden_collections::collection_client::CollectionsClient::from_client(&self.0)
176 }
177
178 pub fn exporters(&self) -> bitwarden_exporters::ExporterClient {
180 self.0.exporters()
181 }
182
183 pub fn importers(&self) -> bitwarden_importers::ImporterClient {
185 self.0.importers()
186 }
187
188 pub fn generator(&self) -> bitwarden_generators::GeneratorClient {
190 self.0.generator()
191 }
192
193 pub fn sends(&self) -> bitwarden_send::SendClient {
195 self.0.sends()
196 }
197
198 pub fn send_sync_handler(&self) -> bitwarden_send::SendSyncHandlerClient {
200 self.0.send_sync_handler()
201 }
202
203 pub fn policies(&self) -> bitwarden_policies::PolicyClient {
205 self.0.policies()
206 }
207
208 pub fn invite_link(&self) -> bitwarden_organization_invite_link::InviteLinkClient {
210 self.0.invite_link()
211 }
212
213 pub fn sync(&self) -> bitwarden_sync::SyncClient {
215 self.0.sync()
216 }
217
218 pub fn is_unlocked(&self) -> bool {
220 use bitwarden_core::key_management::SymmetricKeySlotId;
221 self.0
222 .internal
223 .get_key_store()
224 .context()
225 .has_symmetric_key(SymmetricKeySlotId::User)
226 }
227
228 pub fn unlock(&self) -> bitwarden_unlock::UnlockClient {
230 self.0.unlock()
231 }
232
233 pub async fn save_to_state(
237 data: SaveStateData,
238 reg: &bitwarden_state::registry::StateRegistry,
239 ) -> Result<(), RehydrationError> {
240 bitwarden_core::Client::save_to_state(data, reg).await
241 }
242
243 pub async fn load_from_state(
247 token_handler: std::sync::Arc<dyn bitwarden_core::auth::auth_tokens::TokenHandler>,
248 registry: bitwarden_state::registry::StateRegistry,
249 ) -> Result<Self, RehydrationError> {
250 let client = bitwarden_core::Client::load_from_state(token_handler, registry).await?;
251 Ok(PasswordManagerClient(client))
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use std::sync::Arc;
258
259 use super::*;
260
261 #[test]
262 fn new_with_server_communication_config_constructs() {
263 struct MockCookieProvider;
264
265 #[async_trait::async_trait]
266 impl bitwarden_server_communication_config::CookieProvider for MockCookieProvider {
267 async fn cookies(&self, _hostname: &str) -> Vec<(String, String)> {
268 vec![]
269 }
270
271 async fn acquire_cookie(
272 &self,
273 _hostname: &str,
274 ) -> Result<(), bitwarden_server_communication_config::AcquireCookieError> {
275 Ok(())
276 }
277
278 async fn needs_bootstrap(&self, _hostname: &str) -> bool {
279 false
280 }
281 }
282
283 let _client = PasswordManagerClient::builder()
284 .with_server_communication_config(Arc::new(MockCookieProvider))
285 .build();
286 }
287}