matrix-sdk: Expose an API to start SAS verifications.
parent
42a4ad60e8
commit
7cb25361b2
|
@ -36,7 +36,12 @@ use tracing::{error, info, instrument};
|
|||
use matrix_sdk_base::{BaseClient, BaseClientConfig, Room, Session, StateStore};
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
use matrix_sdk_common::api::r0::to_device::send_event_to_device::Request as ToDeviceRequest;
|
||||
use matrix_sdk_base::Device;
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
use matrix_sdk_common::api::r0::to_device::send_event_to_device::{
|
||||
IncomingRequest as OwnedToDeviceRequest, Request as ToDeviceRequest,
|
||||
};
|
||||
use matrix_sdk_common::{
|
||||
identifiers::ServerName,
|
||||
instant::{Duration, Instant},
|
||||
|
@ -52,7 +57,7 @@ use crate::{
|
|||
events::{room::message::MessageEventContent, EventType},
|
||||
http_client::{DefaultHttpClient, HttpClient, HttpSend},
|
||||
identifiers::{EventId, RoomId, RoomIdOrAliasId, UserId},
|
||||
Endpoint, EventEmitter, Result,
|
||||
Endpoint, Error, EventEmitter, Result,
|
||||
};
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
|
@ -1082,13 +1087,26 @@ impl Client {
|
|||
pub async fn send<Request>(&self, request: Request) -> Result<Request::IncomingResponse>
|
||||
where
|
||||
Request: Endpoint + Debug,
|
||||
crate::Error: From<FromHttpResponseError<Request::ResponseError>>,
|
||||
Error: From<FromHttpResponseError<Request::ResponseError>>,
|
||||
{
|
||||
self.http_client
|
||||
.send(request, self.base_client.session().clone())
|
||||
.await
|
||||
}
|
||||
|
||||
async fn send_to_device(
|
||||
&self,
|
||||
request: OwnedToDeviceRequest,
|
||||
) -> Result<send_event_to_device::Response> {
|
||||
let request = ToDeviceRequest {
|
||||
event_type: request.event_type,
|
||||
txn_id: &request.txn_id,
|
||||
messages: request.messages,
|
||||
};
|
||||
|
||||
self.send(request).await
|
||||
}
|
||||
|
||||
/// Synchronize the client's state with the latest state on the server.
|
||||
///
|
||||
/// If a `StateStore` is provided and this is the initial sync state will
|
||||
|
@ -1217,16 +1235,12 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
for req in self.base_client.outgoing_to_device_requests().await {
|
||||
let request = ToDeviceRequest {
|
||||
event_type: req.event_type,
|
||||
txn_id: &req.txn_id,
|
||||
messages: req.messages,
|
||||
};
|
||||
for request in self.base_client.outgoing_to_device_requests().await {
|
||||
let txn_id = request.txn_id.clone();
|
||||
|
||||
if self.send(request).await.is_ok() {
|
||||
if self.send_to_device(request).await.is_ok() {
|
||||
self.base_client
|
||||
.mark_to_device_request_as_sent(&req.txn_id)
|
||||
.mark_to_device_request_as_sent(&txn_id)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
@ -1307,14 +1321,8 @@ impl Client {
|
|||
.await
|
||||
.expect("Keys don't need to be uploaded");
|
||||
|
||||
for req in requests.drain(..) {
|
||||
let request = ToDeviceRequest {
|
||||
event_type: req.event_type,
|
||||
txn_id: &req.txn_id,
|
||||
messages: req.messages,
|
||||
};
|
||||
|
||||
let _response: send_event_to_device::Response = self.send(request).await?;
|
||||
for request in requests.drain(..) {
|
||||
self.send_to_device(request).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1406,7 +1414,6 @@ impl Client {
|
|||
/// Get a `Sas` verification object with the given flow id.
|
||||
#[cfg(feature = "encryption")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
|
||||
#[instrument]
|
||||
pub async fn get_verification(&self, flow_id: &str) -> Option<Sas> {
|
||||
self.base_client
|
||||
.get_verification(flow_id)
|
||||
|
@ -1418,6 +1425,33 @@ impl Client {
|
|||
homeserver: self.homeserver.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Start a interactive verification with the given `Device`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `device` - The device which we would like to start an interactive
|
||||
/// verification with.
|
||||
///
|
||||
/// Returns a `Sas` that represents the interactive verification flow.
|
||||
#[cfg(feature = "encryption")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
|
||||
pub async fn start_verification(&self, device: Device) -> Result<Sas> {
|
||||
let (sas, request) = self
|
||||
.base_client
|
||||
.start_verification(device)
|
||||
.await
|
||||
.ok_or(Error::AuthenticationRequired)?;
|
||||
|
||||
self.send_to_device(request).await?;
|
||||
|
||||
Ok(Sas {
|
||||
inner: sas,
|
||||
session: self.base_client.session().clone(),
|
||||
http_client: self.http_client.clone(),
|
||||
homeserver: self.homeserver.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -51,7 +51,7 @@ use matrix_sdk_common::{
|
|||
identifiers::{DeviceId, DeviceKeyAlgorithm},
|
||||
};
|
||||
#[cfg(feature = "encryption")]
|
||||
use matrix_sdk_crypto::{CryptoStore, OlmError, OlmMachine, OneTimeKeys, Sas};
|
||||
use matrix_sdk_crypto::{CryptoStore, Device, OlmError, OlmMachine, OneTimeKeys, Sas};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
@ -1849,6 +1849,7 @@ impl BaseClient {
|
|||
/// Get a `Sas` verification object with the given flow id.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `flow_id` - The unique id that identifies a interactive verification
|
||||
/// flow. For in-room verifications this will be the event id of the
|
||||
/// *m.key.verification.request* event that started the flow, for the
|
||||
|
@ -1863,6 +1864,24 @@ impl BaseClient {
|
|||
.as_ref()
|
||||
.and_then(|o| o.get_verification(flow_id))
|
||||
}
|
||||
|
||||
/// Start a interactive verification with the given `Device`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `device` - The device which we would like to start an interactive
|
||||
/// verification with.
|
||||
///
|
||||
/// Returns a `Sas` object and to-device request that needs to be sent out.
|
||||
#[cfg(feature = "encryption")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "encryption")))]
|
||||
pub async fn start_verification(&self, device: Device) -> Option<(Sas, OwnedToDeviceRequest)> {
|
||||
self.olm
|
||||
.lock()
|
||||
.await
|
||||
.as_ref()
|
||||
.and_then(|o| Some(o.start_verification(device)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1057,6 +1057,19 @@ impl OlmMachine {
|
|||
self.verification_machine.get_sas(flow_id)
|
||||
}
|
||||
|
||||
/// Start a interactive verification with the given `Device`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `device` - The device which we would like to start an interactive
|
||||
/// verification with.
|
||||
///
|
||||
///
|
||||
/// Returns a `Sas` object and to-device request that needs to be sent out.
|
||||
pub fn start_verification(&self, device: Device) -> (Sas, OwnedToDeviceRequest) {
|
||||
self.verification_machine.start_sas(device)
|
||||
}
|
||||
|
||||
/// Handle a sync response and update the internal state of the Olm machine.
|
||||
///
|
||||
/// This will decrypt to-device events but will not touch events in the room
|
||||
|
|
|
@ -25,7 +25,7 @@ use matrix_sdk_common::{
|
|||
};
|
||||
|
||||
use super::sas::{content_to_request, Sas};
|
||||
use crate::{Account, CryptoStore, CryptoStoreError};
|
||||
use crate::{Account, CryptoStore, CryptoStoreError, Device};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VerificationMachine {
|
||||
|
@ -45,6 +45,17 @@ impl VerificationMachine {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn start_sas(&self, device: Device) -> (Sas, OwnedToDeviceRequest) {
|
||||
let (sas, content) = Sas::start(self.account.clone(), device.clone(), self.store.clone());
|
||||
let request = content_to_request(
|
||||
device.user_id(),
|
||||
device.device_id(),
|
||||
AnyToDeviceEventContent::KeyVerificationStart(content),
|
||||
);
|
||||
|
||||
(sas, request)
|
||||
}
|
||||
|
||||
pub fn get_sas(&self, transaction_id: &str) -> Option<Sas> {
|
||||
#[allow(clippy::map_clone)]
|
||||
self.verifications.get(transaction_id).map(|s| s.clone())
|
||||
|
|
Loading…
Reference in New Issue