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 @@ -11,6 +11,8 @@ +contentPrekeySignature: string, +notifPrekey: string, +notifPrekeySignature: string, + +username?: ?string, + +walletAddress?: ?string, }; 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 --- 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 @@ -1,4 +1,6 @@ -use grpc_clients::identity::protos::authenticated::InboundKeysForUserRequest; +use grpc_clients::identity::protos::authenticated::{ + inbound_keys_for_user_response::Identifier, InboundKeysForUserRequest, +}; use super::*; @@ -27,12 +29,30 @@ .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))? .into_inner(); - let inbound_key_info = InboundKeyInfoResponse::try_from( + let device_inbound_key_info = DeviceInboundKeyInfo::try_from( response .devices .remove(&device_id) .ok_or(Error::from_status(Status::GenericFailure))?, )?; - Ok(inbound_key_info) + let (username, wallet_address) = match response.identifier { + Some(Identifier::Username(u)) => (Some(u), None), + Some(Identifier::WalletAddress(w)) => (None, Some(w)), + None => (None, None), + }; + + let inbound_key_info_response = InboundKeyInfoResponse { + payload: device_inbound_key_info.payload, + payload_signature: device_inbound_key_info.payload_signature, + social_proof: device_inbound_key_info.social_proof, + content_prekey: device_inbound_key_info.content_prekey, + content_prekey_signature: device_inbound_key_info.content_prekey_signature, + notif_prekey: device_inbound_key_info.notif_prekey, + notif_prekey_signature: device_inbound_key_info.notif_prekey_signature, + username, + wallet_address, + }; + + Ok(inbound_key_info_response) } 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 @@ -140,8 +140,7 @@ pub access_token: String, } -#[napi(object)] -pub struct InboundKeyInfoResponse { +pub struct DeviceInboundKeyInfo { pub payload: String, pub payload_signature: String, pub social_proof: Option, @@ -151,7 +150,7 @@ pub notif_prekey_signature: String, } -impl TryFrom for InboundKeyInfoResponse { +impl TryFrom for DeviceInboundKeyInfo { type Error = Error; fn try_from(key_info: InboundKeyInfo) -> Result { @@ -195,6 +194,19 @@ } } +#[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, + pub username: Option, + pub wallet_address: Option, +} + pub fn handle_grpc_error(error: tonic::Status) -> napi::Error { warn!("Received error: {}", error.message()); Error::new(Status::GenericFailure, error.message()) diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs --- a/services/identity/src/database.rs +++ b/services/identity/src/database.rs @@ -17,7 +17,8 @@ use std::sync::Arc; use crate::ddb_utils::{ - create_one_time_key_partition_key, into_one_time_put_requests, OlmAccountType, + create_one_time_key_partition_key, into_one_time_put_requests, Identifier, + OlmAccountType, }; use crate::error::{consume_error, Error}; use chrono::{DateTime, Utc}; @@ -967,9 +968,7 @@ user_id: &str, get_one_time_keys: bool, ) -> Result, Error> { - let Some(user) = - self.get_item_from_users_table(user_id).await?.item - else { + let Some(user) = self.get_item_from_users_table(user_id).await?.item else { return Ok(None); }; @@ -1098,6 +1097,33 @@ .map_err(|e| Error::AwsSdk(e.into())) } + pub async fn get_user_identifier( + &self, + user_id: &str, + ) -> Result { + let mut user_info = self + .get_item_from_users_table(user_id) + .await? + .item + .ok_or(Error::MissingItem)?; + + let username_result = user_info.take_attr(USERS_TABLE_USERNAME_ATTRIBUTE); + + if let Ok(username) = username_result { + return Ok(Identifier::Username(username)); + } + + let wallet_address_result = + user_info.take_attr(USERS_TABLE_WALLET_ADDRESS_ATTRIBUTE); + + if let Ok(wallet_address) = wallet_address_result { + Ok(Identifier::WalletAddress(wallet_address)) + } else { + error!("Database item is missing an identifier"); + Err(Error::MalformedItem) + } + } + async fn get_all_usernames(&self) -> Result, Error> { let scan_output = self .client diff --git a/services/identity/src/ddb_utils.rs b/services/identity/src/ddb_utils.rs --- a/services/identity/src/ddb_utils.rs +++ b/services/identity/src/ddb_utils.rs @@ -93,3 +93,8 @@ Some(Self::from_utc(naive, Utc)) } } + +pub enum Identifier { + Username(String), + WalletAddress(String), +} diff --git a/services/identity/src/error.rs b/services/identity/src/error.rs --- a/services/identity/src/error.rs +++ b/services/identity/src/error.rs @@ -21,6 +21,8 @@ MissingItem, #[display(...)] DeviceList(DeviceListError), + #[display(...)] + MalformedItem, } #[derive(Debug, derive_more::Display, derive_more::Error)] diff --git a/services/identity/src/grpc_services/authenticated.rs b/services/identity/src/grpc_services/authenticated.rs --- a/services/identity/src/grpc_services/authenticated.rs +++ b/services/identity/src/grpc_services/authenticated.rs @@ -21,10 +21,10 @@ use super::protos::auth::{ find_user_id_request, identity_client_service_server::IdentityClientService, - FindUserIdRequest, FindUserIdResponse, GetDeviceListRequest, - GetDeviceListResponse, InboundKeyInfo, InboundKeysForUserRequest, - InboundKeysForUserResponse, KeyserverKeysResponse, OutboundKeyInfo, - OutboundKeysForUserRequest, OutboundKeysForUserResponse, + inbound_keys_for_user_response, FindUserIdRequest, FindUserIdResponse, + GetDeviceListRequest, GetDeviceListResponse, InboundKeyInfo, + InboundKeysForUserRequest, InboundKeysForUserResponse, KeyserverKeysResponse, + OutboundKeyInfo, OutboundKeysForUserRequest, OutboundKeysForUserResponse, RefreshUserPreKeysRequest, UpdateUserPasswordFinishRequest, UpdateUserPasswordStartRequest, UpdateUserPasswordStartResponse, UploadOneTimeKeysRequest, @@ -163,6 +163,9 @@ &self, request: tonic::Request, ) -> Result, tonic::Status> { + use crate::ddb_utils::Identifier as DBIdentifier; + use inbound_keys_for_user_response::Identifier; + let message = request.into_inner(); let devices_map = self @@ -189,8 +192,21 @@ }) .collect::>(); + let user_identifier = match self + .db_client + .get_user_identifier(&message.user_id) + .await + .map_err(handle_db_error)? + { + DBIdentifier::Username(username) => Identifier::Username(username), + DBIdentifier::WalletAddress(address) => { + Identifier::WalletAddress(address) + } + }; + Ok(tonic::Response::new(InboundKeysForUserResponse { devices: transformed_devices, + identifier: Some(user_identifier), })) } diff --git a/shared/protos/identity_authenticated.proto b/shared/protos/identity_authenticated.proto --- a/shared/protos/identity_authenticated.proto +++ b/shared/protos/identity_authenticated.proto @@ -28,9 +28,10 @@ // - One-time PreKey rpc GetOutboundKeysForUser(OutboundKeysForUserRequest) returns (OutboundKeysForUserResponse) {} - // Called by receivers of a communication request. The reponse will only - // return identity keys (both content and notif keys) and related prekeys per - // device, but will not contain one-time keys. + // Called by receivers of a communication request. The reponse will return + // identity keys (both content and notif keys) and related prekeys per device, + // but will not contain one-time keys. Additionally, the response will contain + // the other user's username. rpc GetInboundKeysForUser(InboundKeysForUserRequest) returns (InboundKeysForUserResponse) {} @@ -114,6 +115,10 @@ message InboundKeysForUserResponse { // Map is keyed on devices' public ed25519 key used for signing map devices = 1; + oneof identifier { + string username = 2; + string wallet_address = 3; + } } message InboundKeysForUserRequest {