feat(crypto-js): Implement OlmMachine.get_verification.

This commit is contained in:
Ivan Enderlin
2022-05-24 16:08:11 +02:00
parent ee648144a2
commit 3194ad1f9a
5 changed files with 401 additions and 3 deletions
@@ -11,6 +11,12 @@ pub struct UserId {
pub(crate) inner: ruma::OwnedUserId,
}
impl UserId {
pub(crate) fn new_with(inner: ruma::OwnedUserId) -> Self {
Self { inner }
}
}
#[wasm_bindgen]
impl UserId {
/// Parse/validate and create a new `UserId`.
@@ -57,6 +63,12 @@ pub struct DeviceId {
pub(crate) inner: ruma::OwnedDeviceId,
}
impl DeviceId {
pub(crate) fn new_with(inner: ruma::OwnedDeviceId) -> Self {
Self { inner }
}
}
#[wasm_bindgen]
impl DeviceId {
/// Create a new `DeviceId`.
@@ -81,6 +93,12 @@ pub struct RoomId {
pub(crate) inner: ruma::OwnedRoomId,
}
impl RoomId {
pub(crate) fn new_with(inner: ruma::OwnedRoomId) -> Self {
Self { inner }
}
}
#[wasm_bindgen]
impl RoomId {
/// Parse/validate and create a new `RoomId`.
+1
View File
@@ -23,6 +23,7 @@ pub mod events;
mod future;
pub mod identifiers;
pub mod machine;
pub mod verifications;
pub mod requests;
pub mod responses;
pub mod sync_events;
+26 -1
View File
@@ -14,7 +14,7 @@ use crate::{
identifiers, requests,
requests::OutgoingRequest,
responses::{self, response_from_string},
sync_events,
sync_events, verifications,
};
#[wasm_bindgen]
@@ -344,6 +344,31 @@ impl OlmMachine {
}
}))
}
/// Get a verification object for the given user ID with the given flow ID.
///
/// Returns a list of `JsValue` to represent either (depending on
/// how the Wasm module has been compiled):
/// * `Sas` (enabled),
/// * `Qr`
#[cfg_attr(feature = "qrcode", doc = "(enabled).")]
#[cfg_attr(not(feature = "qrcode"), doc = "(disabled).")]
///
/// If a verification mode is missing, please try to compile the
/// Wasm module with different features.
#[wasm_bindgen(js_name = "getVerification")]
pub fn get_verification(
&self,
user_id: &identifiers::UserId,
flow_id: &str,
) -> Result<JsValue, JsError> {
self.inner
.get_verification(user_id.inner.as_ref(), flow_id)
.map(verifications::Verification)
.map(JsValue::try_from)
.transpose()
.map(|r| r.unwrap_or_else(|| JsValue::UNDEFINED))
}
}
#[wasm_bindgen]
@@ -49,7 +49,7 @@ impl DeviceLists {
self.inner
.changed
.iter()
.map(|user| identifiers::UserId { inner: user.clone() })
.map(|user| identifiers::UserId::new_with(user.clone()))
.map(JsValue::from)
.collect()
}
@@ -60,7 +60,7 @@ impl DeviceLists {
self.inner
.left
.iter()
.map(|user| identifiers::UserId { inner: user.clone() })
.map(|user| identifiers::UserId::new_with(user.clone()))
.map(JsValue::from)
.collect()
}
@@ -0,0 +1,354 @@
use js_sys::{Array, JsString};
use ruma::events::key::verification::cancel::CancelCode as RumaCancelCode;
use wasm_bindgen::prelude::*;
use crate::identifiers::{DeviceId, RoomId, UserId};
#[wasm_bindgen]
#[derive(Debug)]
pub struct Sas {
inner: matrix_sdk_crypto::Sas,
}
#[wasm_bindgen]
impl Sas {
/// Get our own user ID.
#[wasm_bindgen(js_name = "userId")]
pub fn user_id(&self) -> UserId {
UserId { inner: self.inner.user_id().to_owned() }
}
/// Get our own device ID.
#[wasm_bindgen(js_name = "deviceId")]
pub fn device_id(&self) -> DeviceId {
DeviceId { inner: self.inner.device_id().to_owned() }
}
/// Get the user id of the other side.
#[wasm_bindgen(js_name = "otherUserId")]
pub fn other_user_id(&self) -> UserId {
UserId { inner: self.inner.other_user_id().to_owned() }
}
/// Get the device ID of the other side.
#[wasm_bindgen(js_name = "otherDeviceId")]
pub fn other_device_id(&self) -> DeviceId {
DeviceId { inner: self.inner.other_device_id().to_owned() }
}
#[wasm_bindgen(js_name = "otherDevice")]
pub fn other_device(&self) {
todo!()
}
#[wasm_bindgen(js_name = "flowId")]
pub fn flow_id(&self) {
todo!()
}
/// Get the room ID if the verification is happening inside a
/// room.
#[wasm_bindgen(js_name = "roomId")]
pub fn room_id(&self) -> Option<RoomId> {
self.inner.room_id().map(ToOwned::to_owned).map(RoomId::new_with)
}
/// Does this verification flow support displaying emoji for the
/// short authentication string.
#[wasm_bindgen(js_name = "supportsEmoji")]
pub fn supports_emoji(&self) -> bool {
self.inner.supports_emoji()
}
/// Did this verification flow start from a verification request.
#[wasm_bindgen(js_name = "startedFromRequest")]
pub fn started_from_request(&self) -> bool {
self.inner.started_from_request()
}
/// Is this a verification that is veryfying one of our own
/// devices.
#[wasm_bindgen(js_name = "isSelfVerification")]
pub fn is_self_verification(&self) -> bool {
self.inner.is_self_verification()
}
/// Have we confirmed that the short auth string matches.
#[wasm_bindgen(js_name = "haveWeConfirmed")]
pub fn have_we_confirmed(&self) -> bool {
self.inner.have_we_confirmed()
}
/// Has the verification been accepted by both parties.
#[wasm_bindgen(js_name = "hasBeenAccepted")]
pub fn has_been_accepted(&self) -> bool {
self.inner.has_been_accepted()
}
/// Get info about the cancellation if the verification flow has
/// been cancelled.
#[wasm_bindgen(js_name = "cancelInfo")]
pub fn cancel_info(&self) -> Option<CancelInfo> {
self.inner.cancel_info().map(CancelInfo::new_with)
}
/// Did we initiate the verification flow.
#[wasm_bindgen(js_name = "weStarted")]
pub fn we_started(&self) -> bool {
self.inner.we_started()
}
pub fn accept(&self) {
todo!()
}
#[wasm_bindgen(js_name = "acceptWithSetings")]
pub fn accept_with_settings(&self) {
todo!()
}
pub fn confirm(&self) {
todo!()
}
pub fn cancel(&self) {
todo!()
}
#[wasm_bindgen(js_name = "cancelWithCode")]
pub fn cancel_with_code(&self) {
todo!()
}
/// Has the SAS verification flow timed out.
#[wasm_bindgen(js_name = "timedOut")]
pub fn timed_out(&self) -> bool {
self.inner.timed_out()
}
/// Are we in a state where we can show the short auth string.
#[wasm_bindgen(js_name = "canBePresented")]
pub fn can_be_presented(&self) -> bool {
self.inner.can_be_presented()
}
/// Is the SAS flow done.
#[wasm_bindgen(js_name = "isDone")]
pub fn is_done(&self) -> bool {
self.inner.is_done()
}
/// Is the SAS flow canceled.
#[wasm_bindgen(js_name = "isCancelled")]
pub fn is_cancelled(&self) -> bool {
self.inner.is_cancelled()
}
/// Get the emoji version of the short auth string.
///
/// Returns `undefined` if we can't yet present the short auth string,
/// otherwise seven tuples containing the emoji and description.
pub fn emoji(&self) -> Option<Array> {
Some(
self.inner
.emoji()?
.iter()
.map(|emoji| Emoji::new_with(emoji.clone()))
.map(JsValue::from)
.collect(),
)
}
/// Get the index of the emoji representing the short auth string
///
/// Returns `undefined` if we cant yet present the short auth
/// string, otherwise seven u8 numbers in the range from 0 to 63
/// inclusive which can be converted to an emoji using [the
/// relevant specification
/// entry](https://spec.matrix.org/unstable/client-server-api/#sas-method-emoji).
#[wasm_bindgen(js_name = "emoji_index")]
pub fn emoji_index(&self) -> Option<Array> {
Some(self.inner.emoji_index()?.iter().map(|emoji| *emoji).map(JsValue::from).collect())
}
/// Get the decimal version of the short auth string.
///
/// Returns None if we cant yet present the short auth string,
/// otherwise a tuple containing three 4-digit integers that
/// represent the short auth string.
pub fn decimals(&self) -> Option<Array> {
let decimals = self.inner.decimals()?;
let out = Array::new_with_length(3);
out.set(0, JsValue::from(decimals.0));
out.set(1, JsValue::from(decimals.1));
out.set(2, JsValue::from(decimals.2));
Some(out)
}
}
#[cfg(feature = "qrcode")]
#[wasm_bindgen]
#[derive(Debug)]
pub struct Qr {
inner: matrix_sdk_crypto::QrVerification,
}
#[cfg(feature = "qrcode")]
#[wasm_bindgen]
impl Qr {
#[wasm_bindgen(js_name = "hasBeenScanned")]
pub fn has_been_scanned(&self) -> bool {
self.inner.has_been_scanned()
}
}
pub(crate) struct Verification(pub(crate) matrix_sdk_crypto::Verification);
impl TryFrom<Verification> for JsValue {
type Error = JsError;
fn try_from(verification: Verification) -> Result<Self, Self::Error> {
use matrix_sdk_crypto::Verification::*;
Ok(match verification.0 {
SasV1(sas) => JsValue::from(Sas { inner: sas }),
#[cfg(feature = "qrcode")]
QrV1(qr) => JsValue::from(Qr { inner: qr }),
_ => {
return Err(JsError::new(
"Unknown verification type, expect `m.sas.v1` only for now",
))
}
})
}
}
#[wasm_bindgen]
pub struct CancelInfo {
inner: matrix_sdk_crypto::CancelInfo,
}
impl CancelInfo {
pub(crate) fn new_with(inner: matrix_sdk_crypto::CancelInfo) -> Self {
Self { inner }
}
}
#[wasm_bindgen]
impl CancelInfo {
pub fn reason(&self) -> JsString {
self.inner.reason().into()
}
#[wasm_bindgen(js_name = "cancelCode")]
pub fn cancel_code(&self) -> CancelCode {
self.inner.cancel_code().into()
}
#[wasm_bindgen(js_name = "cancelledbyUs")]
pub fn cancelled_by_us(&self) -> bool {
self.inner.cancelled_by_us()
}
}
#[wasm_bindgen]
pub enum CancelCode {
/// Unknown cancel code.
Other,
/// The user cancelled the verification.
User,
/// The verification process timed out.
///
/// Verification processes can define their own timeout
/// parameters.
Timeout,
/// The device does not know about the given transaction ID.
UnknownTransaction,
/// The device does not know how to handle the requested method.
///
/// Should be sent for `m.key.verification.start` messages and
/// messages defined by individual verification processes.
UnknownMethod,
/// The device received an unexpected message.
///
/// Typically raised when one of the parties is handling the
/// verification out of order.
UnexpectedMessage,
/// The key was not verified.
KeyMismatch,
/// The expected user did not match the user verified.
UserMismatch,
/// The message received was invalid.
InvalidMessage,
/// An `m.key.verification.request` was accepted by a different
/// device.
///
/// The device receiving this error can ignore the verification
/// request.
Accepted,
/// The device receiving this error can ignore the verification
/// request.
MismatchedCommitment,
/// The SAS did not match.
MismatchedSas,
}
impl From<&RumaCancelCode> for CancelCode {
fn from(code: &RumaCancelCode) -> Self {
use RumaCancelCode::*;
match code {
User => Self::User,
Timeout => Self::Timeout,
UnknownTransaction => Self::UnknownTransaction,
UnknownMethod => Self::UnknownMethod,
UnexpectedMessage => Self::UnexpectedMessage,
KeyMismatch => Self::KeyMismatch,
UserMismatch => Self::UserMismatch,
InvalidMessage => Self::InvalidMessage,
Accepted => Self::Accepted,
MismatchedCommitment => Self::MismatchedCommitment,
MismatchedSas => Self::MismatchedSas,
_ => Self::Other,
}
}
}
#[wasm_bindgen]
pub struct Emoji {
inner: matrix_sdk_crypto::Emoji,
}
impl Emoji {
pub(crate) fn new_with(inner: matrix_sdk_crypto::Emoji) -> Self {
Self { inner }
}
}
#[wasm_bindgen]
impl Emoji {
#[wasm_bindgen(getter)]
pub fn symbol(&self) -> JsString {
self.inner.symbol.into()
}
#[wasm_bindgen(getter)]
pub fn description(&self) -> JsString {
self.inner.description.into()
}
}