bitwarden_core/client/
client.rs

1use std::sync::{Arc, RwLock};
2
3use bitwarden_crypto::KeyStore;
4use reqwest::header::{self, HeaderValue};
5
6use super::internal::InternalClient;
7#[cfg(feature = "internal")]
8use crate::client::flags::Flags;
9use crate::client::{
10    client_settings::ClientSettings,
11    internal::{ApiConfigurations, Tokens},
12};
13
14/// The main struct to interact with the Bitwarden SDK.
15#[derive(Debug, Clone)]
16pub struct Client {
17    // Important: The [`Client`] struct requires its `Clone` implementation to return an owned
18    // reference to the same instance. This is required to properly use the FFI API, where we can't
19    // just use normal Rust references effectively. For this to happen, any mutable state needs
20    // to be behind an Arc, ideally as part of the existing [`InternalClient`] struct.
21    #[doc(hidden)]
22    pub internal: Arc<InternalClient>,
23}
24
25impl Client {
26    pub fn new(settings_input: Option<ClientSettings>) -> Self {
27        let settings = settings_input.unwrap_or_default();
28
29        fn new_client_builder() -> reqwest::ClientBuilder {
30            #[allow(unused_mut)]
31            let mut client_builder = reqwest::Client::builder();
32
33            #[cfg(not(target_arch = "wasm32"))]
34            {
35                use rustls::ClientConfig;
36                use rustls_platform_verifier::ConfigVerifierExt;
37                client_builder =
38                    client_builder.use_preconfigured_tls(ClientConfig::with_platform_verifier());
39            }
40
41            client_builder
42        }
43
44        let external_client = new_client_builder().build().expect("Build should not fail");
45
46        let mut headers = header::HeaderMap::new();
47        headers.append(
48            "Device-Type",
49            HeaderValue::from_str(&(settings.device_type as u8).to_string())
50                .expect("All numbers are valid ASCII"),
51        );
52        let client_builder = new_client_builder().default_headers(headers);
53
54        let client = client_builder.build().expect("Build should not fail");
55
56        let identity = bitwarden_api_identity::apis::configuration::Configuration {
57            base_path: settings.identity_url,
58            user_agent: Some(settings.user_agent.clone()),
59            client: client.clone(),
60            basic_auth: None,
61            oauth_access_token: None,
62            bearer_access_token: None,
63            api_key: None,
64        };
65
66        let api = bitwarden_api_api::apis::configuration::Configuration {
67            base_path: settings.api_url,
68            user_agent: Some(settings.user_agent),
69            client,
70            basic_auth: None,
71            oauth_access_token: None,
72            bearer_access_token: None,
73            api_key: None,
74        };
75
76        Self {
77            internal: Arc::new(InternalClient {
78                tokens: RwLock::new(Tokens::default()),
79                login_method: RwLock::new(None),
80                #[cfg(feature = "internal")]
81                flags: RwLock::new(Flags::default()),
82                __api_configurations: RwLock::new(Arc::new(ApiConfigurations {
83                    identity,
84                    api,
85                    device_type: settings.device_type,
86                })),
87                external_client,
88                key_store: KeyStore::default(),
89            }),
90        }
91    }
92}