mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-25 09:11:51 +01:00
Fixed hardcoded sitekey, fixed hasCaptcha being ignored, fixed setState while unmounted
This commit is contained in:
parent
a5512b95e5
commit
328414ab06
@ -5,6 +5,7 @@ export interface MetaResponse {
|
||||
name: string;
|
||||
description?: string;
|
||||
hasCaptcha: boolean;
|
||||
captchaClientKey?: string;
|
||||
}
|
||||
|
||||
export async function getBackendMeta(url: string): Promise<MetaResponse> {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useRef, useState } from "react";
|
||||
import { useCopyToClipboard } from "react-use";
|
||||
import { useCopyToClipboard, useMountedState } from "react-use";
|
||||
|
||||
import { Icon, Icons } from "./Icon";
|
||||
|
||||
@ -9,6 +9,7 @@ export function PassphaseDisplay(props: { mnemonic: string }) {
|
||||
const [, copy] = useCopyToClipboard();
|
||||
|
||||
const [hasCopied, setHasCopied] = useState(false);
|
||||
const isMounted = useMountedState();
|
||||
|
||||
const timeout = useRef<ReturnType<typeof setTimeout>>();
|
||||
|
||||
@ -16,7 +17,7 @@ export function PassphaseDisplay(props: { mnemonic: string }) {
|
||||
copy(props.mnemonic);
|
||||
setHasCopied(true);
|
||||
if (timeout.current) clearTimeout(timeout.current);
|
||||
timeout.current = setTimeout(() => setHasCopied(false), 500);
|
||||
timeout.current = setTimeout(() => isMounted() && setHasCopied(false), 500);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -19,7 +19,7 @@ import { useBackendUrl } from "@/hooks/auth/useBackendUrl";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
|
||||
export interface RegistrationData {
|
||||
recaptchaToken: string;
|
||||
recaptchaToken?: string;
|
||||
mnemonic: string;
|
||||
userData: {
|
||||
device: string;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import { GoogleReCaptchaProvider } from "react-google-recaptcha-v3";
|
||||
|
||||
import { MetaResponse } from "@/backend/accounts/meta";
|
||||
import { SubPageLayout } from "@/pages/layouts/SubPageLayout";
|
||||
import {
|
||||
AccountCreatePart,
|
||||
@ -9,20 +10,38 @@ import {
|
||||
import { PassphraseGeneratePart } from "@/pages/parts/auth/PassphraseGeneratePart";
|
||||
import { TrustBackendPart } from "@/pages/parts/auth/TrustBackendPart";
|
||||
import { VerifyPassphrase } from "@/pages/parts/auth/VerifyPassphrasePart";
|
||||
import { conf } from "@/setup/config";
|
||||
|
||||
function CaptchaProvider(props: {
|
||||
siteKey: string | null;
|
||||
children: JSX.Element;
|
||||
}) {
|
||||
if (!props.siteKey) return props.children;
|
||||
return (
|
||||
<GoogleReCaptchaProvider reCaptchaKey={props.siteKey}>
|
||||
{props.children}
|
||||
</GoogleReCaptchaProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export function RegisterPage() {
|
||||
const [step, setStep] = useState(0);
|
||||
const [mnemonic, setMnemonic] = useState<null | string>(null);
|
||||
const [account, setAccount] = useState<null | AccountProfile>(null);
|
||||
const reCaptchaKey = conf().RECAPTCHA_SITE_KEY;
|
||||
const [siteKey, setSiteKey] = useState<string | null>(null);
|
||||
|
||||
// TODO because of user data loading (in useAuthRestore()), the register page gets unmounted before finishing the register flow
|
||||
|
||||
return (
|
||||
<GoogleReCaptchaProvider reCaptchaKey={reCaptchaKey}>
|
||||
<CaptchaProvider siteKey={siteKey}>
|
||||
<SubPageLayout>
|
||||
{step === 0 ? (
|
||||
<TrustBackendPart
|
||||
onNext={() => {
|
||||
onNext={(meta: MetaResponse) => {
|
||||
setSiteKey(
|
||||
meta.hasCaptcha && meta.captchaClientKey
|
||||
? meta.captchaClientKey
|
||||
: null
|
||||
);
|
||||
setStep(1);
|
||||
}}
|
||||
/>
|
||||
@ -45,6 +64,7 @@ export function RegisterPage() {
|
||||
) : null}
|
||||
{step === 3 ? (
|
||||
<VerifyPassphrase
|
||||
hasCaptcha={!!siteKey}
|
||||
mnemonic={mnemonic}
|
||||
userData={account}
|
||||
onNext={() => {
|
||||
@ -54,6 +74,6 @@ export function RegisterPage() {
|
||||
) : null}
|
||||
{step === 4 ? <p>Success, account now exists</p> : null}
|
||||
</SubPageLayout>
|
||||
</GoogleReCaptchaProvider>
|
||||
</CaptchaProvider>
|
||||
);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import { AccountProfile } from "@/pages/parts/auth/AccountCreatePart";
|
||||
|
||||
interface VerifyPassphraseProps {
|
||||
mnemonic: string | null;
|
||||
hasCaptcha?: boolean;
|
||||
userData: AccountProfile | null;
|
||||
onNext?: () => void;
|
||||
}
|
||||
@ -27,18 +28,20 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
|
||||
|
||||
const [result, execute] = useAsyncFn(
|
||||
async (inputMnemonic: string) => {
|
||||
const recaptchaToken = executeRecaptcha
|
||||
? await executeRecaptcha()
|
||||
: undefined;
|
||||
|
||||
if (!props.mnemonic || !props.userData)
|
||||
throw new Error("Data is not valid");
|
||||
if (!recaptchaToken) throw new Error("ReCaptcha validation failed");
|
||||
|
||||
let recaptchaToken: string | undefined;
|
||||
if (props.hasCaptcha) {
|
||||
recaptchaToken = executeRecaptcha
|
||||
? await executeRecaptcha()
|
||||
: undefined;
|
||||
if (!recaptchaToken) throw new Error("ReCaptcha validation failed");
|
||||
}
|
||||
|
||||
if (inputMnemonic !== props.mnemonic)
|
||||
throw new Error("Passphrase doesn't match");
|
||||
|
||||
// TODO captcha?
|
||||
|
||||
await register({
|
||||
mnemonic: inputMnemonic,
|
||||
userData: props.userData,
|
||||
|
@ -8,7 +8,6 @@ interface Config {
|
||||
CORS_PROXY_URL: string;
|
||||
NORMAL_ROUTER: boolean;
|
||||
BACKEND_URL: string;
|
||||
RECAPTCHA_SITE_KEY: string;
|
||||
}
|
||||
|
||||
export interface RuntimeConfig {
|
||||
@ -19,7 +18,6 @@ export interface RuntimeConfig {
|
||||
NORMAL_ROUTER: boolean;
|
||||
PROXY_URLS: string[];
|
||||
BACKEND_URL: string;
|
||||
RECAPTCHA_SITE_KEY: string;
|
||||
}
|
||||
|
||||
const env: Record<keyof Config, undefined | string> = {
|
||||
@ -30,7 +28,6 @@ const env: Record<keyof Config, undefined | string> = {
|
||||
CORS_PROXY_URL: import.meta.env.VITE_CORS_PROXY_URL,
|
||||
NORMAL_ROUTER: import.meta.env.VITE_NORMAL_ROUTER,
|
||||
BACKEND_URL: import.meta.env.VITE_BACKEND_URL,
|
||||
RECAPTCHA_SITE_KEY: import.meta.env.VITE_RECAPTCHA_SITE_KEY,
|
||||
};
|
||||
|
||||
// loads from different locations, in order: environment (VITE_{KEY}), window (public/config.js)
|
||||
@ -56,6 +53,5 @@ export function conf(): RuntimeConfig {
|
||||
.split(",")
|
||||
.map((v) => v.trim()),
|
||||
NORMAL_ROUTER: getKey("NORMAL_ROUTER", "false") === "true",
|
||||
RECAPTCHA_SITE_KEY: getKey("RECAPTCHA_SITE_KEY"),
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user