Skip to content

Commit

Permalink
[CommCoreModule] cleanup methods for creating backup
Browse files Browse the repository at this point in the history
Summary:
[ENG-9656](https://linear.app/comm/issue/ENG-9656/native-changes-for-minimal-version-of-backup).

Cleaning old code to make it more straightforward, reducing code duplication.

Depends on D13935

Test Plan: Tested in D13937

Reviewers: bartek, tomek

Reviewed By: bartek

Subscribers: ashoat

Differential Revision: https://phab.comm.dev/D13936
  • Loading branch information
xsanm committed Nov 25, 2024
1 parent dd0cfbe commit f2be17b
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 113 deletions.
30 changes: 7 additions & 23 deletions native/backup/use-client-backup.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import * as React from 'react';

import { isLoggedIn } from 'lib/selectors/user-selectors.js';
import { accountHasPassword } from 'lib/shared/account-utils.js';
import {
latestBackupInfoResponseValidator,
type LatestBackupInfo,
Expand All @@ -15,7 +14,7 @@ import { commCoreModule } from '../native-modules.js';
import { useSelector } from '../redux/redux-utils.js';

type ClientBackup = {
+uploadBackupProtocol: () => Promise<void>,
+createFullBackup: () => Promise<void>,
+createUserKeysBackup: () => Promise<void>,
+retrieveLatestBackupInfo: () => Promise<LatestBackupInfo>,
};
Expand All @@ -28,29 +27,14 @@ function useClientBackup(): ClientBackup {
const loggedIn = useSelector(isLoggedIn);
const getBackupSecret = useGetBackupSecretForLoggedInUser();

const uploadBackupProtocol = React.useCallback(async () => {
const createFullBackup = React.useCallback(async () => {
if (!loggedIn || !currentUserID) {
throw new Error('Attempt to upload backup for not logged in user.');
}

console.info('Start uploading backup...');

if (accountHasPassword(currentUserInfo)) {
const backupSecret = await getBackupSecret();
await commCoreModule.createNewBackup(backupSecret);
} else {
const siweBackupSecrets = await commCoreModule.getSIWEBackupSecrets();
if (!siweBackupSecrets) {
throw new Error('SIWE backup message and its signature are missing');
}
await commCoreModule.createNewSIWEBackup(
siweBackupSecrets.signature,
siweBackupSecrets.message,
);
}

console.info('Backup uploaded.');
}, [loggedIn, currentUserID, currentUserInfo, getBackupSecret]);
const backupSecret = await getBackupSecret();
await commCoreModule.createFullBackup(backupSecret);
}, [loggedIn, currentUserID, getBackupSecret]);

const createUserKeysBackup = React.useCallback(async () => {
if (!loggedIn || !currentUserID) {
Expand Down Expand Up @@ -78,11 +62,11 @@ function useClientBackup(): ClientBackup {

return React.useMemo(
() => ({
uploadBackupProtocol,
createFullBackup,
createUserKeysBackup,
retrieveLatestBackupInfo,
}),
[retrieveLatestBackupInfo, uploadBackupProtocol, createUserKeysBackup],
[retrieveLatestBackupInfo, createFullBackup, createUserKeysBackup],
);
}

Expand Down
84 changes: 38 additions & 46 deletions native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2507,15 +2507,46 @@ void CommCoreModule::stopBackupHandler(jsi::Runtime &rt) {
}
}

jsi::Value CommCoreModule::createNewBackupInternal(
jsi::Runtime &rt,
std::string backupSecret,
std::string backupMessage) {
std::string getSIWEBackupMessage() {
std::promise<std::string> backupSIWEMessagePromise;
std::future<std::string> backupSIWEMessageFuture =
backupSIWEMessagePromise.get_future();
GlobalDBSingleton::instance.scheduleOrRunCancellable(
[&backupSIWEMessagePromise]() {
try {
std::string backupSecrets =
DatabaseManager::getQueryExecutor().getMetadata(
"siweBackupSecrets");
if (!backupSecrets.size()) {
backupSIWEMessagePromise.set_value("");
} else {
folly::dynamic backupSecretsJSON = folly::parseJson(backupSecrets);
std::string message = backupSecretsJSON["message"].asString();
backupSIWEMessagePromise.set_value(message);
}
} catch (std::system_error &e) {
backupSIWEMessagePromise.set_exception(std::make_exception_ptr(e));
}
});
return backupSIWEMessageFuture.get();
}

jsi::Value
CommCoreModule::createFullBackup(jsi::Runtime &rt, jsi::String backupSecret) {
std::string backupSecretStr = backupSecret.utf8(rt);
return createPromiseAsJSIValue(
rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
std::string backupMessage;
try {
backupMessage = getSIWEBackupMessage();
} catch (std::system_error &e) {
this->jsInvoker_->invokeAsync(
[=, &innerRt]() { promise->reject(e.what()); });
return;
}

this->cryptoThread->scheduleTask([=, &innerRt]() {
std::string error;

std::string backupID;
try {
backupID = crypto::Tools::generateRandomURLSafeString(32);
Expand All @@ -2542,7 +2573,7 @@ jsi::Value CommCoreModule::createNewBackupInternal(
{promise, this->jsInvoker_, innerRt});
::createBackup(
rust::string(backupID),
rust::string(backupSecret),
rust::string(backupSecretStr),
rust::string(pickleKey),
rust::string(pickledAccount),
rust::string(backupMessage),
Expand All @@ -2555,54 +2586,15 @@ jsi::Value CommCoreModule::createNewBackupInternal(
});
}

jsi::Value
CommCoreModule::createNewBackup(jsi::Runtime &rt, jsi::String backupSecret) {
std::string backupSecretStr = backupSecret.utf8(rt);
return createNewBackupInternal(rt, backupSecretStr, "");
}

jsi::Value CommCoreModule::createNewSIWEBackup(
jsi::Runtime &rt,
jsi::String backupSecret,
jsi::String siweBackupMsg) {
std::string backupSecretStr = backupSecret.utf8(rt);
std::string siweBackupMsgStr = siweBackupMsg.utf8(rt);
return createNewBackupInternal(rt, backupSecretStr, siweBackupMsgStr);
}

jsi::Value CommCoreModule::createUserKeysBackup(
jsi::Runtime &rt,
jsi::String backupSecret) {
std::string backupSecretStr = backupSecret.utf8(rt);
return createPromiseAsJSIValue(
rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
std::promise<std::string> backupSIWEMessagePromise;
std::future<std::string> backupSIWEMessageFuture =
backupSIWEMessagePromise.get_future();

GlobalDBSingleton::instance.scheduleOrRunCancellable(
[=, &backupSIWEMessagePromise]() {
try {
std::string backupSecrets =
DatabaseManager::getQueryExecutor().getMetadata(
"siweBackupSecrets");
if (!backupSecrets.size()) {
backupSIWEMessagePromise.set_value("");
} else {
folly::dynamic backupSecretsJSON =
folly::parseJson(backupSecrets);
std::string message = backupSecretsJSON["message"].asString();
backupSIWEMessagePromise.set_value(message);
}
} catch (std::system_error &e) {
backupSIWEMessagePromise.set_exception(
std::make_exception_ptr(e));
}
});

std::string backupMessage;
try {
backupMessage = backupSIWEMessageFuture.get();
backupMessage = getSIWEBackupMessage();
} catch (std::system_error &e) {
this->jsInvoker_->invokeAsync(
[=, &innerRt]() { promise->reject(e.what()); });
Expand Down
6 changes: 1 addition & 5 deletions native/cpp/CommonCpp/NativeModules/CommCoreModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,7 @@ class CommCoreModule : public facebook::react::CommCoreModuleSchemaCxxSpecJSI {
virtual void startBackupHandler(jsi::Runtime &rt) override;
virtual void stopBackupHandler(jsi::Runtime &rt) override;
virtual jsi::Value
createNewBackup(jsi::Runtime &rt, jsi::String backupSecret) override;
virtual jsi::Value createNewSIWEBackup(
jsi::Runtime &rt,
jsi::String backupSecret,
jsi::String siweBackupMsg) override;
createFullBackup(jsi::Runtime &rt, jsi::String backupSecret) override;
virtual jsi::Value
createUserKeysBackup(jsi::Runtime &rt, jsi::String backupSecret) override;
virtual jsi::Value restoreBackup(
Expand Down
12 changes: 4 additions & 8 deletions native/cpp/CommonCpp/_generated/commJSI-generated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,15 +181,12 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_stopBackupHandle
static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->stopBackupHandler(rt);
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));
}
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewSIWEBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->createNewSIWEBackup(rt, args[0].asString(rt), args[1].asString(rt));
}
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createUserKeysBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->createUserKeysBackup(rt, args[0].asString(rt));
}
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createFullBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->createFullBackup(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), args[1].asString(rt), args[2].asString(rt));
}
Expand Down Expand Up @@ -304,9 +301,8 @@ CommCoreModuleSchemaCxxSpecJSI::CommCoreModuleSchemaCxxSpecJSI(std::shared_ptr<C
methodMap_["clearCommServicesAccessToken"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_clearCommServicesAccessToken};
methodMap_["startBackupHandler"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_startBackupHandler};
methodMap_["stopBackupHandler"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_stopBackupHandler};
methodMap_["createNewBackup"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewBackup};
methodMap_["createNewSIWEBackup"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewSIWEBackup};
methodMap_["createUserKeysBackup"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createUserKeysBackup};
methodMap_["createFullBackup"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createFullBackup};
methodMap_["restoreBackup"] = MethodMetadata {3, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackup};
methodMap_["restoreBackupData"] = MethodMetadata {4, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackupData};
methodMap_["retrieveBackupKeys"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_retrieveBackupKeys};
Expand Down
27 changes: 9 additions & 18 deletions native/cpp/CommonCpp/_generated/commJSI.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,8 @@ class JSI_EXPORT CommCoreModuleSchemaCxxSpecJSI : public TurboModule {
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) = 0;
virtual jsi::Value createNewSIWEBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String siweBackupMsg) = 0;
virtual jsi::Value createUserKeysBackup(jsi::Runtime &rt, jsi::String backupSecret) = 0;
virtual jsi::Value createFullBackup(jsi::Runtime &rt, jsi::String backupSecret) = 0;
virtual jsi::Value restoreBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String maxVersion, jsi::String backupID) = 0;
virtual jsi::Value restoreBackupData(jsi::Runtime &rt, jsi::String backupID, jsi::String backupDataKey, jsi::String backupLogDataKey, jsi::String maxVersion) = 0;
virtual jsi::Value retrieveBackupKeys(jsi::Runtime &rt, jsi::String backupSecret, jsi::String backupID) = 0;
Expand Down Expand Up @@ -549,22 +548,6 @@ class JSI_EXPORT CommCoreModuleSchemaCxxSpec : public TurboModule {
return bridging::callFromJs<void>(
rt, &T::stopBackupHandler, jsInvoker_, instance_);
}
jsi::Value createNewBackup(jsi::Runtime &rt, jsi::String backupSecret) override {
static_assert(
bridging::getParameterCount(&T::createNewBackup) == 2,
"Expected createNewBackup(...) to have 2 parameters");

return bridging::callFromJs<jsi::Value>(
rt, &T::createNewBackup, jsInvoker_, instance_, std::move(backupSecret));
}
jsi::Value createNewSIWEBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String siweBackupMsg) override {
static_assert(
bridging::getParameterCount(&T::createNewSIWEBackup) == 3,
"Expected createNewSIWEBackup(...) to have 3 parameters");

return bridging::callFromJs<jsi::Value>(
rt, &T::createNewSIWEBackup, jsInvoker_, instance_, std::move(backupSecret), std::move(siweBackupMsg));
}
jsi::Value createUserKeysBackup(jsi::Runtime &rt, jsi::String backupSecret) override {
static_assert(
bridging::getParameterCount(&T::createUserKeysBackup) == 2,
Expand All @@ -573,6 +556,14 @@ class JSI_EXPORT CommCoreModuleSchemaCxxSpec : public TurboModule {
return bridging::callFromJs<jsi::Value>(
rt, &T::createUserKeysBackup, jsInvoker_, instance_, std::move(backupSecret));
}
jsi::Value createFullBackup(jsi::Runtime &rt, jsi::String backupSecret) override {
static_assert(
bridging::getParameterCount(&T::createFullBackup) == 2,
"Expected createFullBackup(...) to have 2 parameters");

return bridging::callFromJs<jsi::Value>(
rt, &T::createFullBackup, jsInvoker_, instance_, std::move(backupSecret));
}
jsi::Value restoreBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String maxVersion, jsi::String backupID) override {
static_assert(
bridging::getParameterCount(&T::restoreBackup) == 4,
Expand Down
13 changes: 5 additions & 8 deletions native/profile/backup-menu.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,19 @@ function BackupMenu(props: Props): React.Node {
state => state.localSettings.isBackupEnabled,
);

const {
uploadBackupProtocol,
retrieveLatestBackupInfo,
createUserKeysBackup,
} = useClientBackup();
const { createFullBackup, retrieveLatestBackupInfo, createUserKeysBackup } =
useClientBackup();

const uploadBackup = React.useCallback(async () => {
let message = 'Success';
try {
await uploadBackupProtocol();
await createFullBackup();
} catch (e) {
message = `Backup upload error: ${String(getMessageForException(e))}`;
console.error(message);
}
Alert.alert('Upload protocol result', message);
}, [uploadBackupProtocol]);
}, [createFullBackup]);

const uploadUserKeys = React.useCallback(async () => {
let message = 'Success';
Expand Down Expand Up @@ -173,7 +170,7 @@ function BackupMenu(props: Props): React.Node {
iosHighlightUnderlayColor={colors.panelIosHighlightUnderlay}
iosActiveOpacity={0.85}
>
<Text style={styles.submenuText}>Test backup upload protocol</Text>
<Text style={styles.submenuText}>Test Full Backup upload</Text>
</Button>
</View>
<View style={styles.section}>
Expand Down
6 changes: 1 addition & 5 deletions native/schema/CommCoreModuleSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,8 @@ interface Spec extends TurboModule {
+clearCommServicesAccessToken: () => Promise<void>;
+startBackupHandler: () => void;
+stopBackupHandler: () => void;
+createNewBackup: (backupSecret: string) => Promise<void>;
+createNewSIWEBackup: (
backupSecret: string,
siweBackupMsg: string,
) => Promise<void>;
+createUserKeysBackup: (backupSecret: string) => Promise<void>;
+createFullBackup: (backupSecret: string) => Promise<void>;
+restoreBackup: (
backupSecret: string,
maxVersion: string,
Expand Down

0 comments on commit f2be17b

Please sign in to comment.