diff --git a/keyserver/addons/rust-node-addon/rust-binding-types.js b/keyserver/addons/rust-node-addon/rust-binding-types.js --- a/keyserver/addons/rust-node-addon/rust-binding-types.js +++ b/keyserver/addons/rust-node-addon/rust-binding-types.js @@ -1,17 +1,10 @@ // @flow import type { SignedIdentityKeysBlob } from 'lib/types/crypto-types.js'; -import type { UserLoginResponse } from 'lib/types/identity-service-types.js'; - -type InboundKeyInfoResponse = { - +payload: string, - +payloadSignature: string, - +socialProof?: ?string, - +contentPrekey: string, - +contentPrekeySignature: string, - +notifPrekey: string, - +notifPrekeySignature: string, -}; +import type { + InboundKeyInfoResponse, + UserLoginResponse, +} from 'lib/types/identity-service-types.js'; type RustNativeBindingAPI = { +loginUser: ( diff --git a/lib/types/identity-service-types.js b/lib/types/identity-service-types.js --- a/lib/types/identity-service-types.js +++ b/lib/types/identity-service-types.js @@ -24,3 +24,15 @@ +deviceID: string, +commServicesAccessToken: string, }; + +// This type should not be altered without also updating +// InboundKeyInfoResponse in native/native_rust_library/src/lib.rs +export type InboundKeyInfoResponse = { + +payload: string, + +payloadSignature: string, + +socialProof?: ?string, + +contentPrekey: string, + +contentPrekeySignature: string, + +notifPrekey: string, + +notifPrekeySignature: string, +}; 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 @@ -66,6 +66,12 @@ jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID) override; + virtual jsi::Value getInboundKeysForUser( + jsi::Runtime &rt, + jsi::String authUserID, + jsi::String authDeviceID, + jsi::String authAccessToken, + jsi::String userID) override; virtual jsi::Value versionSupported(jsi::Runtime &rt) override; public: 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 @@ -247,6 +247,30 @@ }); } +jsi::Value CommRustModule::getInboundKeysForUser( + jsi::Runtime &rt, + jsi::String authUserID, + jsi::String authDeviceID, + jsi::String authAccessToken, + jsi::String userID) { + return createPromiseAsJSIValue( + rt, [&, this](jsi::Runtime &innerRt, std::shared_ptr promise) { + std::string error; + try { + auto currentID = RustPromiseManager::instance.addPromise( + promise, this->jsInvoker_, innerRt); + identityGetInboundKeysForUser( + jsiStringToRustString(authUserID, innerRt), + jsiStringToRustString(authDeviceID, innerRt), + jsiStringToRustString(authAccessToken, innerRt), + jsiStringToRustString(userID, innerRt), + currentID); + } catch (const std::exception &e) { + error = e.what(); + }; + }); +} + jsi::Value CommRustModule::versionSupported(jsi::Runtime &rt) { return createPromiseAsJSIValue( rt, [this](jsi::Runtime &innerRt, std::shared_ptr promise) { 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 @@ -33,6 +33,9 @@ static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_getOutboundKeysForUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getOutboundKeysForUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt)); } +static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_getInboundKeysForUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getInboundKeysForUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt)); +} static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_versionSupported(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->versionSupported(rt); } @@ -46,6 +49,7 @@ methodMap_["updatePassword"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_updatePassword}; methodMap_["deleteUser"] = MethodMetadata {3, __hostFunction_CommRustModuleSchemaCxxSpecJSI_deleteUser}; methodMap_["getOutboundKeysForUser"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getOutboundKeysForUser}; + methodMap_["getInboundKeysForUser"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getInboundKeysForUser}; methodMap_["versionSupported"] = MethodMetadata {0, __hostFunction_CommRustModuleSchemaCxxSpecJSI_versionSupported}; } 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 @@ -27,6 +27,7 @@ virtual jsi::Value updatePassword(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String password) = 0; virtual jsi::Value deleteUser(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) = 0; virtual jsi::Value getOutboundKeysForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID) = 0; + virtual jsi::Value getInboundKeysForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID) = 0; virtual jsi::Value versionSupported(jsi::Runtime &rt) = 0; }; @@ -105,6 +106,14 @@ return bridging::callFromJs( rt, &T::getOutboundKeysForUser, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(userID)); } + jsi::Value getInboundKeysForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID) override { + static_assert( + bridging::getParameterCount(&T::getInboundKeysForUser) == 5, + "Expected getInboundKeysForUser(...) to have 5 parameters"); + + return bridging::callFromJs( + rt, &T::getInboundKeysForUser, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(userID)); + } jsi::Value versionSupported(jsi::Runtime &rt) override { static_assert( bridging::getParameterCount(&T::versionSupported) == 1, 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 @@ -3,7 +3,8 @@ use comm_opaque2::grpc::opaque_error_to_grpc_status as handle_error; use ffi::{bool_callback, string_callback, void_callback}; use grpc_clients::identity::protos::authenticated::{ - OutboundKeyInfo, OutboundKeysForUserRequest, UpdateUserPasswordFinishRequest, + InboundKeyInfo, InboundKeysForUserRequest, OutboundKeyInfo, + OutboundKeysForUserRequest, UpdateUserPasswordFinishRequest, UpdateUserPasswordStartRequest, }; use grpc_clients::identity::protos::client::{ @@ -124,6 +125,15 @@ promise_id: u32, ); + #[cxx_name = "identityGetInboundKeysForUser"] + fn get_inbound_keys_for_user( + auth_user_id: String, + auth_device_id: String, + auth_access_token: String, + user_id: String, + promise_id: u32, + ); + #[cxx_name = "identityGenerateNonce"] fn generate_nonce(promise_id: u32); @@ -777,6 +787,10 @@ user_id: String, } +struct GetInboundKeysRequestInfo { + user_id: String, +} + // This struct should not be altered without also updating // OutboundKeyInfoResponse in lib/types/identity-service-types.js #[derive(Serialize)] @@ -793,6 +807,20 @@ pub one_time_notif_prekey: Option, } +// This struct should not be altered without also updating +// InboundKeyInfoResponse in lib/types/identity-service-types.js +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct InboundKeyInfoResponse { + pub payload: String, + pub payload_signature: String, + pub social_proof: Option, + pub content_prekey: String, + pub content_prekey_signature: String, + pub notif_prekey: String, + pub notif_prekey_signature: String, +} + impl TryFrom for OutboundKeyInfoResponse { type Error = Error; @@ -891,6 +919,99 @@ Ok(serde_json::to_string(&outbound_key_info)?) } +impl TryFrom for InboundKeyInfoResponse { + type Error = Error; + + fn try_from(key_info: InboundKeyInfo) -> Result { + let identity_info = + key_info.identity_info.ok_or(Error::MissingResponseData)?; + + let IdentityKeyInfo { + payload, + payload_signature, + social_proof, + } = identity_info; + + let content_prekey = + key_info.content_prekey.ok_or(Error::MissingResponseData)?; + + let PreKey { + pre_key: content_prekey_value, + pre_key_signature: content_prekey_signature, + } = content_prekey; + + let notif_prekey = + key_info.notif_prekey.ok_or(Error::MissingResponseData)?; + + let PreKey { + pre_key: notif_prekey_value, + pre_key_signature: notif_prekey_signature, + } = notif_prekey; + + Ok(Self { + payload, + payload_signature, + social_proof, + content_prekey: content_prekey_value, + content_prekey_signature, + notif_prekey: notif_prekey_value, + notif_prekey_signature, + }) + } +} + +fn get_inbound_keys_for_user( + auth_user_id: String, + auth_device_id: String, + auth_access_token: String, + user_id: String, + promise_id: u32, +) { + RUNTIME.spawn(async move { + let get_inbound_keys_request_info = GetInboundKeysRequestInfo { user_id }; + let auth_info = AuthInfo { + access_token: auth_access_token, + user_id: auth_user_id, + device_id: auth_device_id, + }; + let result = get_inbound_keys_for_user_helper( + get_inbound_keys_request_info, + auth_info, + ) + .await; + handle_string_result_as_callback(result, promise_id); + }); +} + +async fn get_inbound_keys_for_user_helper( + get_inbound_keys_request_info: GetInboundKeysRequestInfo, + auth_info: AuthInfo, +) -> Result { + let mut identity_client = get_auth_client( + IDENTITY_SOCKET_ADDR, + auth_info.user_id, + auth_info.device_id, + auth_info.access_token, + CODE_VERSION, + DEVICE_TYPE.as_str_name().to_lowercase(), + ) + .await?; + let response = identity_client + .get_inbound_keys_for_user(InboundKeysForUserRequest { + user_id: get_inbound_keys_request_info.user_id, + }) + .await? + .into_inner(); + + let inbound_key_info: Vec = response + .devices + .into_values() + .map(InboundKeyInfoResponse::try_from) + .collect::, _>>()?; + + Ok(serde_json::to_string(&inbound_key_info)?) +} + #[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 @@ -61,6 +61,12 @@ authAccessToken: string, userID: string, ) => Promise; + +getInboundKeysForUser: ( + authUserID: string, + authDeviceID: string, + authAccessToken: string, + userID: string, + ) => Promise; +versionSupported: () => Promise; }