Skip to content
33 linesCodeBlameRaw
1/**
2 * Cloudflare Turnstile on email sign-up: a check that a person, not a
3 * script, filled in the form. It is on when the Worker has both
4 * `TURNSTILE_SITE_KEY` (a var: the widget's public site key) and
5 * `TURNSTILE_SECRET` (a secret); without either it is skipped, so an
6 * installation of its own and local development sign up without one. No
7 * Workers imports, so it can be tested under Node; turnstile.server.ts
8 * reads the settings and asks Cloudflare.
9 */
10
11/** The script that draws the widget; the page's policy allows it (page-headers.ts). */
12export const TURNSTILE_SCRIPT = "https://challenges.cloudflare.com/turnstile/v0/api.js";
13/** Where a widget's answer is checked. */
14export const TURNSTILE_VERIFY = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
15/** The form field the widget fills in. */
16export const TURNSTILE_FIELD = "cf-turnstile-response";
17
18/** What sign-up says when the check failed or was not done. */
19export const TURNSTILE_FAILED = "We could not tell that a person sent this form. Wait for the check above the button to finish, then try again.";
20
21export type TurnstileSettings = { siteKey: string; secret: string } | null;
22
23/** The settings, when both are set: otherwise Turnstile is off. */
24export function turnstileSettings(siteKey: string | undefined, secret: string | undefined): TurnstileSettings {
25 const key = (siteKey ?? "").trim();
26 const hidden = (secret ?? "").trim();
27 return key && hidden ? { siteKey: key, secret: hidden } : null;
28}
29
30/** Whether Cloudflare's answer says the check passed. */
31export function turnstilePassed(answer: unknown): boolean {
32 return typeof answer === "object" && answer !== null && (answer as { success?: unknown }).success === true;
33}