init commit,

This commit is contained in:
louiscklaw
2025-05-28 09:55:51 +08:00
commit efe70ceb69
8042 changed files with 951668 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
# Cloudflare Turnstile
Turnstile is Cloudflare's CAPTCHA alternative: https://developers.cloudflare.com/turnstile/get-started/
## Watch the Video Tutorial
[![video tutorial](https://img.youtube.com/vi/OwW0znboh60/0.jpg)](https://www.youtube.com/watch?v=OwW0znboh60)
## Setup
- Follow these steps to set up a new site: https://developers.cloudflare.com/turnstile/get-started/
- Add the Cloudflare Turnstile widget to your site: https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/
## Deploy the server-side validation Edge Functions
- https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
```bash
supabase functions deploy cloudflare-turnstile
supabase secrets set CLOUDFLARE_TURNSTILE_SECRET_KEY=your_secret_key
```
## Invoke the function from your site
```js
const { data, error } = await supabase.functions.invoke('cloudflare-turnstile', {
body: { token },
})
```

View File

@@ -0,0 +1,60 @@
// Follow this setup guide to integrate the Deno language server with your editor:
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.
import { corsHeaders } from '../_shared/cors.ts'
console.log(`Function "cloudflare-turnstile" up and running!`)
function ips(req: Request) {
return req.headers.get('x-forwarded-for')?.split(/\s*,\s*/)
}
Deno.serve(async (req) => {
// This is needed if you're planning to invoke your function from a browser.
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
}
try {
const { token } = await req.json()
if (!token) throw new Error('Missing token!')
const clientIps = ips(req) || ['']
// Validate the token by calling the
// "/siteverify" API endpoint.
const formData = new FormData()
formData.append('secret', Deno.env.get('CLOUDFLARE_TURNSTILE_SECRET_KEY') ?? '')
formData.append('response', token)
formData.append('remoteip', clientIps[0])
const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'
const result = await fetch(url, {
body: formData,
method: 'POST',
})
const outcome = await result.json()
console.log(outcome)
if (outcome.success) {
return new Response(JSON.stringify(outcome), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 200,
})
}
throw new Error('Turnstile validation failed!')
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 400,
})
}
})
// To invoke:
// curl -i --location --request POST 'http://localhost:54321/functions/v1/cloudflare-turnstile' \
// --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
// --header 'Content-Type: application/json' \
// --data '{"token":"cf-turnstile-response"}'