feat: captcha
This commit is contained in:
parent
b79ee0c08a
commit
9a99f934b6
12 changed files with 184 additions and 11 deletions
|
|
@ -15,3 +15,14 @@ if (!building) {
|
|||
}
|
||||
|
||||
export { client as redis };
|
||||
|
||||
const TURNSTILE_PREFIX = 'turnstile:verified:';
|
||||
const TURNSTILE_TTL = 5 * 60; // 5 minutes
|
||||
|
||||
export async function setTurnstileVerifiedRedis(userId: string) {
|
||||
await client.set(`${TURNSTILE_PREFIX}${userId}`, '1', { EX: TURNSTILE_TTL });
|
||||
}
|
||||
|
||||
export async function isTurnstileVerifiedRedis(userId: string): Promise<boolean> {
|
||||
return !!(await client.get(`${TURNSTILE_PREFIX}${userId}`));
|
||||
}
|
||||
|
|
|
|||
20
website/src/lib/server/turnstile.ts
Normal file
20
website/src/lib/server/turnstile.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { env } from '$env/dynamic/private';
|
||||
|
||||
const TURNSTILE_SECRET = env.TURNSTILE_SECRET_KEY;
|
||||
|
||||
export async function verifyTurnstile(token: string, request: Request): Promise<boolean> {
|
||||
if (!TURNSTILE_SECRET) return false;
|
||||
const ip = request.headers.get('x-forwarded-for') || request.headers.get('cf-connecting-ip') || undefined;
|
||||
const body = new URLSearchParams({
|
||||
secret: TURNSTILE_SECRET,
|
||||
response: token,
|
||||
...(ip ? { remoteip: ip } : {})
|
||||
});
|
||||
const res = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
|
||||
method: 'POST',
|
||||
body,
|
||||
headers: { 'content-type': 'application/x-www-form-urlencoded' }
|
||||
});
|
||||
const data = await res.json();
|
||||
return !!data.success;
|
||||
}
|
||||
Reference in a new issue