Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 69ccc5a9f9 | |||
| f9f83eaa39 | |||
| f243a684d4 | |||
| a82de88963 | |||
| 97e15feb0d | |||
| 51072a5dab | |||
| 500bb6e940 | |||
| 140630745f | |||
| 1ea9c9a915 | |||
| b8001b78b4 | |||
| a6916dd9dd | |||
| b96624890e | |||
| 7e9090399b | |||
| 9c53c478d9 | |||
| e0447c8190 | |||
| 4bcbcb146e | |||
| ae0f4c4cc5 | |||
| d6d51ef4b1 | |||
| 82a99b5267 | |||
| 349e3cae06 | |||
| 24253128ae | |||
| 8f46a87f52 | |||
| c47ac8d6b1 | |||
| 3f09a6abdd | |||
| df65081785 | |||
| 9b90175500 | |||
| 44f6e7a0cf | |||
| 55692802c0 |
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "matrix-qrcode"
|
||||
description = "Library to encode and decode QR codes for interactive verifications in Matrix land"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
authors = ["Damir Jelić <poljar@termina.org.uk>"]
|
||||
edition = "2018"
|
||||
homepage = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||
|
||||
@@ -8,16 +8,17 @@ license = "Apache-2.0"
|
||||
name = "matrix-sdk"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["docs"]
|
||||
rustdoc-args = ["--cfg", "feature=\"docs\""]
|
||||
|
||||
[features]
|
||||
default = ["encryption", "sled_cryptostore", "sled_state_store", "require_auth_for_profile_requests", "native-tls"]
|
||||
default = ["encryption", "qrcode", "sled_cryptostore", "sled_state_store", "require_auth_for_profile_requests", "native-tls"]
|
||||
|
||||
encryption = ["matrix-sdk-base/encryption"]
|
||||
qrcode = ["encryption", "matrix-sdk-base/qrcode"]
|
||||
sled_state_store = ["matrix-sdk-base/sled_state_store"]
|
||||
sled_cryptostore = ["matrix-sdk-base/sled_cryptostore"]
|
||||
markdown = ["ruma/markdown"]
|
||||
@@ -49,7 +50,7 @@ bytes = "1.0.1"
|
||||
matrix-sdk-common = { version = "0.4.0", path = "../matrix_sdk_common" }
|
||||
|
||||
[dependencies.matrix-sdk-base]
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
path = "../matrix_sdk_base"
|
||||
default_features = false
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ More examples can be found in the [examples] directory.
|
||||
The following crate feature flags are available:
|
||||
|
||||
* `encryption`: Enables end-to-end encryption support in the library.
|
||||
* `qrcode`: Enables qrcode verification support in the library. This will also
|
||||
enable `encryption`. Enabled by default.
|
||||
* `sled_cryptostore`: Enables a Sled based store for the encryption keys. If
|
||||
this is disabled and `encryption` support is enabled the keys will by
|
||||
default be stored only in memory and thus lost after the client is
|
||||
|
||||
+31
-63
@@ -138,11 +138,13 @@ use ruma::{
|
||||
DeviceIdBox, RoomId, RoomIdOrAliasId, ServerName, UInt, UserId,
|
||||
};
|
||||
|
||||
#[cfg(all(feature = "qrcode", feature = "encryption"))]
|
||||
use crate::verification::QrVerification;
|
||||
#[cfg(feature = "encryption")]
|
||||
use crate::{
|
||||
error::RoomKeyImportError,
|
||||
identities::{Device, UserDevices},
|
||||
verification::{QrVerification, SasVerification, Verification, VerificationRequest},
|
||||
verification::{SasVerification, Verification, VerificationRequest},
|
||||
};
|
||||
use crate::{
|
||||
error::{HttpError, HttpResult},
|
||||
@@ -925,6 +927,7 @@ impl Client {
|
||||
/// # let homeserver = Url::parse("http://localhost:8080").unwrap();
|
||||
/// # let client = Client::new(homeserver).unwrap();
|
||||
/// use matrix_sdk::{
|
||||
/// deserialized_responses::EncryptionInfo,
|
||||
/// room::Room,
|
||||
/// ruma::{
|
||||
/// events::{
|
||||
@@ -950,10 +953,20 @@ impl Client {
|
||||
/// )
|
||||
/// .await
|
||||
/// .register_event_handler(
|
||||
/// |ev: SyncMessageEvent<MessageEventContent>,
|
||||
/// room: Room,
|
||||
/// encryption_info: Option<EncryptionInfo>| async move {
|
||||
/// // An `Option<EncryptionInfo>` parameter lets you distinguish between
|
||||
/// // unencrypted events and events that were decrypted by the SDK.
|
||||
/// },
|
||||
/// )
|
||||
/// .await
|
||||
/// .register_event_handler(
|
||||
/// |ev: SyncStateEvent<TopicEventContent>| async move {
|
||||
/// // Also possible: Omit any or all arguments after the first.
|
||||
/// // You can omit any or all arguments after the first.
|
||||
/// }
|
||||
/// ).await;
|
||||
/// )
|
||||
/// .await;
|
||||
///
|
||||
/// // Custom events work exactly the same way, you just need to declare
|
||||
/// // the content struct and use the EventContent derive macro on it.
|
||||
@@ -2121,7 +2134,10 @@ impl Client {
|
||||
self.process_sync(response).await
|
||||
}
|
||||
|
||||
async fn process_sync(&self, response: sync_events::Response) -> Result<SyncResponse> {
|
||||
pub(crate) async fn process_sync(
|
||||
&self,
|
||||
response: sync_events::Response,
|
||||
) -> Result<SyncResponse> {
|
||||
let response = self.base_client.receive_sync_response(response).await?;
|
||||
let SyncResponse {
|
||||
next_batch: _,
|
||||
@@ -2178,8 +2194,12 @@ impl Client {
|
||||
}
|
||||
|
||||
// FIXME: Destructure room_info
|
||||
self.handle_sync_events(EventKind::InitialState, &room, &room_info.invite_state.events)
|
||||
.await?;
|
||||
self.handle_sync_events(
|
||||
EventKind::StrippedState,
|
||||
&room,
|
||||
&room_info.invite_state.events,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
for handler in &*self.notification_handlers.read().await {
|
||||
@@ -2561,6 +2581,7 @@ impl Client {
|
||||
matrix_sdk_base::crypto::Verification::SasV1(s) => {
|
||||
SasVerification { inner: s, client: self.clone() }.into()
|
||||
}
|
||||
#[cfg(feature = "qrcode")]
|
||||
matrix_sdk_base::crypto::Verification::QrV1(qr) => {
|
||||
QrVerification { inner: qr, client: self.clone() }.into()
|
||||
}
|
||||
@@ -3165,14 +3186,12 @@ impl Client {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
pub(crate) mod test {
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
convert::{TryFrom, TryInto},
|
||||
future,
|
||||
io::Cursor,
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
@@ -3202,20 +3221,19 @@ mod test {
|
||||
event_id,
|
||||
events::{
|
||||
room::{
|
||||
member::MemberEventContent,
|
||||
message::{ImageMessageEventContent, MessageEventContent},
|
||||
ImageInfo,
|
||||
},
|
||||
AnyMessageEventContent, AnySyncStateEvent, EventType, SyncStateEvent,
|
||||
AnyMessageEventContent, AnySyncStateEvent, EventType,
|
||||
},
|
||||
mxc_uri, room_id, thirdparty, uint, user_id, UserId,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use super::{Client, Session, SyncSettings, Url};
|
||||
use crate::{room, ClientConfig, HttpError, RequestConfig, RoomMember};
|
||||
use crate::{ClientConfig, HttpError, RequestConfig, RoomMember};
|
||||
|
||||
async fn logged_in_client() -> Client {
|
||||
pub(crate) async fn logged_in_client() -> Client {
|
||||
let session = Session {
|
||||
access_token: "1234".to_owned(),
|
||||
user_id: user_id!("@example:localhost"),
|
||||
@@ -3473,56 +3491,6 @@ mod test {
|
||||
// assert_eq!(1, ignored_users.len())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn event_handler() {
|
||||
use std::sync::atomic::{AtomicU8, Ordering::SeqCst};
|
||||
|
||||
let client = logged_in_client().await;
|
||||
|
||||
let member_count = Arc::new(AtomicU8::new(0));
|
||||
let typing_count = Arc::new(AtomicU8::new(0));
|
||||
let power_levels_count = Arc::new(AtomicU8::new(0));
|
||||
|
||||
client
|
||||
.register_event_handler({
|
||||
let member_count = member_count.clone();
|
||||
move |_ev: SyncStateEvent<MemberEventContent>, _room: room::Room| {
|
||||
member_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
})
|
||||
.await
|
||||
.register_event_handler({
|
||||
let typing_count = typing_count.clone();
|
||||
move |_ev: SyncStateEvent<MemberEventContent>| {
|
||||
typing_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
})
|
||||
.await
|
||||
.register_event_handler({
|
||||
let power_levels_count = power_levels_count.clone();
|
||||
move |_ev: SyncStateEvent<MemberEventContent>,
|
||||
_client: Client,
|
||||
_room: room::Room| {
|
||||
power_levels_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
||||
let response = EventBuilder::default()
|
||||
.add_room_event(EventsJson::Member)
|
||||
.add_ephemeral(EventsJson::Typing)
|
||||
.add_state_event(EventsJson::PowerLevels)
|
||||
.build_sync_response();
|
||||
client.process_sync(response).await.unwrap();
|
||||
|
||||
assert_eq!(member_count.load(SeqCst), 1);
|
||||
assert_eq!(typing_count.load(SeqCst), 1);
|
||||
assert_eq!(power_levels_count.load(SeqCst), 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn room_creation() {
|
||||
let client = logged_in_client().await;
|
||||
|
||||
+150
-41
@@ -32,7 +32,7 @@
|
||||
|
||||
use std::{borrow::Cow, future::Future, ops::Deref};
|
||||
|
||||
use matrix_sdk_base::deserialized_responses::SyncRoomEvent;
|
||||
use matrix_sdk_base::deserialized_responses::{EncryptionInfo, SyncRoomEvent};
|
||||
use ruma::{events::AnySyncStateEvent, serde::Raw};
|
||||
use serde::Deserialize;
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
@@ -47,7 +47,7 @@ pub enum EventKind {
|
||||
EphemeralRoomData,
|
||||
Message { redacted: bool },
|
||||
State { redacted: bool },
|
||||
StrippedState { redacted: bool },
|
||||
StrippedState,
|
||||
InitialState,
|
||||
ToDevice,
|
||||
Presence,
|
||||
@@ -117,6 +117,7 @@ pub struct EventHandlerData<'a> {
|
||||
pub client: Client,
|
||||
pub room: Option<room::Room>,
|
||||
pub raw: &'a RawJsonValue,
|
||||
pub encryption_info: Option<&'a EncryptionInfo>,
|
||||
}
|
||||
|
||||
/// Context for an event handler.
|
||||
@@ -169,6 +170,12 @@ impl EventHandlerContext for RawEvent {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventHandlerContext for Option<EncryptionInfo> {
|
||||
fn from_data(data: &EventHandlerData<'_>) -> Option<Self> {
|
||||
Some(data.encryption_info.cloned())
|
||||
}
|
||||
}
|
||||
|
||||
/// Return types supported for event handlers implement this trait.
|
||||
///
|
||||
/// It is not meant to be implemented outside of matrix-sdk.
|
||||
@@ -211,7 +218,19 @@ impl Client {
|
||||
room: &Option<room::Room>,
|
||||
events: &[Raw<T>],
|
||||
) -> serde_json::Result<()> {
|
||||
self.handle_sync_events_wrapped(kind, room, events, |x| x).await
|
||||
#[derive(Deserialize)]
|
||||
struct ExtractType<'a> {
|
||||
#[serde(borrow, rename = "type")]
|
||||
event_type: Cow<'a, str>,
|
||||
}
|
||||
|
||||
self.handle_sync_events_wrapped_with(
|
||||
room,
|
||||
events,
|
||||
|ev| (ev, None),
|
||||
|raw| Ok((kind, raw.deserialize_as::<ExtractType>()?.event_type)),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn handle_sync_state_events(
|
||||
@@ -226,11 +245,16 @@ impl Client {
|
||||
unsigned: Option<UnsignedDetails>,
|
||||
}
|
||||
|
||||
self.handle_sync_events_wrapped_with(room, state_events, std::convert::identity, |raw| {
|
||||
let StateEventDetails { event_type, unsigned } = raw.deserialize_as()?;
|
||||
let redacted = unsigned.and_then(|u| u.redacted_because).is_some();
|
||||
Ok((EventKind::State { redacted }, event_type))
|
||||
})
|
||||
self.handle_sync_events_wrapped_with(
|
||||
room,
|
||||
state_events,
|
||||
|ev| (ev, None),
|
||||
|raw| {
|
||||
let StateEventDetails { event_type, unsigned } = raw.deserialize_as()?;
|
||||
let redacted = unsigned.and_then(|u| u.redacted_because).is_some();
|
||||
Ok((EventKind::State { redacted }, event_type))
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -239,7 +263,6 @@ impl Client {
|
||||
room: &Option<room::Room>,
|
||||
timeline_events: &[SyncRoomEvent],
|
||||
) -> serde_json::Result<()> {
|
||||
// FIXME: add EncryptionInfo to context
|
||||
#[derive(Deserialize)]
|
||||
struct TimelineEventDetails<'a> {
|
||||
#[serde(borrow, rename = "type")]
|
||||
@@ -251,7 +274,7 @@ impl Client {
|
||||
self.handle_sync_events_wrapped_with(
|
||||
room,
|
||||
timeline_events,
|
||||
|e| &e.event,
|
||||
|e| (&e.event, e.encryption_info.as_ref()),
|
||||
|raw| {
|
||||
let TimelineEventDetails { event_type, state_key, unsigned } =
|
||||
raw.deserialize_as()?;
|
||||
@@ -268,35 +291,16 @@ impl Client {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn handle_sync_events_wrapped<'a, T: 'a, U: 'a>(
|
||||
&self,
|
||||
kind: EventKind,
|
||||
room: &Option<room::Room>,
|
||||
events: &'a [U],
|
||||
get_event: impl Fn(&'a U) -> &'a Raw<T>,
|
||||
) -> Result<(), serde_json::Error> {
|
||||
#[derive(Deserialize)]
|
||||
struct ExtractType<'a> {
|
||||
#[serde(borrow, rename = "type")]
|
||||
event_type: Cow<'a, str>,
|
||||
}
|
||||
|
||||
self.handle_sync_events_wrapped_with(room, events, get_event, |raw| {
|
||||
Ok((kind, raw.deserialize_as::<ExtractType>()?.event_type))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn handle_sync_events_wrapped_with<'a, T: 'a, U: 'a>(
|
||||
&self,
|
||||
room: &Option<room::Room>,
|
||||
list: &'a [U],
|
||||
get_event: impl Fn(&'a U) -> &'a Raw<T>,
|
||||
get_event_details: impl Fn(&'a U) -> (&'a Raw<T>, Option<&'a EncryptionInfo>),
|
||||
get_id: impl Fn(&Raw<T>) -> serde_json::Result<(EventKind, Cow<'_, str>)>,
|
||||
) -> serde_json::Result<()> {
|
||||
for x in list {
|
||||
let event = get_event(x);
|
||||
let (ev_kind, ev_type) = get_id(event)?;
|
||||
let (raw_event, encryption_info) = get_event_details(x);
|
||||
let (ev_kind, ev_type) = get_id(raw_event)?;
|
||||
let event_handler_id = (ev_kind, &*ev_type);
|
||||
|
||||
if let Some(handlers) = self.event_handlers.read().await.get(&event_handler_id) {
|
||||
@@ -304,7 +308,8 @@ impl Client {
|
||||
let data = EventHandlerData {
|
||||
client: self.clone(),
|
||||
room: room.clone(),
|
||||
raw: event.json(),
|
||||
raw: raw_event.json(),
|
||||
encryption_info,
|
||||
};
|
||||
matrix_sdk_common::executor::spawn((handler)(data));
|
||||
}
|
||||
@@ -393,8 +398,7 @@ mod static_events {
|
||||
where
|
||||
C: StaticEventContent + events::StateEventContent,
|
||||
{
|
||||
const ID: (EventKind, &'static str) =
|
||||
(EventKind::StrippedState { redacted: false }, C::TYPE);
|
||||
const ID: (EventKind, &'static str) = (EventKind::StrippedState, C::TYPE);
|
||||
}
|
||||
|
||||
impl<C> SyncEvent for events::InitialStateEvent<C>
|
||||
@@ -428,12 +432,117 @@ mod static_events {
|
||||
{
|
||||
const ID: (EventKind, &'static str) = (EventKind::State { redacted: true }, C::TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> SyncEvent for events::RedactedStrippedStateEvent<C>
|
||||
where
|
||||
C: StaticEventContent + events::RedactedStateEventContent,
|
||||
{
|
||||
const ID: (EventKind, &'static str) =
|
||||
(EventKind::StrippedState { redacted: true }, C::TYPE);
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::{future, sync::Arc};
|
||||
|
||||
use matrix_sdk_test::{EventBuilder, EventsJson};
|
||||
use ruma::{
|
||||
events::{room::member::MemberEventContent, StrippedStateEvent, SyncStateEvent},
|
||||
room_id,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{room, Client};
|
||||
|
||||
#[tokio::test]
|
||||
async fn event_handler() -> crate::Result<()> {
|
||||
use std::sync::atomic::{AtomicU8, Ordering::SeqCst};
|
||||
|
||||
let client = crate::client::test::logged_in_client().await;
|
||||
|
||||
let member_count = Arc::new(AtomicU8::new(0));
|
||||
let typing_count = Arc::new(AtomicU8::new(0));
|
||||
let power_levels_count = Arc::new(AtomicU8::new(0));
|
||||
let invited_member_count = Arc::new(AtomicU8::new(0));
|
||||
|
||||
client
|
||||
.register_event_handler({
|
||||
let member_count = member_count.clone();
|
||||
move |_ev: SyncStateEvent<MemberEventContent>, _room: room::Room| {
|
||||
member_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
})
|
||||
.await
|
||||
.register_event_handler({
|
||||
let typing_count = typing_count.clone();
|
||||
move |_ev: SyncStateEvent<MemberEventContent>| {
|
||||
typing_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
})
|
||||
.await
|
||||
.register_event_handler({
|
||||
let power_levels_count = power_levels_count.clone();
|
||||
move |_ev: SyncStateEvent<MemberEventContent>,
|
||||
_client: Client,
|
||||
_room: room::Room| {
|
||||
power_levels_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
})
|
||||
.await
|
||||
.register_event_handler({
|
||||
let invited_member_count = invited_member_count.clone();
|
||||
move |_ev: StrippedStateEvent<MemberEventContent>| {
|
||||
invited_member_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
||||
let response = EventBuilder::default()
|
||||
.add_room_event(EventsJson::Member)
|
||||
.add_ephemeral(EventsJson::Typing)
|
||||
.add_state_event(EventsJson::PowerLevels)
|
||||
.add_custom_invited_event(
|
||||
&room_id!("!test_invited:example.org"),
|
||||
json!({
|
||||
"content": {
|
||||
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||
"displayname": "Alice",
|
||||
"membership": "invite",
|
||||
},
|
||||
"event_id": "$143273582443PhrSn:example.org",
|
||||
"origin_server_ts": 1432735824653u64,
|
||||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||
"sender": "@example:example.org",
|
||||
"state_key": "@alice:example.org",
|
||||
"type": "m.room.member",
|
||||
"unsigned": {
|
||||
"age": 1234,
|
||||
"invite_room_state": [
|
||||
{
|
||||
"content": {
|
||||
"name": "Example Room"
|
||||
},
|
||||
"sender": "@bob:example.org",
|
||||
"state_key": "",
|
||||
"type": "m.room.name"
|
||||
},
|
||||
{
|
||||
"content": {
|
||||
"join_rule": "invite"
|
||||
},
|
||||
"sender": "@bob:example.org",
|
||||
"state_key": "",
|
||||
"type": "m.room.join_rules"
|
||||
}
|
||||
]
|
||||
}
|
||||
}),
|
||||
)
|
||||
.build_sync_response();
|
||||
client.process_sync(response).await?;
|
||||
|
||||
assert_eq!(member_count.load(SeqCst), 1);
|
||||
assert_eq!(typing_count.load(SeqCst), 1);
|
||||
assert_eq!(power_levels_count.load(SeqCst), 1);
|
||||
assert_eq!(invited_member_count.load(SeqCst), 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,8 @@ impl Device {
|
||||
/// The default methods that are supported are `m.sas.v1` and
|
||||
/// `m.qr_code.show.v1`, if this isn't desirable the
|
||||
/// [`request_verification_with_methods()`] method can be used to override
|
||||
/// this.
|
||||
/// this. `m.qr_code.show.v1` is only avaliable if the `qrcode` feature is
|
||||
/// enabled, which it is by default.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
||||
@@ -82,7 +82,8 @@ impl UserIdentity {
|
||||
/// The default methods that are supported are `m.sas.v1` and
|
||||
/// `m.qr_code.show.v1`, if this isn't desirable the
|
||||
/// [`request_verification_with_methods()`] method can be used to override
|
||||
/// this.
|
||||
/// this. `m.qr_code.show.v1` is only avaliable if the `qrcode` feature is
|
||||
/// enabled, which it is by default.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
||||
@@ -30,11 +30,14 @@
|
||||
//! string.
|
||||
//! * [`QrVerification`] - Interactive verification using QR codes.
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
mod qrcode;
|
||||
mod requests;
|
||||
mod sas;
|
||||
|
||||
pub use matrix_sdk_base::crypto::{AcceptSettings, CancelInfo};
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
pub use qrcode::QrVerification;
|
||||
pub use requests::VerificationRequest;
|
||||
pub use sas::SasVerification;
|
||||
@@ -44,6 +47,8 @@ pub use sas::SasVerification;
|
||||
pub enum Verification {
|
||||
/// The `m.sas.v1` verification variant.
|
||||
SasV1(SasVerification),
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
/// The `m.qr_code.*.v1` verification variant.
|
||||
QrV1(QrVerification),
|
||||
}
|
||||
@@ -51,6 +56,7 @@ pub enum Verification {
|
||||
impl Verification {
|
||||
/// Try to deconstruct this verification enum into a SAS verification.
|
||||
pub fn sas(self) -> Option<SasVerification> {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Verification::SasV1(sas) = self {
|
||||
Some(sas)
|
||||
} else {
|
||||
@@ -58,6 +64,7 @@ impl Verification {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
/// Try to deconstruct this verification enum into a QR code verification.
|
||||
pub fn qr(self) -> Option<QrVerification> {
|
||||
if let Verification::QrV1(qr) = self {
|
||||
@@ -71,6 +78,7 @@ impl Verification {
|
||||
pub fn is_done(&self) -> bool {
|
||||
match self {
|
||||
Verification::SasV1(s) => s.is_done(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(qr) => qr.is_done(),
|
||||
}
|
||||
}
|
||||
@@ -79,6 +87,7 @@ impl Verification {
|
||||
pub fn is_cancelled(&self) -> bool {
|
||||
match self {
|
||||
Verification::SasV1(s) => s.is_cancelled(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(qr) => qr.is_cancelled(),
|
||||
}
|
||||
}
|
||||
@@ -88,6 +97,7 @@ impl Verification {
|
||||
pub fn cancel_info(&self) -> Option<CancelInfo> {
|
||||
match self {
|
||||
Verification::SasV1(s) => s.cancel_info(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(q) => q.cancel_info(),
|
||||
}
|
||||
}
|
||||
@@ -96,6 +106,7 @@ impl Verification {
|
||||
pub fn own_user_id(&self) -> &ruma::UserId {
|
||||
match self {
|
||||
Verification::SasV1(v) => v.own_user_id(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(v) => v.own_user_id(),
|
||||
}
|
||||
}
|
||||
@@ -105,6 +116,7 @@ impl Verification {
|
||||
pub fn other_user_id(&self) -> &ruma::UserId {
|
||||
match self {
|
||||
Verification::SasV1(v) => v.inner.other_user_id(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(v) => v.inner.other_user_id(),
|
||||
}
|
||||
}
|
||||
@@ -113,6 +125,7 @@ impl Verification {
|
||||
pub fn is_self_verification(&self) -> bool {
|
||||
match self {
|
||||
Verification::SasV1(v) => v.is_self_verification(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(v) => v.is_self_verification(),
|
||||
}
|
||||
}
|
||||
@@ -121,6 +134,7 @@ impl Verification {
|
||||
pub fn we_started(&self) -> bool {
|
||||
match self {
|
||||
Verification::SasV1(s) => s.we_started(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(q) => q.we_started(),
|
||||
}
|
||||
}
|
||||
@@ -132,6 +146,7 @@ impl From<SasVerification> for Verification {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
impl From<QrVerification> for Verification {
|
||||
fn from(qr: QrVerification) -> Self {
|
||||
Self::QrV1(qr)
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
use matrix_sdk_base::crypto::{CancelInfo, VerificationRequest as BaseVerificationRequest};
|
||||
use ruma::events::key::verification::VerificationMethod;
|
||||
|
||||
use super::{QrVerification, SasVerification};
|
||||
#[cfg(feature = "qrcode")]
|
||||
use super::QrVerification;
|
||||
use super::SasVerification;
|
||||
use crate::{Client, Result};
|
||||
|
||||
/// An object controlling the interactive verification flow.
|
||||
@@ -83,8 +85,10 @@ impl VerificationRequest {
|
||||
|
||||
/// Accept the verification request.
|
||||
///
|
||||
/// This method will accept the request and signal that it supports the
|
||||
/// `m.sas.v1`, the `m.qr_code.show.v1`, and `m.reciprocate.v1` method.
|
||||
/// This method will accept the request and signal by default that it
|
||||
/// supports the `m.sas.v1`, the `m.qr_code.show.v1`, and `m.reciprocate.v1`
|
||||
/// method. If the `qrcode` feature is disabled it will only signal that it
|
||||
/// supports the `m.sas.v1` method.
|
||||
///
|
||||
/// If QR code scanning should be supported or QR code showing shouldn't be
|
||||
/// supported the [`accept_with_methods()`] method should be used instead.
|
||||
@@ -113,6 +117,8 @@ impl VerificationRequest {
|
||||
}
|
||||
|
||||
/// Generate a QR code
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
pub async fn generate_qr_code(&self) -> Result<Option<QrVerification>> {
|
||||
Ok(self
|
||||
.inner
|
||||
|
||||
@@ -36,7 +36,7 @@ tracing = "0.1"
|
||||
url = "2"
|
||||
warp = { git = "https://github.com/seanmonstar/warp.git", rev = "629405", optional = true, default-features = false }
|
||||
|
||||
matrix-sdk = { version = "0.3", path = "../matrix_sdk", default-features = false, features = ["appservice"] }
|
||||
matrix-sdk = { version = "0.4", path = "../matrix_sdk", default-features = false, features = ["appservice"] }
|
||||
|
||||
[dependencies.ruma]
|
||||
version = "0.4.0"
|
||||
|
||||
@@ -8,7 +8,7 @@ license = "Apache-2.0"
|
||||
name = "matrix-sdk-base"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["docs"]
|
||||
@@ -17,6 +17,7 @@ rustdoc-args = ["--cfg", "feature=\"docs\""]
|
||||
[features]
|
||||
default = []
|
||||
encryption = ["matrix-sdk-crypto"]
|
||||
qrcode = ["matrix-sdk-crypto/qrcode"]
|
||||
sled_state_store = ["sled", "pbkdf2", "hmac", "sha2", "rand", "chacha20poly1305"]
|
||||
sled_cryptostore = ["matrix-sdk-crypto/sled_cryptostore"]
|
||||
|
||||
@@ -31,7 +32,7 @@ serde_json = "1.0.64"
|
||||
tracing = "0.1.26"
|
||||
|
||||
matrix-sdk-common = { version = "0.4.0", path = "../matrix_sdk_common" }
|
||||
matrix-sdk-crypto = { version = "0.3.0", path = "../matrix_sdk_crypto", optional = true }
|
||||
matrix-sdk-crypto = { version = "0.4.0", path = "../matrix_sdk_crypto", optional = true }
|
||||
|
||||
# Misc dependencies
|
||||
thiserror = "1.0.25"
|
||||
|
||||
@@ -30,6 +30,7 @@ use crate::deserialized_responses::MemberEvent;
|
||||
pub struct RoomMember {
|
||||
pub(crate) event: Arc<MemberEvent>,
|
||||
pub(crate) profile: Arc<Option<MemberEventContent>>,
|
||||
#[allow(dead_code)]
|
||||
pub(crate) presence: Arc<Option<PresenceEvent>>,
|
||||
pub(crate) power_levels: Arc<Option<SyncStateEvent<PowerLevelsEventContent>>>,
|
||||
pub(crate) max_power_level: i64,
|
||||
|
||||
@@ -8,11 +8,10 @@ license = "Apache-2.0"
|
||||
name = "matrix-sdk-common"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.50"
|
||||
instant = { version = "0.1.9", features = ["wasm-bindgen", "now"] }
|
||||
ruma = { version = "0.4.0", features = ["client-api-c"] }
|
||||
serde = "1.0.126"
|
||||
|
||||
@@ -24,6 +23,14 @@ version = "1.7.1"
|
||||
default-features = false
|
||||
features = ["rt", "sync"]
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies.instant]
|
||||
version = "0.1.9"
|
||||
features = ["wasm-bindgen", "now"]
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.instant]
|
||||
version = "0.1.9"
|
||||
features = ["now"]
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
futures = "0.3.15"
|
||||
futures-locks = { version = "0.6.0", default-features = false }
|
||||
|
||||
@@ -8,7 +8,7 @@ license = "Apache-2.0"
|
||||
name = "matrix-sdk-crypto"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["docs"]
|
||||
@@ -16,11 +16,12 @@ rustdoc-args = ["--cfg", "feature=\"docs\""]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
qrcode = ["matrix-qrcode"]
|
||||
sled_cryptostore = ["sled"]
|
||||
docs = ["sled_cryptostore"]
|
||||
|
||||
[dependencies]
|
||||
matrix-qrcode = { version = "0.1.0", path = "../matrix_qrcode" }
|
||||
matrix-qrcode = { version = "0.2.0", path = "../matrix_qrcode" , optional = true}
|
||||
matrix-sdk-common = { version = "0.4.0", path = "../matrix_sdk_common" }
|
||||
ruma = { version = "0.4.0", features = ["client-api-c", "unstable-pre-spec"] }
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ use super::{atomic_bool_deserializer, atomic_bool_serializer};
|
||||
use crate::{
|
||||
error::{EventError, OlmError, OlmResult, SignatureError},
|
||||
identities::{ReadOnlyOwnUserIdentity, ReadOnlyUserIdentities},
|
||||
olm::{InboundGroupSession, PrivateCrossSigningIdentity, Session, Utility},
|
||||
olm::{InboundGroupSession, Session, Utility},
|
||||
store::{Changes, CryptoStore, DeviceChanges, Result as StoreResult},
|
||||
verification::VerificationMachine,
|
||||
OutgoingVerificationRequest, Sas, ToDeviceRequest, VerificationRequest,
|
||||
@@ -296,7 +296,6 @@ impl Device {
|
||||
#[derive(Debug)]
|
||||
pub struct UserDevices {
|
||||
pub(crate) inner: HashMap<DeviceIdBox, ReadOnlyDevice>,
|
||||
pub(crate) private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
|
||||
pub(crate) verification_machine: VerificationMachine,
|
||||
pub(crate) own_identity: Option<ReadOnlyOwnUserIdentity>,
|
||||
pub(crate) device_owner_identity: Option<ReadOnlyUserIdentities>,
|
||||
|
||||
@@ -47,6 +47,8 @@ pub use identities::{
|
||||
ReadOnlyUserIdentities, ReadOnlyUserIdentity, UserDevices, UserIdentities, UserIdentity,
|
||||
};
|
||||
pub use machine::OlmMachine;
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
pub use matrix_qrcode;
|
||||
pub(crate) use olm::ReadOnlyAccount;
|
||||
pub use olm::{CrossSigningStatus, EncryptionSettings};
|
||||
@@ -55,6 +57,7 @@ pub use requests::{
|
||||
OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest, UploadSigningKeysRequest,
|
||||
};
|
||||
pub use store::{CrossSigningKeyExport, CryptoStoreError, SecretImportError};
|
||||
pub use verification::{
|
||||
AcceptSettings, CancelInfo, QrVerification, Sas, Verification, VerificationRequest,
|
||||
};
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
pub use verification::QrVerification;
|
||||
pub use verification::{AcceptSettings, CancelInfo, Sas, Verification, VerificationRequest};
|
||||
|
||||
@@ -309,7 +309,6 @@ impl Store {
|
||||
|
||||
Ok(UserDevices {
|
||||
inner: devices,
|
||||
private_identity: self.identity.clone(),
|
||||
verification_machine: self.verification_machine.clone(),
|
||||
own_identity,
|
||||
device_owner_identity,
|
||||
|
||||
@@ -164,7 +164,6 @@ pub struct SledStore {
|
||||
identities: Tree,
|
||||
|
||||
tracked_users: Tree,
|
||||
users_for_key_query: Tree,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SledStore {
|
||||
@@ -246,7 +245,6 @@ impl SledStore {
|
||||
let outbound_group_sessions = db.open_tree("outbound_group_sessions")?;
|
||||
|
||||
let tracked_users = db.open_tree("tracked_users")?;
|
||||
let users_for_key_query = db.open_tree("users_for_key_query")?;
|
||||
let olm_hashes = db.open_tree("olm_hashes")?;
|
||||
|
||||
let devices = db.open_tree("devices")?;
|
||||
@@ -283,7 +281,6 @@ impl SledStore {
|
||||
secret_requests_by_info,
|
||||
devices,
|
||||
tracked_users,
|
||||
users_for_key_query,
|
||||
olm_hashes,
|
||||
identities,
|
||||
})
|
||||
|
||||
@@ -20,10 +20,9 @@ use ruma::{DeviceId, UserId};
|
||||
use tracing::trace;
|
||||
|
||||
use super::{event_enums::OutgoingContent, Sas, Verification};
|
||||
use crate::{
|
||||
OutgoingRequest, OutgoingVerificationRequest, QrVerification, RoomMessageRequest,
|
||||
ToDeviceRequest,
|
||||
};
|
||||
#[cfg(feature = "qrcode")]
|
||||
use crate::QrVerification;
|
||||
use crate::{OutgoingRequest, OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VerificationCache {
|
||||
@@ -55,10 +54,14 @@ impl VerificationCache {
|
||||
self.insert(sas);
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
pub fn insert_qr(&self, qr: QrVerification) {
|
||||
self.insert(qr)
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
pub fn get_qr(&self, sender: &UserId, flow_id: &str) -> Option<QrVerification> {
|
||||
self.get(sender, flow_id).and_then(|v| {
|
||||
if let Verification::QrV1(qr) = v {
|
||||
@@ -91,6 +94,7 @@ impl VerificationCache {
|
||||
.value()
|
||||
.iter()
|
||||
.filter_map(|s| {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Verification::SasV1(s) = s.value() {
|
||||
s.cancel_if_timed_out()
|
||||
} else {
|
||||
@@ -106,6 +110,7 @@ impl VerificationCache {
|
||||
|
||||
pub fn get_sas(&self, user_id: &UserId, flow_id: &str) -> Option<Sas> {
|
||||
self.get(user_id, flow_id).and_then(|v| {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Verification::SasV1(sas) = v {
|
||||
Some(sas)
|
||||
} else {
|
||||
|
||||
@@ -387,6 +387,7 @@ impl VerificationMachine {
|
||||
// This won't produce an outgoing content
|
||||
let _ = sas.receive_any_event(event.sender(), &content);
|
||||
}
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(qr) => qr.receive_cancel(event.sender(), c),
|
||||
}
|
||||
}
|
||||
@@ -477,6 +478,7 @@ impl VerificationMachine {
|
||||
verification.receive_done(event.sender(), c);
|
||||
}
|
||||
|
||||
#[allow(clippy::single_match)]
|
||||
match self.get_verification(event.sender(), flow_id.as_str()) {
|
||||
Some(Verification::SasV1(sas)) => {
|
||||
let content = sas.receive_any_event(event.sender(), &content);
|
||||
@@ -485,6 +487,7 @@ impl VerificationMachine {
|
||||
self.mark_sas_as_done(sas, content).await?;
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "qrcode")]
|
||||
Some(Verification::QrV1(qr)) => {
|
||||
let (cancellation, request) = qr.receive_done(c).await?;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
mod cache;
|
||||
mod event_enums;
|
||||
mod machine;
|
||||
#[cfg(feature = "qrcode")]
|
||||
mod qrcode;
|
||||
mod requests;
|
||||
mod sas;
|
||||
@@ -27,6 +28,8 @@ use std::{
|
||||
use event_enums::OutgoingContent;
|
||||
pub use machine::VerificationMachine;
|
||||
use matrix_sdk_common::locks::Mutex;
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
pub use qrcode::QrVerification;
|
||||
pub use requests::VerificationRequest;
|
||||
use ruma::{
|
||||
@@ -115,6 +118,8 @@ impl VerificationStore {
|
||||
pub enum Verification {
|
||||
/// The `m.sas.v1` verification variant.
|
||||
SasV1(Sas),
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
/// The `m.qr_code.*.v1` verification variant.
|
||||
QrV1(QrVerification),
|
||||
}
|
||||
@@ -122,6 +127,7 @@ pub enum Verification {
|
||||
impl Verification {
|
||||
/// Try to deconstruct this verification enum into a SAS verification.
|
||||
pub fn sas_v1(self) -> Option<Sas> {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Verification::SasV1(sas) = self {
|
||||
Some(sas)
|
||||
} else {
|
||||
@@ -129,6 +135,8 @@ impl Verification {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
/// Try to deconstruct this verification enum into a QR code verification.
|
||||
pub fn qr_v1(self) -> Option<QrVerification> {
|
||||
if let Verification::QrV1(qr) = self {
|
||||
@@ -142,6 +150,7 @@ impl Verification {
|
||||
pub fn is_done(&self) -> bool {
|
||||
match self {
|
||||
Verification::SasV1(s) => s.is_done(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(qr) => qr.is_done(),
|
||||
}
|
||||
}
|
||||
@@ -150,6 +159,7 @@ impl Verification {
|
||||
pub fn flow_id(&self) -> &str {
|
||||
match self {
|
||||
Verification::SasV1(s) => s.flow_id().as_str(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(qr) => qr.flow_id().as_str(),
|
||||
}
|
||||
}
|
||||
@@ -158,6 +168,7 @@ impl Verification {
|
||||
pub fn is_cancelled(&self) -> bool {
|
||||
match self {
|
||||
Verification::SasV1(s) => s.is_cancelled(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(qr) => qr.is_cancelled(),
|
||||
}
|
||||
}
|
||||
@@ -166,6 +177,7 @@ impl Verification {
|
||||
pub fn user_id(&self) -> &UserId {
|
||||
match self {
|
||||
Verification::SasV1(v) => v.user_id(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(v) => v.user_id(),
|
||||
}
|
||||
}
|
||||
@@ -174,6 +186,7 @@ impl Verification {
|
||||
pub fn other_user(&self) -> &UserId {
|
||||
match self {
|
||||
Verification::SasV1(s) => s.other_user_id(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(qr) => qr.other_user_id(),
|
||||
}
|
||||
}
|
||||
@@ -182,6 +195,7 @@ impl Verification {
|
||||
pub fn is_self_verification(&self) -> bool {
|
||||
match self {
|
||||
Verification::SasV1(v) => v.is_self_verification(),
|
||||
#[cfg(feature = "qrcode")]
|
||||
Verification::QrV1(v) => v.is_self_verification(),
|
||||
}
|
||||
}
|
||||
@@ -193,6 +207,8 @@ impl From<Sas> for Verification {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
impl From<QrVerification> for Verification {
|
||||
fn from(qr: QrVerification) -> Self {
|
||||
Self::QrV1(qr)
|
||||
@@ -376,6 +392,7 @@ pub struct IdentitiesBeingVerified {
|
||||
}
|
||||
|
||||
impl IdentitiesBeingVerified {
|
||||
#[cfg(feature = "qrcode")]
|
||||
async fn can_sign_devices(&self) -> bool {
|
||||
self.private_identity.can_sign_devices().await
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ pub enum ScanError {
|
||||
#[derive(Clone)]
|
||||
pub struct QrVerification {
|
||||
flow_id: FlowId,
|
||||
store: VerificationStore,
|
||||
inner: Arc<QrVerificationData>,
|
||||
state: Arc<Mutex<InnerState>>,
|
||||
identities: IdentitiesBeingVerified,
|
||||
@@ -429,7 +428,6 @@ impl QrVerification {
|
||||
}
|
||||
|
||||
pub(crate) fn new_self(
|
||||
store: VerificationStore,
|
||||
flow_id: FlowId,
|
||||
own_master_key: String,
|
||||
other_device_key: String,
|
||||
@@ -447,7 +445,7 @@ impl QrVerification {
|
||||
)
|
||||
.into();
|
||||
|
||||
Self::new_helper(store, flow_id, inner, identities, we_started, request_handle)
|
||||
Self::new_helper(flow_id, inner, identities, we_started, request_handle)
|
||||
}
|
||||
|
||||
pub(crate) fn new_self_no_master(
|
||||
@@ -468,11 +466,10 @@ impl QrVerification {
|
||||
)
|
||||
.into();
|
||||
|
||||
Self::new_helper(store, flow_id, inner, identities, we_started, request_handle)
|
||||
Self::new_helper(flow_id, inner, identities, we_started, request_handle)
|
||||
}
|
||||
|
||||
pub(crate) fn new_cross(
|
||||
store: VerificationStore,
|
||||
flow_id: FlowId,
|
||||
own_master_key: String,
|
||||
other_master_key: String,
|
||||
@@ -491,7 +488,7 @@ impl QrVerification {
|
||||
let inner: QrVerificationData =
|
||||
VerificationData::new(event_id, own_master_key, other_master_key, secret).into();
|
||||
|
||||
Self::new_helper(store, flow_id, inner, identities, we_started, request_handle)
|
||||
Self::new_helper(flow_id, inner, identities, we_started, request_handle)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -585,7 +582,6 @@ impl QrVerification {
|
||||
let own_device_id = store.account.device_id().to_owned();
|
||||
|
||||
Ok(Self {
|
||||
store,
|
||||
flow_id,
|
||||
inner: qr_code.into(),
|
||||
state: Mutex::new(InnerState::Reciprocated(QrState {
|
||||
@@ -599,7 +595,6 @@ impl QrVerification {
|
||||
}
|
||||
|
||||
fn new_helper(
|
||||
store: VerificationStore,
|
||||
flow_id: FlowId,
|
||||
inner: QrVerificationData,
|
||||
identities: IdentitiesBeingVerified,
|
||||
@@ -609,7 +604,6 @@ impl QrVerification {
|
||||
let secret = inner.secret().to_owned();
|
||||
|
||||
Self {
|
||||
store,
|
||||
flow_id,
|
||||
inner: inner.into(),
|
||||
state: Mutex::new(InnerState::Created(QrState { state: Created { secret } })).into(),
|
||||
@@ -851,7 +845,6 @@ mod test {
|
||||
assert_eq!(verification.inner.second_key(), &master_key);
|
||||
|
||||
let verification = QrVerification::new_self(
|
||||
store.clone(),
|
||||
flow_id,
|
||||
master_key.clone(),
|
||||
device_key.clone(),
|
||||
@@ -870,7 +863,6 @@ mod test {
|
||||
let flow_id = FlowId::InRoom(room_id!("!test:example"), event_id!("$EVENTID"));
|
||||
|
||||
let verification = QrVerification::new_cross(
|
||||
store.clone(),
|
||||
flow_id,
|
||||
master_key.clone(),
|
||||
bob_master_key.clone(),
|
||||
@@ -972,6 +964,7 @@ mod test {
|
||||
assert!(bob_verification.is_done());
|
||||
|
||||
let identity = alice_verification
|
||||
.identities
|
||||
.store
|
||||
.get_user_identity(alice_account.user_id())
|
||||
.await
|
||||
|
||||
@@ -17,8 +17,11 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
use matrix_qrcode::QrVerificationData;
|
||||
use matrix_sdk_common::{instant::Instant, uuid::Uuid};
|
||||
#[cfg(feature = "qrcode")]
|
||||
use ruma::DeviceKeyAlgorithm;
|
||||
use ruma::{
|
||||
events::{
|
||||
key::verification::{
|
||||
@@ -32,7 +35,7 @@ use ruma::{
|
||||
AnyMessageEventContent, AnyToDeviceEventContent,
|
||||
},
|
||||
to_device::DeviceIdOrAllDevices,
|
||||
DeviceId, DeviceIdBox, DeviceKeyAlgorithm, MilliSecondsSinceUnixEpoch, RoomId, UserId,
|
||||
DeviceId, DeviceIdBox, MilliSecondsSinceUnixEpoch, RoomId, UserId,
|
||||
};
|
||||
use tracing::{info, trace, warn};
|
||||
|
||||
@@ -41,8 +44,12 @@ use super::{
|
||||
event_enums::{
|
||||
CancelContent, DoneContent, OutgoingContent, ReadyContent, RequestContent, StartContent,
|
||||
},
|
||||
CancelInfo, Cancelled, FlowId, VerificationStore,
|
||||
};
|
||||
#[cfg(feature = "qrcode")]
|
||||
use super::{
|
||||
qrcode::{QrVerification, ScanError},
|
||||
CancelInfo, Cancelled, FlowId, IdentitiesBeingVerified, VerificationStore,
|
||||
IdentitiesBeingVerified,
|
||||
};
|
||||
use crate::{
|
||||
olm::{PrivateCrossSigningIdentity, ReadOnlyAccount},
|
||||
@@ -52,6 +59,7 @@ use crate::{
|
||||
|
||||
const SUPPORTED_METHODS: &[VerificationMethod] = &[
|
||||
VerificationMethod::SasV1,
|
||||
#[cfg(feature = "qrcode")]
|
||||
VerificationMethod::QrCodeShowV1,
|
||||
VerificationMethod::ReciprocateV1,
|
||||
];
|
||||
@@ -299,6 +307,8 @@ impl VerificationRequest {
|
||||
matches!(&*self.inner.lock().unwrap(), InnerRequest::Cancelled(_))
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
/// Generate a QR code that can be used by another client to start a QR code
|
||||
/// based verification.
|
||||
pub async fn generate_qr_code(&self) -> Result<Option<QrVerification>, CryptoStoreError> {
|
||||
@@ -308,7 +318,9 @@ impl VerificationRequest {
|
||||
.generate_qr_code(self.we_started, self.inner.clone().into())
|
||||
.await
|
||||
}
|
||||
|
||||
///
|
||||
#[cfg(feature = "qrcode")]
|
||||
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
|
||||
/// Start a QR code verification by providing a scanned QR code for this
|
||||
/// verification flow.
|
||||
///
|
||||
@@ -399,8 +411,11 @@ impl VerificationRequest {
|
||||
/// This method will accept the request and signal that it supports the
|
||||
/// `m.sas.v1`, the `m.qr_code.show.v1`, and `m.reciprocate.v1` method.
|
||||
///
|
||||
/// If QR code scanning should be supported or QR code showing shouldn't be
|
||||
/// supported the [`accept_with_methods()`] method should be used instead.
|
||||
/// `m.qr_code.show.v1` will only be signaled if the `qrcode` feature is
|
||||
/// enabled. This feature is disabled by default. If it's enabeled and QR
|
||||
/// code scanning should be supported or QR code showing shouldn't be
|
||||
/// supported the [`accept_with_methods()`] method should be used
|
||||
/// instead.
|
||||
///
|
||||
/// [`accept_with_methods()`]: #method.accept_with_methods
|
||||
pub fn accept(&self) -> Option<OutgoingVerificationRequest> {
|
||||
@@ -452,6 +467,7 @@ impl VerificationRequest {
|
||||
{
|
||||
match verification {
|
||||
crate::Verification::SasV1(s) => s.cancel_with_code(cancel_code),
|
||||
#[cfg(feature = "qrcode")]
|
||||
crate::Verification::QrV1(q) => q.cancel_with_code(cancel_code),
|
||||
};
|
||||
}
|
||||
@@ -720,6 +736,7 @@ impl InnerRequest {
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
async fn generate_qr_code(
|
||||
&self,
|
||||
we_started: bool,
|
||||
@@ -938,6 +955,7 @@ impl RequestState<Ready> {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "qrcode")]
|
||||
async fn generate_qr_code(
|
||||
&self,
|
||||
we_started: bool,
|
||||
@@ -981,7 +999,6 @@ impl RequestState<Ready> {
|
||||
identites.other_device().get_key(DeviceKeyAlgorithm::Ed25519)
|
||||
{
|
||||
Some(QrVerification::new_self(
|
||||
self.store.clone(),
|
||||
self.flow_id.as_ref().to_owned(),
|
||||
master_key.to_owned(),
|
||||
device_key.to_owned(),
|
||||
@@ -1030,7 +1047,6 @@ impl RequestState<Ready> {
|
||||
.and_then(|m| m.get_first_key().map(|m| m.to_owned()))
|
||||
{
|
||||
Some(QrVerification::new_cross(
|
||||
self.store.clone(),
|
||||
self.flow_id.as_ref().to_owned(),
|
||||
own_master,
|
||||
other_master.to_owned(),
|
||||
@@ -1141,6 +1157,7 @@ impl RequestState<Ready> {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "qrcode")]
|
||||
StartMethod::ReciprocateV1(_) => {
|
||||
if let Some(qr_verification) =
|
||||
self.verification_cache.get_qr(sender, content.flow_id())
|
||||
@@ -1232,6 +1249,7 @@ impl RequestState<Ready> {
|
||||
#[derive(Clone, Debug)]
|
||||
struct Passive {
|
||||
/// The device id of the device that responded to the verification request.
|
||||
#[allow(dead_code)]
|
||||
pub other_device_id: DeviceIdBox,
|
||||
}
|
||||
|
||||
|
||||
@@ -665,7 +665,7 @@ impl SasState<WeAccepted> {
|
||||
last_event_time: Instant::now().into(),
|
||||
started_from_request: self.started_from_request,
|
||||
state: Arc::new(KeyReceived {
|
||||
we_started: false,
|
||||
we_started: self.state.we_started,
|
||||
their_pubkey,
|
||||
accepted_protocols: self.state.accepted_protocols.clone(),
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user