Skip to content

Commit

Permalink
Extra-nudge users to add recovery on legacy (#1248)
Browse files Browse the repository at this point in the history
* Extra-nudge users to add recovery on legacy

This adds another nudge on the anchor management screen to make sure
users of ic0.app _do_ add a recovery phrase.

* Check for phrase, not device
  • Loading branch information
nmattia authored Feb 17, 2023
1 parent 3f057bf commit 109f49f
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 18 deletions.
3 changes: 2 additions & 1 deletion src/frontend/src/banner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const showWarningIfNecessary = (): void => {
}
};

export const showWarning = (message: TemplateResult): void => {
export const showWarning = (message: TemplateResult): HTMLDivElement => {
const container = document.createElement("div");
container.className = "features-warning-container";
container.setAttribute("role", "alert");
Expand Down Expand Up @@ -72,4 +72,5 @@ export const showWarning = (message: TemplateResult): void => {

render(warning, container);
document.body.prepend(container);
return container;
};
26 changes: 25 additions & 1 deletion src/frontend/src/flows/manage/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { TemplateResult, render, html } from "lit-html";
import { LEGACY_II_URL } from "../../config";
import { Connection, AuthenticatedConnection } from "../../utils/iiConnection";
import { withLoader } from "../../components/loader";
import { unreachable } from "../../utils/utils";
import { logoutSection } from "../../components/logout";
import { deviceSettings } from "./deviceSettings";
import { showWarning } from "../../banner";
import {
DeviceData,
IdentityAnchorInfo,
Expand All @@ -14,7 +16,7 @@ import {
authenticateBox,
AuthnTemplates,
} from "../../components/authenticateBox";
import { setupRecovery } from "../recovery/setupRecovery";
import { setupRecovery, setupPhrase } from "../recovery/setupRecovery";
import { recoveryWizard } from "../recovery/recoveryWizard";
import { pollForTentativeDevice } from "../addDevice/manage/pollForTentativeDevice";
import { chooseDeviceAddFlow } from "../addDevice/manage";
Expand Down Expand Up @@ -304,6 +306,24 @@ export const displayManage = (
renderManage(userNumber, connection);
}
);

// When visiting the legacy URL (ic0.app) we extra-nudge the users to create a recovery phrase,
// if they don't have one already. We lead them straight to recovery phrase creation, because
// recovery _device_ would be tied to the domain (which we want to avoid).
if (window.location.origin === LEGACY_II_URL && !hasRecoveryPhrase(devices)) {
const elem = showWarning(html`<strong class="t-strong">Important!</strong>
Create a recovery phrase.
<button
class="features-warning-btn"
@click=${async () => {
await setupPhrase(userNumber, connection);
elem.remove();
renderManage(userNumber, connection);
}}
>
Create
</button> `);
}
render(template, container);
renderDevices(userNumber, connection, devices);
};
Expand Down Expand Up @@ -365,6 +385,10 @@ const renderDevices = async (
const hasRecoveryDevice = (devices: DeviceData[]): boolean =>
devices.some((device) => "recovery" in device.purpose);

// Whether the user has a recovery phrase or not
const hasRecoveryPhrase = (devices: DeviceData[]): boolean =>
devices.some((device) => device.alias === "Recovery phrase");

const unknownError = (): Error => {
return new Error("Unknown error");
};
39 changes: 23 additions & 16 deletions src/frontend/src/flows/recovery/setupRecovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,7 @@ export const setupRecovery = async (
);
}
case "seedPhrase": {
const name = "Recovery phrase";
const seedPhrase = generate().trim();
const recoverIdentity = await fromMnemonicWithoutValidation(
seedPhrase,
IC_DERIVATION_PATH
);
await withLoader(() =>
connection.add(
name,
{ seed_phrase: null },
{ recovery: null },
recoverIdentity.getPublicKey().toDer(),
{ unprotected: null }
)
);
await displaySeedPhrase(userNumber.toString(10) + " " + seedPhrase);
await setupPhrase(userNumber, connection);
break;
}
}
Expand All @@ -82,3 +67,25 @@ export const setupRecovery = async (
});
}
};

export const setupPhrase = async (
userNumber: bigint,
connection: AuthenticatedConnection
) => {
const name = "Recovery phrase";
const seedPhrase = generate().trim();
const recoverIdentity = await fromMnemonicWithoutValidation(
seedPhrase,
IC_DERIVATION_PATH
);
await withLoader(() =>
connection.add(
name,
{ seed_phrase: null },
{ recovery: null },
recoverIdentity.getPublicKey().toDer(),
{ unprotected: null }
)
);
await displaySeedPhrase(userNumber.toString(10) + " " + seedPhrase);
};

0 comments on commit 109f49f

Please sign in to comment.