bitwarden_server_communication_config/wasm/client.rs
1use wasm_bindgen::prelude::*;
2
3use crate::{
4 ServerCommunicationConfig, ServerCommunicationConfigClient, SetCommunicationTypeRequest,
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 /// Previously acquired cookies are preserved automatically.
90 ///
91 /// # Arguments
92 ///
93 /// * `hostname` - The server hostname (e.g., "vault.acme.com")
94 /// * `request` - The server communication configuration to store
95 ///
96 /// # Errors
97 ///
98 /// Returns an error if the repository save operation fails
99 #[wasm_bindgen(js_name = setCommunicationType)]
100 pub async fn set_communication_type(
101 &self,
102 hostname: String,
103 request: SetCommunicationTypeRequest,
104 ) -> Result<(), String> {
105 self.client.set_communication_type(hostname, request).await
106 }
107
108 /// Acquires a cookie from the platform and saves it to the repository
109 ///
110 /// This method calls the platform API to trigger cookie acquisition (e.g., browser
111 /// redirect to IdP), then validates and stores the acquired cookie in the repository.
112 ///
113 /// # Arguments
114 ///
115 /// * `hostname` - The server hostname (e.g., "vault.acme.com")
116 ///
117 /// # Errors
118 ///
119 /// Returns an error if:
120 /// - Cookie acquisition was cancelled by the user
121 /// - Server configuration doesn't support SSO cookies (Direct bootstrap)
122 /// - Acquired cookie name doesn't match expected name
123 /// - Repository operations fail
124 #[wasm_bindgen(js_name = acquireCookie)]
125 pub async fn acquire_cookie(&self, hostname: String) -> Result<(), String> {
126 self.client
127 .acquire_cookie(&hostname)
128 .await
129 .map_err(|e| e.to_string())
130 }
131}