diff --git a/native/cpp/CommonCpp/NativeModules/CommRustModule.h b/native/cpp/CommonCpp/NativeModules/CommRustModule.h --- a/native/cpp/CommonCpp/NativeModules/CommRustModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommRustModule.h @@ -86,14 +86,30 @@ jsi::String authDeviceID, jsi::String authAccessToken, jsi::String keyserverID) override; - virtual jsi::Value getDeviceListForUser( - virtual jsi::Value updateDeviceList(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String updatePayload) override; - jsi::Runtime &rt, - jsi::String authUserID, - jsi::String authDeviceID, - jsi::String authAccessToken, - jsi::String userID, - std::optional sinceTimestamp) override; + virtual jsi::Value + getDeviceListForUser(virtual jsi::Value updateDeviceList( + jsi::Runtime &rt, + jsi::String authUserID, + jsi::String authDeviceID, + jsi::String authAccessToken, + jsi::String updatePayload) override; + virtual jsi::Value logInSecondaryDevice( + jsi::Runtime & rt, + jsi::String userID, + jsi::String keyPayload, + jsi::String keyPayloadSignature, + jsi::String contentPrekey, + jsi::String contentPrekeySignature, + jsi::String notifPrekey, + jsi::String notifPrekeySignature, + jsi::Array contentOneTimeKeys, + jsi::Array notifOneTimeKeys) override; + jsi::Runtime & rt, + jsi::String authUserID, + jsi::String authDeviceID, + jsi::String authAccessToken, + jsi::String userID, + std::optional sinceTimestamp) override; public: CommRustModule(std::shared_ptr jsInvoker); diff --git a/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp b/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp @@ -476,4 +476,55 @@ }); } +jsi::Value CommRustModule::logInSecondaryDevice( + jsi::Runtime &rt, + jsi::String userID, + jsi::String keyPayload, + jsi::String keyPayloadSignature, + jsi::String contentPrekey, + jsi::String contentPrekeySignature, + jsi::String notifPrekey, + jsi::String notifPrekeySignature, + jsi::Array contentOneTimeKeys, + jsi::Array notifOneTimeKeys) { + auto userIDRust = jsiStringToRustString(userID, rt); + auto keyPayloadRust = jsiStringToRustString(keyPayload, rt); + auto keyPayloadSignatureRust = jsiStringToRustString(keyPayloadSignature, rt); + auto contentPrekeyRust = jsiStringToRustString(contentPrekey, rt); + auto contentPrekeySignatureRust = + jsiStringToRustString(contentPrekeySignature, rt); + auto notifPrekeyRust = jsiStringToRustString(notifPrekey, rt); + auto notifPrekeySignatureRust = + jsiStringToRustString(notifPrekeySignature, rt); + auto contentOneTimeKeysRust = jsiStringArrayToRustVec(contentOneTimeKeys, rt); + auto notifOneTimeKeysRust = jsiStringArrayToRustVec(notifOneTimeKeys, rt); + + return createPromiseAsJSIValue( + rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr promise) { + std::string error; + try { + auto currentID = RustPromiseManager::instance.addPromise( + {promise, this->jsInvoker_, innerRt}); + identityLogInSecondaryDevice( + userIDRust, + keyPayloadRust, + keyPayloadSignatureRust, + contentPrekeyRust, + contentPrekeySignatureRust, + notifPrekeyRust, + notifPrekeySignatureRust, + contentOneTimeKeysRust, + notifOneTimeKeysRust, + currentID); + } catch (const std::exception &e) { + error = e.what(); + }; + if (!error.empty()) { + this->jsInvoker_->invokeAsync( + [error, promise]() { promise->reject(error); }); + } + }); + return jsi::Value::undefined(); +} + } // namespace comm diff --git a/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp b/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp --- a/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp @@ -51,6 +51,9 @@ static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_updateDeviceList(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->updateDeviceList(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt)); } +static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_logInSecondaryDevice(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->logInSecondaryDevice(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asObject(rt).asArray(rt), args[8].asObject(rt).asArray(rt)); +} CommRustModuleSchemaCxxSpecJSI::CommRustModuleSchemaCxxSpecJSI(std::shared_ptr jsInvoker) : TurboModule("CommRustTurboModule", jsInvoker) { @@ -67,6 +70,7 @@ methodMap_["getKeyserverKeys"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getKeyserverKeys}; methodMap_["getDeviceListForUser"] = MethodMetadata {5, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getDeviceListForUser}; methodMap_["updateDeviceList"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_updateDeviceList}; + methodMap_["logInSecondaryDevice"] = MethodMetadata {9, __hostFunction_CommRustModuleSchemaCxxSpecJSI_logInSecondaryDevice}; } diff --git a/native/cpp/CommonCpp/_generated/rustJSI.h b/native/cpp/CommonCpp/_generated/rustJSI.h --- a/native/cpp/CommonCpp/_generated/rustJSI.h +++ b/native/cpp/CommonCpp/_generated/rustJSI.h @@ -33,6 +33,7 @@ virtual jsi::Value getKeyserverKeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String keyserverID) = 0; virtual jsi::Value getDeviceListForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID, std::optional sinceTimestamp) = 0; virtual jsi::Value updateDeviceList(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String updatePayload) = 0; + virtual jsi::Value logInSecondaryDevice(jsi::Runtime &rt, jsi::String userID, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys) = 0; }; @@ -158,6 +159,14 @@ return bridging::callFromJs( rt, &T::updateDeviceList, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(updatePayload)); } + jsi::Value logInSecondaryDevice(jsi::Runtime &rt, jsi::String userID, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys) override { + static_assert( + bridging::getParameterCount(&T::logInSecondaryDevice) == 10, + "Expected logInSecondaryDevice(...) to have 10 parameters"); + + return bridging::callFromJs( + rt, &T::logInSecondaryDevice, jsInvoker_, instance_, std::move(userID), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature), std::move(contentOneTimeKeys), std::move(notifOneTimeKeys)); + } private: T *instance_; 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 @@ -14,7 +14,8 @@ use grpc_clients::identity::protos::unauth::{ DeviceKeyUpload, DeviceType, Empty, IdentityKeyInfo, OpaqueLoginFinishRequest, OpaqueLoginStartRequest, Prekey, - RegistrationFinishRequest, RegistrationStartRequest, WalletLoginRequest, + RegistrationFinishRequest, RegistrationStartRequest, + SecondaryDeviceLoginRequest, WalletLoginRequest, }; use grpc_clients::identity::{ get_auth_client, get_unauthenticated_client, REQUEST_METADATA_COOKIE_KEY, @@ -194,6 +195,20 @@ promise_id: u32, ); + #[cxx_name = "identityLogInSecondaryDevice"] + fn log_in_secondary_device( + user_id: String, + key_payload: String, + key_payload_signature: String, + content_prekey: String, + content_prekey_signature: String, + notif_prekey: String, + notif_prekey_signature: String, + content_one_time_keys: Vec, + notif_one_time_keys: Vec, + promise_id: u32, + ); + // Argon2 #[cxx_name = "compute_backup_key"] fn compute_backup_key_str( @@ -1355,6 +1370,72 @@ Ok(response.signed_device_list) } +fn log_in_secondary_device( + user_id: String, + key_payload: String, + key_payload_signature: String, + content_prekey: String, + content_prekey_signature: String, + notif_prekey: String, + notif_prekey_signature: String, + content_one_time_keys: Vec, + notif_one_time_keys: Vec, + promise_id: u32, +) { + RUNTIME.spawn(async move { + let device_key_upload = DeviceKeyUpload { + device_key_info: Some(IdentityKeyInfo { + payload: key_payload, + payload_signature: key_payload_signature, + social_proof: None, + }), + content_upload: Some(Prekey { + prekey: content_prekey, + prekey_signature: content_prekey_signature, + }), + notif_upload: Some(Prekey { + prekey: notif_prekey, + prekey_signature: notif_prekey_signature, + }), + one_time_content_prekeys: content_one_time_keys, + one_time_notif_prekeys: notif_one_time_keys, + device_type: DEVICE_TYPE.into(), + }; + + let result = + log_in_secondary_device_helper(user_id, device_key_upload).await; + handle_string_result_as_callback(result, promise_id); + }); +} + +async fn log_in_secondary_device_helper( + user_id: String, + device_key_upload: DeviceKeyUpload, +) -> Result { + let mut identity_client = get_unauthenticated_client( + IDENTITY_SOCKET_ADDR, + CODE_VERSION, + DEVICE_TYPE.as_str_name().to_lowercase(), + ) + .await?; + + let request = SecondaryDeviceLoginRequest { + user_id, + device_key_upload: Some(device_key_upload), + }; + + let response = identity_client + .log_in_secondary_device(request) + .await? + .into_inner(); + + let user_id_and_access_token = UserIDAndDeviceAccessToken { + user_id: response.user_id, + access_token: response.access_token, + }; + Ok(serde_json::to_string(&user_id_and_access_token)?) +} + #[derive( Debug, derive_more::Display, derive_more::From, derive_more::Error, )] diff --git a/native/schema/CommRustModuleSchema.js b/native/schema/CommRustModuleSchema.js --- a/native/schema/CommRustModuleSchema.js +++ b/native/schema/CommRustModuleSchema.js @@ -94,6 +94,17 @@ authAccessToken: string, updatePayload: string, ) => Promise; + +logInSecondaryDevice: ( + userID: string, + keyPayload: string, + keyPayloadSignature: string, + contentPrekey: string, + contentPrekeySignature: string, + notifPrekey: string, + notifPrekeySignature: string, + contentOneTimeKeys: $ReadOnlyArray, + notifOneTimeKeys: $ReadOnlyArray, + ) => Promise; } export default (TurboModuleRegistry.getEnforcing(