diff --git a/lib/types/backup-types.js b/lib/types/backup-types.js --- a/lib/types/backup-types.js +++ b/lib/types/backup-types.js @@ -33,3 +33,17 @@ siweBackupMsgStatement: t.String, siweBackupMsgIssuedAt: t.String, }); + +// This type should match `LatestBackupInfo` in +// `native/native_rust_library/src/backup.rs` +export type LatestBackupInfo = { + +backupID: string, + +userID: string, + +siweBackupData?: ?SIWEBackupData, +}; +export const latestBackupInfoResponseValidator: TInterface = + tShape({ + backupID: t.String, + userID: t.String, + siweBackupData: t.maybe(siweBackupDataValidator), + }); diff --git a/native/native_rust_library/src/backup.rs b/native/native_rust_library/src/backup.rs --- a/native/native_rust_library/src/backup.rs +++ b/native/native_rust_library/src/backup.rs @@ -273,6 +273,54 @@ handle_string_result_as_callback(serialize_result, promise_id); }); } + + pub fn retrieve_latest_backup_info(user_identifier: String, promise_id: u32) { + RUNTIME.spawn(async move { + let latest_backup_id_response = + download_latest_backup_info(user_identifier) + .await + .map_err(|err| err.to_string()); + + let result = match latest_backup_id_response { + Ok(result) => result, + Err(error) => { + string_callback(error, promise_id, "".to_string()); + return; + } + }; + + let LatestBackupInfoResponse { + backup_id, + user_id, + siwe_backup_msg, + } = result; + + let siwe_backup_data = match siwe_backup_msg { + Some(siwe_backup_msg_value) => { + match get_siwe_backup_data_from_msg( + backup_id.clone(), + siwe_backup_msg_value, + ) { + Ok(data) => Some(data), + Err(err) => { + string_callback(err, promise_id, "".to_string()); + return; + } + } + } + None => None, + }; + + let result = LatestBackupInfo { + backup_id, + user_id, + siwe_backup_data, + }; + + let serialize_result = serde_json::to_string(&result); + handle_string_result_as_callback(serialize_result, promise_id); + }); + } } pub async fn create_userkeys_compaction( @@ -356,6 +404,30 @@ }) } +async fn download_latest_backup_info( + user_identifier: String, +) -> Result> { + let backup_client = BackupClient::new(BACKUP_SOCKET_ADDR)?; + + let latest_backup_descriptor = BackupDescriptor::Latest { user_identifier }; + + let backup_info_response = backup_client + .download_backup_data(&latest_backup_descriptor, RequestedData::BackupInfo) + .await?; + + let LatestBackupInfoResponse { + backup_id, + user_id, + siwe_backup_msg, + } = serde_json::from_slice(&backup_info_response)?; + + Ok(LatestBackupInfoResponse { + backup_id, + user_id, + siwe_backup_msg, + }) +} + async fn download_backup_keys( backup_id: String, backup_secret: String, @@ -461,7 +533,7 @@ } // This struct should match `SIWEBackupData` in `lib/types/backup-types.js` -#[derive(Debug, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct SIWEBackupData { #[serde(rename = "backupID")] @@ -471,6 +543,17 @@ siwe_backup_msg_issued_at: String, } +// This struct should match `LatestBackupInfo` in `lib/types/backup-types.js` +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct LatestBackupInfo { + #[serde(rename = "backupID")] + pub backup_id: String, + #[serde(rename = "userID")] + pub user_id: String, + pub siwe_backup_data: Option, +} + struct CompactionDownloadResult { backup_id: String, backup_restoration_path: PathBuf, diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -458,6 +458,9 @@ #[cxx_name = "retrieveLatestSIWEBackupData"] fn retrieve_latest_siwe_backup_data(promise_id: u32); + + #[cxx_name = "retrieveLatestBackupInfo"] + fn retrieve_latest_backup_info(user_identifier: String, promise_id: u32); } // Secure store