web: add support for cloudflare turnstile
This commit is contained in:
parent
c1813aa33f
commit
384c6deced
8 changed files with 89 additions and 5 deletions
|
@ -161,6 +161,9 @@ importers:
|
||||||
tslib:
|
tslib:
|
||||||
specifier: ^2.4.1
|
specifier: ^2.4.1
|
||||||
version: 2.6.3
|
version: 2.6.3
|
||||||
|
turnstile-types:
|
||||||
|
specifier: ^1.2.2
|
||||||
|
version: 1.2.2
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.4.5
|
specifier: ^5.4.5
|
||||||
version: 5.5.4
|
version: 5.5.4
|
||||||
|
@ -2136,6 +2139,9 @@ packages:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
turnstile-types@1.2.2:
|
||||||
|
resolution: {integrity: sha512-FlsojSOGe7OxdC5UXVXVyNV3zdWTSaC6tG6cLPWeTSkcBuCzPP+0xUwc1l090ISDcfDEt398GLbXopcGZesY/A==}
|
||||||
|
|
||||||
type-check@0.4.0:
|
type-check@0.4.0:
|
||||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
@ -4077,6 +4083,8 @@ snapshots:
|
||||||
- tsx
|
- tsx
|
||||||
- yaml
|
- yaml
|
||||||
|
|
||||||
|
turnstile-types@1.2.2: {}
|
||||||
|
|
||||||
type-check@0.4.0:
|
type-check@0.4.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
prelude-ls: 1.2.1
|
prelude-ls: 1.2.1
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
"svelte-check": "^3.6.0",
|
"svelte-check": "^3.6.0",
|
||||||
"svelte-preprocess": "^6.0.2",
|
"svelte-preprocess": "^6.0.2",
|
||||||
"tslib": "^2.4.1",
|
"tslib": "^2.4.1",
|
||||||
|
"turnstile-types": "^1.2.2",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"typescript-eslint": "^7.13.1",
|
"typescript-eslint": "^7.13.1",
|
||||||
"vite": "^5.0.3"
|
"vite": "^5.0.3"
|
||||||
|
|
41
web/src/components/misc/Turnstile.svelte
Normal file
41
web/src/components/misc/Turnstile.svelte
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import env from "$lib/env";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
let turnstileElement: HTMLElement;
|
||||||
|
let turnstileScript: HTMLElement;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (!env.TURNSTILE_KEY) return;
|
||||||
|
|
||||||
|
turnstileScript.addEventListener("load", () => {
|
||||||
|
window.turnstile?.render(turnstileElement, {
|
||||||
|
sitekey: env.TURNSTILE_KEY,
|
||||||
|
"error-callback": (error) => {
|
||||||
|
console.log("turnstile error code:", error);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<script
|
||||||
|
bind:this={turnstileScript}
|
||||||
|
src="https://challenges.cloudflare.com/turnstile/v0/api.js"
|
||||||
|
defer
|
||||||
|
></script>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<div id="turnstile-container">
|
||||||
|
<div bind:this={turnstileElement} id="turnstile-widget"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#turnstile-container {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,8 +1,10 @@
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
|
import turnstile from "$lib/turnstile";
|
||||||
import env, { apiURL } from "$lib/env";
|
import env, { apiURL } from "$lib/env";
|
||||||
import { t } from "$lib/i18n/translations";
|
import { t } from "$lib/i18n/translations";
|
||||||
import settings, { updateSetting } from "$lib/state/settings";
|
import settings, { updateSetting } from "$lib/state/settings";
|
||||||
|
|
||||||
import { createDialog } from "$lib/dialogs";
|
import { createDialog } from "$lib/dialogs";
|
||||||
|
|
||||||
import type { CobaltAPIResponse } from "$lib/types/api";
|
import type { CobaltAPIResponse } from "$lib/types/api";
|
||||||
|
@ -88,16 +90,29 @@ const request = async (url: string) => {
|
||||||
api = env.DEFAULT_API;
|
api = env.DEFAULT_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let turnstileHeader = {};
|
||||||
|
if (env.TURNSTILE_KEY) {
|
||||||
|
const turnstileResponse = turnstile.getResponse();
|
||||||
|
if (turnstileResponse) {
|
||||||
|
turnstileHeader = {
|
||||||
|
"cf-turnstile-response": turnstileResponse
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const response: Optional<CobaltAPIResponse> = await fetch(api, {
|
const response: Optional<CobaltAPIResponse> = await fetch(api, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
redirect: "manual",
|
redirect: "manual",
|
||||||
signal: AbortSignal.timeout(10000),
|
signal: AbortSignal.timeout(10000),
|
||||||
body: JSON.stringify(request),
|
body: JSON.stringify(request),
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
"Accept": "application/json",
|
||||||
'Content-Type': 'application/json'
|
"Content-Type": "application/json",
|
||||||
}
|
...turnstileHeader,
|
||||||
}).then(r => r.json()).catch((e) => {
|
},
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.catch((e) => {
|
||||||
if (e?.message?.includes("timed out")) {
|
if (e?.message?.includes("timed out")) {
|
||||||
return {
|
return {
|
||||||
status: "error",
|
status: "error",
|
||||||
|
|
|
@ -5,6 +5,7 @@ const variables = {
|
||||||
PLAUSIBLE_HOST: env.PUBLIC_PLAUSIBLE_HOST,
|
PLAUSIBLE_HOST: env.PUBLIC_PLAUSIBLE_HOST,
|
||||||
PLAUSIBLE_ENABLED: env.PUBLIC_HOST && env.PUBLIC_PLAUSIBLE_HOST,
|
PLAUSIBLE_ENABLED: env.PUBLIC_HOST && env.PUBLIC_PLAUSIBLE_HOST,
|
||||||
DEFAULT_API: env.PUBLIC_DEFAULT_API,
|
DEFAULT_API: env.PUBLIC_DEFAULT_API,
|
||||||
|
TURNSTILE_KEY: env.PUBLIC_TURNSTILE_KEY,
|
||||||
}
|
}
|
||||||
|
|
||||||
const contacts = {
|
const contacts = {
|
||||||
|
|
13
web/src/lib/turnstile.ts
Normal file
13
web/src/lib/turnstile.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
const getResponse = () => {
|
||||||
|
const turnstileElement = document.getElementById("turnstile-widget");
|
||||||
|
|
||||||
|
if (turnstileElement) {
|
||||||
|
return window?.turnstile?.getResponse(turnstileElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getResponse
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
import "@fontsource/ibm-plex-mono/500.css";
|
import "@fontsource/ibm-plex-mono/500.css";
|
||||||
|
|
||||||
import Sidebar from "$components/sidebar/Sidebar.svelte";
|
import Sidebar from "$components/sidebar/Sidebar.svelte";
|
||||||
|
import Turnstile from "$components/misc/Turnstile.svelte";
|
||||||
import NotchSticker from "$components/misc/NotchSticker.svelte";
|
import NotchSticker from "$components/misc/NotchSticker.svelte";
|
||||||
import DialogHolder from "$components/dialog/DialogHolder.svelte";
|
import DialogHolder from "$components/dialog/DialogHolder.svelte";
|
||||||
import UpdateNotification from "$components/misc/UpdateNotification.svelte";
|
import UpdateNotification from "$components/misc/UpdateNotification.svelte";
|
||||||
|
@ -61,6 +62,9 @@
|
||||||
<DialogHolder />
|
<DialogHolder />
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
{#if env.TURNSTILE_KEY}
|
||||||
|
<Turnstile />
|
||||||
|
{/if}
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"moduleResolution": "bundler"
|
"moduleResolution": "bundler",
|
||||||
|
"types": ["turnstile-types"]
|
||||||
}
|
}
|
||||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||||
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
|
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
|
||||||
|
|
Loading…
Reference in a new issue