feat(crypto) Implement OlmMachine.receive_sync_changes & friends.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
//! Types for [Matrix](https://matrix.org/) identifiers for devices,
|
||||
//! events, keys, rooms, servers, users and URIs.
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
/// A Matrix [user ID].
|
||||
///
|
||||
/// [user ID]: https://spec.matrix.org/v1.2/appendices/#user-identifiers
|
||||
#[wasm_bindgen]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UserId {
|
||||
pub(crate) inner: ruma::OwnedUserId,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl UserId {
|
||||
/// Parse/validate and create a new `UserId`.
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(id: &str) -> Result<UserId, String> {
|
||||
Ok(Self { inner: ruma::UserId::parse(id).map_err(|e| e.to_string())? })
|
||||
}
|
||||
|
||||
/// Returns the user's localpart.
|
||||
pub fn localpart(&self) -> String {
|
||||
self.inner.localpart().to_owned()
|
||||
}
|
||||
|
||||
/// Whether this user ID is a historical one.
|
||||
///
|
||||
/// A historical user ID is one that doesn't conform to the latest
|
||||
/// specification of the user ID grammar but is still accepted
|
||||
/// because it was previously allowed.
|
||||
#[wasm_bindgen(getter, js_name = "isHistorical")]
|
||||
pub fn is_historical(&self) -> bool {
|
||||
self.inner.is_historical()
|
||||
}
|
||||
}
|
||||
|
||||
/// A Matrix key ID.
|
||||
///
|
||||
/// Device identifiers in Matrix are completely opaque character
|
||||
/// sequences. This type is provided simply for its semantic value.
|
||||
#[wasm_bindgen]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeviceId {
|
||||
pub(crate) inner: ruma::OwnedDeviceId,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl DeviceId {
|
||||
/// Create a new `DeviceId`.
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(id: &str) -> DeviceId {
|
||||
Self { inner: id.into() }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
|
||||
use js_sys::{Array, Map, Promise, Set};
|
||||
use ruma::{DeviceKeyAlgorithm, UInt};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::future_to_promise;
|
||||
|
||||
use crate::js::{identifiers, sync_events};
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: String);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Debug)]
|
||||
pub struct OlmMachine {
|
||||
inner: Arc<crate::OlmMachine>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "js", wasm_bindgen)]
|
||||
impl OlmMachine {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(user_id: &identifiers::UserId, device_id: &identifiers::DeviceId) -> Promise {
|
||||
let user_id = user_id.inner.clone();
|
||||
let device_id = device_id.inner.clone();
|
||||
|
||||
future_to_promise(async move {
|
||||
Ok(JsValue::from(OlmMachine {
|
||||
inner: Arc::new(crate::OlmMachine::new(user_id.as_ref(), device_id.as_ref()).await),
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn receive_sync_changes(
|
||||
&self,
|
||||
to_device_events: &str,
|
||||
changed_devices: &sync_events::DeviceLists,
|
||||
one_time_key_counts: &Map,
|
||||
unused_fallback_keys: &Set,
|
||||
) -> Promise {
|
||||
let to_device_events = serde_json::from_str(to_device_events).unwrap();
|
||||
let changed_devices = changed_devices.inner.clone();
|
||||
let one_time_key_counts: BTreeMap<DeviceKeyAlgorithm, UInt> = one_time_key_counts
|
||||
.entries()
|
||||
.into_iter()
|
||||
.filter_map(|js_value| {
|
||||
let pair = Array::from(&js_value.ok()?);
|
||||
let (key, value) = (
|
||||
DeviceKeyAlgorithm::from(pair.at(0).as_string()?),
|
||||
UInt::new(pair.at(1).as_f64()? as u64)?,
|
||||
);
|
||||
|
||||
Some((key, value))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let unused_fallback_keys: Option<Vec<DeviceKeyAlgorithm>> = Some(
|
||||
unused_fallback_keys
|
||||
.values()
|
||||
.into_iter()
|
||||
.filter_map(|js_value| Some(DeviceKeyAlgorithm::from(js_value.ok()?.as_string()?)))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let me = self.inner.clone();
|
||||
|
||||
future_to_promise(async move {
|
||||
Ok(JsValue::from(
|
||||
serde_json::to_string(
|
||||
&me.receive_sync_changes(
|
||||
to_device_events,
|
||||
&changed_devices,
|
||||
&one_time_key_counts,
|
||||
unused_fallback_keys.as_deref(),
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,5 @@
|
||||
//! 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<UserId, String> {
|
||||
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() }
|
||||
}
|
||||
}
|
||||
pub mod identifiers;
|
||||
pub mod machine;
|
||||
pub mod sync_events;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//! `GET /_matrix/client/*/sync`
|
||||
|
||||
use js_sys::Array;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::js::identifiers;
|
||||
|
||||
/// Information on E2E device updates.
|
||||
#[wasm_bindgen]
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceLists {
|
||||
pub(crate) inner: ruma::api::client::sync::sync_events::v3::DeviceLists,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl DeviceLists {
|
||||
/// Create an empty `DeviceLists`.
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> DeviceLists {
|
||||
Self { inner: Default::default() }
|
||||
}
|
||||
|
||||
/// Returns true if there are no device list updates.
|
||||
#[wasm_bindgen(js_name = "isEmpty")]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.inner.is_empty()
|
||||
}
|
||||
|
||||
/// List of users who have updated their device identity keys or who now
|
||||
/// share an encrypted room with the client since the previous sync
|
||||
pub fn changed(&self) -> Array {
|
||||
self.inner
|
||||
.changed
|
||||
.iter()
|
||||
.map(|user| identifiers::UserId { inner: user.clone() })
|
||||
.map(JsValue::from)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// List of users who no longer share encrypted rooms since the previous
|
||||
/// sync response.
|
||||
pub fn left(&self) -> Array {
|
||||
self.inner
|
||||
.left
|
||||
.iter()
|
||||
.map(|user| identifiers::UserId { inner: user.clone() })
|
||||
.map(JsValue::from)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -47,14 +47,10 @@ 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,
|
||||
@@ -76,7 +72,6 @@ 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.
|
||||
@@ -1520,26 +1515,6 @@ impl OlmMachine {
|
||||
}
|
||||
}
|
||||
|
||||
#[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)]
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
build:
|
||||
wasm-pack build --target nodejs ../../crates/matrix-sdk-crypto --features js
|
||||
wasm-pack build --release --target nodejs ../../crates/matrix-sdk-crypto --features js
|
||||
|
||||
+19
-5
@@ -1,14 +1,28 @@
|
||||
const { UserId, DeviceId, OlmMachine } = require('../../crates/matrix-sdk-crypto/pkg');
|
||||
const { UserId, DeviceId, OlmMachine, ToDevice, DeviceLists } = 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 device_id = new DeviceId('DEVICE_ID');
|
||||
|
||||
const olm_machine = await new OlmMachine(user_id, device_id);
|
||||
console.log(olm_machine);
|
||||
|
||||
const to_device_events = '{}';
|
||||
const changed_devices = new DeviceLists();
|
||||
const one_time_key_counts = new Map();
|
||||
one_time_key_counts.set('foo', 42);
|
||||
one_time_key_counts.set('bar', 153);
|
||||
const unused_fallback_keys = new Set();
|
||||
unused_fallback_keys.add('baz');
|
||||
unused_fallback_keys.add('qux');
|
||||
|
||||
const decrypted_to_device = await olm_machine.receive_sync_changes(
|
||||
to_device_events,
|
||||
changed_devices,
|
||||
one_time_key_counts,
|
||||
unused_fallback_keys,
|
||||
);
|
||||
console.log(JSON.parse(decrypted_to_device));
|
||||
}
|
||||
|
||||
run_example();
|
||||
|
||||
Reference in New Issue
Block a user