bitwarden_server_communication_config/wasm/client.rs
1use wasm_bindgen::prelude::*;
2
3use crate::{
4 ServerCommunicationConfig, ServerCommunicationConfigClient,
5 wasm::{
6 JsServerCommunicationConfigPlatformApi, JsServerCommunicationConfigRepository,
7 RawJsServerCommunicationConfigPlatformApi, RawJsServerCommunicationConfigRepository,
8 },
9};
10
11/// JavaScript wrapper for ServerCommunicationConfigClient
12///
13/// This provides TypeScript access to the server communication configuration client,
14/// allowing clients to check bootstrap requirements and retrieve cookies for HTTP requests.
15#[wasm_bindgen(js_name = ServerCommunicationConfigClient)]
16pub struct JsServerCommunicationConfigClient {
17 client: ServerCommunicationConfigClient<
18 JsServerCommunicationConfigRepository,
19 JsServerCommunicationConfigPlatformApi,
20 >,
21}
22
23#[wasm_bindgen(js_class = ServerCommunicationConfigClient)]
24impl JsServerCommunicationConfigClient {
25 /// Creates a new ServerCommunicationConfigClient with a JavaScript repository and platform API
26 ///
27 /// The repository should be backed by StateProvider (or equivalent
28 /// storage mechanism) for persistence.
29 ///
30 /// # Arguments
31 ///
32 /// * `repository` - JavaScript implementation of the repository interface
33 /// * `platform_api` - JavaScript implementation of the platform API interface
34 #[wasm_bindgen(constructor)]
35 pub fn new(
36 repository: RawJsServerCommunicationConfigRepository,
37 platform_api: RawJsServerCommunicationConfigPlatformApi,
38 ) -> Self {
39 let js_repository = JsServerCommunicationConfigRepository::new(repository);
40 let js_platform_api = JsServerCommunicationConfigPlatformApi::new(platform_api);
41 Self {
42 client: ServerCommunicationConfigClient::new(js_repository, js_platform_api),
43 }
44 }
45
46 /// Retrieves the server communication configuration for a hostname
47 ///
48 /// If no configuration exists, returns a default Direct bootstrap configuration.
49 ///
50 /// # Arguments
51 ///
52 /// * `hostname` - The server hostname (e.g., "vault.acme.com")
53 ///
54 /// # Errors
55 ///
56 /// Returns an error if the repository fails to retrieve the configuration.
57 #[wasm_bindgen(js_name = getConfig)]
58 pub async fn get_config(&self, hostname: String) -> Result<ServerCommunicationConfig, String> {
59 self.client.get_config(hostname).await
60 }
61
62 /// Determines if cookie bootstrapping is needed for this hostname
63 ///
64 /// # Arguments
65 ///
66 /// * `hostname` - The server hostname (e.g., "vault.acme.com")
67 #[wasm_bindgen(js_name = needsBootstrap)]
68 pub async fn needs_bootstrap(&self, hostname: String) -> bool {
69 self.client.needs_bootstrap(hostname).await
70 }
71
72 /// Returns all cookies that should be included in requests to this server
73 ///
74 /// Returns an array of [cookie_name, cookie_value] pairs.
75 ///
76 /// # Arguments
77 ///
78 /// * `hostname` - The server hostname (e.g., "vault.acme.com")
79 #[wasm_bindgen(js_name = cookies)]
80 pub async fn cookies(&self, hostname: String) -> Result<JsValue, JsError> {
81 let cookies = self.client.cookies(hostname).await;
82 serde_wasm_bindgen::to_value(&cookies).map_err(|e| JsError::new(&e.to_string()))
83 }
84
85 /// Sets the server communication configuration for a hostname
86 ///
87 /// This method saves the provided communication configuration to the repository.
88 /// Typically called when receiving the `/api/config` response from the server.
89 ///
90 /// # Arguments
91 ///
92 /// * `hostname` - The server hostname (e.g., "vault.acme.com")
93 /// * `config` - The server communication configuration to store
94 ///
95 /// # Errors
96 ///
97 /// Returns an error if the repository save operation fails
98 #[wasm_bindgen(js_name = setCommunicationType)]
99 pub async fn set_communication_type(
100 &self,
101 hostname: String,
102 config: ServerCommunicationConfig,
103 ) -> Result<(), String> {
104 self.client.set_communication_type(hostname, config).await
105 }
106
107 /// Acquires a cookie from the platform and saves it to the repository
108 ///
109 /// This method calls the platform API to trigger cookie acquisition (e.g., browser
110 /// redirect to IdP), then validates and stores the acquired cookie in the repository.
111 ///
112 /// # Arguments
113 ///
114 /// * `hostname` - The server hostname (e.g., "vault.acme.com")
115 ///
116 /// # Errors
117 ///
118 /// Returns an error if:
119 /// - Cookie acquisition was cancelled by the user
120 /// - Server configuration doesn't support SSO cookies (Direct bootstrap)
121 /// - Acquired cookie name doesn't match expected name
122 /// - Repository operations fail
123 #[wasm_bindgen(js_name = acquireCookie)]
124 pub async fn acquire_cookie(&self, hostname: String) -> Result<(), String> {
125 self.client
126 .acquire_cookie(&hostname)
127 .await
128 .map_err(|e| e.to_string())
129 }
130}