From 53ff51fc333a5c4d72f49577a5ab93c2289145b5 Mon Sep 17 00:00:00 2001 From: yougotwill Date: Fri, 7 Feb 2025 16:41:11 +1100 Subject: [PATCH] feat: validate display names correctly when restoring an account if you use an empty name or just a space it will flag it with the correct error message --- .../registration/stages/RestoreAccount.tsx | 79 +++++++++---------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/ts/components/registration/stages/RestoreAccount.tsx b/ts/components/registration/stages/RestoreAccount.tsx index a48670927..71361c928 100644 --- a/ts/components/registration/stages/RestoreAccount.tsx +++ b/ts/components/registration/stages/RestoreAccount.tsx @@ -1,12 +1,17 @@ import { Dispatch } from '@reduxjs/toolkit'; import { isEmpty } from 'lodash'; import { useDispatch } from 'react-redux'; +import { useState } from 'react'; import { ONBOARDING_TIMES } from '../../../session/constants'; import { InvalidWordsError, NotEnoughWordsError } from '../../../session/crypto/mnemonic'; import { ProfileManager } from '../../../session/profile_manager/ProfileManager'; import { PromiseUtils } from '../../../session/utils'; import { TaskTimedOutError } from '../../../session/utils/Promise'; -import { NotFoundError, RetrieveDisplayNameError } from '../../../session/utils/errors'; +import { + EmptyDisplayNameError, + NotFoundError, + RetrieveDisplayNameError, +} from '../../../session/utils/errors'; import { trigger } from '../../../shims/events'; import { AccountRestoration, @@ -41,11 +46,14 @@ import { resetRegistration } from '../RegistrationStages'; import { ContinueButton, OnboardDescription, OnboardHeading } from '../components'; import { BackButtonWithinContainer } from '../components/BackButton'; import { useRecoveryProgressEffect } from '../hooks'; -import { displayNameIsValid, sanitizeDisplayNameOrToast } from '../utils'; -import { AccountDetails } from './CreateAccount'; import { localize } from '../../../localization/localeTools'; +import { sanitizeDisplayNameOrToast } from '../utils'; -type AccountRestoreDetails = AccountDetails & { dispatch: Dispatch; abortSignal?: AbortSignal }; +type AccountRestoreDetails = { + recoveryPassword: string; + dispatch: Dispatch; + abortSignal?: AbortSignal; +}; export async function finishRestore(pubkey: string, displayName: string) { await setSignWithRecoveryPhrase(true); @@ -96,21 +104,14 @@ async function signInWithNewDisplayName({ displayName, recoveryPassword, dispatch, -}: AccountRestoreDetails) { +}: AccountRestoreDetails & { displayName: string }) { try { - const validDisplayName = displayNameIsValid(displayName); - await resetRegistration(); - await registerSingleDevice( - recoveryPassword, - 'english', - validDisplayName, - async (pubkey: string) => { - dispatch(setHexGeneratedPubKey(pubkey)); - dispatch(setDisplayName(validDisplayName)); - await finishRestore(pubkey, validDisplayName); - } - ); + await registerSingleDevice(recoveryPassword, 'english', displayName, async (pubkey: string) => { + dispatch(setHexGeneratedPubKey(pubkey)); + dispatch(setDisplayName(displayName)); + await finishRestore(pubkey, displayName); + }); } catch (e) { await resetRegistration(); throw e; @@ -129,6 +130,8 @@ export const RestoreAccount = () => { const dispatch = useDispatch(); + const [cannotContinue, setCannotContinue] = useState(true); + useRecoveryProgressEffect(); const recoverAndFetchDisplayName = async () => { @@ -171,18 +174,20 @@ export const RestoreAccount = () => { }; const recoverAndEnterDisplayName = async () => { - if ( - isEmpty(recoveryPassword) || - !isEmpty(recoveryPasswordError) || - isEmpty(displayName) || - !isEmpty(displayNameError) - ) { + if (isEmpty(recoveryPassword) || !isEmpty(recoveryPasswordError)) { return; } try { + const sanitizedName = sanitizeDisplayNameOrToast(displayName); + + // this should never happen, but just in case + if (isEmpty(sanitizedName)) { + return; + } + // this will throw if the display name is too long - const validName = await ProfileManager.updateOurProfileDisplayNameOnboarding(displayName); + const validName = await ProfileManager.updateOurProfileDisplayNameOnboarding(sanitizedName); const trimmedPassword = recoveryPassword.trim(); setRecoveryPassword(trimmedPassword); @@ -196,16 +201,17 @@ export const RestoreAccount = () => { window.log.error( `[onboarding] restore account: Failed with new display name! Error: ${err.message || String(err)}` ); + + setCannotContinue(true); dispatch(setAccountRestorationStep(AccountRestoration.DisplayName)); - if (err instanceof RetrieveDisplayNameError) { + if (err instanceof EmptyDisplayNameError || err instanceof RetrieveDisplayNameError) { dispatch(setDisplayNameError(localize('displayNameErrorDescription').toString())); - return; + } else { + // Note: we have to assume here that libsession threw an error because the name was too long since we covered the other cases. + // The error reported by libsession is not localized + dispatch(setDisplayNameError(localize('displayNameErrorDescriptionShorter').toString())); } - - // Note: we have to assume here that libsession threw an error because the name was too long since we covered the other cases. - // The error reported by libsession is not localized - dispatch(setDisplayNameError(localize('displayNameErrorDescriptionShorter').toString())); } }; @@ -313,12 +319,8 @@ export const RestoreAccount = () => { placeholder={window.i18n('displayNameEnter')} value={displayName} onValueChanged={(name: string) => { - const sanitizedName = sanitizeDisplayNameOrToast( - name, - setDisplayNameError, - dispatch - ); - dispatch(setDisplayName(sanitizedName)); + dispatch(setDisplayName(name)); + setCannotContinue(false); }} onEnterPressed={recoverAndEnterDisplayName} error={displayNameError} @@ -328,10 +330,7 @@ export const RestoreAccount = () => {