Merge branch 'feature/qrcode-feature'

master
Damir Jelić 2021-09-10 19:20:08 +02:00
commit 4bcbcb146e
14 changed files with 98 additions and 20 deletions

View File

@ -15,9 +15,10 @@ features = ["docs"]
rustdoc-args = ["--cfg", "feature=\"docs\""] rustdoc-args = ["--cfg", "feature=\"docs\""]
[features] [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"] encryption = ["matrix-sdk-base/encryption"]
qrcode = ["encryption", "matrix-sdk-base/qrcode"]
sled_state_store = ["matrix-sdk-base/sled_state_store"] sled_state_store = ["matrix-sdk-base/sled_state_store"]
sled_cryptostore = ["matrix-sdk-base/sled_cryptostore"] sled_cryptostore = ["matrix-sdk-base/sled_cryptostore"]
markdown = ["ruma/markdown"] markdown = ["ruma/markdown"]

View File

@ -45,6 +45,8 @@ More examples can be found in the [examples] directory.
The following crate feature flags are available: The following crate feature flags are available:
* `encryption`: Enables end-to-end encryption support in the library. * `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 * `sled_cryptostore`: Enables a Sled based store for the encryption keys. If
this is disabled and `encryption` support is enabled the keys will by 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 default be stored only in memory and thus lost after the client is

View File

@ -138,11 +138,13 @@ use ruma::{
DeviceIdBox, RoomId, RoomIdOrAliasId, ServerName, UInt, UserId, DeviceIdBox, RoomId, RoomIdOrAliasId, ServerName, UInt, UserId,
}; };
#[cfg(all(feature = "qrcode", feature = "encryption"))]
use crate::verification::QrVerification;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
use crate::{ use crate::{
error::RoomKeyImportError, error::RoomKeyImportError,
identities::{Device, UserDevices}, identities::{Device, UserDevices},
verification::{QrVerification, SasVerification, Verification, VerificationRequest}, verification::{SasVerification, Verification, VerificationRequest},
}; };
use crate::{ use crate::{
error::{HttpError, HttpResult}, error::{HttpError, HttpResult},
@ -2561,6 +2563,7 @@ impl Client {
matrix_sdk_base::crypto::Verification::SasV1(s) => { matrix_sdk_base::crypto::Verification::SasV1(s) => {
SasVerification { inner: s, client: self.clone() }.into() SasVerification { inner: s, client: self.clone() }.into()
} }
#[cfg(feature = "qrcode")]
matrix_sdk_base::crypto::Verification::QrV1(qr) => { matrix_sdk_base::crypto::Verification::QrV1(qr) => {
QrVerification { inner: qr, client: self.clone() }.into() QrVerification { inner: qr, client: self.clone() }.into()
} }

View File

@ -55,7 +55,8 @@ impl Device {
/// The default methods that are supported are `m.sas.v1` and /// The default methods that are supported are `m.sas.v1` and
/// `m.qr_code.show.v1`, if this isn't desirable the /// `m.qr_code.show.v1`, if this isn't desirable the
/// [`request_verification_with_methods()`] method can be used to override /// [`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 /// # Examples
/// ///

View File

@ -82,7 +82,8 @@ impl UserIdentity {
/// The default methods that are supported are `m.sas.v1` and /// The default methods that are supported are `m.sas.v1` and
/// `m.qr_code.show.v1`, if this isn't desirable the /// `m.qr_code.show.v1`, if this isn't desirable the
/// [`request_verification_with_methods()`] method can be used to override /// [`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 /// # Examples
/// ///

View File

@ -30,11 +30,14 @@
//! string. //! string.
//! * [`QrVerification`] - Interactive verification using QR codes. //! * [`QrVerification`] - Interactive verification using QR codes.
#[cfg(feature = "qrcode")]
mod qrcode; mod qrcode;
mod requests; mod requests;
mod sas; mod sas;
pub use matrix_sdk_base::crypto::{AcceptSettings, CancelInfo}; pub use matrix_sdk_base::crypto::{AcceptSettings, CancelInfo};
#[cfg(feature = "qrcode")]
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
pub use qrcode::QrVerification; pub use qrcode::QrVerification;
pub use requests::VerificationRequest; pub use requests::VerificationRequest;
pub use sas::SasVerification; pub use sas::SasVerification;
@ -44,6 +47,8 @@ pub use sas::SasVerification;
pub enum Verification { pub enum Verification {
/// The `m.sas.v1` verification variant. /// The `m.sas.v1` verification variant.
SasV1(SasVerification), SasV1(SasVerification),
#[cfg(feature = "qrcode")]
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
/// The `m.qr_code.*.v1` verification variant. /// The `m.qr_code.*.v1` verification variant.
QrV1(QrVerification), QrV1(QrVerification),
} }
@ -51,6 +56,7 @@ pub enum Verification {
impl Verification { impl Verification {
/// Try to deconstruct this verification enum into a SAS verification. /// Try to deconstruct this verification enum into a SAS verification.
pub fn sas(self) -> Option<SasVerification> { pub fn sas(self) -> Option<SasVerification> {
#[allow(irrefutable_let_patterns)]
if let Verification::SasV1(sas) = self { if let Verification::SasV1(sas) = self {
Some(sas) Some(sas)
} else { } else {
@ -58,6 +64,7 @@ impl Verification {
} }
} }
#[cfg(feature = "qrcode")]
/// Try to deconstruct this verification enum into a QR code verification. /// Try to deconstruct this verification enum into a QR code verification.
pub fn qr(self) -> Option<QrVerification> { pub fn qr(self) -> Option<QrVerification> {
if let Verification::QrV1(qr) = self { if let Verification::QrV1(qr) = self {
@ -71,6 +78,7 @@ impl Verification {
pub fn is_done(&self) -> bool { pub fn is_done(&self) -> bool {
match self { match self {
Verification::SasV1(s) => s.is_done(), Verification::SasV1(s) => s.is_done(),
#[cfg(feature = "qrcode")]
Verification::QrV1(qr) => qr.is_done(), Verification::QrV1(qr) => qr.is_done(),
} }
} }
@ -79,6 +87,7 @@ impl Verification {
pub fn is_cancelled(&self) -> bool { pub fn is_cancelled(&self) -> bool {
match self { match self {
Verification::SasV1(s) => s.is_cancelled(), Verification::SasV1(s) => s.is_cancelled(),
#[cfg(feature = "qrcode")]
Verification::QrV1(qr) => qr.is_cancelled(), Verification::QrV1(qr) => qr.is_cancelled(),
} }
} }
@ -88,6 +97,7 @@ impl Verification {
pub fn cancel_info(&self) -> Option<CancelInfo> { pub fn cancel_info(&self) -> Option<CancelInfo> {
match self { match self {
Verification::SasV1(s) => s.cancel_info(), Verification::SasV1(s) => s.cancel_info(),
#[cfg(feature = "qrcode")]
Verification::QrV1(q) => q.cancel_info(), Verification::QrV1(q) => q.cancel_info(),
} }
} }
@ -96,6 +106,7 @@ impl Verification {
pub fn own_user_id(&self) -> &ruma::UserId { pub fn own_user_id(&self) -> &ruma::UserId {
match self { match self {
Verification::SasV1(v) => v.own_user_id(), Verification::SasV1(v) => v.own_user_id(),
#[cfg(feature = "qrcode")]
Verification::QrV1(v) => v.own_user_id(), Verification::QrV1(v) => v.own_user_id(),
} }
} }
@ -105,6 +116,7 @@ impl Verification {
pub fn other_user_id(&self) -> &ruma::UserId { pub fn other_user_id(&self) -> &ruma::UserId {
match self { match self {
Verification::SasV1(v) => v.inner.other_user_id(), Verification::SasV1(v) => v.inner.other_user_id(),
#[cfg(feature = "qrcode")]
Verification::QrV1(v) => v.inner.other_user_id(), Verification::QrV1(v) => v.inner.other_user_id(),
} }
} }
@ -113,6 +125,7 @@ impl Verification {
pub fn is_self_verification(&self) -> bool { pub fn is_self_verification(&self) -> bool {
match self { match self {
Verification::SasV1(v) => v.is_self_verification(), Verification::SasV1(v) => v.is_self_verification(),
#[cfg(feature = "qrcode")]
Verification::QrV1(v) => v.is_self_verification(), Verification::QrV1(v) => v.is_self_verification(),
} }
} }
@ -121,6 +134,7 @@ impl Verification {
pub fn we_started(&self) -> bool { pub fn we_started(&self) -> bool {
match self { match self {
Verification::SasV1(s) => s.we_started(), Verification::SasV1(s) => s.we_started(),
#[cfg(feature = "qrcode")]
Verification::QrV1(q) => q.we_started(), Verification::QrV1(q) => q.we_started(),
} }
} }
@ -132,6 +146,7 @@ impl From<SasVerification> for Verification {
} }
} }
#[cfg(feature = "qrcode")]
impl From<QrVerification> for Verification { impl From<QrVerification> for Verification {
fn from(qr: QrVerification) -> Self { fn from(qr: QrVerification) -> Self {
Self::QrV1(qr) Self::QrV1(qr)

View File

@ -15,7 +15,9 @@
use matrix_sdk_base::crypto::{CancelInfo, VerificationRequest as BaseVerificationRequest}; use matrix_sdk_base::crypto::{CancelInfo, VerificationRequest as BaseVerificationRequest};
use ruma::events::key::verification::VerificationMethod; use ruma::events::key::verification::VerificationMethod;
use super::{QrVerification, SasVerification}; #[cfg(feature = "qrcode")]
use super::QrVerification;
use super::SasVerification;
use crate::{Client, Result}; use crate::{Client, Result};
/// An object controlling the interactive verification flow. /// An object controlling the interactive verification flow.
@ -83,8 +85,10 @@ impl VerificationRequest {
/// Accept the verification request. /// Accept the verification request.
/// ///
/// This method will accept the request and signal that it supports the /// This method will accept the request and signal by default that it
/// `m.sas.v1`, the `m.qr_code.show.v1`, and `m.reciprocate.v1` method. /// 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 /// If QR code scanning should be supported or QR code showing shouldn't be
/// supported the [`accept_with_methods()`] method should be used instead. /// supported the [`accept_with_methods()`] method should be used instead.
@ -113,6 +117,8 @@ impl VerificationRequest {
} }
/// Generate a QR code /// Generate a QR code
#[cfg(feature = "qrcode")]
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
pub async fn generate_qr_code(&self) -> Result<Option<QrVerification>> { pub async fn generate_qr_code(&self) -> Result<Option<QrVerification>> {
Ok(self Ok(self
.inner .inner

View File

@ -17,6 +17,7 @@ rustdoc-args = ["--cfg", "feature=\"docs\""]
[features] [features]
default = [] default = []
encryption = ["matrix-sdk-crypto"] encryption = ["matrix-sdk-crypto"]
qrcode = ["matrix-sdk-crypto/qrcode"]
sled_state_store = ["sled", "pbkdf2", "hmac", "sha2", "rand", "chacha20poly1305"] sled_state_store = ["sled", "pbkdf2", "hmac", "sha2", "rand", "chacha20poly1305"]
sled_cryptostore = ["matrix-sdk-crypto/sled_cryptostore"] sled_cryptostore = ["matrix-sdk-crypto/sled_cryptostore"]

View File

@ -16,11 +16,12 @@ rustdoc-args = ["--cfg", "feature=\"docs\""]
[features] [features]
default = [] default = []
qrcode = ["matrix-qrcode"]
sled_cryptostore = ["sled"] sled_cryptostore = ["sled"]
docs = ["sled_cryptostore"] docs = ["sled_cryptostore"]
[dependencies] [dependencies]
matrix-qrcode = { version = "0.1.0", path = "../matrix_qrcode" } matrix-qrcode = { version = "0.1.0", path = "../matrix_qrcode" , optional = true}
matrix-sdk-common = { version = "0.4.0", path = "../matrix_sdk_common" } matrix-sdk-common = { version = "0.4.0", path = "../matrix_sdk_common" }
ruma = { version = "0.4.0", features = ["client-api-c", "unstable-pre-spec"] } ruma = { version = "0.4.0", features = ["client-api-c", "unstable-pre-spec"] }

View File

@ -47,6 +47,8 @@ pub use identities::{
ReadOnlyUserIdentities, ReadOnlyUserIdentity, UserDevices, UserIdentities, UserIdentity, ReadOnlyUserIdentities, ReadOnlyUserIdentity, UserDevices, UserIdentities, UserIdentity,
}; };
pub use machine::OlmMachine; pub use machine::OlmMachine;
#[cfg(feature = "qrcode")]
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
pub use matrix_qrcode; pub use matrix_qrcode;
pub(crate) use olm::ReadOnlyAccount; pub(crate) use olm::ReadOnlyAccount;
pub use olm::{CrossSigningStatus, EncryptionSettings}; pub use olm::{CrossSigningStatus, EncryptionSettings};
@ -55,6 +57,7 @@ pub use requests::{
OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest, UploadSigningKeysRequest, OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest, UploadSigningKeysRequest,
}; };
pub use store::{CrossSigningKeyExport, CryptoStoreError, SecretImportError}; pub use store::{CrossSigningKeyExport, CryptoStoreError, SecretImportError};
pub use verification::{ #[cfg(feature = "qrcode")]
AcceptSettings, CancelInfo, QrVerification, Sas, Verification, VerificationRequest, #[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
}; pub use verification::QrVerification;
pub use verification::{AcceptSettings, CancelInfo, Sas, Verification, VerificationRequest};

View File

@ -20,10 +20,9 @@ use ruma::{DeviceId, UserId};
use tracing::trace; use tracing::trace;
use super::{event_enums::OutgoingContent, Sas, Verification}; use super::{event_enums::OutgoingContent, Sas, Verification};
use crate::{ #[cfg(feature = "qrcode")]
OutgoingRequest, OutgoingVerificationRequest, QrVerification, RoomMessageRequest, use crate::QrVerification;
ToDeviceRequest, use crate::{OutgoingRequest, OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest};
};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct VerificationCache { pub struct VerificationCache {
@ -55,10 +54,14 @@ impl VerificationCache {
self.insert(sas); self.insert(sas);
} }
#[cfg(feature = "qrcode")]
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
pub fn insert_qr(&self, qr: QrVerification) { pub fn insert_qr(&self, qr: QrVerification) {
self.insert(qr) 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> { pub fn get_qr(&self, sender: &UserId, flow_id: &str) -> Option<QrVerification> {
self.get(sender, flow_id).and_then(|v| { self.get(sender, flow_id).and_then(|v| {
if let Verification::QrV1(qr) = v { if let Verification::QrV1(qr) = v {
@ -91,6 +94,7 @@ impl VerificationCache {
.value() .value()
.iter() .iter()
.filter_map(|s| { .filter_map(|s| {
#[allow(irrefutable_let_patterns)]
if let Verification::SasV1(s) = s.value() { if let Verification::SasV1(s) = s.value() {
s.cancel_if_timed_out() s.cancel_if_timed_out()
} else { } else {
@ -106,6 +110,7 @@ impl VerificationCache {
pub fn get_sas(&self, user_id: &UserId, flow_id: &str) -> Option<Sas> { pub fn get_sas(&self, user_id: &UserId, flow_id: &str) -> Option<Sas> {
self.get(user_id, flow_id).and_then(|v| { self.get(user_id, flow_id).and_then(|v| {
#[allow(irrefutable_let_patterns)]
if let Verification::SasV1(sas) = v { if let Verification::SasV1(sas) = v {
Some(sas) Some(sas)
} else { } else {

View File

@ -387,6 +387,7 @@ impl VerificationMachine {
// This won't produce an outgoing content // This won't produce an outgoing content
let _ = sas.receive_any_event(event.sender(), &content); let _ = sas.receive_any_event(event.sender(), &content);
} }
#[cfg(feature = "qrcode")]
Verification::QrV1(qr) => qr.receive_cancel(event.sender(), c), Verification::QrV1(qr) => qr.receive_cancel(event.sender(), c),
} }
} }
@ -477,6 +478,7 @@ impl VerificationMachine {
verification.receive_done(event.sender(), c); verification.receive_done(event.sender(), c);
} }
#[allow(clippy::single_match)]
match self.get_verification(event.sender(), flow_id.as_str()) { match self.get_verification(event.sender(), flow_id.as_str()) {
Some(Verification::SasV1(sas)) => { Some(Verification::SasV1(sas)) => {
let content = sas.receive_any_event(event.sender(), &content); let content = sas.receive_any_event(event.sender(), &content);
@ -485,6 +487,7 @@ impl VerificationMachine {
self.mark_sas_as_done(sas, content).await?; self.mark_sas_as_done(sas, content).await?;
} }
} }
#[cfg(feature = "qrcode")]
Some(Verification::QrV1(qr)) => { Some(Verification::QrV1(qr)) => {
let (cancellation, request) = qr.receive_done(c).await?; let (cancellation, request) = qr.receive_done(c).await?;

View File

@ -15,6 +15,7 @@
mod cache; mod cache;
mod event_enums; mod event_enums;
mod machine; mod machine;
#[cfg(feature = "qrcode")]
mod qrcode; mod qrcode;
mod requests; mod requests;
mod sas; mod sas;
@ -27,6 +28,8 @@ use std::{
use event_enums::OutgoingContent; use event_enums::OutgoingContent;
pub use machine::VerificationMachine; pub use machine::VerificationMachine;
use matrix_sdk_common::locks::Mutex; use matrix_sdk_common::locks::Mutex;
#[cfg(feature = "qrcode")]
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
pub use qrcode::QrVerification; pub use qrcode::QrVerification;
pub use requests::VerificationRequest; pub use requests::VerificationRequest;
use ruma::{ use ruma::{
@ -115,6 +118,8 @@ impl VerificationStore {
pub enum Verification { pub enum Verification {
/// The `m.sas.v1` verification variant. /// The `m.sas.v1` verification variant.
SasV1(Sas), SasV1(Sas),
#[cfg(feature = "qrcode")]
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
/// The `m.qr_code.*.v1` verification variant. /// The `m.qr_code.*.v1` verification variant.
QrV1(QrVerification), QrV1(QrVerification),
} }
@ -122,6 +127,7 @@ pub enum Verification {
impl Verification { impl Verification {
/// Try to deconstruct this verification enum into a SAS verification. /// Try to deconstruct this verification enum into a SAS verification.
pub fn sas_v1(self) -> Option<Sas> { pub fn sas_v1(self) -> Option<Sas> {
#[allow(irrefutable_let_patterns)]
if let Verification::SasV1(sas) = self { if let Verification::SasV1(sas) = self {
Some(sas) Some(sas)
} else { } 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. /// Try to deconstruct this verification enum into a QR code verification.
pub fn qr_v1(self) -> Option<QrVerification> { pub fn qr_v1(self) -> Option<QrVerification> {
if let Verification::QrV1(qr) = self { if let Verification::QrV1(qr) = self {
@ -142,6 +150,7 @@ impl Verification {
pub fn is_done(&self) -> bool { pub fn is_done(&self) -> bool {
match self { match self {
Verification::SasV1(s) => s.is_done(), Verification::SasV1(s) => s.is_done(),
#[cfg(feature = "qrcode")]
Verification::QrV1(qr) => qr.is_done(), Verification::QrV1(qr) => qr.is_done(),
} }
} }
@ -150,6 +159,7 @@ impl Verification {
pub fn flow_id(&self) -> &str { pub fn flow_id(&self) -> &str {
match self { match self {
Verification::SasV1(s) => s.flow_id().as_str(), Verification::SasV1(s) => s.flow_id().as_str(),
#[cfg(feature = "qrcode")]
Verification::QrV1(qr) => qr.flow_id().as_str(), Verification::QrV1(qr) => qr.flow_id().as_str(),
} }
} }
@ -158,6 +168,7 @@ impl Verification {
pub fn is_cancelled(&self) -> bool { pub fn is_cancelled(&self) -> bool {
match self { match self {
Verification::SasV1(s) => s.is_cancelled(), Verification::SasV1(s) => s.is_cancelled(),
#[cfg(feature = "qrcode")]
Verification::QrV1(qr) => qr.is_cancelled(), Verification::QrV1(qr) => qr.is_cancelled(),
} }
} }
@ -166,6 +177,7 @@ impl Verification {
pub fn user_id(&self) -> &UserId { pub fn user_id(&self) -> &UserId {
match self { match self {
Verification::SasV1(v) => v.user_id(), Verification::SasV1(v) => v.user_id(),
#[cfg(feature = "qrcode")]
Verification::QrV1(v) => v.user_id(), Verification::QrV1(v) => v.user_id(),
} }
} }
@ -174,6 +186,7 @@ impl Verification {
pub fn other_user(&self) -> &UserId { pub fn other_user(&self) -> &UserId {
match self { match self {
Verification::SasV1(s) => s.other_user_id(), Verification::SasV1(s) => s.other_user_id(),
#[cfg(feature = "qrcode")]
Verification::QrV1(qr) => qr.other_user_id(), Verification::QrV1(qr) => qr.other_user_id(),
} }
} }
@ -182,6 +195,7 @@ impl Verification {
pub fn is_self_verification(&self) -> bool { pub fn is_self_verification(&self) -> bool {
match self { match self {
Verification::SasV1(v) => v.is_self_verification(), Verification::SasV1(v) => v.is_self_verification(),
#[cfg(feature = "qrcode")]
Verification::QrV1(v) => v.is_self_verification(), 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 { impl From<QrVerification> for Verification {
fn from(qr: QrVerification) -> Self { fn from(qr: QrVerification) -> Self {
Self::QrV1(qr) Self::QrV1(qr)
@ -376,6 +392,7 @@ pub struct IdentitiesBeingVerified {
} }
impl IdentitiesBeingVerified { impl IdentitiesBeingVerified {
#[cfg(feature = "qrcode")]
async fn can_sign_devices(&self) -> bool { async fn can_sign_devices(&self) -> bool {
self.private_identity.can_sign_devices().await self.private_identity.can_sign_devices().await
} }

View File

@ -17,8 +17,11 @@ use std::{
time::Duration, time::Duration,
}; };
#[cfg(feature = "qrcode")]
use matrix_qrcode::QrVerificationData; use matrix_qrcode::QrVerificationData;
use matrix_sdk_common::{instant::Instant, uuid::Uuid}; use matrix_sdk_common::{instant::Instant, uuid::Uuid};
#[cfg(feature = "qrcode")]
use ruma::DeviceKeyAlgorithm;
use ruma::{ use ruma::{
events::{ events::{
key::verification::{ key::verification::{
@ -32,7 +35,7 @@ use ruma::{
AnyMessageEventContent, AnyToDeviceEventContent, AnyMessageEventContent, AnyToDeviceEventContent,
}, },
to_device::DeviceIdOrAllDevices, to_device::DeviceIdOrAllDevices,
DeviceId, DeviceIdBox, DeviceKeyAlgorithm, MilliSecondsSinceUnixEpoch, RoomId, UserId, DeviceId, DeviceIdBox, MilliSecondsSinceUnixEpoch, RoomId, UserId,
}; };
use tracing::{info, trace, warn}; use tracing::{info, trace, warn};
@ -41,8 +44,12 @@ use super::{
event_enums::{ event_enums::{
CancelContent, DoneContent, OutgoingContent, ReadyContent, RequestContent, StartContent, CancelContent, DoneContent, OutgoingContent, ReadyContent, RequestContent, StartContent,
}, },
CancelInfo, Cancelled, FlowId, VerificationStore,
};
#[cfg(feature = "qrcode")]
use super::{
qrcode::{QrVerification, ScanError}, qrcode::{QrVerification, ScanError},
CancelInfo, Cancelled, FlowId, IdentitiesBeingVerified, VerificationStore, IdentitiesBeingVerified,
}; };
use crate::{ use crate::{
olm::{PrivateCrossSigningIdentity, ReadOnlyAccount}, olm::{PrivateCrossSigningIdentity, ReadOnlyAccount},
@ -52,6 +59,7 @@ use crate::{
const SUPPORTED_METHODS: &[VerificationMethod] = &[ const SUPPORTED_METHODS: &[VerificationMethod] = &[
VerificationMethod::SasV1, VerificationMethod::SasV1,
#[cfg(feature = "qrcode")]
VerificationMethod::QrCodeShowV1, VerificationMethod::QrCodeShowV1,
VerificationMethod::ReciprocateV1, VerificationMethod::ReciprocateV1,
]; ];
@ -299,6 +307,8 @@ impl VerificationRequest {
matches!(&*self.inner.lock().unwrap(), InnerRequest::Cancelled(_)) 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 /// Generate a QR code that can be used by another client to start a QR code
/// based verification. /// based verification.
pub async fn generate_qr_code(&self) -> Result<Option<QrVerification>, CryptoStoreError> { 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()) .generate_qr_code(self.we_started, self.inner.clone().into())
.await .await
} }
///
#[cfg(feature = "qrcode")]
#[cfg_attr(feature = "docs", doc(cfg(qrcode)))]
/// Start a QR code verification by providing a scanned QR code for this /// Start a QR code verification by providing a scanned QR code for this
/// verification flow. /// verification flow.
/// ///
@ -399,8 +411,11 @@ impl VerificationRequest {
/// This method will accept the request and signal that it supports the /// 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. /// `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 /// `m.qr_code.show.v1` will only be signaled if the `qrcode` feature is
/// supported the [`accept_with_methods()`] method should be used instead. /// 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 /// [`accept_with_methods()`]: #method.accept_with_methods
pub fn accept(&self) -> Option<OutgoingVerificationRequest> { pub fn accept(&self) -> Option<OutgoingVerificationRequest> {
@ -452,6 +467,7 @@ impl VerificationRequest {
{ {
match verification { match verification {
crate::Verification::SasV1(s) => s.cancel_with_code(cancel_code), crate::Verification::SasV1(s) => s.cancel_with_code(cancel_code),
#[cfg(feature = "qrcode")]
crate::Verification::QrV1(q) => q.cancel_with_code(cancel_code), crate::Verification::QrV1(q) => q.cancel_with_code(cancel_code),
}; };
} }
@ -720,6 +736,7 @@ impl InnerRequest {
}); });
} }
#[cfg(feature = "qrcode")]
async fn generate_qr_code( async fn generate_qr_code(
&self, &self,
we_started: bool, we_started: bool,
@ -938,6 +955,7 @@ impl RequestState<Ready> {
) )
} }
#[cfg(feature = "qrcode")]
async fn generate_qr_code( async fn generate_qr_code(
&self, &self,
we_started: bool, we_started: bool,
@ -1141,6 +1159,7 @@ impl RequestState<Ready> {
} }
} }
} }
#[cfg(feature = "qrcode")]
StartMethod::ReciprocateV1(_) => { StartMethod::ReciprocateV1(_) => {
if let Some(qr_verification) = if let Some(qr_verification) =
self.verification_cache.get_qr(sender, content.flow_id()) self.verification_cache.get_qr(sender, content.flow_id())