diff --git a/resources/js/components/turnstile_captcha.js b/resources/js/components/turnstile_captcha.js new file mode 100644 index 00000000..3658adc7 --- /dev/null +++ b/resources/js/components/turnstile_captcha.js @@ -0,0 +1,147 @@ +import React, { useEffect, useRef, useState } from "react"; +import { Turnstile } from "@marsidev/react-turnstile"; +import Button from "@material-ui/core/Button"; +import Grid from "@material-ui/core/Grid"; + +// Turnstile does not always invoke onError when its iframe cannot be loaded (e.g. a network +// error reaching challenges.cloudflare.com): the widget just never renders and never issues a +// token. Without a token the backend rejects the form, so after this long without one we treat +// the security check as failed and let the user retry it. +export const CAPTCHA_LOAD_TIMEOUT_MS = 15000; + +export const CAPTCHA_STATUS = { + VERIFYING: "verifying", + // Turnstile is showing a challenge the user has to complete: not a load failure. + INTERACTIVE: "interactive", + SOLVED: "solved", + FAILED: "failed", +}; + +export const CAPTCHA_MESSAGES = { + VERIFYING: "Please wait while we verify you are human, then submit again.", + INTERACTIVE: "Complete the security check, then submit again.", + FAILED: + "We couldn't load the security check. Check your connection or disable any content blocker, then retry.", +}; + +// Id of the