Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3392497
D10859.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
16 KB
Referenced Files
None
Subscribers
None
D10859.diff
View Options
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
@@ -16,7 +16,7 @@
};
type ClientBackup = {
- +uploadBackupProtocol: (userData: UserData) => Promise<void>,
+ +uploadBackupProtocol: () => Promise<void>,
+restoreBackupProtocol: (
expectedUserData: UserData,
) => Promise<{ +dataIntegritySuccess: boolean }>,
@@ -37,30 +37,24 @@
);
const loggedIn = useSelector(isLoggedIn);
- const uploadBackupProtocol = React.useCallback(
- async (userData: UserData) => {
- if (!loggedIn || !currentUserID) {
- throw new Error('Attempt to upload backup for not logged in user.');
- }
- console.info('Start uploading backup...');
+ 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...');
- const ed25519 = await getContentSigningKey();
- await commCoreModule.setCommServicesAuthMetadata(
- currentUserID,
- ed25519,
- accessToken ? accessToken : '',
- );
+ const ed25519 = await getContentSigningKey();
+ await commCoreModule.setCommServicesAuthMetadata(
+ currentUserID,
+ ed25519,
+ accessToken ? accessToken : '',
+ );
- const backupSecret = await getBackupSecret();
- await commCoreModule.createNewBackup(
- backupSecret,
- JSON.stringify(userData),
- );
+ const backupSecret = await getBackupSecret();
+ await commCoreModule.createNewBackup(backupSecret);
- console.info('Backup uploaded.');
- },
- [accessToken, currentUserID, loggedIn],
- );
+ console.info('Backup uploaded.');
+ }, [accessToken, currentUserID, loggedIn]);
const restoreBackupProtocol = React.useCallback(
async (expectedUserData: UserData) => {
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
@@ -23,6 +23,7 @@
std::string SQLiteQueryExecutor::encryptionKey;
std::once_flag SQLiteQueryExecutor::initialized;
int SQLiteQueryExecutor::sqlcipherEncryptionKeySize = 64;
+// Should match constant defined in `native_rust_library/src/constants.rs`
std::string SQLiteQueryExecutor::secureStoreEncryptionKeyID =
"comm.encryptionKey";
int SQLiteQueryExecutor::backupLogsEncryptionKeySize = 32;
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
@@ -135,10 +135,8 @@
virtual jsi::Value clearCommServicesAccessToken(jsi::Runtime &rt) override;
virtual void startBackupHandler(jsi::Runtime &rt) override;
virtual void stopBackupHandler(jsi::Runtime &rt) override;
- virtual jsi::Value createNewBackup(
- jsi::Runtime &rt,
- jsi::String backupSecret,
- jsi::String userData) override;
+ virtual jsi::Value
+ createNewBackup(jsi::Runtime &rt, jsi::String backupSecret) override;
virtual jsi::Value
restoreBackup(jsi::Runtime &rt, jsi::String backupSecret) override;
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
@@ -1426,12 +1426,9 @@
}
}
-jsi::Value CommCoreModule::createNewBackup(
- jsi::Runtime &rt,
- jsi::String backupSecret,
- jsi::String userData) {
+jsi::Value
+CommCoreModule::createNewBackup(jsi::Runtime &rt, jsi::String backupSecret) {
std::string backupSecretStr = backupSecret.utf8(rt);
- std::string userDataStr = userData.utf8(rt);
return createPromiseAsJSIValue(
rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
this->cryptoThread->scheduleTask([=, &innerRt]() {
@@ -1466,7 +1463,6 @@
rust::string(backupSecretStr),
rust::string(pickleKey),
rust::string(pickledAccount),
- rust::string(userDataStr),
currentID);
} else {
this->jsInvoker_->invokeAsync(
diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
--- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
+++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
@@ -155,7 +155,7 @@
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
- return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->createNewBackup(rt, args[0].asString(rt), args[1].asString(rt));
+ return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->createNewBackup(rt, args[0].asString(rt));
}
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->restoreBackup(rt, args[0].asString(rt));
@@ -208,7 +208,7 @@
methodMap_["clearCommServicesAccessToken"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_clearCommServicesAccessToken};
methodMap_["startBackupHandler"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_startBackupHandler};
methodMap_["stopBackupHandler"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_stopBackupHandler};
- methodMap_["createNewBackup"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewBackup};
+ methodMap_["createNewBackup"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewBackup};
methodMap_["restoreBackup"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackup};
}
diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h
--- a/native/cpp/CommonCpp/_generated/commJSI.h
+++ b/native/cpp/CommonCpp/_generated/commJSI.h
@@ -65,7 +65,7 @@
virtual jsi::Value clearCommServicesAccessToken(jsi::Runtime &rt) = 0;
virtual void startBackupHandler(jsi::Runtime &rt) = 0;
virtual void stopBackupHandler(jsi::Runtime &rt) = 0;
- virtual jsi::Value createNewBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String userData) = 0;
+ virtual jsi::Value createNewBackup(jsi::Runtime &rt, jsi::String backupSecret) = 0;
virtual jsi::Value restoreBackup(jsi::Runtime &rt, jsi::String backupSecret) = 0;
};
@@ -448,13 +448,13 @@
return bridging::callFromJs<void>(
rt, &T::stopBackupHandler, jsInvoker_, instance_);
}
- jsi::Value createNewBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String userData) override {
+ jsi::Value createNewBackup(jsi::Runtime &rt, jsi::String backupSecret) override {
static_assert(
- bridging::getParameterCount(&T::createNewBackup) == 3,
- "Expected createNewBackup(...) to have 3 parameters");
+ bridging::getParameterCount(&T::createNewBackup) == 2,
+ "Expected createNewBackup(...) to have 2 parameters");
return bridging::callFromJs<jsi::Value>(
- rt, &T::createNewBackup, jsInvoker_, instance_, std::move(backupSecret), std::move(userData));
+ rt, &T::createNewBackup, jsInvoker_, instance_, std::move(backupSecret));
}
jsi::Value restoreBackup(jsi::Runtime &rt, jsi::String backupSecret) override {
static_assert(
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
@@ -4,14 +4,16 @@
use crate::argon2_tools::{compute_backup_key, compute_backup_key_str};
use crate::constants::{aes, secure_store};
-use crate::ffi::secure_store_get;
+use crate::ffi::{
+ create_main_compaction, get_backup_user_keys_file_path, secure_store_get,
+};
+use crate::future_manager;
+use crate::handle_string_result_as_callback;
use crate::BACKUP_SOCKET_ADDR;
use crate::RUNTIME;
-use crate::{handle_string_result_as_callback, handle_void_result_as_callback};
use backup_client::{
- BackupClient, BackupData, BackupDescriptor, DownloadLogsRequest,
- LatestBackupIDResponse, LogUploadConfirmation, LogWSResponse, RequestedData,
- SinkExt, StreamExt, UploadLogRequest, UserIdentity,
+ BackupClient, BackupDescriptor, DownloadLogsRequest, LatestBackupIDResponse,
+ LogWSResponse, RequestedData, SinkExt, StreamExt, UserIdentity,
};
use serde::{Deserialize, Serialize};
use serde_json::json;
@@ -22,24 +24,41 @@
pub use upload_handler::ffi::*;
- pub fn create_backup_sync(
+ pub fn create_backup(
backup_id: String,
backup_secret: String,
pickle_key: String,
pickled_account: String,
- user_data: String,
promise_id: u32,
) {
+ compaction_upload_promises::insert(backup_id.clone(), promise_id);
+
RUNTIME.spawn(async move {
- let result = create_backup(
- backup_id,
+ let result = create_userkeys_compaction(
+ backup_id.clone(),
backup_secret,
pickle_key,
pickled_account,
- user_data,
)
- .await;
- handle_void_result_as_callback(result, promise_id);
+ .await
+ .map_err(|err| err.to_string());
+
+ if let Err(err) = result {
+ compaction_upload_promises::resolve(&backup_id, Err(err));
+ return;
+ }
+
+ let (future_id, future) = future_manager::new_future::<()>().await;
+ create_main_compaction(&backup_id, future_id);
+ if let Err(err) = future.await {
+ compaction_upload_promises::resolve(&backup_id, Err(err));
+ tokio::spawn(upload_handler::compaction::cleanup_files(backup_id));
+ return;
+ }
+
+ trigger_backup_file_upload();
+
+ // The promise will be resolved when the backup is uploaded
});
}
@@ -51,21 +70,17 @@
}
}
-pub async fn create_backup(
+pub async fn create_userkeys_compaction(
backup_id: String,
backup_secret: String,
pickle_key: String,
pickled_account: String,
- user_data: String,
) -> Result<(), Box<dyn Error>> {
let mut backup_key =
compute_backup_key(backup_secret.as_bytes(), backup_id.as_bytes())?;
- let mut user_data = user_data.into_bytes();
-
- let mut backup_data_key = [0; aes::KEY_SIZE];
- crate::ffi::generate_key(&mut backup_data_key)?;
- let encrypted_user_data = encrypt(&mut backup_data_key, &mut user_data)?;
+ let backup_data_key =
+ secure_store_get(secure_store::SECURE_STORE_ENCRYPTION_KEY_ID)?;
let user_keys = UserKeys {
backup_data_key,
@@ -74,46 +89,8 @@
};
let encrypted_user_keys = user_keys.encrypt(&mut backup_key)?;
- let backup_client = BackupClient::new(BACKUP_SOCKET_ADDR)?;
-
- let user_identity = get_user_identity_from_secure_store()?;
-
- let backup_data = BackupData {
- backup_id: backup_id.clone(),
- user_data: encrypted_user_data,
- user_keys: encrypted_user_keys,
- attachments: Vec::new(),
- };
-
- backup_client
- .upload_backup(&user_identity, backup_data)
- .await?;
-
- let (tx, rx) = backup_client.upload_logs(&user_identity).await?;
-
- tokio::pin!(tx);
- tokio::pin!(rx);
-
- let log_data = UploadLogRequest {
- backup_id: backup_id.clone(),
- log_id: 1,
- content: (1..100).collect(),
- attachments: None,
- };
- tx.send(log_data.clone()).await?;
- match rx.next().await {
- Some(Ok(LogUploadConfirmation {
- backup_id: response_backup_id,
- log_id: 1,
- }))
- if backup_id == response_backup_id =>
- {
- // Correctly uploaded
- }
- response => {
- return Err(Box::new(InvalidWSLogResponse(format!("{response:?}"))))
- }
- };
+ let user_keys_file = get_backup_user_keys_file_path(&backup_id)?;
+ tokio::fs::write(user_keys_file, encrypted_user_keys).await?;
Ok(())
}
@@ -142,7 +119,7 @@
.download_backup_data(&latest_backup_descriptor, RequestedData::UserKeys)
.await?;
- let mut user_keys =
+ let user_keys =
UserKeys::from_encrypted(&mut encrypted_user_keys, &mut backup_key)?;
let backup_data_descriptor = BackupDescriptor::BackupID {
@@ -154,8 +131,10 @@
.download_backup_data(&backup_data_descriptor, RequestedData::UserData)
.await?;
- let user_data =
- decrypt(&mut user_keys.backup_data_key, &mut encrypted_user_data)?;
+ 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)?;
@@ -210,7 +189,7 @@
#[derive(Debug, Serialize, Deserialize)]
struct UserKeys {
- backup_data_key: [u8; 32],
+ backup_data_key: String,
pickle_key: String,
pickled_account: String,
}
diff --git a/native/native_rust_library/src/constants.rs b/native/native_rust_library/src/constants.rs
--- a/native/native_rust_library/src/constants.rs
+++ b/native/native_rust_library/src/constants.rs
@@ -1,16 +1,19 @@
use std::time::Duration;
+#[allow(unused)]
pub mod aes {
pub const KEY_SIZE: usize = 32; // bytes
pub const IV_LENGTH: usize = 12; // bytes - unique Initialization Vector (nonce)
pub const TAG_LENGTH: usize = 16; // bytes - GCM auth tag
}
-/// Should match constants defined in `CommSecureStore.h`
pub mod secure_store {
+ /// Should match constants defined in `CommSecureStore.h`
pub const COMM_SERVICES_ACCESS_TOKEN: &str = "accessToken";
pub const USER_ID: &str = "userID";
pub const DEVICE_ID: &str = "deviceID";
+ /// Should match constant defined in `SQLiteQueryExecutor.h`
+ pub const SECURE_STORE_ENCRYPTION_KEY_ID: &str = "comm.encryptionKey";
}
pub const BACKUP_SERVICE_CONNECTION_RETRY_DELAY: Duration =
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
@@ -310,12 +310,11 @@
fn trigger_backup_file_upload();
#[cxx_name = "createBackup"]
- fn create_backup_sync(
+ fn create_backup(
backup_id: String,
backup_secret: String,
pickle_key: String,
pickled_account: String,
- user_data: String,
promise_id: u32,
);
@@ -341,18 +340,15 @@
unsafe extern "C++" {
include!("RustBackupExecutor.h");
- #[allow(unused)]
#[cxx_name = "getBackupDirectoryPath"]
fn get_backup_directory_path() -> Result<String>;
- #[allow(unused)]
#[cxx_name = "getBackupFilePath"]
fn get_backup_file_path(
backup_id: &str,
is_attachments: bool,
) -> Result<String>;
- #[allow(unused)]
#[cxx_name = "getBackupLogFilePath"]
fn get_backup_log_file_path(
backup_id: &str,
@@ -360,7 +356,6 @@
is_attachments: bool,
) -> Result<String>;
- #[allow(unused)]
#[cxx_name = "getBackupUserKeysFilePath"]
fn get_backup_user_keys_file_path(backup_id: &str) -> Result<String>;
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
@@ -31,7 +31,18 @@
state => state.localSettings.isBackupEnabled,
);
- const { restoreBackupProtocol } = useClientBackup();
+ const { uploadBackupProtocol, restoreBackupProtocol } = useClientBackup();
+
+ const uploadBackup = React.useCallback(async () => {
+ let message = 'Success';
+ try {
+ await uploadBackupProtocol();
+ } catch (e) {
+ message = `Backup upload error: ${String(getMessageForException(e))}`;
+ console.error(message);
+ }
+ Alert.alert('Upload protocol result', message);
+ }, [uploadBackupProtocol]);
const testRestore = React.useCallback(async () => {
let message;
@@ -71,6 +82,17 @@
</View>
<Text style={styles.header}>ACTIONS</Text>
+ <View style={styles.section}>
+ <Button
+ onPress={uploadBackup}
+ style={styles.row}
+ iosFormat="highlight"
+ iosHighlightUnderlayColor={colors.panelIosHighlightUnderlay}
+ iosActiveOpacity={0.85}
+ >
+ <Text style={styles.submenuText}>Test backup upload protocol</Text>
+ </Button>
+ </View>
<View style={styles.section}>
<Button
onPress={testRestore}
diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js
--- a/native/schema/CommCoreModuleSchema.js
+++ b/native/schema/CommCoreModuleSchema.js
@@ -123,7 +123,7 @@
+clearCommServicesAccessToken: () => Promise<void>;
+startBackupHandler: () => void;
+stopBackupHandler: () => void;
- +createNewBackup: (backupSecret: string, userData: string) => Promise<void>;
+ +createNewBackup: (backupSecret: string) => Promise<void>;
+restoreBackup: (backupSecret: string) => Promise<string>;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 1, 8:52 AM (19 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2604465
Default Alt Text
D10859.diff (16 KB)
Attached To
Mode
D10859: [native] Create and upload backup compaction
Attached
Detach File
Event Timeline
Log In to Comment