diff options
| author | Adam Soltys <[email protected]> | 2026-02-06 22:52:09 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-02-06 22:52:09 -0800 |
| commit | 7cb3a8db191a0d67b6caccd0aabda15a35015058 (patch) | |
| tree | 7f7fe79cb93c0a5bd3a2dd9138d0e72f5f804103 | |
| parent | 3a27ae85e5167c0745a28061d03c7cd9c4f52230 (diff) | |
| download | coinos-ui-7cb3a8db191a0d67b6caccd0aabda15a35015058.tar.gz coinos-ui-7cb3a8db191a0d67b6caccd0aabda15a35015058.zip | |
skip captcha for funds
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | src/lib/utils.ts | 13 | ||||
| -rw-r--r-- | src/routes/(app)/fund/[id]/sweep/[...amount]/+page.server.ts | 77 | ||||
| -rw-r--r-- | src/routes/(app)/fund/[id]/sweep/[...amount]/+page.svelte | 118 |
4 files changed, 61 insertions, 148 deletions
@@ -4,6 +4,7 @@ node_modules /.svelte-kit /package .env +.env*.local ios .history/ db diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 92b602d5..efb7b239 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -170,6 +170,7 @@ export const login = async ( cookies, ip: string, host?: string, + extraHeaders?: Record<string, string>, ) => { const maxAge = 380 * 24 * 60 * 60; @@ -177,6 +178,7 @@ export const login = async ( "content-type": "application/json", accept: "application/json", "cf-connecting-ip": ip, + ...extraHeaders, }; if (host) headers["x-forwarded-host"] = host; @@ -497,18 +499,23 @@ export const ago = (t) => { return `${days}d`; }; -export const register = async (user, ip, cookies, loginRedirect, host?) => { +export const register = async (user, ip, cookies, loginRedirect, host?, extraHeaders?: Record<string, string>) => { let error; + const headers: Record<string, string> = { + ...extraHeaders, + }; + if (ip) headers["cf-connecting-ip"] = ip; + let sk; try { - ({ sk } = await post("/register", { user }, { "cf-connecting-ip": ip })); + ({ sk } = await post("/register", { user }, headers)); } catch (e) { ({ message: error } = e as Error); } try { - await login(user, cookies, ip, host); + await login(user, cookies, ip, host, extraHeaders); error = null; } catch (e) { const { message } = e as Error; diff --git a/src/routes/(app)/fund/[id]/sweep/[...amount]/+page.server.ts b/src/routes/(app)/fund/[id]/sweep/[...amount]/+page.server.ts index 13ce5e9d..8cc463c2 100644 --- a/src/routes/(app)/fund/[id]/sweep/[...amount]/+page.server.ts +++ b/src/routes/(app)/fund/[id]/sweep/[...amount]/+page.server.ts @@ -1,9 +1,10 @@ import { randomName, randomPassword } from "$lib/random"; import getRates from "$lib/rates"; -import { auth, get, login, post, sats } from "$lib/utils"; +import { auth, get, post, register, sats } from "$lib/utils"; import { error, redirect } from "@sveltejs/kit"; +import { env } from "$env/dynamic/private"; -export async function load({ cookies, params, parent }) { +export async function load({ cookies, request, params, parent }) { let { user } = await parent(); const { id } = params; let [amount, currency] = params.amount.split("/"); @@ -21,59 +22,35 @@ export async function load({ cookies, params, parent }) { amount = Math.round((amount * sats) / rate); } - if (!amount) redirect(307, `/fund/${id}`); - - if (user) { - try { - ({ amount } = await post("/take", { amount, id }, auth(cookies))); - } catch (e) { - redirect(307, `/fund/${id}`); - } - - return { amount, currency, id, rate, rates, password: null }; - } - - return { amount, currency, id, rate, rates, needsCaptcha: true }; -} + const username = randomName() + Math.floor(Math.random() * 99) + 1; + const password = randomPassword(); -export const actions = { - default: async ({ cookies, request, params }) => { - const { id } = params; - const form = await request.formData(); - const recaptcha = form.get("recaptcha") as string; - const amount = Number(form.get("amount")); + if (!amount) redirect(307, `/fund/${id}`); + if (!user) { const ip = request.headers.get("cf-connecting-ip"); - const host = request.headers.get("host"); - - const username = randomName() + Math.floor(Math.random() * 99) + 1; - const password = randomPassword(); - const user = { username, password, fresh: true, recaptcha }; + user = { + username, + password, + fresh: true, + }; - const { sk } = await post( - "/register", - { user }, - { "cf-connecting-ip": ip }, - ); + let redirectUrl = `/fund/${id}/sweep`; + if (params.amount && !params.currency) redirectUrl += `/${params.amount}`; + if (params.currency) redirectUrl += `/${params.amount}/params.currency}`; - await login(user, cookies, ip, host); + const extraHeaders: Record<string, string> = {}; + if (env.INTERNAL_API_KEY) + extraHeaders["x-api-key"] = env.INTERNAL_API_KEY; - const expires = new Date(); - expires.setSeconds(expires.getSeconds() + 21000000); - cookies.set("sk", sk, { - path: "/", - expires, - httpOnly: false, - sameSite: "lax", - }); + await register(user, ip, cookies, redirectUrl, undefined, extraHeaders); + } - let swept; - try { - swept = await post("/take", { amount, id }, auth(cookies)); - } catch (e) { - redirect(307, `/fund/${id}`); - } + try { + ({ amount } = await post("/take", { amount, id }, auth(cookies))); + } catch (e) { + redirect(307, `/fund/${id}`); + } - return { amount: swept.amount, password, username }; - }, -}; + return { amount, currency, id, rate, rates, password }; +} diff --git a/src/routes/(app)/fund/[id]/sweep/[...amount]/+page.svelte b/src/routes/(app)/fund/[id]/sweep/[...amount]/+page.svelte index fbe8e6ca..7a7d5402 100644 --- a/src/routes/(app)/fund/[id]/sweep/[...amount]/+page.svelte +++ b/src/routes/(app)/fund/[id]/sweep/[...amount]/+page.svelte @@ -1,108 +1,36 @@ <script> - import { PUBLIC_RECAPTCHA_SITE_KEY } from "$env/static/public"; - import { onDestroy, onMount, tick } from "svelte"; - import { browser } from "$app/environment"; - import { enhance } from "$app/forms"; + import { onMount } from "svelte"; import { password } from "$lib/store"; + import Amount from "$comp/Amount.svelte"; import Success from "$comp/Success.svelte"; - import Spinner from "$comp/Spinner.svelte"; + import { scale } from "svelte/transition"; + import { toFiat, f, s } from "$lib/utils"; + import Icon from "$comp/Icon.svelte"; import { t } from "$lib/translations"; import { loc } from "$lib/utils"; let { data } = $props(); - let { amount, currency, id, user, rate, rates, needsCaptcha } = $derived(data); - let locale = $derived(loc(user)); - - let recaptchaToken = $state(""); - let formEl = $state(); - let loading = $state(!!needsCaptcha); - let swept = $state(!needsCaptcha); - let sweptAmount = $state(amount); - let sweptUsername = $state(user?.username); - let recaptchaSiteKey = PUBLIC_RECAPTCHA_SITE_KEY; - let isTor = browser && location.hostname.endsWith(".onion"); - - function handleEnhance() { - return async ({ result }) => { - if (result.type === "success") { - sweptAmount = result.data.amount; - sweptUsername = result.data.username; - $password = result.data.password; - loading = false; - swept = true; - } - }; - } - onMount(() => { - if (!needsCaptcha) { - $password = data.password; - return; - } - - if (isTor || !recaptchaSiteKey) { - recaptchaToken = ""; - tick().then(() => formEl?.requestSubmit()); - return; - } - - let s = document.createElement("script"); - s.src = - "https://www.google.com/recaptcha/api.js?render=" + recaptchaSiteKey; - s.onload = () => { - grecaptcha.ready(() => { - grecaptcha - .execute(recaptchaSiteKey, { action: "register" }) - .then((token) => { - recaptchaToken = token; - tick().then(() => formEl?.requestSubmit()); - }); - }); - }; - document.head.appendChild(s); - }); + let { amount, currency, id, user, rate, rates, password: pw } = data; + let locale = $derived(loc(user)); - onDestroy(() => { - if (!browser) return; - const nodeBadge = document.querySelector(".grecaptcha-badge"); - if (nodeBadge) { - document.body.removeChild(nodeBadge.parentNode); - } - const scriptSelector = - "script[src='https://www.google.com/recaptcha/api.js?render=" + - recaptchaSiteKey + - "']"; - const script = document.querySelector(scriptSelector); - if (script) { - script.remove(); - } - }); + onMount(() => ($password = pw)); </script> -{#if loading} - <div class="flex justify-center items-center h-64"> - <Spinner /> - </div> - <form method="POST" class="hidden" bind:this={formEl} use:enhance={handleEnhance}> - <input type="hidden" name="recaptcha" value={recaptchaToken} /> - <input type="hidden" name="amount" value={amount} /> - </form> -{:else if swept} - <div class="container px-4 text-center mx-auto"> - <Success - amount={sweptAmount} - {rate} - {currency} - {locale} - title={$t("payments.received")} - /> - </div> +<div class="container px-4 text-center mx-auto"> + <Success + {amount} + {rate} + {currency} + {locale} + title={$t("payments.received")} + /> +</div> - <a href={`/${sweptUsername}`} aria-label="Continue"> - <div class="opacity-0 w-screen h-screen fixed top-24 left-0 z-50"></div> - </a> +<a href={`/${user.username}`} aria-label="Continue"> + <div class="opacity-0 w-screen h-screen fixed top-24 left-0 z-50"></div> +</a> - <div class="flex justify-center mt-4"> - {$t("payments.tapAnywhere")} - </div> -{/if} +<div class="flex justify-center mt-4"> + {$t("payments.tapAnywhere")} +</div> |
