crypto: Test our in-memory device store.
parent
616a67c1cb
commit
aeb93e19e2
|
@ -18,9 +18,9 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use atomic::Atomic;
|
use atomic::Atomic;
|
||||||
|
|
||||||
use ruma_client_api::r0::keys::{DeviceKeys, KeyAlgorithm};
|
use crate::api::r0::keys::{DeviceKeys, KeyAlgorithm};
|
||||||
use ruma_events::Algorithm;
|
use crate::events::Algorithm;
|
||||||
use ruma_identifiers::{DeviceId, UserId};
|
use crate::identifiers::{DeviceId, UserId};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
|
@ -82,3 +82,61 @@ impl From<&DeviceKeys> for Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Device {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.user_id() == other.user_id() && self.device_id() == other.device_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) mod test {
|
||||||
|
use serde_json::json;
|
||||||
|
use std::convert::{From, TryFrom};
|
||||||
|
|
||||||
|
use crate::api::r0::keys::DeviceKeys;
|
||||||
|
use crate::crypto::device::Device;
|
||||||
|
use crate::identifiers::UserId;
|
||||||
|
|
||||||
|
pub(crate) fn get_device() -> Device {
|
||||||
|
let user_id = UserId::try_from("@alice:example.org").unwrap();
|
||||||
|
let device_id = "DEVICEID";
|
||||||
|
|
||||||
|
let device_keys = json!({
|
||||||
|
"algorithms": vec![
|
||||||
|
"m.olm.v1.curve25519-aes-sha2",
|
||||||
|
"m.megolm.v1.aes-sha2"
|
||||||
|
],
|
||||||
|
"device_id": device_id,
|
||||||
|
"user_id": user_id.to_string(),
|
||||||
|
"keys": {
|
||||||
|
"curve25519:DEVICEID": "wjLpTLRqbqBzLs63aYaEv2Boi6cFEbbM/sSRQ2oAKk4",
|
||||||
|
"ed25519:DEVICEID": "nE6W2fCblxDcOFmeEtCHNl8/l8bXcu7GKyAswA4r3mM"
|
||||||
|
},
|
||||||
|
"signatures": {
|
||||||
|
user_id.to_string(): {
|
||||||
|
"ed25519:DEVICEID": "m53Wkbh2HXkc3vFApZvCrfXcX3AI51GsDHustMhKwlv3TuOJMj4wistcOTM8q2+e/Ro7rWFUb9ZfnNbwptSUBA"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unsigned": {
|
||||||
|
"device_display_name": "Alice's mobile phone"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let device_keys: DeviceKeys = serde_json::from_value(device_keys).unwrap();
|
||||||
|
|
||||||
|
Device::from(&device_keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_a_device() {
|
||||||
|
let user_id = UserId::try_from("@alice:example.org").unwrap();
|
||||||
|
let device_id = "DEVICEID";
|
||||||
|
|
||||||
|
let device = get_device();
|
||||||
|
|
||||||
|
assert_eq!(&user_id, device.user_id());
|
||||||
|
assert_eq!(device_id, device.device_id());
|
||||||
|
assert_eq!(device.algorithms.len(), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -114,36 +114,45 @@ impl GroupSessionStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In-memory store holding the devices of users.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct DeviceStore {
|
pub struct DeviceStore {
|
||||||
entries: Arc<DashMap<UserId, DashMap<String, Device>>>,
|
entries: Arc<DashMap<UserId, DashMap<String, Device>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A read only view over all devices belonging to a user.
|
||||||
pub struct UserDevices {
|
pub struct UserDevices {
|
||||||
entries: ReadOnlyView<DeviceId, Device>,
|
entries: ReadOnlyView<DeviceId, Device>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserDevices {
|
impl UserDevices {
|
||||||
|
/// Get the specific device with the given device id.
|
||||||
pub fn get(&self, device_id: &str) -> Option<Device> {
|
pub fn get(&self, device_id: &str) -> Option<Device> {
|
||||||
self.entries.get(device_id).cloned()
|
self.entries.get(device_id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterator over all the device ids of the user devices.
|
||||||
pub fn keys(&self) -> impl Iterator<Item = &DeviceId> {
|
pub fn keys(&self) -> impl Iterator<Item = &DeviceId> {
|
||||||
self.entries.keys()
|
self.entries.keys()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterator over all the devices of the user devices.
|
||||||
pub fn devices(&self) -> impl Iterator<Item = &Device> {
|
pub fn devices(&self) -> impl Iterator<Item = &Device> {
|
||||||
self.entries.values()
|
self.entries.values()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceStore {
|
impl DeviceStore {
|
||||||
|
/// Create a new empty device store.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
DeviceStore {
|
DeviceStore {
|
||||||
entries: Arc::new(DashMap::new()),
|
entries: Arc::new(DashMap::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a device to the store.
|
||||||
|
///
|
||||||
|
/// Returns true if the device was already in the store, false otherwise.
|
||||||
pub fn add(&self, device: Device) -> bool {
|
pub fn add(&self, device: Device) -> bool {
|
||||||
let user_id = device.user_id();
|
let user_id = device.user_id();
|
||||||
|
|
||||||
|
@ -157,12 +166,14 @@ impl DeviceStore {
|
||||||
.is_some()
|
.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the device with the given device_id and belonging to the given user.
|
||||||
pub fn get(&self, user_id: &UserId, device_id: &str) -> Option<Device> {
|
pub fn get(&self, user_id: &UserId, device_id: &str) -> Option<Device> {
|
||||||
self.entries
|
self.entries
|
||||||
.get(user_id)
|
.get(user_id)
|
||||||
.and_then(|m| m.get(device_id).map(|d| d.value().clone()))
|
.and_then(|m| m.get(device_id).map(|d| d.value().clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a read-only view over all devices of the given user.
|
||||||
pub fn user_devices(&self, user_id: &UserId) -> UserDevices {
|
pub fn user_devices(&self, user_id: &UserId) -> UserDevices {
|
||||||
if !self.entries.contains_key(user_id) {
|
if !self.entries.contains_key(user_id) {
|
||||||
self.entries.insert(user_id.clone(), DashMap::new());
|
self.entries.insert(user_id.clone(), DashMap::new());
|
||||||
|
@ -179,6 +190,7 @@ mod test {
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use crate::api::r0::keys::SignedKey;
|
use crate::api::r0::keys::SignedKey;
|
||||||
|
use crate::crypto::device::test::get_device;
|
||||||
use crate::crypto::memory_stores::{DeviceStore, GroupSessionStore, SessionStore};
|
use crate::crypto::memory_stores::{DeviceStore, GroupSessionStore, SessionStore};
|
||||||
use crate::crypto::olm::{Account, InboundGroupSession, OutboundGroupSession, Session};
|
use crate::crypto::olm::{Account, InboundGroupSession, OutboundGroupSession, Session};
|
||||||
use crate::identifiers::RoomId;
|
use crate::identifiers::RoomId;
|
||||||
|
@ -226,6 +238,21 @@ mod test {
|
||||||
assert_eq!(&session, loaded_session);
|
assert_eq!(&session, loaded_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_session_store_bulk_storing() {
|
||||||
|
let (account, session) = get_account_and_session().await;
|
||||||
|
|
||||||
|
let mut store = SessionStore::new();
|
||||||
|
store.set_for_sender(&session.sender_key, vec![session.clone()]);
|
||||||
|
|
||||||
|
let sessions = store.get(&session.sender_key).unwrap();
|
||||||
|
let sessions = sessions.lock().await;
|
||||||
|
|
||||||
|
let loaded_session = &sessions[0];
|
||||||
|
|
||||||
|
assert_eq!(&session, loaded_session);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_group_session_store() {
|
async fn test_group_session_store() {
|
||||||
let alice = Account::new();
|
let alice = Account::new();
|
||||||
|
@ -254,4 +281,26 @@ mod test {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(inbound, loaded_session);
|
assert_eq!(inbound, loaded_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_device_store() {
|
||||||
|
let device = get_device();
|
||||||
|
let store = DeviceStore::new();
|
||||||
|
|
||||||
|
assert!(!store.add(device.clone()));
|
||||||
|
assert!(store.add(device.clone()));
|
||||||
|
|
||||||
|
let loaded_device = store.get(device.user_id(), device.device_id()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(device, loaded_device);
|
||||||
|
|
||||||
|
let user_devices = store.user_devices(device.user_id());
|
||||||
|
|
||||||
|
assert_eq!(user_devices.keys().nth(0).unwrap(), device.device_id());
|
||||||
|
assert_eq!(user_devices.devices().nth(0).unwrap(), &device);
|
||||||
|
|
||||||
|
let loaded_device = user_devices.get(device.device_id()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(device, loaded_device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue