bitwarden_importers/
wasm.rs1use bitwarden_threading::ThreadBoundRunner;
9use wasm_bindgen::prelude::*;
10
11use crate::{OnePasswordTotpResult, OnePasswordTwoFactorUi};
12
13#[wasm_bindgen(typescript_custom_section)]
14const TS_CUSTOM_TYPES: &'static str = r#"
15/**
16 * Asks the user for a 1Password two-step verification code during a direct import.
17 */
18export interface OnePasswordTwoFactorUi {
19 /**
20 * Provides a TOTP passcode for the given zero-based attempt. A wrong code restarts the
21 * sign-in, so `attempt` grows as the user retries.
22 *
23 * @returns the passcode, or undefined if the user declined to provide one.
24 */
25 provideTotp(attempt: number): Promise<string | undefined>;
26}
27"#;
28
29#[wasm_bindgen]
30extern "C" {
31 #[wasm_bindgen(js_name = OnePasswordTwoFactorUi, typescript_type = "OnePasswordTwoFactorUi")]
33 pub type RawJsOnePasswordTwoFactorUi;
34
35 #[wasm_bindgen(catch, method, structural, js_name = provideTotp)]
36 async fn provide_totp(
37 this: &RawJsOnePasswordTwoFactorUi,
38 attempt: u32,
39 ) -> Result<JsValue, JsValue>;
40}
41
42pub(crate) struct JsOnePasswordTwoFactorUi(ThreadBoundRunner<RawJsOnePasswordTwoFactorUi>);
47
48impl JsOnePasswordTwoFactorUi {
49 pub(crate) fn new(ui: RawJsOnePasswordTwoFactorUi) -> Self {
50 Self(ThreadBoundRunner::new(ui))
51 }
52}
53
54#[async_trait::async_trait]
55impl OnePasswordTwoFactorUi for JsOnePasswordTwoFactorUi {
56 async fn provide_totp(&self, attempt: u32) -> OnePasswordTotpResult {
57 let code = self
58 .0
59 .run_in_thread(move |ui| async move {
60 ui.provide_totp(attempt)
61 .await
62 .ok()
63 .and_then(|code| code.as_string())
64 })
65 .await;
66
67 match code {
70 Ok(Some(code)) => OnePasswordTotpResult::Code(code),
71 Ok(None) | Err(_) => OnePasswordTotpResult::Cancel,
72 }
73 }
74}