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
pull/3281/head
yougotwill 3 months ago
parent 5a20f53906
commit 53ff51fc33

@ -1,12 +1,17 @@
import { Dispatch } from '@reduxjs/toolkit'; import { Dispatch } from '@reduxjs/toolkit';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useState } from 'react';
import { ONBOARDING_TIMES } from '../../../session/constants'; import { ONBOARDING_TIMES } from '../../../session/constants';
import { InvalidWordsError, NotEnoughWordsError } from '../../../session/crypto/mnemonic'; import { InvalidWordsError, NotEnoughWordsError } from '../../../session/crypto/mnemonic';
import { ProfileManager } from '../../../session/profile_manager/ProfileManager'; import { ProfileManager } from '../../../session/profile_manager/ProfileManager';
import { PromiseUtils } from '../../../session/utils'; import { PromiseUtils } from '../../../session/utils';
import { TaskTimedOutError } from '../../../session/utils/Promise'; 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 { trigger } from '../../../shims/events';
import { import {
AccountRestoration, AccountRestoration,
@ -41,11 +46,14 @@ import { resetRegistration } from '../RegistrationStages';
import { ContinueButton, OnboardDescription, OnboardHeading } from '../components'; import { ContinueButton, OnboardDescription, OnboardHeading } from '../components';
import { BackButtonWithinContainer } from '../components/BackButton'; import { BackButtonWithinContainer } from '../components/BackButton';
import { useRecoveryProgressEffect } from '../hooks'; import { useRecoveryProgressEffect } from '../hooks';
import { displayNameIsValid, sanitizeDisplayNameOrToast } from '../utils';
import { AccountDetails } from './CreateAccount';
import { localize } from '../../../localization/localeTools'; 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) { export async function finishRestore(pubkey: string, displayName: string) {
await setSignWithRecoveryPhrase(true); await setSignWithRecoveryPhrase(true);
@ -96,21 +104,14 @@ async function signInWithNewDisplayName({
displayName, displayName,
recoveryPassword, recoveryPassword,
dispatch, dispatch,
}: AccountRestoreDetails) { }: AccountRestoreDetails & { displayName: string }) {
try { try {
const validDisplayName = displayNameIsValid(displayName);
await resetRegistration(); await resetRegistration();
await registerSingleDevice( await registerSingleDevice(recoveryPassword, 'english', displayName, async (pubkey: string) => {
recoveryPassword, dispatch(setHexGeneratedPubKey(pubkey));
'english', dispatch(setDisplayName(displayName));
validDisplayName, await finishRestore(pubkey, displayName);
async (pubkey: string) => { });
dispatch(setHexGeneratedPubKey(pubkey));
dispatch(setDisplayName(validDisplayName));
await finishRestore(pubkey, validDisplayName);
}
);
} catch (e) { } catch (e) {
await resetRegistration(); await resetRegistration();
throw e; throw e;
@ -129,6 +130,8 @@ export const RestoreAccount = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [cannotContinue, setCannotContinue] = useState(true);
useRecoveryProgressEffect(); useRecoveryProgressEffect();
const recoverAndFetchDisplayName = async () => { const recoverAndFetchDisplayName = async () => {
@ -171,18 +174,20 @@ export const RestoreAccount = () => {
}; };
const recoverAndEnterDisplayName = async () => { const recoverAndEnterDisplayName = async () => {
if ( if (isEmpty(recoveryPassword) || !isEmpty(recoveryPasswordError)) {
isEmpty(recoveryPassword) ||
!isEmpty(recoveryPasswordError) ||
isEmpty(displayName) ||
!isEmpty(displayNameError)
) {
return; return;
} }
try { 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 // 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(); const trimmedPassword = recoveryPassword.trim();
setRecoveryPassword(trimmedPassword); setRecoveryPassword(trimmedPassword);
@ -196,16 +201,17 @@ export const RestoreAccount = () => {
window.log.error( window.log.error(
`[onboarding] restore account: Failed with new display name! Error: ${err.message || String(err)}` `[onboarding] restore account: Failed with new display name! Error: ${err.message || String(err)}`
); );
setCannotContinue(true);
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName)); dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
if (err instanceof RetrieveDisplayNameError) { if (err instanceof EmptyDisplayNameError || err instanceof RetrieveDisplayNameError) {
dispatch(setDisplayNameError(localize('displayNameErrorDescription').toString())); 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')} placeholder={window.i18n('displayNameEnter')}
value={displayName} value={displayName}
onValueChanged={(name: string) => { onValueChanged={(name: string) => {
const sanitizedName = sanitizeDisplayNameOrToast( dispatch(setDisplayName(name));
name, setCannotContinue(false);
setDisplayNameError,
dispatch
);
dispatch(setDisplayName(sanitizedName));
}} }}
onEnterPressed={recoverAndEnterDisplayName} onEnterPressed={recoverAndEnterDisplayName}
error={displayNameError} error={displayNameError}
@ -328,10 +330,7 @@ export const RestoreAccount = () => {
<ContinueButton <ContinueButton
onClick={recoverAndEnterDisplayName} onClick={recoverAndEnterDisplayName}
disabled={ disabled={
isEmpty(recoveryPassword) || isEmpty(recoveryPassword) || !isEmpty(recoveryPasswordError) || cannotContinue
!isEmpty(recoveryPasswordError) ||
isEmpty(displayName) ||
!isEmpty(displayNameError)
} }
/> />
</Flex> </Flex>

Loading…
Cancel
Save