| 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). */ |
| 12 | export const TURNSTILE_SCRIPT = "https://challenges.cloudflare.com/turnstile/v0/api.js"; |
| 13 | /** Where a widget's answer is checked. */ |
| 14 | export const TURNSTILE_VERIFY = "https://challenges.cloudflare.com/turnstile/v0/siteverify"; |
| 15 | /** The form field the widget fills in. */ |
| 16 | export const TURNSTILE_FIELD = "cf-turnstile-response"; |
| 17 | |
| 18 | /** What sign-up says when the check failed or was not done. */ |
| 19 | export 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 | |
| 21 | export type TurnstileSettings = { siteKey: string; secret: string } | null; |
| 22 | |
| 23 | /** The settings, when both are set: otherwise Turnstile is off. */ |
| 24 | export 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. */ |
| 31 | export function turnstilePassed(answer: unknown): boolean { |
| 32 | return typeof answer === "object" && answer !== null && (answer as { success?: unknown }).success === true; |
| 33 | } |