Skip to content

Commit

Permalink
Refactor add device success screen to be shown consistently (#2377)
Browse files Browse the repository at this point in the history
This PR refactors the add device success screen to be shown consistently
(regardless from where the flow is started) by making it part of the
tentative device flow rather than having that logic in the top-level
`index.ts` file.

Given the screen is part of both sides of the flow (the new device _and_
the existing one) I moved the corresponding files out of the `manage`
folder).
  • Loading branch information
frederikrothenberger committed Mar 22, 2024
1 parent b0fbd18 commit 0924366
Show file tree
Hide file tree
Showing 10 changed files with 23 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/frontend/src/components/authenticateBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export const authenticateBoxFlow = async <T, I>({
templates: AuthnTemplates;
addDevice: (
userNumber?: bigint
) => Promise<{ tag: "deviceAdded"; alias: string } | { tag: "canceled" }>;
) => Promise<{ tag: "deviceAdded" } | { tag: "canceled" }>;
loginPasskey: (
userNumber: bigint
) => Promise<
Expand Down Expand Up @@ -652,7 +652,7 @@ const loginPinIdentityMaterial = ({
const asNewDevice = async (
connection: Connection,
prefilledUserNumber?: bigint
): Promise<{ tag: "deviceAdded"; alias: string } | { tag: "canceled" }> => {
): Promise<{ tag: "deviceAdded" } | { tag: "canceled" }> => {
// Prompt the user for an anchor and provide additional information about the flow.
// If the user number is already known, it is prefilled in the screen.
const userNumberResult = await promptUserNumber({
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/flows/addDevice/manage/addDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { displayError } from "$src/components/displayError";
import { withLoader } from "$src/components/loader";
import { AuthenticatedConnection } from "$src/utils/iiConnection";
import { isNullish } from "@dfinity/utils";
import { addDeviceSuccess } from "./addDeviceSuccess";
import { addDeviceSuccess } from "../addDeviceSuccess";
import { addFIDODevice } from "./addFIDODevice";
import { pollForTentativeDevice } from "./pollForTentativeDevice";
import { verifyTentativeDevice } from "./verifyTentativeDevice";
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/flows/addDevice/manage/addFIDODevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
isWebAuthnDuplicateDevice,
} from "$src/utils/webAuthnErrorUtils";
import { WebAuthnIdentity } from "@dfinity/identity";
import { addDeviceSuccess } from "./addDeviceSuccess";
import { addDeviceSuccess } from "../addDeviceSuccess";

const displayFailedToAddDevice = (error: Error) =>
displayError({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from "$generated/internet_identity_types";
import { displayError } from "$src/components/displayError";
import { withLoader } from "$src/components/loader";
import { addDeviceSuccess } from "$src/flows/addDevice/addDeviceSuccess";
import { inferPasskeyAlias, loadUAParser } from "$src/flows/register";
import { setAnchorUsed } from "$src/storage";
import { authenticatorAttachmentToKeyType } from "$src/utils/authenticatorAttachment";
Expand All @@ -21,14 +22,22 @@ import { deviceRegistrationDisabledInfo } from "./deviceRegistrationModeDisabled
import { showVerificationCode } from "./showVerificationCode";

/**
* Prompts the user to enter a device alias. When clicking next, the device is added tentatively to the given identity anchor.
* Runs the tentative device registration flow on a _new_ device:
* 1. The user interacts with the authenticator to create a new credential.
* 2. After adding it tentatively, the user is prompted to enter the verification
* code on an existing device.
* 3. This flows polls for the user to complete the verification.
* 4. Once verification is completed, a success screen is shown.
*
* If the user cancels at any point, the flow is aborted.
*
* @param userNumber anchor to add the tentative device to.
* @param connection connection to interact with the II canister.
*/
export const registerTentativeDevice = async (
userNumber: bigint,
connection: Connection
): Promise<{ tag: "deviceAdded"; alias: string } | { tag: "canceled" }> => {
): Promise<{ tag: "deviceAdded" } | { tag: "canceled" }> => {
// Kick-off fetching "ua-parser-js";
const uaParser = loadUAParser();

Expand Down Expand Up @@ -101,7 +110,9 @@ export const registerTentativeDevice = async (
}

verificationCodeResult satisfies "ok";
return { tag: "deviceAdded", alias };

await addDeviceSuccess({ deviceAlias: alias });
return { tag: "deviceAdded" };
};

/** Create new WebAuthn credentials */
Expand Down
5 changes: 0 additions & 5 deletions src/frontend/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { handleLoginFlowResult } from "$src/components/authenticateBox";
import { addDeviceSuccess } from "$src/flows/addDevice/manage/addDeviceSuccess";
import { nonNullish } from "@dfinity/utils";
import { registerTentativeDevice } from "./flows/addDevice/welcomeView/registerTentativeDevice";
import { authFlowAuthorize } from "./flows/authorize";
Expand All @@ -22,10 +21,6 @@ void createSpa(async (connection) => {
return authFlowManage(connection);
}
registerDeviceResult satisfies { tag: "deviceAdded" };
const { alias: deviceAlias } = registerDeviceResult;

// Display a success page once device added (above registerTentativeDevice **never** returns if it fails)
await addDeviceSuccess({ deviceAlias });

const renderManage = renderManageWarmup();

Expand Down
4 changes: 4 additions & 0 deletions src/frontend/src/test-e2e/addDevice.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ test("Add remote device starting on new device", async () => {
await addDeviceSuccessView.continue();

// browser 2 again
const addDeviceSuccessView2 = new AddDeviceSuccessView(browser2);
await addDeviceSuccessView2.waitForDisplay();
await addDeviceSuccessView2.continue();

// make sure the browser now shows the sign-in screen with the user number
// pre-filled
await focusBrowser(browser2);
Expand Down
2 changes: 1 addition & 1 deletion src/showcase/src/pages/addDeviceSuccess.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Screen from "../layouts/Screen.astro";
import { toast } from "$src/components/toast";
import { i18n } from "../i18n";
import { chromeDevice } from "../constants";
import { addDeviceSuccessPage } from "$src/flows/addDevice/manage/addDeviceSuccess";
import { addDeviceSuccessPage } from "$src/flows/addDevice/addDeviceSuccess";

addDeviceSuccessPage({
i18n,
Expand Down

0 comments on commit 0924366

Please sign in to comment.