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 @@ -220,6 +220,8 @@ jsi::Runtime &rt, jsi::String backupSecret, jsi::String siweBackupMsg) override; + virtual jsi::Value + createUserKeysBackup(jsi::Runtime &rt, jsi::String backupSecret) override; virtual jsi::Value restoreBackup( jsi::Runtime &rt, jsi::String backupSecret, 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 @@ -2570,6 +2570,86 @@ 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) { + std::promise backupSIWEMessagePromise; + std::future 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(); + } 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); + } catch (const std::exception &e) { + error = "Failed to generate backupID"; + } + + std::string pickleKey; + std::string pickledAccount; + if (!error.size()) { + try { + pickleKey = crypto::Tools::generateRandomString(64); + crypto::Persist persist = + this->contentCryptoModule->storeAsB64(pickleKey); + pickledAccount = + std::string(persist.account.begin(), persist.account.end()); + } catch (const std::exception &e) { + error = "Failed to pickle crypto account"; + } + } + + if (!error.size()) { + auto currentID = RustPromiseManager::instance.addPromise( + {promise, this->jsInvoker_, innerRt}); + ::createUserKeysBackup( + rust::string(backupID), + rust::string(backupSecretStr), + rust::string(pickleKey), + rust::string(pickledAccount), + rust::string(backupMessage), + currentID); + } else { + this->jsInvoker_->invokeAsync( + [=, &innerRt]() { promise->reject(error); }); + } + }); + }); +} + jsi::Value CommCoreModule::restoreBackup( jsi::Runtime &rt, jsi::String backupSecret, 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 @@ -187,6 +187,9 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewSIWEBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&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(&turboModule)->createUserKeysBackup(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(&turboModule)->restoreBackup(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt)); } @@ -303,6 +306,7 @@ 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_["restoreBackup"] = MethodMetadata {3, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackup}; methodMap_["restoreBackupData"] = MethodMetadata {4, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackupData}; methodMap_["retrieveBackupKeys"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_retrieveBackupKeys}; 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 @@ -76,6 +76,7 @@ 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 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; @@ -564,6 +565,14 @@ return bridging::callFromJs( 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, + "Expected createUserKeysBackup(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::createUserKeysBackup, 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, diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -161,6 +161,7 @@ backupSecret: string, siweBackupMsg: string, ) => Promise; + +createUserKeysBackup: (backupSecret: string) => Promise; +restoreBackup: ( backupSecret: string, maxVersion: string,