Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: recover an account with a new display name if linking fails #3075

Merged
merged 1 commit into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -578,5 +578,6 @@
"resolution": "Resolution",
"duration": "Duration",
"notApplicable": "N/A",
"unknownError": "Unknown Error"
"unknownError": "Unknown Error",
"displayNameErrorNew": "We were unable to load your display name. Please enter a new display name to continue."
}
36 changes: 17 additions & 19 deletions ts/components/registration/RegistrationStages.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import React, { createContext, useEffect, useState } from 'react';
import { SignUpMode, SignUpTab } from './SignUpTab';
import { SignInMode, SignInTab } from './SignInTab';
import { Data } from '../../data/data';
import { SettingsKey } from '../../data/settings-key';
import { getSwarmPollingInstance } from '../../session/apis/snode_api';
import { getConversationController } from '../../session/conversations';
import { mnDecode } from '../../session/crypto/mnemonic';
import { PromiseUtils, StringUtils, ToastUtils } from '../../session/utils';
import { TaskTimedOutError } from '../../session/utils/Promise';
import { fromHex } from '../../session/utils/String';
import { trigger } from '../../shims/events';
import {
generateMnemonic,
registerSingleDevice,
sessionGenerateKeyPair,
signInByLinkingDevice,
} from '../../util/accountManager';
import { fromHex } from '../../session/utils/String';
import { setSignInByLinking, setSignWithRecoveryPhrase, Storage } from '../../util/storage';
import { SettingsKey } from '../../data/settings-key';
import { Storage, setSignInByLinking, setSignWithRecoveryPhrase } from '../../util/storage';
import { SignInMode, SignInTab } from './SignInTab';
import { SignUpMode, SignUpTab } from './SignUpTab';

export async function resetRegistration() {
await Data.removeAll();
Expand Down Expand Up @@ -104,7 +103,10 @@ export async function signInWithRecovery(signInDetails: {
* This is will try to sign in with the user recovery phrase.
* If no ConfigurationMessage is received in 60seconds, the loading will be canceled.
*/
export async function signInWithLinking(signInDetails: { userRecoveryPhrase: string }) {
export async function signInWithLinking(
signInDetails: { userRecoveryPhrase: string },
setSignInMode: (phase: SignInMode) => void
) {
const { userRecoveryPhrase } = signInDetails;
window?.log?.info('LINKING DEVICE');

Expand Down Expand Up @@ -136,18 +138,14 @@ export async function signInWithLinking(signInDetails: { userRecoveryPhrase: str
trigger('openInbox');
} catch (e) {
await resetRegistration();
if (e instanceof TaskTimedOutError) {
ToastUtils.pushToastError(
'registrationError',
'Could not find your display name. Please Sign In by Restoring Your Account instead.'
);
} else {
ToastUtils.pushToastError(
'registrationError',
`Error: ${e.message || 'Something went wrong'}`
);
}
window?.log?.warn('exception during registration:', e);
ToastUtils.pushToastError('registrationError', window.i18n('displayNameErrorNew'));
window?.log?.error(
'[signInWithLinking] Error during sign in by linking lets try and sign in by recovery phrase',
e.message || e
);
getSwarmPollingInstance().stop(e);
await setSignWithRecoveryPhrase(false);
setSignInMode(SignInMode.UsingRecoveryPhrase);
}
}

Expand Down
11 changes: 7 additions & 4 deletions ts/components/registration/SignInTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export const SignInTab = () => {
// from the configuration message will be used.
const showDisplayNameField = isRecovery;

// Display name is required only on isRecoveryMode
// Display name is required only on isRecoveryMode or if linking a device fails
const displayNameOK = (isRecovery && !displayNameError && !!displayName) || isLinking;

// Seed is mandatory no matter which mode
Expand All @@ -139,9 +139,12 @@ export const SignInTab = () => {
});
} else if (isLinking) {
setIsLoading(true);
await signInWithLinking({
userRecoveryPhrase: recoveryPhrase,
});
await signInWithLinking(
{
userRecoveryPhrase: recoveryPhrase,
},
setSignInMode
);
setIsLoading(false);
}
};
Expand Down
25 changes: 20 additions & 5 deletions ts/session/apis/snode_api/swarmPolling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export function extractWebSocketContent(
}

let instance: SwarmPolling | undefined;
const timeouts: Array<NodeJS.Timeout> = [];

export const getSwarmPollingInstance = () => {
if (!instance) {
instance = new SwarmPolling();
Expand Down Expand Up @@ -84,9 +86,11 @@ export class SwarmPolling {
if (waitForFirstPoll) {
await this.pollForAllKeys();
} else {
setTimeout(() => {
void this.pollForAllKeys();
}, 4000);
timeouts.push(
setTimeout(() => {
void this.pollForAllKeys();
}, 4000)
);
}
}

Expand All @@ -98,6 +102,17 @@ export class SwarmPolling {
this.hasStarted = false;
}

// TODO[epic=ses-50] this is a temporary solution until onboarding is merged
public stop(e: Error) {
window.log.error(`[swarmPolling] stopped polling due to error: ${e.message || e}`);

for (let i = 0; i < timeouts.length; i++) {
clearTimeout(timeouts[i]);
window.log.debug(`[swarmPolling] cleared timeout ${timeouts[i]} `);
}
this.resetSwarmPolling();
}

public forcePolledTimestamp(pubkey: PubKey, lastPoll: number) {
this.groupPolling = this.groupPolling.map(group => {
if (PubKey.isEqual(pubkey, group.pubkey)) {
Expand Down Expand Up @@ -163,7 +178,7 @@ export class SwarmPolling {
if (!window.getGlobalOnlineStatus()) {
window?.log?.error('pollForAllKeys: offline');
// Very important to set up a new polling call so we do retry at some point
setTimeout(this.pollForAllKeys.bind(this), SWARM_POLLING_TIMEOUT.ACTIVE);
timeouts.push(setTimeout(this.pollForAllKeys.bind(this), SWARM_POLLING_TIMEOUT.ACTIVE));
return;
}
// we always poll as often as possible for our pubkey
Expand Down Expand Up @@ -200,7 +215,7 @@ export class SwarmPolling {
window?.log?.warn('pollForAllKeys exception: ', e);
throw e;
} finally {
setTimeout(this.pollForAllKeys.bind(this), SWARM_POLLING_TIMEOUT.ACTIVE);
timeouts.push(setTimeout(this.pollForAllKeys.bind(this), SWARM_POLLING_TIMEOUT.ACTIVE));
}
}

Expand Down
1 change: 1 addition & 0 deletions ts/types/LocalizerKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export type LocalizerKeys =
| 'disappears'
| 'displayName'
| 'displayNameEmpty'
| 'displayNameErrorNew'
| 'displayNameTooLong'
| 'document'
| 'documents'
Expand Down
Loading