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 @@ -12,11 +12,14 @@ }, http::{ auth_service::Authenticated, - multipart::{get_named_text_field, get_text_field}, + multipart::{ + get_all_remaining_fields, get_named_text_field, get_text_field, + parse_bytes_to_string, + }, }, tools::Defer, }; -use std::convert::Infallible; +use std::{collections::HashMap, convert::Infallible}; use tokio_stream::{wrappers::ReceiverStream, StreamExt}; use tracing::{info, instrument, trace, warn}; @@ -49,7 +52,8 @@ let (attachments, attachments_revokes) = multipart.process_attachmens_field(&blob_client).await?; - let siwe_backup_msg = multipart.get_siwe_backup_msg().await?; + let aux_data = multipart.get_aux_data().await?; + let siwe_backup_msg = aux_data.get_siwe_backup_msg()?; let item = BackupItem::new( user.user_id.clone(), @@ -326,7 +330,8 @@ .forward_field_to_blob(blob_client, "user_keys_hash", "user_keys") .await?; - let siwe_backup_msg = multipart.get_siwe_backup_msg().await?; + let aux_data = multipart.get_aux_data().await?; + let siwe_backup_msg = aux_data.get_siwe_backup_msg()?; let ordered_backup_item = db_client .find_last_backup_item(user_id) .await @@ -453,9 +458,6 @@ data_field_name: &str, ) -> actix_web::Result<(BlobInfo, Defer<'revoke>)>; - /// Consumes a text field named `siwe_backup_msg` - async fn get_siwe_backup_msg(&mut self) -> actix_web::Result>; - /// Consumes a text field named `attachments`. /// For each attachment hash, establishes a new blob holder. /// Returns BlobInfos and a revoke handle for removing the holder @@ -465,6 +467,9 @@ &mut self, blob_client: &'blob BlobServiceClient, ) -> Result<(Vec, Vec>), BackupError>; + + /// Consumes all remaining fields and stores them in [`BackupAuxFields`] + async fn get_aux_data(&mut self) -> actix_web::Result; } impl BackupRequestInput for actix_multipart::Multipart { @@ -539,16 +544,6 @@ Ok((blob_info, revoke_holder)) } - #[instrument(skip_all)] - async fn get_siwe_backup_msg(&mut self) -> actix_web::Result> { - Ok( - get_text_field(self) - .await? - .filter(|(name, _)| name == "siwe_backup_msg") - .map(|(_, siwe_backup_msg)| siwe_backup_msg), - ) - } - #[instrument(skip_all)] async fn process_attachmens_field<'revoke, 'blob: 'revoke>( &mut self, @@ -573,6 +568,24 @@ blob_utils::create_holders_for_blob_hashes(attachments_hashes, blob_client) .await } + + async fn get_aux_data(&mut self) -> actix_web::Result { + let field_map = get_all_remaining_fields(self).await?; + Ok(BackupAuxFields(field_map)) + } +} + +struct BackupAuxFields(HashMap>); + +impl BackupAuxFields { + fn get_siwe_backup_msg(&self) -> actix_web::Result> { + let Some(buf) = self.0.get("siwe_backup_msg") else { + return Ok(None); + }; + + let siwe_backup_msg = parse_bytes_to_string(buf.clone())?; + Ok(Some(siwe_backup_msg)) + } } mod blob_utils { diff --git a/shared/comm-lib/src/http/multipart.rs b/shared/comm-lib/src/http/multipart.rs --- a/shared/comm-lib/src/http/multipart.rs +++ b/shared/comm-lib/src/http/multipart.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use actix_multipart::{Field, MultipartError}; use actix_web::error::{ErrorBadRequest, ParseError}; use tokio_stream::StreamExt; @@ -36,8 +38,7 @@ buf.extend_from_slice(&chunk); } - let text = - String::from_utf8(buf).map_err(|err| ParseError::Utf8(err.utf8_error()))?; + let text = parse_bytes_to_string(buf)?; Ok(Some((name, text))) } @@ -58,3 +59,28 @@ Ok(backup_id) } + +pub async fn get_all_remaining_fields( + multipart: &mut actix_multipart::Multipart, +) -> Result>, MultipartError> { + let mut found_fields = HashMap::new(); + + while let Some(mut field) = multipart.try_next().await? { + let name = field.name().to_string(); + let mut buf = Vec::new(); + while let Some(chunk) = field.try_next().await? { + buf.extend_from_slice(&chunk); + } + found_fields.insert(name, buf); + } + + Ok(found_fields) +} + +pub fn parse_bytes_to_string( + utf8_buffer: Vec, +) -> Result { + let parsed_string = String::from_utf8(utf8_buffer) + .map_err(|err| ParseError::Utf8(err.utf8_error()))?; + Ok(parsed_string) +}