Browse Source

verification: Get user crypto identity remotely if we do not have it locally

merge-requests/1716/head
Kévin Commaille 2 years ago
parent
commit
d2c7639d3c
No known key found for this signature in database
GPG Key ID: C971D9DBC9D678D
  1. 83
      src/session/model/user.rs
  2. 2
      src/session/model/verification/verification_list.rs

83
src/session/model/user.rs

@ -146,9 +146,15 @@ impl User {
obj
}
/// Get the cryptographic identity (aka cross-signing identity) of this
/// user.
pub async fn crypto_identity(&self) -> Option<UserIdentity> {
/// Get the local cryptographic identity (aka cross-signing identity) of
/// this user.
///
/// Locally, we should always have the crypto identity of our own user and
/// of users with whom we share an encrypted room.
///
/// To get the crypto identity of a user with whom we do not share an
/// encrypted room, use [`Self::ensure_crypto_identity()`].
pub async fn local_crypto_identity(&self) -> Option<UserIdentity> {
let encryption = self.session().client().encryption();
let user_id = self.user_id().clone();
let handle = spawn_tokio!(async move { encryption.get_user_identity(&user_id).await });
@ -156,7 +162,67 @@ impl User {
match handle.await.unwrap() {
Ok(identity) => identity,
Err(error) => {
error!("Could not find crypto identity: {error}");
error!("Could not get local crypto identity: {error}");
None
}
}
}
/// Get the cryptographic identity (aka cross-signing identity) of this
/// user.
///
/// First, we try to get the local crypto identity if we are sure that it is
/// up-to-date. If we do not have the crypto identity locally, we request it
/// from the homeserver.
pub async fn ensure_crypto_identity(&self) -> Option<UserIdentity> {
let session = self.session();
let encryption = session.client().encryption();
let user_id = self.user_id();
// First, see if we should have an updated crypto identity for the user locally.
// When we get the remote crypto identity of a user manually, it is cached
// locally but it is not kept up-to-date unless the user is tracked. That's why
// it's important to only use the local crypto identity if the user is tracked.
let should_have_local = if user_id == session.user_id() {
true
} else {
// We should have the updated user identity locally for tracked users.
let encryption_clone = encryption.clone();
let handle = spawn_tokio!(async move { encryption_clone.tracked_users().await });
match handle.await.unwrap() {
Ok(tracked_users) => {
tracing::debug!("Got tracked users");
tracked_users.contains(user_id)
}
Err(error) => {
error!("Could not get tracked users: {error}");
// We are not sure, but let us try to get the local user identity first.
true
}
}
};
tracing::debug!("should_have_local: {should_have_local:?}");
// Try to get the local crypto identity.
if should_have_local {
if let Some(identity) = self.local_crypto_identity().await {
tracing::debug!("Local identity: {identity:?}");
return Some(identity);
}
}
// Now, try to request the crypto identity from the homeserver.
let user_id_clone = user_id.clone();
let handle =
spawn_tokio!(async move { encryption.request_user_identity(&user_id_clone).await });
match handle.await.unwrap() {
Ok(identity) => {
tracing::debug!("remote identity: {identity:?}");
identity
}
Err(error) => {
error!("Could not request remote crypto identity: {error}");
None
}
}
@ -176,7 +242,11 @@ impl User {
#[weak(rename_to = obj)]
self,
async move {
let verified = obj.crypto_identity().await.is_some_and(|i| i.is_verified());
// If a user is verified, we should have their crypto identity locally.
let verified = obj
.local_crypto_identity()
.await
.is_some_and(|i| i.is_verified());
if verified == obj.verified() {
return;
@ -230,8 +300,7 @@ impl User {
/// Get or create a direct chat with this user.
///
/// If there is no existing direct chat, a new one is created. If a direct
/// chat exists but the other user has left the room, we re-invite them.
/// If there is no existing direct chat, a new one is created.
pub async fn get_or_create_direct_chat(&self) -> Result<Room, ()> {
let user_id = self.user_id();

2
src/session/model/verification/verification_list.rs

@ -329,7 +329,7 @@ impl VerificationList {
let supported_methods = load_supported_verification_methods().await;
let Some(identity) = user.crypto_identity().await else {
let Some(identity) = user.ensure_crypto_identity().await else {
error!("Could not create identity verification: cryptographic identity not found");
return Err(());
};

Loading…
Cancel
Save