Skip to content

Commit

Permalink
[native][backup_client] Handle BackupNotFound in retrieve_latest_back…
Browse files Browse the repository at this point in the history
…up_info

Summary:
Rust part of [[ https://linear.app/comm/issue/ENG-10039/allow-checking-if-a-user-has-a-backup | ENG-10039 ]]

Depends on D14189

Test Plan:
For:
- user with backup
- without backup
- not existing user

```
lang=javascript
try {
  const result = await retrieveLatestBackupInfo('username123');
  if (result === null) {
    console.log('backup not found');
  } else {
    console.log('backup found', result);
  }
} catch (e) {
  const msg = getMessageForException(e);
  if (msg === 'user_not_found') {
    console.log('user not found');
  } else {
    console.log('error: ' + msg);
  }
}
````

Reviewers: kamil, tomek

Reviewed By: tomek

Subscribers: ashoat

Differential Revision: https://phab.comm.dev/D14190
  • Loading branch information
barthap committed Jan 13, 2025
1 parent 7fa801f commit 5e98f07
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 7 deletions.
29 changes: 23 additions & 6 deletions native/native_rust_library/src/backup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,11 @@ pub mod ffi {
.map_err(|err| err.to_string());

let result = match latest_backup_id_response {
Ok(result) => result,
Ok(Some(result)) => result,
Ok(None) => {
string_callback("".to_string(), promise_id, "null".to_string());
return;
}
Err(error) => {
string_callback(error, promise_id, "".to_string());
return;
Expand Down Expand Up @@ -321,26 +325,34 @@ pub async fn create_siwe_backup_msg_compaction(

async fn download_latest_backup_info(
user_identifier: String,
) -> Result<LatestBackupInfoResponse, Box<dyn Error>> {
) -> Result<Option<LatestBackupInfoResponse>, Box<dyn Error>> {
let backup_client = BackupClient::new(BACKUP_SOCKET_ADDR)?;

let latest_backup_descriptor = BackupDescriptor::Latest { user_identifier };

let backup_info_response = backup_client
let backup_info_response = match backup_client
.download_backup_data(&latest_backup_descriptor, RequestedData::BackupInfo)
.await?;
.await
{
Ok(response) => response,
Err(err) if err.is_backup_not_found() => return Ok(None),
Err(err) if err.is_user_not_found() => {
return Err(Box::new(UserNotFoundError))
}
Err(err) => return Err(err.into()),
};

let LatestBackupInfoResponse {
backup_id,
user_id,
siwe_backup_msg,
} = serde_json::from_slice(&backup_info_response)?;

Ok(LatestBackupInfoResponse {
Ok(Some(LatestBackupInfoResponse {
backup_id,
user_id,
siwe_backup_msg,
})
}))
}

async fn download_backup_keys(
Expand Down Expand Up @@ -419,6 +431,11 @@ fn get_user_identity_from_secure_store() -> Result<UserIdentity, cxx::Exception>
})
}

/// helper struct to generate proper error message string
#[derive(Debug, derive_more::Error, derive_more::Display)]
#[display(fmt = "user_not_found")]
struct UserNotFoundError;

// This struct should match `SIWEBackupData` in `lib/types/backup-types.js`
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
Expand Down
12 changes: 11 additions & 1 deletion shared/backup_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ impl BackupClient {
let response = request.send().await?;

let result = response.error_for_status()?.bytes().await?.to_vec();

Ok(result)
}
}
Expand Down Expand Up @@ -398,6 +397,17 @@ pub enum Error {
Unauthenticated,
InvalidRequest,
}

impl Error {
pub fn is_user_not_found(&self) -> bool {
matches!(self, Self::ReqwestError(err) if err.status() == Some(StatusCode::BAD_REQUEST))
}

pub fn is_backup_not_found(&self) -> bool {
matches!(self, Self::ReqwestError(err) if err.status() == Some(StatusCode::NOT_FOUND))
}
}

impl std::error::Error for Error {}

impl From<InvalidHeaderValue> for Error {
Expand Down

0 comments on commit 5e98f07

Please sign in to comment.