diff --git a/native/native_rust_library/src/backup.rs b/native/native_rust_library/src/backup.rs --- a/native/native_rust_library/src/backup.rs +++ b/native/native_rust_library/src/backup.rs @@ -257,6 +257,7 @@ backup_id, user_id, siwe_backup_msg, + .. } = result; let siwe_backup_data = match siwe_backup_msg { @@ -382,12 +383,14 @@ backup_id, user_id, siwe_backup_msg, + keyserver_device_id, } = serde_json::from_slice(&backup_info_response)?; Ok(Some(LatestBackupInfoResponse { backup_id, user_id, siwe_backup_msg, + keyserver_device_id, })) } diff --git a/services/backup/src/http/handlers/backup.rs b/services/backup/src/http/handlers/backup.rs --- a/services/backup/src/http/handlers/backup.rs +++ b/services/backup/src/http/handlers/backup.rs @@ -17,7 +17,7 @@ use tokio_stream::{wrappers::ReceiverStream, StreamExt}; use tracing::{info, instrument, trace, warn}; -use crate::identity::find_user_id; +use crate::identity::{find_keyserver_device_for_user, find_user_id}; use crate::{ database::{backup_item::BackupItem, DatabaseClient}, error::BackupError, @@ -429,6 +429,7 @@ pub async fn get_latest_backup_info( path: web::Path<String>, db_client: web::Data<DatabaseClient>, + auth_service: comm_lib::auth::AuthService, ) -> actix_web::Result<impl Responder> { let user_identifier = path.into_inner(); let user_id = find_user_id(&user_identifier).await?; @@ -441,10 +442,14 @@ return Err(BackupError::NoBackup.into()); }; + let keyserver_device_id = + find_keyserver_device_for_user(&user_id, &auth_service).await?; + let response = LatestBackupInfoResponse { backup_id: backup_item.backup_id, user_id, siwe_backup_msg: backup_item.siwe_backup_msg, + keyserver_device_id, }; Ok(web::Json(response)) diff --git a/services/backup/src/identity/mod.rs b/services/backup/src/identity/mod.rs --- a/services/backup/src/identity/mod.rs +++ b/services/backup/src/identity/mod.rs @@ -2,12 +2,18 @@ use grpc_clients::{ error::Error, identity::{ - get_unauthenticated_client, protos::unauth::FindUserIdRequest, - protos::unauthenticated::find_user_id_request::Identifier, - PlatformMetadata, + authenticated::get_services_auth_client, + get_unauthenticated_client, + protos::{ + auth::{PeersDeviceListsRequest, UserDevicesPlatformDetails}, + unauth::FindUserIdRequest, + unauthenticated::find_user_id_request::Identifier, + }, + DeviceType, PlatformMetadata, }, tonic::Request, }; +use tracing::debug; use crate::config::CONFIG; use crate::error::BackupError; @@ -49,3 +55,43 @@ None => Err(BackupError::NoUserID), } } + +pub async fn find_keyserver_device_for_user( + user_id: &str, + auth_service: &comm_lib::auth::AuthService, +) -> Result<Option<String>, BackupError> { + let services_token = auth_service.get_services_token().await?; + let mut grpc_client = get_services_auth_client( + &CONFIG.identity_endpoint, + services_token.as_str().to_owned(), + PlatformMetadata::new(PLACEHOLDER_CODE_VERSION, DEVICE_TYPE), + ) + .await?; + + let request = PeersDeviceListsRequest { + user_ids: vec![user_id.to_string()], + }; + let response = grpc_client + .get_device_lists_for_users(Request::new(request)) + .await + .map_err(Error::GrpcStatus)? + .into_inner(); + + let Some(UserDevicesPlatformDetails { + devices_platform_details, + }) = response.users_devices_platform_details.get(user_id) + else { + debug!("No device list found for user {user_id}"); + return Ok(None); + }; + + for (device_id, device_details) in devices_platform_details { + if device_details.device_type() == DeviceType::Keyserver { + debug!("Found keyserver for user {user_id}. Device ID: {device_id}"); + return Ok(Some(device_id.to_string())); + } + } + + debug!("No keyserver found for user {user_id}"); + Ok(None) +} diff --git a/shared/comm-lib/src/backup/mod.rs b/shared/comm-lib/src/backup/mod.rs --- a/shared/comm-lib/src/backup/mod.rs +++ b/shared/comm-lib/src/backup/mod.rs @@ -12,6 +12,8 @@ #[serde(rename = "userID")] pub user_id: String, pub siwe_backup_msg: Option<String>, + #[serde(rename = "keyserverDeviceID")] + pub keyserver_device_id: Option<String>, } #[derive(Debug, Clone, Serialize, Deserialize)]