bitwarden_uniffi/
lib.rs

1#![doc = include_str!("../README.md")]
2
3uniffi::setup_scaffolding!();
4
5use std::sync::Arc;
6
7use auth::AuthClient;
8use bitwarden_core::{ClientSettings, client::internal::ClientManagedTokens};
9
10#[allow(missing_docs)]
11pub mod auth;
12#[allow(missing_docs)]
13pub mod crypto;
14mod error;
15#[allow(missing_docs)]
16pub mod platform;
17#[allow(missing_docs)]
18pub mod tool;
19mod uniffi_support;
20#[allow(missing_docs)]
21pub mod vault;
22
23#[cfg(target_os = "android")]
24mod android_support;
25
26use crypto::CryptoClient;
27use error::{Error, Result};
28use platform::PlatformClient;
29use tool::{ExporterClient, GeneratorClients, SendClient, SshClient};
30use vault::VaultClient;
31
32#[allow(missing_docs)]
33#[derive(uniffi::Object)]
34pub struct Client(pub(crate) bitwarden_pm::PasswordManagerClient);
35
36#[uniffi::export(async_runtime = "tokio")]
37impl Client {
38    /// Initialize a new instance of the SDK client
39    #[uniffi::constructor]
40    pub fn new(
41        token_provider: Arc<dyn ClientManagedTokens>,
42        settings: Option<ClientSettings>,
43    ) -> Self {
44        init_logger();
45        setup_error_converter();
46
47        #[cfg(target_os = "android")]
48        android_support::init();
49
50        Self(bitwarden_pm::PasswordManagerClient::new_with_client_tokens(
51            settings,
52            token_provider,
53        ))
54    }
55
56    /// Crypto operations
57    pub fn crypto(&self) -> CryptoClient {
58        CryptoClient(self.0.crypto())
59    }
60
61    /// Vault item operations
62    pub fn vault(&self) -> VaultClient {
63        VaultClient(self.0.vault())
64    }
65
66    #[allow(missing_docs)]
67    pub fn platform(&self) -> PlatformClient {
68        PlatformClient(self.0.0.clone())
69    }
70
71    /// Generator operations
72    pub fn generators(&self) -> GeneratorClients {
73        GeneratorClients(self.0.generator())
74    }
75
76    /// Exporters
77    pub fn exporters(&self) -> ExporterClient {
78        ExporterClient(self.0.exporters())
79    }
80
81    /// Sends operations
82    pub fn sends(&self) -> SendClient {
83        SendClient(self.0.sends())
84    }
85
86    /// SSH operations
87    pub fn ssh(&self) -> SshClient {
88        SshClient()
89    }
90
91    /// Auth operations
92    pub fn auth(&self) -> AuthClient {
93        AuthClient(self.0.0.clone())
94    }
95
96    /// Test method, echoes back the input
97    pub fn echo(&self, msg: String) -> String {
98        msg
99    }
100
101    /// Test method, calls http endpoint
102    pub async fn http_get(&self, url: String) -> Result<String> {
103        let client = self.0.0.internal.get_http_client();
104        let res = client
105            .get(&url)
106            .send()
107            .await
108            .map_err(|e| Error::Api(e.into()))?;
109
110        res.text().await.map_err(|e| Error::Api(e.into()))
111    }
112}
113
114fn init_logger() {
115    #[cfg(not(any(target_os = "android", target_os = "ios")))]
116    let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
117        .try_init();
118
119    #[cfg(target_os = "ios")]
120    let _ = oslog::OsLogger::new("com.8bit.bitwarden")
121        .level_filter(log::LevelFilter::Info)
122        .init();
123
124    #[cfg(target_os = "android")]
125    android_logger::init_once(
126        android_logger::Config::default()
127            .with_tag("com.bitwarden.sdk")
128            .with_max_level(log::LevelFilter::Info),
129    );
130}
131
132/// Setup the error converter to ensure conversion errors don't cause panics
133/// Check [`bitwarden_uniffi_error`] for more details
134fn setup_error_converter() {
135    bitwarden_uniffi_error::set_error_to_uniffi_error(|e| {
136        crate::error::BitwardenError::Conversion(e.to_string()).into()
137    });
138}