diff --git a/native/backup/use-client-backup.js b/native/backup/use-client-backup.js --- a/native/backup/use-client-backup.js +++ b/native/backup/use-client-backup.js @@ -2,13 +2,15 @@ import * as React from 'react'; +import { useInvalidCSATLogOut } from 'lib/actions/user-actions.js'; import { isLoggedIn } from 'lib/selectors/user-selectors.js'; import { - latestBackupInfoResponseValidator, type LatestBackupInfo, + latestBackupInfoResponseValidator, type UserKeys, userKeysResponseValidator, } from 'lib/types/backup-types.js'; +import { getMessageForException } from 'lib/utils/errors.js'; import { assertWithValidator } from 'lib/utils/validation-utils.js'; import { useGetBackupSecretForLoggedInUser } from './use-get-backup-secret.js'; @@ -53,14 +55,31 @@ const loggedIn = useSelector(isLoggedIn); const getBackupSecret = useGetBackupSecretForLoggedInUser(); + const invalidTokenLogOut = useInvalidCSATLogOut(); + const authVerifiedEndpoint: (backupCallPromise: Promise) => Promise = + React.useCallback( + async backupCallPromise => { + try { + return await backupCallPromise; + } catch (e) { + const message = getMessageForException(e); + if (message === 'Unauthenticated') { + void invalidTokenLogOut(); + } + throw e; + } + }, + [invalidTokenLogOut], + ); + const createFullBackup = React.useCallback(async () => { if (!loggedIn || !currentUserID) { throw new Error('Attempt to upload backup for not logged in user.'); } const backupSecret = await getBackupSecret(); - return commCoreModule.createFullBackup(backupSecret); - }, [loggedIn, currentUserID, getBackupSecret]); + return authVerifiedEndpoint(commCoreModule.createFullBackup(backupSecret)); + }, [loggedIn, currentUserID, getBackupSecret, authVerifiedEndpoint]); const createUserKeysBackup = React.useCallback(async () => { if (!loggedIn || !currentUserID) { @@ -68,8 +87,10 @@ } const backupSecret = await getBackupSecret(); - return commCoreModule.createUserKeysBackup(backupSecret); - }, [loggedIn, currentUserID, getBackupSecret]); + return authVerifiedEndpoint( + commCoreModule.createUserKeysBackup(backupSecret), + ); + }, [loggedIn, currentUserID, getBackupSecret, authVerifiedEndpoint]); const retrieveLatestBackupInfo = React.useCallback(async () => { if (!loggedIn || !currentUserID || !currentUserInfo?.username) { 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 @@ -240,11 +240,12 @@ siwe_backup_msg, }; - backup_client + let result = backup_client .upload_backup(user_identity, backup_data) - .await?; + .await + .map_err(|e| e.to_string()); - compaction_upload_promises::resolve(&backup_id, Ok(())); + compaction_upload_promises::resolve(&backup_id, result); tokio::spawn(cleanup_files(backup_id)); Ok(()) 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 @@ -12,7 +12,7 @@ use reqwest::{ header::InvalidHeaderValue, multipart::{Form, Part}, - Body, + Body, StatusCode, }; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; @@ -96,6 +96,13 @@ .send() .await?; + if matches!( + response.status(), + StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN + ) { + return Err(Error::Unauthenticated); + } + response.error_for_status()?; Ok(())