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 @@ -7,6 +7,16 @@ +accessToken: string, }; +type InboundKeyInfoResponse = { + +payload: string, + +payloadSignature: string, + +socialProof?: ?string, + +contentPrekey: string, + +contentPrekeySignature: string, + +notifPrekey: string, + +notifPrekeySignature: string, +}; + type RustNativeBindingAPI = { +loginUser: ( username: string, @@ -35,7 +45,7 @@ message: string, signature: string, ) => Promise, - +publish_prekeys: ( + +publishPrekeys: ( userId: string, deviceId: string, accessToken: string, @@ -44,6 +54,11 @@ notifPrekey: string, notifPrekeySignature: string, ) => Promise, + +getInboundKeysForUserDevice: ( + identifierType: string, + identifierValue: string, + deviceId: string, + ) => Promise, }; export type { RustNativeBindingAPI }; diff --git a/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs b/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs new file mode 100644 --- /dev/null +++ b/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs @@ -0,0 +1,36 @@ +use super::*; + +#[napi] +#[instrument(skip_all)] +pub async fn get_inbound_keys_for_user_device( + identifier_type: String, + identifier_value: String, + device_id: String, +) -> Result { + // Set up the gRPC client that will be used to talk to the Identity service + let channel = get_identity_service_channel().await?; + let mut identity_client = IdentityClientServiceClient::new(channel); + + let identifier = match identifier_type.as_str() { + "walletAddress" => Some(Identifier::WalletAddress(identifier_value)), + "username" => Some(Identifier::Username(identifier_value)), + _ => return Err(Error::from_status(Status::GenericFailure)), + }; + + let inbound_keys_for_user_request = InboundKeysForUserRequest { identifier }; + + let mut response = identity_client + .get_inbound_keys_for_user(inbound_keys_for_user_request) + .await + .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))? + .into_inner(); + + let inbound_key_info = InboundKeyInfoResponse::try_from( + response + .devices + .remove(&device_id) + .ok_or(Error::from_status(Status::GenericFailure))?, + )?; + + Ok(inbound_key_info) +} diff --git a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs --- a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs @@ -1,5 +1,6 @@ pub mod add_reserved_usernames; pub mod auth_client; +pub mod get_inbound_keys_for_user; pub mod login; pub mod prekey; pub mod register_user; @@ -10,9 +11,10 @@ use identity_client::identity_client_service_client::IdentityClientServiceClient; use identity_client::{ - AddReservedUsernamesRequest, DeviceKeyUpload, DeviceType, IdentityKeyInfo, - PreKey, RegistrationFinishRequest, RegistrationStartRequest, - RemoveReservedUsernameRequest, + inbound_keys_for_user_request::Identifier, AddReservedUsernamesRequest, + DeviceKeyUpload, DeviceType, IdentityKeyInfo, InboundKeyInfo, + InboundKeysForUserRequest, PreKey, RegistrationFinishRequest, + RegistrationStartRequest, RemoveReservedUsernameRequest, }; use lazy_static::lazy_static; use napi::bindgen_prelude::*; @@ -118,6 +120,61 @@ pub access_token: String, } +#[napi(object)] +pub 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 InboundKeyInfoResponse { + type Error = Error; + + fn try_from(key_info: InboundKeyInfo) -> Result { + let identity_info = key_info + .identity_info + .ok_or(Error::from_status(Status::GenericFailure))?; + + let IdentityKeyInfo { + payload, + payload_signature, + social_proof, + } = identity_info; + + let content_prekey = key_info + .content_prekey + .ok_or(Error::from_status(Status::GenericFailure))?; + + 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::from_status(Status::GenericFailure))?; + + 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, + }) + } +} + pub fn handle_grpc_error(error: tonic::Status) -> napi::Error { warn!("Received error: {}", error.message()); Error::new(Status::GenericFailure, error.message())