From b66a1437c4a0ad1149dbfb9ac3163ca8990950e3 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 25 Jul 2024 14:39:50 +0300 Subject: [PATCH] ffi: Expose identity reset mechanism --- bindings/matrix-sdk-ffi/src/encryption.rs | 72 ++++++++++++++++++++++- bindings/matrix-sdk-ffi/src/ruma.rs | 30 ++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/bindings/matrix-sdk-ffi/src/encryption.rs b/bindings/matrix-sdk-ffi/src/encryption.rs index 46b4f7424ee..e1fa6868303 100644 --- a/bindings/matrix-sdk-ffi/src/encryption.rs +++ b/bindings/matrix-sdk-ffi/src/encryption.rs @@ -9,7 +9,7 @@ use thiserror::Error; use zeroize::Zeroize; use super::RUNTIME; -use crate::{client::Client, error::ClientError, task_handle::TaskHandle}; +use crate::{client::Client, error::ClientError, ruma::AuthData, task_handle::TaskHandle}; #[derive(uniffi::Object)] pub struct Encryption { @@ -357,6 +357,20 @@ impl Encryption { Ok(result?) } + pub async fn reset_identity(&self) -> Result>, ClientError> { + if let Some(reset_handle) = self + .inner + .recovery() + .reset_identity() + .await + .map_err(|e| ClientError::Generic { msg: e.to_string() })? + { + return Ok(Some(Arc::new(IdentityResetHandle { inner: reset_handle }))); + } + + Ok(None) + } + pub async fn recover(&self, mut recovery_key: String) -> Result<()> { let result = self.inner.recovery().recover(&recovery_key).await; @@ -387,3 +401,59 @@ impl Encryption { self.inner.wait_for_e2ee_initialization_tasks().await; } } + +#[derive(uniffi::Object)] +pub struct IdentityResetHandle { + pub(crate) inner: matrix_sdk::encryption::recovery::IdentityResetHandle, +} + +#[uniffi::export(async_runtime = "tokio")] +impl IdentityResetHandle { + pub fn auth_type(&self) -> CrossSigningResetAuthType { + self.inner.auth_type().into() + } + + pub async fn reset(&self, auth: Option) -> Result<(), ClientError> { + if let Some(auth) = auth { + self.inner + .reset(Some(auth.into())) + .await + .map_err(|e| ClientError::Generic { msg: e.to_string() }) + } else { + self.inner.reset(None).await.map_err(|e| ClientError::Generic { msg: e.to_string() }) + } + } +} + +#[derive(uniffi::Enum)] +pub enum CrossSigningResetAuthType { + /// The homeserver requires user-interactive authentication. + Uiaa, + // /// OIDC is used for authentication and the user needs to open a URL to + // /// approve the upload of cross-signing keys. + Oidc(OidcCrossSigningResetInfo), +} + +impl From<&matrix_sdk::encryption::CrossSigningResetAuthType> for CrossSigningResetAuthType { + fn from(value: &matrix_sdk::encryption::CrossSigningResetAuthType) -> Self { + match value { + encryption::CrossSigningResetAuthType::Uiaa(_) => Self::Uiaa, + encryption::CrossSigningResetAuthType::Oidc(info) => Self::Oidc(info.into()), + } + } +} + +#[derive(uniffi::Record)] +pub struct OidcCrossSigningResetInfo { + /// The error message we received from the homeserver after we attempted to + /// reset the cross-signing keys. + pub error: String, + /// The URL where the user can approve the reset of the cross-signing keys. + pub approval_url: String, +} + +impl From<&matrix_sdk::encryption::OidcCrossSigningResetInfo> for OidcCrossSigningResetInfo { + fn from(value: &matrix_sdk::encryption::OidcCrossSigningResetInfo) -> Self { + Self { error: value.error.to_owned(), approval_url: value.approval_url.to_string() } + } +} diff --git a/bindings/matrix-sdk-ffi/src/ruma.rs b/bindings/matrix-sdk-ffi/src/ruma.rs index f54be0581e9..415e080ee04 100644 --- a/bindings/matrix-sdk-ffi/src/ruma.rs +++ b/bindings/matrix-sdk-ffi/src/ruma.rs @@ -57,6 +57,36 @@ use crate::{ utils::u64_to_uint, }; +#[derive(uniffi::Enum)] +pub enum AuthData { + /// Password-based authentication (`m.login.password`). + Password(AuthDataPassword), +} + +#[derive(uniffi::Record)] +pub struct AuthDataPassword { + /// One of the user's identifiers. + identifier: String, + + /// The plaintext password. + password: String, +} + +impl From for ruma::api::client::uiaa::AuthData { + fn from(value: AuthData) -> ruma::api::client::uiaa::AuthData { + match value { + AuthData::Password(data) => { + let user_id = ruma::UserId::parse(data.identifier).unwrap(); + + ruma::api::client::uiaa::AuthData::Password(ruma::api::client::uiaa::Password::new( + user_id.into(), + data.password, + )) + } + } + } +} + /// Parse a matrix entity from a given URI, be it either /// a `matrix.to` link or a `matrix:` URI #[uniffi::export]