diff --git a/native/components/prekeys-handler.react.js b/native/components/prekeys-handler.react.js new file mode 100644 --- /dev/null +++ b/native/components/prekeys-handler.react.js @@ -0,0 +1,49 @@ +// @flow + +import * as React from 'react'; + +import { isLoggedIn } from 'lib/selectors/user-selectors.js'; +import { useSelector } from 'lib/utils/redux-utils.js'; + +import { commCoreModule } from '../native-modules.js'; + +// Time after which rotation is started +const PREKEY_ROTATION_TIMEOUT = 3 * 1000; // in milliseconds + +function PrekeysHandler(): null { + const loggedIn = useSelector(isLoggedIn); + + React.useEffect(() => { + if (!loggedIn) { + return undefined; + } + + const timeoutID = setTimeout(async () => { + const authMetadata = await commCoreModule.getCommServicesAuthMetadata(); + const { userID, deviceID, accessToken } = authMetadata; + if (!userID || !deviceID || !accessToken) { + console.log( + 'CommServicesAuthMetadata is missing while validating prekeys', + ); + return; + } + + try { + await commCoreModule.initializeCryptoAccount(); + await commCoreModule.validateAndUploadPrekeys( + userID, + deviceID, + accessToken, + ); + } catch (e) { + console.log('Prekey validation error: ', e.message); + } + }, PREKEY_ROTATION_TIMEOUT); + + return () => clearTimeout(timeoutID); + }, [loggedIn]); + + return null; +} + +export default PrekeysHandler; 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 @@ -72,7 +72,11 @@ jsi::Runtime &rt, double oneTimeKeysAmount) override; virtual jsi::Value generateAndGetPrekeys(jsi::Runtime &rt) override; - virtual jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt) override; + virtual jsi::Value validateAndUploadPrekeys( + jsi::Runtime &rt, + jsi::String authUserID, + jsi::String authDeviceID, + jsi::String authAccessToken) override; virtual jsi::Value initializeNotificationsSession( jsi::Runtime &rt, jsi::String identityKeys, 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 @@ -12,6 +12,7 @@ #include #include +#include "JSIRust.h" #include "lib.rs.h" #include @@ -654,7 +655,14 @@ }); } -jsi::Value CommCoreModule::validateAndUploadPrekeys(jsi::Runtime &rt) { +jsi::Value CommCoreModule::validateAndUploadPrekeys( + jsi::Runtime &rt, + jsi::String authUserID, + jsi::String authDeviceID, + jsi::String authAccessToken) { + auto authUserIDRust = jsiStringToRustString(authUserID, rt); + auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt); + auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt); return createPromiseAsJSIValue( rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { taskType job = [=, &innerRt]() { @@ -688,7 +696,6 @@ try { std::string prekeySignature = this->cryptoModule->getPrekeySignature(); - // TODO: Implement notifs prekey rotation. // Notifications prekey is not rotated at this moment. It // is fetched with signature to match identity service API. std::string notificationsPrekey = @@ -697,7 +704,23 @@ NotificationsCryptoModule::getNotificationsPrekeySignature( "Comm"); try { - // TODO: upload prekey to identity service + std::promise prekeyPromise; + std::future prekeyFuture = + prekeyPromise.get_future(); + RustPromiseManager::CPPPromiseInfo promiseInfo = { + std::move(prekeyPromise)}; + auto currentID = RustPromiseManager::instance.addPromise( + std::move(promiseInfo)); + ::identityRefreshUserPrekeys( + authUserIDRust, + authDeviceIDRust, + authAccessTokenRust, + rust::string(prekeyToUpload), + rust::string(prekeySignature), + rust::string(notificationsPrekey), + rust::string(notificationsPrekeySignature), + currentID); + prekeyFuture.get(); } catch (const std::exception &e) { prekeyUploadError = e.what(); } 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 @@ -76,7 +76,7 @@ return static_cast(&turboModule)->generateAndGetPrekeys(rt); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_validateAndUploadPrekeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->validateAndUploadPrekeys(rt); + return static_cast(&turboModule)->validateAndUploadPrekeys(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt)); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->initializeNotificationsSession(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt)); @@ -180,7 +180,7 @@ methodMap_["getPrimaryOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getPrimaryOneTimeKeys}; methodMap_["getNotificationsOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getNotificationsOneTimeKeys}; methodMap_["generateAndGetPrekeys"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_generateAndGetPrekeys}; - methodMap_["validateAndUploadPrekeys"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_validateAndUploadPrekeys}; + methodMap_["validateAndUploadPrekeys"] = MethodMetadata {3, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_validateAndUploadPrekeys}; methodMap_["initializeNotificationsSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeNotificationsSession}; methodMap_["isNotificationsSessionInitialized"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_isNotificationsSessionInitialized}; methodMap_["initializeContentOutboundSession"] = MethodMetadata {5, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeContentOutboundSession}; 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 @@ -40,7 +40,7 @@ virtual jsi::Value getPrimaryOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; virtual jsi::Value getNotificationsOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; virtual jsi::Value generateAndGetPrekeys(jsi::Runtime &rt) = 0; - virtual jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt) = 0; + virtual jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken) = 0; virtual jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys, jsi::String keyserverID) = 0; virtual jsi::Value isNotificationsSessionInitialized(jsi::Runtime &rt) = 0; virtual jsi::Value initializeContentOutboundSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys, jsi::String deviceID) = 0; @@ -247,13 +247,13 @@ return bridging::callFromJs( rt, &T::generateAndGetPrekeys, jsInvoker_, instance_); } - jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt) override { + jsi::Value validateAndUploadPrekeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken) override { static_assert( - bridging::getParameterCount(&T::validateAndUploadPrekeys) == 1, - "Expected validateAndUploadPrekeys(...) to have 1 parameters"); + bridging::getParameterCount(&T::validateAndUploadPrekeys) == 4, + "Expected validateAndUploadPrekeys(...) to have 4 parameters"); return bridging::callFromJs( - rt, &T::validateAndUploadPrekeys, jsInvoker_, instance_); + rt, &T::validateAndUploadPrekeys, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken)); } jsi::Value initializeNotificationsSession(jsi::Runtime &rt, jsi::String identityKeys, jsi::String prekey, jsi::String prekeySignature, jsi::String oneTimeKeys, jsi::String keyserverID) override { static_assert( diff --git a/native/root.react.js b/native/root.react.js --- a/native/root.react.js +++ b/native/root.react.js @@ -42,6 +42,7 @@ import MessageEditingContextProvider from './chat/message-editing-context-provider.react.js'; import { FeatureFlagsProvider } from './components/feature-flags-provider.react.js'; import PersistedStateGate from './components/persisted-state-gate.js'; +import PrekeysHandler from './components/prekeys-handler.react.js'; import VersionSupportedChecker from './components/version-supported.react.js'; import ConnectedStatusBar from './connected-status-bar.react.js'; import { SQLiteDataHandler } from './data/sqlite-data-handler.js'; @@ -340,6 +341,7 @@ } /> + {navigation} diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -82,7 +82,11 @@ oneTimeKeysAmount: number, ) => Promise; +generateAndGetPrekeys: () => Promise; - +validateAndUploadPrekeys: () => Promise; + +validateAndUploadPrekeys: ( + authUserID: string, + authDeviceID: string, + authAccessToken: string, + ) => Promise; +initializeNotificationsSession: ( identityKeys: string, prekey: string,