// A sign-up form behind Cloudflare Turnstile: the widget in the form, the answer checked on the
// server with the hostname and action, before the account is made.
//
//   TURNSTILE_SITE_KEY=... TURNSTILE_SECRET=... quillo run captcha_verify.qwe      then open http://localhost:8080/signup
//
// Without keys it uses Cloudflare's test keys, which always pass. CAPTCHA_VERIFY_URL (SINK_URL in
// tests) sends the check to another server.

use "captcha_verify.qwer"

let SITE_KEY = env("TURNSTILE_SITE_KEY", "1x00000000000000000000AA")
let SECRET = env("TURNSTILE_SECRET", "1x0000000000000000000000000000000AA")
let VERIFY_URL = env("CAPTCHA_VERIFY_URL", null) ?? env("SINK_URL", "")

route GET /signup = respond(200, `<!doctype html><title>Sign up</title>
<form method="post" action="/signup">
  <input name="email" type="email" required>
  ${captcha_widget("turnstile", SITE_KEY, "signup")?}
  <button>Create account</button>
</form>`, { "content-type": "text/html; charset=utf-8" })

route POST /signup { form: { email: str } } {
    let result = captcha_verify("turnstile", SECRET, request.form["cf-turnstile-response"] ?? "", request.ip, VERIFY_URL)?
    let ok = captcha_verify_rules(result, { hostname: "shop.example.com", action: "signup" })
    if is_err(ok) { reply 403 ok.error }
    `Welcome, ${email}`
}

// The checks without a browser: the stand-in answers without "success", and a reCAPTCHA v3
// answer is judged by its score.
route GET /check {
    let r = captcha_verify("turnstile", SECRET, "XXXX.DUMMY.TOKEN.XXXX", "203.0.113.7", VERIFY_URL)?
    {
        asked: r.provider,
        passed: r.success,
        missing_token: captcha_verify("hcaptcha", "0x0000000000000000000000000000000000000000", "", "", VERIFY_URL)?.error_codes,
        low_score: captcha_verify_rules({ success: true, hostname: "shop.example.com", action: "login", score: 0.3 }, { action: "login", min_score: 0.5 }).error,
        other_site: captcha_verify_rules({ success: true, hostname: "evil.example" }, { hostname: "shop.example.com" }).error,
    }
}
