crypto: Load unsent outgoing key requests when we open a store

master
Damir Jelić 2021-04-15 17:48:37 +02:00
parent d4c56cc5b3
commit f9d290746c
5 changed files with 66 additions and 13 deletions

View File

@ -149,6 +149,23 @@ pub struct OutgoingKeyRequest {
pub sent_out: bool,
}
impl OutgoingKeyRequest {
fn into_request(
&self,
recipient: &UserId,
own_device_id: &DeviceId,
) -> Result<OutgoingRequest, serde_json::Error> {
let content = RoomKeyRequestToDeviceEventContent {
action: Action::Request,
request_id: self.request_id.to_string(),
requesting_device_id: own_device_id.to_owned(),
body: Some(self.info.clone()),
};
wrap_key_request_content(recipient.to_owned(), self.request_id, &content)
}
}
impl PartialEq for OutgoingKeyRequest {
fn eq(&self, other: &Self) -> bool {
self.request_id == other.request_id
@ -204,6 +221,25 @@ impl KeyRequestMachine {
}
}
/// Load stored non-sent out outgoing requests
pub async fn load_outgoing_requests(&mut self) -> Result<(), CryptoStoreError> {
let infos: Vec<OutgoingKeyRequest> = vec![];
let requests: DashMap<Uuid, OutgoingRequest> = infos
.iter()
.filter(|i| !i.sent_out)
.filter_map(|info| {
Some((
info.request_id,
info.into_request(self.user_id(), self.device_id()).ok()?,
))
})
.collect();
self.outgoing_to_device_requests = requests.into();
Ok(())
}
/// Our own user id.
pub fn user_id(&self) -> &UserId {
&self.user_id
@ -542,21 +578,14 @@ impl KeyRequestMachine {
let id = Uuid::new_v4();
let content = RoomKeyRequestToDeviceEventContent {
action: Action::Request,
request_id: id.to_string(),
requesting_device_id: (&*self.device_id).clone(),
body: Some(key_info),
};
let request = wrap_key_request_content(self.user_id().clone(), id, &content)?;
let info = OutgoingKeyRequest {
request_id: id,
info: content.body.unwrap(),
info: key_info,
sent_out: false,
};
let request = info.into_request(self.user_id(), self.device_id())?;
self.save_outgoing_key_info(info).await?;
self.outgoing_to_device_requests.insert(id, request);

View File

@ -245,9 +245,10 @@ impl OlmMachine {
}
};
Ok(OlmMachine::new_helper(
&user_id, device_id, store, account, identity,
))
let mut machine = OlmMachine::new_helper(&user_id, device_id, store, account, identity);
machine.key_request_machine.load_outgoing_requests().await?;
Ok(machine)
}
/// Create a new machine with the default crypto store.

View File

@ -268,6 +268,14 @@ impl CryptoStore for MemoryStore {
.and_then(|i| self.outgoing_key_requests.get(&i).map(|r| r.clone())))
}
async fn get_outgoing_key_requests(&self) -> Result<Vec<OutgoingKeyRequest>> {
Ok(self
.outgoing_key_requests
.iter()
.map(|i| i.value().clone())
.collect())
}
async fn delete_outgoing_key_request(&self, request_id: Uuid) -> Result<()> {
self.outgoing_key_requests
.remove(&request_id)

View File

@ -449,6 +449,9 @@ pub trait CryptoStore: AsyncTraitDeps {
key_info: &RequestedKeyInfo,
) -> Result<Option<OutgoingKeyRequest>>;
/// Get all outgoing key requests that we have in the store.
async fn get_outgoing_key_requests(&self) -> Result<Vec<OutgoingKeyRequest>>;
/// Delete an outoing key request that we created that matches the given
/// request id.
///

View File

@ -709,6 +709,16 @@ impl CryptoStore for SledStore {
}
}
async fn get_outgoing_key_requests(&self) -> Result<Vec<OutgoingKeyRequest>> {
let requests: Result<Vec<OutgoingKeyRequest>> = self
.outgoing_key_requests
.iter()
.map(|i| serde_json::from_slice(&i?.1).map_err(CryptoStoreError::from))
.collect();
requests
}
async fn delete_outgoing_key_request(&self, request_id: Uuid) -> Result<()> {
let ret: Result<(), TransactionError<serde_json::Error>> =
(&self.outgoing_key_requests, &self.key_requests_by_info).transaction(
@ -1318,6 +1328,7 @@ mod test {
let stored_request = store.get_key_request_by_info(&info).await.unwrap();
assert_eq!(request, stored_request);
assert!(!store.get_outgoing_key_requests().await.unwrap().is_empty());
store.delete_outgoing_key_request(id).await.unwrap();
@ -1326,5 +1337,6 @@ mod test {
let stored_request = store.get_key_request_by_info(&info).await.unwrap();
assert_eq!(None, stored_request);
assert!(store.get_outgoing_key_requests().await.unwrap().is_empty());
}
}