diff --git a/Cargo.lock b/Cargo.lock --- a/Cargo.lock +++ b/Cargo.lock @@ -3125,6 +3125,7 @@ "reqwest 0.11.27", "serde", "serde_json", + "sha2 0.10.8", "siwe", "time", "tokio", diff --git a/services/identity/Cargo.toml b/services/identity/Cargo.toml --- a/services/identity/Cargo.toml +++ b/services/identity/Cargo.toml @@ -17,7 +17,7 @@ "aws", "grpc_clients", "blob-client", - "crypto" + "crypto", ] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter", "json"] } @@ -42,7 +42,8 @@ regex = { workspace = true } tower-http = { workspace = true, features = ["cors"] } http = { workspace = true } -reqwest = { workspace = true, features = ["json", "rustls-tls"] } +reqwest = { workspace = true, features = ["json", "multipart", "rustls-tls"] } +sha2 = { workspace = true } futures = { workspace = true } url = { workspace = true } tower = { workspace = true } diff --git a/services/identity/src/comm_service/backup.rs b/services/identity/src/comm_service/backup.rs --- a/services/identity/src/comm_service/backup.rs +++ b/services/identity/src/comm_service/backup.rs @@ -1,4 +1,7 @@ -use comm_lib::auth::AuthService; +use comm_lib::{auth::AuthService, backup::database::BackupItem}; +use hex::ToHex; +use reqwest::multipart::Part; +use sha2::{Digest, Sha256}; use crate::{ config::CONFIG, @@ -82,3 +85,70 @@ } } } + +pub async fn prepare_user_keys( + auth_service: &AuthService, + user_id: &str, + backup_id: &str, + user_keys: Vec, + siwe_backup_msg: Option, +) -> Result { + let path = "/utils/prepare_user_keys"; + let url = CONFIG + .backup_service_url + .join(path) + .expect("failed to construct backup service URL"); + + let services_token = auth_service + .get_services_token() + .await + .map_err(|err| { + tracing::error!( + errorType = error_types::HTTP_LOG, + "Failed to retrieve service-to-service token: {err:?}", + ); + tonic::Status::aborted(tonic_status_messages::UNEXPECTED_ERROR) + })? + .as_authorization_token()?; + + let client = reqwest::Client::builder().build()?; + let mut form = reqwest::multipart::Form::new() + .text("user_id", user_id.to_string()) + .text("backup_id", backup_id.to_string()) + .text( + "user_keys_hash", + Sha256::digest(&user_keys).encode_hex::(), + ) + .part("user_keys", Part::bytes(user_keys)); + + if let Some(siwe_backup_msg_value) = siwe_backup_msg { + form = form.text("siwe_backup_msg", siwe_backup_msg_value); + } + + let response = client + .post(url) + .bearer_auth(services_token) + .multipart(form) + .send() + .await?; + + if let Err(err) = response.error_for_status_ref() { + let response_status = response.status(); + let response_body = response + .text() + .await + .unwrap_or("[failed to get response text]".to_string()); + tracing::error!( + errorType = error_types::HTTP_LOG, + "Backup service failed to prepare user keys: {} - {}", + response_status, + response_body, + ); + + return Err(err.into()); + } + + let backup_item: BackupItem = response.json().await?; + + Ok(backup_item) +}