Page MenuHomePhabricator

D10987.id37592.diff
No OneTemporary

D10987.id37592.diff

diff --git a/native/backup/use-client-backup.js b/native/backup/use-client-backup.js
--- a/native/backup/use-client-backup.js
+++ b/native/backup/use-client-backup.js
@@ -1,25 +1,17 @@
// @flow
-import _isEqual from 'lodash/fp/isEqual.js';
import * as React from 'react';
import { isLoggedIn } from 'lib/selectors/user-selectors.js';
-import type { UserStore } from 'lib/types/user-types.js';
import { fetchNativeKeychainCredentials } from '../account/native-credentials.js';
import { commCoreModule } from '../native-modules.js';
import { useSelector } from '../redux/redux-utils.js';
import { getContentSigningKey } from '../utils/crypto-utils.js';
-type UserData = {
- +userStore: UserStore,
-};
-
type ClientBackup = {
+uploadBackupProtocol: () => Promise<void>,
- +restoreBackupProtocol: (
- expectedUserData: UserData,
- ) => Promise<{ +dataIntegritySuccess: boolean }>,
+ +restoreBackupProtocol: () => Promise<void>,
};
async function getBackupSecret(): Promise<string> {
@@ -37,11 +29,10 @@
);
const loggedIn = useSelector(isLoggedIn);
- const uploadBackupProtocol = React.useCallback(async () => {
- if (!loggedIn || !currentUserID) {
- throw new Error('Attempt to upload backup for not logged in user.');
+ const setMockCommServicesAuthMetadata = React.useCallback(async () => {
+ if (!currentUserID) {
+ return;
}
- console.info('Start uploading backup...');
const ed25519 = await getContentSigningKey();
await commCoreModule.setCommServicesAuthMetadata(
@@ -49,27 +40,35 @@
ed25519,
accessToken ? accessToken : '',
);
+ }, [accessToken, currentUserID]);
+
+ const uploadBackupProtocol = React.useCallback(async () => {
+ if (!loggedIn || !currentUserID) {
+ throw new Error('Attempt to upload backup for not logged in user.');
+ }
+ console.info('Start uploading backup...');
+
+ await setMockCommServicesAuthMetadata();
const backupSecret = await getBackupSecret();
await commCoreModule.createNewBackup(backupSecret);
console.info('Backup uploaded.');
- }, [accessToken, currentUserID, loggedIn]);
+ }, [currentUserID, loggedIn, setMockCommServicesAuthMetadata]);
- const restoreBackupProtocol = React.useCallback(
- async (expectedUserData: UserData) => {
- if (!loggedIn || !currentUserID) {
- throw new Error('Attempt to restore backup for not logged in user.');
- }
+ const restoreBackupProtocol = React.useCallback(async () => {
+ if (!loggedIn || !currentUserID) {
+ throw new Error('Attempt to restore backup for not logged in user.');
+ }
- const backupSecret = await getBackupSecret();
- const restoreResultStr = await commCoreModule.restoreBackup(backupSecret);
- const { userData }: { userData: UserData } = JSON.parse(restoreResultStr);
+ console.info('Start restoring backup...');
- return { dataIntegritySuccess: !!_isEqual(userData, expectedUserData) };
- },
- [currentUserID, loggedIn],
- );
+ await setMockCommServicesAuthMetadata();
+ const backupSecret = await getBackupSecret();
+ await commCoreModule.restoreBackup(backupSecret);
+
+ console.info('Backup restored.');
+ }, [currentUserID, loggedIn, setMockCommServicesAuthMetadata]);
return { uploadBackupProtocol, restoreBackupProtocol };
}
diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h
--- a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h
+++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h
@@ -9,7 +9,8 @@
static void createMainCompaction(std::string backupID, size_t futureID);
static void restoreFromMainCompaction(
std::string mainCompactionPath,
- std::string mainCompactionEncryptionKey);
+ std::string mainCompactionEncryptionKey,
+ size_t futureID);
static void restoreFromBackupLog(const std::vector<std::uint8_t> &backupLog);
};
} // namespace comm
diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp
--- a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp
+++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp
@@ -2,6 +2,7 @@
#include "DatabaseManager.h"
#include "GlobalDBSingleton.h"
#include "Logger.h"
+#include "RustPromiseManager.h"
#include "WorkerThread.h"
#include "lib.rs.h"
@@ -24,17 +25,18 @@
void BackupOperationsExecutor::restoreFromMainCompaction(
std::string mainCompactionPath,
- std::string mainCompactionEncryptionKey) {
- taskType job = [mainCompactionPath, mainCompactionEncryptionKey]() {
+ std::string mainCompactionEncryptionKey,
+ size_t futureID) {
+ taskType job = [mainCompactionPath, mainCompactionEncryptionKey, futureID]() {
try {
DatabaseManager::getQueryExecutor().restoreFromMainCompaction(
mainCompactionPath, mainCompactionEncryptionKey);
+ ::resolveUnitFuture(futureID);
} catch (const std::exception &e) {
- // TODO: Inform Rust networking about failure
- // of restoration from main compaction.
+ std::string errorDetails = std::string(e.what());
Logger::log(
- "Restore from main compaction failed. Details: " +
- std::string(e.what()));
+ "Restore from main compaction failed. Details: " + errorDetails);
+ ::rejectFuture(futureID, errorDetails);
}
};
GlobalDBSingleton::instance.scheduleOrRunCancellable(job);
diff --git a/native/native_rust_library/RustBackupExecutor.h b/native/native_rust_library/RustBackupExecutor.h
--- a/native/native_rust_library/RustBackupExecutor.h
+++ b/native/native_rust_library/RustBackupExecutor.h
@@ -11,8 +11,9 @@
rust::String getBackupUserKeysFilePath(rust::Str backupID);
void createMainCompaction(rust::Str backupID, size_t futureID);
void restoreFromMainCompaction(
- rust::String mainCompactionPath,
- rust::String mainCompactionEncryptionKey);
+ rust::Str mainCompactionPath,
+ rust::Str mainCompactionEncryptionKey,
+ size_t futureID);
void restoreFromBackupLog(rust::Vec<std::uint8_t> backupLog);
} // namespace comm
diff --git a/native/native_rust_library/RustBackupExecutor.cpp b/native/native_rust_library/RustBackupExecutor.cpp
--- a/native/native_rust_library/RustBackupExecutor.cpp
+++ b/native/native_rust_library/RustBackupExecutor.cpp
@@ -32,11 +32,13 @@
}
void restoreFromMainCompaction(
- rust::String mainCompactionPath,
- rust::String mainCompactionEncryptionKey) {
+ rust::Str mainCompactionPath,
+ rust::Str mainCompactionEncryptionKey,
+ size_t futureID) {
BackupOperationsExecutor::restoreFromMainCompaction(
std::string(mainCompactionPath),
- std::string(mainCompactionEncryptionKey));
+ std::string(mainCompactionEncryptionKey),
+ futureID);
}
void restoreFromBackupLog(rust::Vec<std::uint8_t> backupLog) {
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
@@ -5,10 +5,11 @@
use crate::argon2_tools::{compute_backup_key, compute_backup_key_str};
use crate::constants::{aes, secure_store};
use crate::ffi::{
- create_main_compaction, get_backup_user_keys_file_path, secure_store_get,
+ create_main_compaction, get_backup_directory_path,
+ get_backup_user_keys_file_path, restore_from_main_compaction,
+ secure_store_get, void_callback,
};
use crate::future_manager;
-use crate::handle_string_result_as_callback;
use crate::BACKUP_SOCKET_ADDR;
use crate::RUNTIME;
use backup_client::{
@@ -16,8 +17,8 @@
UserIdentity,
};
use serde::{Deserialize, Serialize};
-use serde_json::json;
use std::error::Error;
+use std::path::PathBuf;
pub mod ffi {
use super::*;
@@ -62,10 +63,33 @@
});
}
- pub fn restore_backup_sync(backup_secret: String, promise_id: u32) {
+ pub fn restore_backup(backup_secret: String, promise_id: u32) {
RUNTIME.spawn(async move {
- let result = restore_backup(backup_secret).await;
- handle_string_result_as_callback(result, promise_id);
+ let result = download_backup(backup_secret)
+ .await
+ .map_err(|err| err.to_string());
+
+ let result = match result {
+ Ok(result) => result,
+ Err(error) => {
+ void_callback(error, promise_id);
+ return;
+ }
+ };
+
+ let (future_id, future) = future_manager::new_future::<()>().await;
+ restore_from_main_compaction(
+ &result.backup_restoration_path.to_string_lossy(),
+ &result.backup_data_key,
+ future_id,
+ );
+
+ if let Err(error) = future.await {
+ void_callback(error, promise_id);
+ return;
+ }
+
+ void_callback(String::new(), promise_id);
});
}
}
@@ -95,9 +119,9 @@
Ok(())
}
-pub async fn restore_backup(
+async fn download_backup(
backup_secret: String,
-) -> Result<String, Box<dyn Error>> {
+) -> Result<CompactionDownloadResult, Box<dyn Error>> {
let backup_client = BackupClient::new(BACKUP_SOCKET_ADDR)?;
let user_identity = get_user_identity_from_secure_store()?;
@@ -127,25 +151,20 @@
user_identity: user_identity.clone(),
};
- let mut encrypted_user_data = backup_client
+ let encrypted_user_data = backup_client
.download_backup_data(&backup_data_descriptor, RequestedData::UserData)
.await?;
- let user_data = decrypt(
- &mut user_keys.backup_data_key.as_bytes().to_vec(),
- &mut encrypted_user_data,
- )?;
-
- let user_data: serde_json::Value = serde_json::from_slice(&user_data)?;
-
- Ok(
- json!({
- "userData": user_data,
- "pickleKey": user_keys.pickle_key,
- "pickledAccount": user_keys.pickled_account,
- })
- .to_string(),
- )
+ let backup_restoration_path =
+ PathBuf::from(get_backup_directory_path()?).join("restore_compaction");
+
+ tokio::fs::write(&backup_restoration_path, encrypted_user_data).await?;
+
+ Ok(CompactionDownloadResult {
+ backup_id,
+ backup_restoration_path,
+ backup_data_key: user_keys.backup_data_key,
+ })
}
fn get_user_identity_from_secure_store() -> Result<UserIdentity, cxx::Exception>
@@ -157,6 +176,12 @@
})
}
+struct CompactionDownloadResult {
+ backup_id: String,
+ backup_restoration_path: PathBuf,
+ backup_data_key: String,
+}
+
#[derive(Debug, Serialize, Deserialize)]
struct UserKeys {
backup_data_key: String,
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
@@ -319,7 +319,7 @@
);
#[cxx_name = "restoreBackup"]
- fn restore_backup_sync(backup_secret: String, promise_id: u32);
+ fn restore_backup(backup_secret: String, promise_id: u32);
}
// Secure store
@@ -362,12 +362,12 @@
#[cxx_name = "createMainCompaction"]
fn create_main_compaction(backup_id: &str, future_id: usize);
- #[allow(unused)]
#[cxx_name = "restoreFromMainCompaction"]
fn restore_from_main_compaction(
- main_compaction_path: String,
- main_compaction_encryption_key: String,
- ) -> Result<()>;
+ main_compaction_path: &str,
+ main_compaction_encryption_key: &str,
+ future_id: usize,
+ );
#[allow(unused)]
#[cxx_name = "restoreFromBackupLog"]
diff --git a/native/profile/backup-menu.react.js b/native/profile/backup-menu.react.js
--- a/native/profile/backup-menu.react.js
+++ b/native/profile/backup-menu.react.js
@@ -5,7 +5,6 @@
import { ScrollView } from 'react-native-gesture-handler';
import { getMessageForException } from 'lib/utils/errors.js';
-import { entries } from 'lib/utils/objects.js';
import { useDispatch } from 'lib/utils/redux-utils.js';
import type { ProfileNavigationProp } from './profile.react.js';
@@ -26,7 +25,6 @@
const dispatch = useDispatch();
const colors = useColors();
- const userStore = useSelector(state => state.userStore);
const isBackupEnabled = useSelector(
state => state.localSettings.isBackupEnabled,
);
@@ -45,18 +43,15 @@
}, [uploadBackupProtocol]);
const testRestore = React.useCallback(async () => {
- let message;
+ let message = 'success';
try {
- const result = await restoreBackupProtocol({ userStore });
- message = entries(result)
- .map(([key, value]) => `${key}: ${String(value)}`)
- .join('\n');
+ await restoreBackupProtocol();
} catch (e) {
message = `Backup restore error: ${String(getMessageForException(e))}`;
console.error(message);
}
Alert.alert('Restore protocol result', message);
- }, [restoreBackupProtocol, userStore]);
+ }, [restoreBackupProtocol]);
const onBackupToggled = React.useCallback(
(value: boolean) => {
diff --git a/shared/backup_client/Cargo.lock b/shared/backup_client/Cargo.lock
--- a/shared/backup_client/Cargo.lock
+++ b/shared/backup_client/Cargo.lock
@@ -159,6 +159,7 @@
"reqwest",
"serde_json",
"sha2",
+ "tokio",
"tokio-tungstenite",
"url",
]

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 28, 11:00 AM (21 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2593820
Default Alt Text
D10987.id37592.diff (13 KB)

Event Timeline