diff --git a/bindings/matrix-sdk-ffi/CHANGELOG.md b/bindings/matrix-sdk-ffi/CHANGELOG.md index 44eaaa65eff..39107041daf 100644 --- a/bindings/matrix-sdk-ffi/CHANGELOG.md +++ b/bindings/matrix-sdk-ffi/CHANGELOG.md @@ -31,4 +31,5 @@ Breaking changes: Additions: +- Add `Room::pin_user_identity` - Add `ClientBuilder::room_key_recipient_strategy` diff --git a/bindings/matrix-sdk-ffi/src/room.rs b/bindings/matrix-sdk-ffi/src/room.rs index 8c21f7ca55f..bb721bfbcf7 100644 --- a/bindings/matrix-sdk-ffi/src/room.rs +++ b/bindings/matrix-sdk-ffi/src/room.rs @@ -609,6 +609,10 @@ impl Room { }))) } + pub fn pin_user_identity(&self, user_id: &str) -> Result<(), ClientError> { + Ok(self.inner.pin_user_identity(user_id.try_into()?)) + } + /// Set (or unset) a flag on the room to indicate that the user has /// explicitly marked it as unread. pub async fn set_unread_flag(&self, new_value: bool) -> Result<(), ClientError> { diff --git a/crates/matrix-sdk-crypto/src/identities/user.rs b/crates/matrix-sdk-crypto/src/identities/user.rs index 6948516d9b7..fd30488f27f 100644 --- a/crates/matrix-sdk-crypto/src/identities/user.rs +++ b/crates/matrix-sdk-crypto/src/identities/user.rs @@ -125,6 +125,22 @@ impl UserIdentity { } } + /// Consider this identity to be trusted. + /// + /// Resets this identity to the same "pinned" state assigned the first time + /// a user is encountered, where we follow "trust on first use" and + /// consider it trusted. + pub async fn pin(&self) -> Result<(), CryptoStoreError> { + match self { + UserIdentity::Own(_) => { + // Nothing to be done for our own identity: we already + // consider it trusted in this sense. + Ok(()) + } + UserIdentity::Other(u) => u.pin_current_master_key().await, + } + } + /// Was this identity previously verified, and is no longer? pub fn has_verification_violation(&self) -> bool { match self { diff --git a/crates/matrix-sdk/CHANGELOG.md b/crates/matrix-sdk/CHANGELOG.md index 8610707e991..3d77cfb7c72 100644 --- a/crates/matrix-sdk/CHANGELOG.md +++ b/crates/matrix-sdk/CHANGELOG.md @@ -28,6 +28,7 @@ Breaking changes: Additions: +- new `Room::pin_user_identity` method. - new `ClientBuilder::with_decryption_trust_requirement` method. - new `ClientBuilder::with_room_key_recipient_strategy` method - new `Room.set_account_data` and `Room.set_account_data_raw` RoomAccountData setters, analogous to the GlobalAccountData diff --git a/crates/matrix-sdk/src/encryption/identities/users.rs b/crates/matrix-sdk/src/encryption/identities/users.rs index b2f989e46a8..c00a25364e9 100644 --- a/crates/matrix-sdk/src/encryption/identities/users.rs +++ b/crates/matrix-sdk/src/encryption/identities/users.rs @@ -422,6 +422,15 @@ impl UserIdentity { self.inner.withdraw_verification().await } + /// Consider this identity to be trusted. + /// + /// Resets this identity to the same "pinned" state assigned the first time + /// a user is encountered, where we follow "trust on first use" and + /// consider it trusted. + pub async fn pin(&self) -> Result<(), CryptoStoreError> { + self.inner.pin().await + } + /// Get the public part of the Master key of this user identity. /// /// The public part of the Master key is usually used to uniquely identify diff --git a/crates/matrix-sdk/src/error.rs b/crates/matrix-sdk/src/error.rs index 6aed7490326..f7fda197ec9 100644 --- a/crates/matrix-sdk/src/error.rs +++ b/crates/matrix-sdk/src/error.rs @@ -379,6 +379,10 @@ pub enum Error { /// Backups are not enabled #[error("backups are not enabled")] BackupNotEnabled, + + /// The user was not found + #[error("user was not found")] + UserNotFound, } #[rustfmt::skip] // stop rustfmt breaking the `` in docs across multiple lines diff --git a/crates/matrix-sdk/src/room/identity_status_changes.rs b/crates/matrix-sdk/src/room/identity_status_changes.rs index ce93f326a46..6cfbf21bfa3 100644 --- a/crates/matrix-sdk/src/room/identity_status_changes.rs +++ b/crates/matrix-sdk/src/room/identity_status_changes.rs @@ -430,9 +430,8 @@ mod tests { ); // Pin it - self.crypto_other_identity() - .await - .pin_current_master_key() + self.room + .pin_user_identity(self.user_id()) .await .expect("Should not fail to pin"); } else { diff --git a/crates/matrix-sdk/src/room/mod.rs b/crates/matrix-sdk/src/room/mod.rs index 4c5a83ced86..174f34947f0 100644 --- a/crates/matrix-sdk/src/room/mod.rs +++ b/crates/matrix-sdk/src/room/mod.rs @@ -403,6 +403,18 @@ impl Room { IdentityStatusChanges::create_stream(self.clone()).await } + /// Mark this user as "pinned" meaning that we have seen their cryptographic + /// identity before. + #[cfg(feature = "e2e-encryption")] + pub async fn pin_user_identity(&self, user_id: &UserId) -> Result<()> { + let x = self.client.encryption().get_user_identity(user_id).await?; + + match x { + Some(x) => Ok(x.pin().await?), + None => Err(Error::UserNotFound), + } + } + /// Returns a wrapping `TimelineEvent` for the input `AnyTimelineEvent`, /// decrypted if needs be. ///