Skip to content

Commit

Permalink
Add support for recovery email being a separate route on its own
Browse files Browse the repository at this point in the history
  • Loading branch information
deepjyoti30-st committed Jan 20, 2025
1 parent 5476719 commit 7ca8eac
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import GeneralError from "../../../../emailpassword/components/library/generalEr
import { ThemeBase } from "../themeBase";

import { PasskeyEmailSent } from "./emailSent";
import { PasskeyRecoverAccountForm } from "./recoverAccountForm";
import { PasskeyRecoverAccount } from "./recoverAccountForm";

import type { SendRecoveryEmailFormThemeProps } from "../../../types";

Expand Down Expand Up @@ -39,11 +39,10 @@ export const SendRecoveryEmailFormThemeInner = (
};

return props.activeScreen === SendRecoveryEmailScreen.RecoverAccount ? (
<PasskeyRecoverAccountForm
<PasskeyRecoverAccount
onSuccess={onRecoverAccountFormSuccess}
onBackClick={onRecoverAccountBackClick}
recipeImplementation={props.recipeImplementation}
setError={(error) => console.error(error)}
/>
) : props.activeScreen === SendRecoveryEmailScreen.RecoverEmailSent ? (
<PasskeyEmailSent email={recoverAccountEmail} onEmailChangeClick={onEmailChangeClick} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { handleCallAPI } from "../../../../../utils";
import { Label } from "../../../../emailpassword/components/library";
import FormBase from "../../../../emailpassword/components/library/formBase";
import { defaultEmailValidator } from "../../../../emailpassword/validators";
import { DEFAULT_WEBAUTHN_SEND_RECOVERY_EMAIL_PATH } from "../../../constants";

import { PasskeyConfirmation } from "./confirmation";
import { ContinueWithoutPasskey } from "./continueWithoutPasskey";
Expand Down Expand Up @@ -75,7 +76,7 @@ export const SignUpFormInner = withOverride(
<div data-supertokens="formLabelWithLinkWrapper">
<Label value={"WEBAUTHN_SIGN_UP_LABEL"} data-supertokens="emailInputLabel" />
<a
onClick={() => console.error("Recover account link: to be defined")}
href={DEFAULT_WEBAUTHN_SEND_RECOVERY_EMAIL_PATH}
data-supertokens="link linkButton formLabelLinkBtn recoverAccountTrigger">
{t("WEBAUTHN_RECOVER_ACCOUNT_LABEL")}
</a>
Expand Down
2 changes: 2 additions & 0 deletions lib/ts/recipe/webauthn/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@
* under the License.
*/
export const DEFAULT_WEBAUTHN_RECOVERY_PATH = "/webauthn/recover";

export const DEFAULT_WEBAUTHN_SEND_RECOVERY_EMAIL_PATH = "/webauthn/recover/send-email";
30 changes: 27 additions & 3 deletions lib/ts/recipe/webauthn/prebuiltui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import SessionAuth from "../session/sessionAuth";

import { useRecipeComponentOverrideContext } from "./componentOverrideContext";
import { RecoverAccountUsingToken } from "./components/features/recoverAccountWithToken";
import { SendRecoveryEmailForm } from "./components/features/sendRecoveryEmail";
import SignInWithPasskeyFeature from "./components/features/signIn";
import SignUpFeature, { SignUpWithPasskeyFeature } from "./components/features/signUp";
import { defaultTranslationsWebauthn } from "./components/themes/translations";
import { DEFAULT_WEBAUTHN_RECOVERY_PATH } from "./constants";
import { DEFAULT_WEBAUTHN_RECOVERY_PATH, DEFAULT_WEBAUTHN_SEND_RECOVERY_EMAIL_PATH } from "./constants";
import WebauthnRecipe from "./recipe";

import type { GenericComponentOverrideMap } from "../../components/componentOverride/componentOverrideContext";
Expand Down Expand Up @@ -46,7 +47,7 @@ export class WebauthnPreBuiltUI extends RecipeRouter {
return WebauthnPreBuiltUI.getInstanceOrInitAndGetInstance().getFeatures(useComponentOverrides);
}
static getFeatureComponent(
componentName: "webauthn-recover-account",
componentName: "webauthn-recover-account" | "webauthn-send-recovery-email",
props: FeatureBaseProps<{ userContext?: UserContext }>,
useComponentOverrides: () => GenericComponentOverrideMap<any> = useRecipeComponentOverrideContext
): JSX.Element {
Expand All @@ -72,12 +73,23 @@ export class WebauthnPreBuiltUI extends RecipeRouter {
this.getFeatureComponent("webauthn-recover-account", props, useComponentOverrides),
recipeID: WebauthnRecipe.RECIPE_ID,
};

const normalisedFullPathForRecoveryThroughEmail =
this.recipeInstance.config.appInfo.websiteBasePath.appendPath(
new NormalisedURLPath(DEFAULT_WEBAUTHN_SEND_RECOVERY_EMAIL_PATH)
);
features[normalisedFullPathForRecoveryThroughEmail.getAsStringDangerous()] = {
matches: matchRecipeIdUsingQueryParams(this.recipeInstance.config.recipeId),
component: (props: any) =>
this.getFeatureComponent("webauthn-send-recovery-email", props, useComponentOverrides),
recipeID: WebauthnRecipe.RECIPE_ID,
};
}
return features;
};

getFeatureComponent = (
componentName: "webauthn-recover-account",
componentName: "webauthn-recover-account" | "webauthn-send-recovery-email",
props: FeatureBaseProps<{ userContext?: UserContext }>,
useComponentOverrides: () => GenericComponentOverrideMap<any> = useRecipeComponentOverrideContext
): JSX.Element => {
Expand All @@ -93,6 +105,18 @@ export class WebauthnPreBuiltUI extends RecipeRouter {
</SessionAuth>
</UserContextWrapper>
);
} else if (componentName === "webauthn-send-recovery-email") {
return (
<UserContextWrapper userContext={props.userContext}>
<SessionAuth requireAuth={false} doRedirection={false}>
<SendRecoveryEmailForm
recipe={this.recipeInstance}
{...props}
useComponentOverrides={useComponentOverrides}
/>
</SessionAuth>
</UserContextWrapper>
);
}
throw new Error("Should never come here.");
};
Expand Down
9 changes: 9 additions & 0 deletions stories/allrecipes.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ export const RecoverAccountWithToken: Story = {
},
};

export const SendRecoveryEmail: Story = {
args: {
path: "/auth/webauthn/recover/send-email",
"multifactorauth.initialized": false,
"passwordless.initialized": false,
"webauthn.initialized": true,
},
};

export const SignUpFieldErrors: Story = {
args: {
path: "/auth",
Expand Down

0 comments on commit 7ca8eac

Please sign in to comment.