use std::{collections::BTreeMap, ops::Deref};
use matrix_sdk_base::crypto::{
Device as BaseDevice, DeviceData, LocalTrust, UserDevices as BaseUserDevices,
store::CryptoStoreError,
};
use ruma::{DeviceId, OwnedDeviceId, OwnedUserId, events::key::verification::VerificationMethod};
use super::ManualVerifyError;
use crate::{
Client,
encryption::verification::{SasVerification, VerificationRequest},
error::Result,
};
#[derive(Clone, Debug, Default)]
pub struct DeviceUpdates {
pub new: BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceId, Device>>,
pub changed: BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceId, Device>>,
}
impl DeviceUpdates {
pub(crate) fn new(
client: Client,
updates: matrix_sdk_base::crypto::store::types::DeviceUpdates,
) -> Self {
let map_devices = |(user_id, devices)| {
let devices: BTreeMap<_, _> = devices;
(
user_id,
devices
.into_iter()
.map(|(device_id, device)| {
(device_id, Device { inner: device, client: client.to_owned() })
})
.collect(),
)
};
let new = updates.new.into_iter().map(map_devices).collect();
let changed = updates.changed.into_iter().map(map_devices).collect();
DeviceUpdates { new, changed }
}
}
#[derive(Clone, Debug)]
pub struct Device {
pub(crate) inner: BaseDevice,
pub(crate) client: Client,
}
impl Deref for Device {
type Target = DeviceData;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl Device {
pub async fn request_verification(&self) -> Result<VerificationRequest> {
let (verification, request) = self.inner.request_verification();
self.client.send_verification_request(request).await?;
Ok(VerificationRequest { inner: verification, client: self.client.clone() })
}
pub async fn request_verification_with_methods(
&self,
methods: Vec<VerificationMethod>,
) -> Result<VerificationRequest> {
assert!(!methods.is_empty(), "The list of verification methods can't be non-empty");
let (verification, request) = self.inner.request_verification_with_methods(methods);
self.client.send_verification_request(request).await?;
Ok(VerificationRequest { inner: verification, client: self.client.clone() })
}
#[deprecated(
since = "0.4.0",
note = "directly starting a verification is deprecated in the spec. \
Users should instead use request_verification()"
)]
pub async fn start_verification(&self) -> Result<SasVerification> {
let (sas, request) = self.inner.start_verification().await?;
self.client.send_to_device(&request).await?;
Ok(SasVerification { inner: Box::new(sas), client: self.client.clone() })
}
pub async fn verify(&self) -> Result<(), ManualVerifyError> {
let request = self.inner.verify().await?;
self.client.send(request).await?;
Ok(())
}
pub fn is_verified(&self) -> bool {
self.inner.is_verified()
}
pub fn is_verified_with_cross_signing(&self) -> bool {
self.inner.is_cross_signing_trusted()
}
pub async fn set_local_trust(&self, trust_state: LocalTrust) -> Result<(), CryptoStoreError> {
self.inner.set_local_trust(trust_state).await
}
pub fn is_cross_signed_by_owner(&self) -> bool {
self.inner.is_cross_signed_by_owner()
}
}
#[derive(Debug)]
pub struct UserDevices {
pub(crate) inner: BaseUserDevices,
pub(crate) client: Client,
}
impl UserDevices {
pub fn get(&self, device_id: &DeviceId) -> Option<Device> {
self.inner.get(device_id).map(|d| Device { inner: d, client: self.client.clone() })
}
pub fn keys(&self) -> impl Iterator<Item = &DeviceId> {
self.inner.keys()
}
pub fn devices(&self) -> impl Iterator<Item = Device> + '_ {
let client = self.client.clone();
self.inner.devices().map(move |d| Device { inner: d, client: client.clone() })
}
}