From 3318789a8b3bbacee12e1cea200ee289cac8966c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 9 May 2022 17:22:16 +0200 Subject: [PATCH] feat(crypto) Implement `UserId`, `DeviceId` and `OlmMachine` in Wasm for JS. --- crates/matrix-sdk-crypto/Cargo.toml | 6 ++-- crates/matrix-sdk-crypto/src/js/mod.rs | 40 +++++++++++++++++++++++++ crates/matrix-sdk-crypto/src/lib.rs | 3 ++ crates/matrix-sdk-crypto/src/machine.rs | 26 ++++++++++++++++ examples/js/Makefile | 2 ++ examples/js/index.js | 14 +++++++++ 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 crates/matrix-sdk-crypto/src/js/mod.rs create mode 100644 examples/js/Makefile create mode 100644 examples/js/index.js diff --git a/crates/matrix-sdk-crypto/Cargo.toml b/crates/matrix-sdk-crypto/Cargo.toml index d19d67348..3e197c718 100644 --- a/crates/matrix-sdk-crypto/Cargo.toml +++ b/crates/matrix-sdk-crypto/Cargo.toml @@ -54,13 +54,15 @@ tracing = "0.1.34" zeroize = { version = "1.3.0", features = ["zeroize_derive"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -ruma = { version = "0.6.1", features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"] } +ruma = { version = "0.6.2", features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac", rev = "e09c93f2c8df9770793abeec57ed984d5e1f3834" } [target.'cfg(target_arch = "wasm32")'.dependencies] -ruma = { version = "0.6.1", features = ["client-api-c", "js", "rand", "unstable-msc2676", "unstable-msc2677"] } +ruma = { version = "0.6.2", features = ["client-api-c", "js", "rand", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac", rev = "e09c93f2c8df9770793abeec57ed984d5e1f3834", features = ["js"] } wasm-bindgen = "0.2.80" +wasm-bindgen-futures = "0.4.30" +js-sys = "0.3.49" [dev-dependencies] futures = { version = "0.3.21", default-features = false, features = ["executor"] } diff --git a/crates/matrix-sdk-crypto/src/js/mod.rs b/crates/matrix-sdk-crypto/src/js/mod.rs new file mode 100644 index 000000000..e9ab50793 --- /dev/null +++ b/crates/matrix-sdk-crypto/src/js/mod.rs @@ -0,0 +1,40 @@ +//! Additional API that can be useful from JavaScript. + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[derive(Debug, Clone)] +pub struct UserId { + pub(crate) inner: ruma::OwnedUserId, +} + +#[wasm_bindgen] +impl UserId { + #[wasm_bindgen(constructor)] + pub fn new(id: &str) -> Result { + Ok(Self { inner: ruma::UserId::parse(id).map_err(|e| e.to_string())? }) + } + + pub fn localpart(&self) -> String { + self.inner.localpart().to_owned() + } + + #[wasm_bindgen(getter, js_name = "isHistorical")] + pub fn is_historical(&self) -> bool { + self.inner.is_historical() + } +} + +#[wasm_bindgen] +#[derive(Debug, Clone)] +pub struct DeviceId { + pub(crate) inner: ruma::OwnedDeviceId, +} + +#[wasm_bindgen] +impl DeviceId { + #[wasm_bindgen(constructor)] + pub fn new(id: &str) -> DeviceId { + Self { inner: id.into() } + } +} diff --git a/crates/matrix-sdk-crypto/src/lib.rs b/crates/matrix-sdk-crypto/src/lib.rs index ea981d3cc..1f2e59395 100644 --- a/crates/matrix-sdk-crypto/src/lib.rs +++ b/crates/matrix-sdk-crypto/src/lib.rs @@ -26,6 +26,7 @@ mod error; mod file_encryption; mod gossiping; mod identities; +mod js; mod machine; pub mod olm; mod requests; @@ -82,6 +83,8 @@ pub use identities::{ Device, LocalTrust, MasterPubkey, OwnUserIdentity, ReadOnlyDevice, ReadOnlyOwnUserIdentity, ReadOnlyUserIdentities, ReadOnlyUserIdentity, UserDevices, UserIdentities, UserIdentity, }; +#[cfg(feature = "js")] +pub use js::*; pub use machine::OlmMachine; #[cfg(feature = "qrcode")] pub use matrix_qrcode; diff --git a/crates/matrix-sdk-crypto/src/machine.rs b/crates/matrix-sdk-crypto/src/machine.rs index 0d5ee4bd0..20d9244c5 100644 --- a/crates/matrix-sdk-crypto/src/machine.rs +++ b/crates/matrix-sdk-crypto/src/machine.rs @@ -47,10 +47,14 @@ use ruma::{ }; use serde_json::Value; use tracing::{debug, error, info, trace, warn}; +#[cfg(feature = "js")] +use wasm_bindgen::prelude::*; use zeroize::Zeroize; #[cfg(feature = "backups_v1")] use crate::backups::BackupMachine; +#[cfg(feature = "js")] +use crate::js; use crate::{ error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult}, gossiping::GossipMachine, @@ -72,6 +76,7 @@ use crate::{ /// State machine implementation of the Olm/Megolm encryption protocol used for /// Matrix end to end encryption. +#[cfg_attr(feature = "js", wasm_bindgen)] #[derive(Clone)] pub struct OlmMachine { /// The unique user id that owns this account. @@ -1514,6 +1519,27 @@ impl OlmMachine { &self.backup_machine } } + +#[cfg_attr(feature = "js", wasm_bindgen)] +impl OlmMachine { + #[wasm_bindgen(constructor)] + pub async fn js_new(user_id: js::UserId, device_id: js::DeviceId) -> js_sys::Promise { + js_sys::Promise::new(&mut |resolve, reject| { + let user_id = user_id.inner.clone(); + let device_id = device_id.inner.clone(); + + wasm_bindgen_futures::spawn_local(async move { + let result = Self::new(user_id.as_ref(), device_id.as_ref()).await; + + resolve + .call1(&wasm_bindgen::JsValue::UNDEFINED, &wasm_bindgen::JsValue::from(result)) + .unwrap_throw(); + }) + }) + } + //pub async fn new(user_id: &UserId, device_id: &DeviceId) -> Self { +} + #[cfg(any(feature = "testing", test))] pub(crate) mod testing { #![allow(dead_code)] diff --git a/examples/js/Makefile b/examples/js/Makefile new file mode 100644 index 000000000..0f840ce07 --- /dev/null +++ b/examples/js/Makefile @@ -0,0 +1,2 @@ +build: + wasm-pack build --target nodejs ../../crates/matrix-sdk-crypto --features js diff --git a/examples/js/index.js b/examples/js/index.js new file mode 100644 index 000000000..c94be972b --- /dev/null +++ b/examples/js/index.js @@ -0,0 +1,14 @@ +const { UserId, DeviceId, OlmMachine } = require('../../crates/matrix-sdk-crypto/pkg'); + +async function run_example() { + const user_id = new UserId('@alice:example.org'); + console.log(user_id); + + const device_id = new DeviceId("DEVICE_ID"); + console.log(device_id); + + const olm_machine = await new OlmMachine(user_id, device_id); + console.log(olm_machine); +} + +run_example();