diff --git a/native/native_rust_library/src/backup/upload_handler.rs b/native/native_rust_library/src/backup/upload_handler.rs --- a/native/native_rust_library/src/backup/upload_handler.rs +++ b/native/native_rust_library/src/backup/upload_handler.rs @@ -196,10 +196,17 @@ backup_id: String, ) -> Result<(), BackupHandlerError> { let user_data_path = get_backup_file_path(&backup_id, false)?; - let user_data = tokio::fs::read(&user_data_path).await?; - + let user_data = match tokio::fs::read(&user_data_path).await { + Ok(data) => Some(data), + Err(err) if err.kind() == ErrorKind::NotFound => None, + Err(err) => return Err(err.into()), + }; let user_keys_path = get_backup_user_keys_file_path(&backup_id)?; - let user_keys = tokio::fs::read(&user_keys_path).await?; + let user_keys = match tokio::fs::read(&user_keys_path).await { + Ok(data) => Some(data), + Err(err) if err.kind() == ErrorKind::NotFound => None, + Err(err) => return Err(err.into()), + }; let attachments_path = get_backup_file_path(&backup_id, true)?; let attachments = match tokio::fs::read(&attachments_path).await { diff --git a/services/commtest/src/backup/backup_utils.rs b/services/commtest/src/backup/backup_utils.rs --- a/services/commtest/src/backup/backup_utils.rs +++ b/services/commtest/src/backup/backup_utils.rs @@ -11,14 +11,14 @@ pub fn generate_backup_data(predefined_byte_value: u8) -> BackupData { BackupData { backup_id: Uuid::new_v4().to_string(), - user_keys: generate_stable_nbytes( + user_keys: Some(generate_stable_nbytes( ByteSize::kib(4).as_u64() as usize, Some(predefined_byte_value), - ), - user_data: generate_stable_nbytes( + )), + user_data: Some(generate_stable_nbytes( ByteSize::mib(4).as_u64() as usize, Some(predefined_byte_value), - ), + )), attachments: vec![], siwe_backup_msg: None, } diff --git a/services/commtest/tests/backup_integration_test.rs b/services/commtest/tests/backup_integration_test.rs --- a/services/commtest/tests/backup_integration_test.rs +++ b/services/commtest/tests/backup_integration_test.rs @@ -57,12 +57,12 @@ let user_keys = backup_client .download_backup_data(&second_backup_descriptor, RequestedData::UserKeys) .await?; - assert_eq!(user_keys, backup_data.user_keys); + assert_eq!(Some(user_keys), backup_data.user_keys); let user_data = backup_client .download_backup_data(&second_backup_descriptor, RequestedData::UserData) .await?; - assert_eq!(user_data, backup_data.user_data); + assert_eq!(Some(user_data), backup_data.user_data); // Test latest backup lookup for nonexistent user let latest_backup_descriptor = BackupDescriptor::Latest { @@ -91,7 +91,7 @@ let user_keys = backup_client .download_backup_data(&latest_backup_descriptor, RequestedData::UserKeys) .await?; - assert_eq!(user_keys, backup_data.user_keys); + assert_eq!(Some(user_keys), backup_data.user_keys); // Test log download let log_stream = backup_client diff --git a/services/commtest/tests/backup_performance_test.rs b/services/commtest/tests/backup_performance_test.rs --- a/services/commtest/tests/backup_performance_test.rs +++ b/services/commtest/tests/backup_performance_test.rs @@ -124,7 +124,7 @@ .find(|data| data.backup_id == *backup_id) .expect("Request should return existing backup data"); - assert_eq!(backup.user_keys, user_keys); + assert_eq!(backup.user_keys, Some(user_keys)); } let mut latest_user_data_for_user = vec![]; @@ -159,7 +159,7 @@ .find(|data| data.backup_id == *backup_id) .expect("Request should return existing backup data"); - assert_eq!(backup.user_data, user_data); + assert_eq!(backup.user_data, Some(user_data)); } }) .await diff --git a/shared/backup_client/src/lib.rs b/shared/backup_client/src/lib.rs --- a/shared/backup_client/src/lib.rs +++ b/shared/backup_client/src/lib.rs @@ -57,26 +57,46 @@ } = backup_data; let client = reqwest::Client::new(); - let mut form = Form::new() - .text("backup_id", backup_id) - .text( - "user_keys_hash", - Sha256::digest(&user_keys).encode_hex::(), - ) - .part("user_keys", Part::stream(Body::from(user_keys))) - .text( - "user_data_hash", - Sha256::digest(&user_data).encode_hex::(), - ) - .part("user_data", Part::stream(Body::from(user_data))) - .text("attachments", attachments.join("\n")); + let mut form = Form::new().text("backup_id", backup_id); + + if let Some(user_keys_value) = user_keys.clone() { + form = form + .text( + "user_keys_hash", + Sha256::digest(&user_keys_value).encode_hex::(), + ) + .part("user_keys", Part::stream(Body::from(user_keys_value))); + } + + if let Some(user_data_value) = user_data.clone() { + form = form + .text( + "user_data_hash", + Sha256::digest(&user_data_value).encode_hex::(), + ) + .part("user_data", Part::stream(Body::from(user_data_value))); + } + + form = form.text("attachments", attachments.join("\n")); if let Some(siwe_backup_msg_value) = siwe_backup_msg { form = form.text("siwe_backup_msg", siwe_backup_msg_value); } + if user_data.is_none() && user_keys.is_none() { + return Err(Error::InvalidRequest); + } + + let endpoint = if user_data.is_some() && user_keys.is_some() { + "backups" + } else if user_data.is_some() { + "backups/user_data" + } else { + "backups/user_keys" + }; + let response = client - .post(self.url.join("backups")?) + .post(self.url.join(endpoint)?) .bearer_auth(user_identity.as_authorization_token()?) .multipart(form) .send() @@ -319,8 +339,8 @@ #[derive(Debug, Clone)] pub struct BackupData { pub backup_id: String, - pub user_keys: Vec, - pub user_data: Vec, + pub user_keys: Option>, + pub user_data: Option>, pub attachments: Vec, pub siwe_backup_msg: Option, } @@ -375,6 +395,7 @@ LogMissing, WSClosed, Unauthenticated, + InvalidRequest, } impl std::error::Error for Error {}