Skip to content

Commit 0f34947

Browse files
committed
feat(ffi): Allow passing in a SecretsBundle while logging in
1 parent 6c18f73 commit 0f34947

File tree

3 files changed

+76
-5
lines changed

3 files changed

+76
-5
lines changed

bindings/matrix-sdk-ffi/src/authentication.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use matrix_sdk::{
2929
use ruma::serde::Raw;
3030
use url::Url;
3131

32-
use crate::client::{Client, OidcPrompt, SlidingSyncVersion};
32+
use crate::client::{Client, OidcPrompt, SecretsBundle, SlidingSyncVersion};
3333

3434
#[derive(uniffi::Object)]
3535
pub struct HomeserverLoginDetails {
@@ -95,12 +95,24 @@ impl SsoHandler {
9595
}
9696

9797
/// Completes the SSO login process.
98-
pub async fn finish(&self, callback_url: String) -> Result<(), SsoError> {
98+
pub async fn finish(
99+
&self,
100+
callback_url: String,
101+
secrets_bundle: Option<Arc<SecretsBundle>>,
102+
) -> Result<(), SsoError> {
99103
let auth = self.client.inner.matrix_auth();
100104
let url = Url::parse(&callback_url).map_err(|_| SsoError::CallbackUrlInvalid)?;
101105
let builder =
102106
auth.login_with_sso_callback(url).map_err(|_| SsoError::CallbackUrlInvalid)?;
103107
builder.await.map_err(|_| SsoError::LoginWithTokenFailed)?;
108+
109+
if let Some(bundle) = secrets_bundle {
110+
self.client
111+
.import_secrets_bundle(&bundle)
112+
.await
113+
.map_err(|e| SsoError::Generic { message: e.to_string() })?;
114+
}
115+
104116
Ok(())
105117
}
106118
}

bindings/matrix-sdk-ffi/src/client.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,23 @@ impl From<PushFormat> for RumaPushFormat {
203203
}
204204
}
205205

206+
#[derive(uniffi::Object)]
207+
pub struct SecretsBundle {
208+
inner: matrix_sdk_base::crypto::types::SecretsBundle,
209+
}
210+
211+
impl SecretsBundle {
212+
pub fn bundle_from_str(bundle: &str) -> Result<Arc<Self>, ClientError> {
213+
let bundle = serde_json::from_str(bundle)?;
214+
215+
Ok(Self { inner: bundle }.into())
216+
}
217+
218+
pub fn from_database(database_path: &str) -> Result<Arc<Self>, ClientError> {
219+
todo!()
220+
}
221+
}
222+
206223
#[matrix_sdk_ffi_macros::export(callback_interface)]
207224
pub trait ClientDelegate: SyncOutsideWasm + SendOutsideWasm {
208225
/// A callback invoked whenever the SDK runs into an unknown token error.
@@ -418,6 +435,24 @@ impl Client {
418435

419436
Ok(client)
420437
}
438+
439+
pub(crate) async fn import_secrets_bundle(
440+
&self,
441+
secrets_bundle: &SecretsBundle,
442+
) -> Result<(), ClientError> {
443+
self.inner
444+
.encryption()
445+
.import_secrets_bundle(&secrets_bundle.inner)
446+
.await
447+
.map_err(|e| ClientError::from_err(e))?;
448+
449+
// Upload the device keys, this will ensure that other devices see us as a fully
450+
// verified device ass soon as this method returns.
451+
self.inner.encryption().ensure_device_keys_upload().await?;
452+
self.inner.encryption().wait_for_e2ee_initialization_tasks().await;
453+
454+
Ok(())
455+
}
421456
}
422457

423458
#[matrix_sdk_ffi_macros::export]
@@ -486,15 +521,24 @@ impl Client {
486521
password: String,
487522
initial_device_name: Option<String>,
488523
device_id: Option<String>,
524+
secrets_bundle: Option<Arc<SecretsBundle>>,
489525
) -> Result<(), ClientError> {
490526
let mut builder = self.inner.matrix_auth().login_username(&username, &password);
527+
491528
if let Some(initial_device_name) = initial_device_name.as_ref() {
492529
builder = builder.initial_device_display_name(initial_device_name);
493530
}
531+
494532
if let Some(device_id) = device_id.as_ref() {
495533
builder = builder.device_id(device_id);
496534
}
535+
497536
builder.send().await?;
537+
538+
if let Some(bundle) = secrets_bundle {
539+
self.import_secrets_bundle(&bundle).await?;
540+
}
541+
498542
Ok(())
499543
}
500544

@@ -506,6 +550,7 @@ impl Client {
506550
jwt: String,
507551
initial_device_name: Option<String>,
508552
device_id: Option<String>,
553+
secrets_bundle: Option<Arc<SecretsBundle>>,
509554
) -> Result<(), ClientError> {
510555
let data = json!({ "token": jwt }).as_object().unwrap().clone();
511556

@@ -520,6 +565,11 @@ impl Client {
520565
}
521566

522567
builder.send().await?;
568+
569+
if let Some(bundle) = secrets_bundle {
570+
self.import_secrets_bundle(&bundle).await?;
571+
}
572+
523573
Ok(())
524574
}
525575

@@ -530,6 +580,7 @@ impl Client {
530580
password: String,
531581
initial_device_name: Option<String>,
532582
device_id: Option<String>,
583+
secrets_bundle: Option<Arc<SecretsBundle>>,
533584
) -> Result<(), ClientError> {
534585
let mut builder = self
535586
.inner
@@ -546,6 +597,10 @@ impl Client {
546597

547598
builder.send().await?;
548599

600+
if let Some(bundle) = secrets_bundle {
601+
self.import_secrets_bundle(&bundle).await?;
602+
}
603+
549604
Ok(())
550605
}
551606

@@ -637,7 +692,11 @@ impl Client {
637692
}
638693

639694
/// Completes the OIDC login process.
640-
pub async fn login_with_oidc_callback(&self, callback_url: String) -> Result<(), OidcError> {
695+
pub async fn login_with_oidc_callback(
696+
&self,
697+
callback_url: String,
698+
secrets_bundle: Option<Arc<SecretsBundle>>,
699+
) -> Result<(), OidcError> {
641700
let url = Url::parse(&callback_url).or(Err(OidcError::CallbackUrlInvalid))?;
642701

643702
self.inner.oauth().finish_login(url.into()).await?;

crates/matrix-sdk/src/encryption/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ impl Encryption {
826826
}
827827
}
828828

829-
pub(crate) async fn import_secrets_bundle(
829+
pub async fn import_secrets_bundle(
830830
&self,
831831
bundle: &matrix_sdk_base::crypto::types::SecretsBundle,
832832
) -> Result<(), SecretImportError> {
@@ -1890,7 +1890,7 @@ impl Encryption {
18901890
/// **Warning**: Do not use this method if we're already calling
18911891
/// [`Client::send_outgoing_request()`]. This method is intended for
18921892
/// explicitly uploading the device keys before starting a sync.
1893-
pub(crate) async fn ensure_device_keys_upload(&self) -> Result<()> {
1893+
pub async fn ensure_device_keys_upload(&self) -> Result<()> {
18941894
let olm = self.client.olm_machine().await;
18951895
let olm = olm.as_ref().ok_or(Error::NoOlmMachine)?;
18961896

0 commit comments

Comments
 (0)