From 192e60b94119b49b2279514e1aef9dfdd9e070de Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Wed, 19 Mar 2025 18:41:52 +0100 Subject: [PATCH] chore(www): hcaptcha opt-out verification (#34265) * chore(www): hcaptcha opt-out verification * invisible HCaptcha * small styling updates --- apps/www/.env.local.example | 2 + apps/www/app/api-v2/opt-out/[ref]/route.ts | 41 +++++- apps/www/package.json | 1 + apps/www/pages/opt-out/[ref].tsx | 64 +++++++++- pnpm-lock.yaml | 141 +++++---------------- turbo.json | 2 + 6 files changed, 134 insertions(+), 117 deletions(-) diff --git a/apps/www/.env.local.example b/apps/www/.env.local.example index 966ee6a10f..0256131331 100644 --- a/apps/www/.env.local.example +++ b/apps/www/.env.local.example @@ -10,3 +10,5 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJz NEXT_PUBLIC_SUPABASE_URL="https://xguihxuzqibwxjnimxev.supabase.co" SUPABASE_COM_SERVICE_ROLE_KEY="secret" NEXT_PUBLIC_URL="http://localhost:3000" +NEXT_PUBLIC_HCAPTCHA_SITE_KEY="10000000-ffff-ffff-ffff-000000000001" +HCAPTCHA_SECRET_KEY="0x0000000000000000000000000000000000000000 diff --git a/apps/www/app/api-v2/opt-out/[ref]/route.ts b/apps/www/app/api-v2/opt-out/[ref]/route.ts index 15456e39ba..288f3ce9a3 100644 --- a/apps/www/app/api-v2/opt-out/[ref]/route.ts +++ b/apps/www/app/api-v2/opt-out/[ref]/route.ts @@ -3,10 +3,33 @@ import { createClient } from '@supabase/supabase-js' const supabaseUrl = process.env.NEXT_PUBLIC_EMAIL_ABUSE_URL as string const supabaseServiceKey = process.env.EMAIL_ABUSE_SERVICE_KEY as string +const hcaptchaSecret = process.env.HCAPTCHA_SECRET_KEY as string + +// Function to verify hCaptcha token +async function verifyCaptcha(token: string): Promise { + try { + const response = await fetch('https://api.hcaptcha.com/siteverify', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams({ + secret: hcaptchaSecret, + response: token, + }), + }) + + const data = await response.json() + return data.success === true + } catch (error) { + console.error('Error verifying captcha:', error) + return false + } +} export async function POST(req: NextRequest, { params }: { params: { ref: string } }) { const ref = params.ref - const { reason, email } = await req.json() + const { reason, email, captchaToken } = await req.json() const supabase = createClient(supabaseUrl, supabaseServiceKey) @@ -27,6 +50,22 @@ export async function POST(req: NextRequest, { params }: { params: { ref: string ) } + // Verify captcha token + if (!captchaToken) { + return NextResponse.json( + { error: 'Bad Request: Missing captcha verification.' }, + { status: 400 } + ) + } + + const isValidCaptcha = await verifyCaptcha(captchaToken) + if (!isValidCaptcha) { + return NextResponse.json( + { error: 'Bad Request: Invalid captcha verification.' }, + { status: 400 } + ) + } + try { const { error: supabaseError } = await supabase .from('manual_reports') diff --git a/apps/www/package.json b/apps/www/package.json index cc019fd9e7..41a01760b1 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -18,6 +18,7 @@ }, "dependencies": { "@code-hike/mdx": "^0.9.0", + "@hcaptcha/react-hcaptcha": "^1.11.1", "@heroicons/react": "^1.0.6", "@mdx-js/react": "^2.3.0", "@next/bundle-analyzer": "^14.2.3", diff --git a/apps/www/pages/opt-out/[ref].tsx b/apps/www/pages/opt-out/[ref].tsx index b164d18390..0b5b45c7ce 100644 --- a/apps/www/pages/opt-out/[ref].tsx +++ b/apps/www/pages/opt-out/[ref].tsx @@ -1,8 +1,10 @@ +import HCaptcha from '@hcaptcha/react-hcaptcha' import { zodResolver } from '@hookform/resolvers/zod' import Layout from 'components/Layouts/Default' import { NextSeo } from 'next-seo' +import { useTheme } from 'next-themes' import { useRouter } from 'next/router' -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { useForm } from 'react-hook-form' import { Button, @@ -24,25 +26,29 @@ import { z } from 'zod' const formSchema = z.object({ ref: z.string(), reason: z.string().optional(), + captchaToken: z.string().min(1, 'Please complete the captcha verification'), }) export default function OptOutPage() { const router = useRouter() + const { resolvedTheme } = useTheme() const ref = router.query.ref as string const email = router.query.email as string | undefined const [formMessage, setFormMessage] = useState(null) const [submissionType, setSubmissionType] = useState<'success' | 'error' | null>(null) + const captchaRef = useRef(null) const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { ref: ref, reason: undefined, + captchaToken: '', }, }) - const { register } = form + const { register, setValue } = form // Ensure ref is a string const refString = typeof ref !== 'string' @@ -50,6 +56,10 @@ export default function OptOutPage() { const refIsInvalid = !refString && !refPattern.test(ref) const SelectItemContainerClasses = 'flex flex-col text-sm items-start' + const handleCaptchaVerify = (token: string) => { + setValue('captchaToken', token) + } + const onSubmit = async (data: z.infer) => { try { setSubmissionType(null) @@ -60,7 +70,11 @@ export default function OptOutPage() { headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ reason: data.reason, email: email }), + body: JSON.stringify({ + reason: data.reason, + email: email, + captchaToken: data.captchaToken, + }), }) const message = await response.text() @@ -68,17 +82,35 @@ export default function OptOutPage() { setFormMessage('Error: Invalid project reference.') setSubmissionType('error') } else if (response.ok) { - setFormMessage(message) + try { + const parsedMessage = JSON.parse(message) + if (!parsedMessage.message) { + throw new Error() + } + + setFormMessage(parsedMessage.message) + } catch { + setFormMessage(message) + } + setSubmissionType('success') } else { console.error('Form submission failed:', message) setFormMessage('Error: Form submission failed.') setSubmissionType('error') } + + // Reset captcha after submission + captchaRef.current?.resetCaptcha() + setValue('captchaToken', '') } catch (error) { console.error('Error submitting form:', error) setFormMessage('Error: An unexpected error occurred.') setSubmissionType('error') + + // Reset captcha after error + captchaRef.current?.resetCaptcha() + setValue('captchaToken', '') } } @@ -94,7 +126,7 @@ export default function OptOutPage() { } useEffect(() => { - form.reset({ ref: ref, reason: '' }) + form.reset({ ref: ref, reason: '', captchaToken: '' }) }, [ref]) return ( @@ -114,8 +146,9 @@ export default function OptOutPage() { )} -
+ + )} /> + +
+ { + captchaRef.current = ref + ref?.execute() + }} + theme={resolvedTheme} + size="invisible" + /> + {form.formState.errors.captchaToken && ( +

+ {form.formState.errors.captchaToken.message} +

+ )} +
+ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 77d8e0f670..b218e25ba4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -88,10 +88,10 @@ importers: version: 1.2.0 next: specifier: 'catalog:' - version: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + version: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) next-contentlayer2: specifier: 0.4.6 - version: 0.4.6(contentlayer2@0.4.6(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.1)(markdown-wasm@1.2.0)(next@14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(supports-color@8.1.1) + version: 0.4.6(contentlayer2@0.4.6(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.1)(markdown-wasm@1.2.0)(next@14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(supports-color@8.1.1) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -341,7 +341,7 @@ importers: version: 1.0.1 next: specifier: 'catalog:' - version: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + version: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) next-mdx-remote: specifier: ^4.4.1 version: 4.4.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(supports-color@8.1.1) @@ -868,7 +868,7 @@ importers: version: 9.3.4 '@testing-library/jest-dom': specifier: ^6.4.6 - version: 6.4.6(@jest/globals@29.7.0(supports-color@8.1.1))(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.11)(supports-color@8.1.1))(vitest@3.0.4) + version: 6.4.6(@jest/globals@29.7.0(supports-color@8.1.1))(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.11)(supports-color@8.1.1))(vitest@3.0.4(@types/node@20.12.11)(@vitest/ui@3.0.4)(jsdom@20.0.3(supports-color@8.1.1))(msw@2.4.11(typescript@5.5.2))(sass@1.72.0)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.19.3)(yaml@2.4.5)) '@testing-library/react': specifier: ^14.0.0 version: 14.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1004,6 +1004,9 @@ importers: '@code-hike/mdx': specifier: ^0.9.0 version: 0.9.0(encoding@0.1.13)(react@18.2.0) + '@hcaptcha/react-hcaptcha': + specifier: ^1.11.1 + version: 1.11.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@heroicons/react': specifier: ^1.0.6 version: 1.0.6(react@18.2.0) @@ -1096,7 +1099,7 @@ importers: version: 1.2.0 next: specifier: 'catalog:' - version: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + version: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) next-contentlayer2: specifier: 0.5.3 version: 0.5.3(contentlayer2@0.5.3(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.1)(markdown-wasm@1.2.0)(next@14.2.21(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(supports-color@8.1.1) @@ -1353,7 +1356,7 @@ importers: version: 0.7.12 '@vercel/flags': specifier: ^2.6.0 - version: 2.6.0(next@14.2.21(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 2.6.0(next@14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) api-types: specifier: workspace:* version: link:../api-types @@ -1368,7 +1371,7 @@ importers: version: 4.17.21 next: specifier: 'catalog:' - version: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + version: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1492,7 +1495,7 @@ importers: version: 8.11.11 '@vitest/coverage-v8': specifier: 2.1.8 - version: 2.1.8(supports-color@8.1.1)(vitest@3.0.4) + version: 2.1.8(supports-color@8.1.1)(vitest@3.0.4(@types/node@22.13.10)(@vitest/ui@3.0.4)(jsdom@20.0.3(supports-color@8.1.1))(msw@2.4.11(typescript@5.5.2))(sass@1.72.0)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.19.3)(yaml@2.4.5)) npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -1658,7 +1661,7 @@ importers: version: 0.436.0(react@18.2.0) next: specifier: 'catalog:' - version: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + version: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1758,7 +1761,7 @@ importers: version: 3.6.1 '@testing-library/jest-dom': specifier: ^6.1.3 - version: 6.4.6(@jest/globals@29.7.0(supports-color@8.1.1))(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.11)(supports-color@8.1.1))(vitest@3.0.4) + version: 6.4.6(@jest/globals@29.7.0(supports-color@8.1.1))(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.11)(supports-color@8.1.1))(vitest@3.0.4(@types/node@20.12.11)(@vitest/ui@3.0.4)(jsdom@20.0.3(supports-color@8.1.1))(msw@2.4.11(typescript@5.5.2))(sass@1.72.0)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.19.3)(yaml@2.4.5)) '@testing-library/react': specifier: ^14.0.0 version: 14.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1866,7 +1869,7 @@ importers: version: 0.33.0 next: specifier: 'catalog:' - version: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + version: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) next-themes: specifier: '*' version: 0.3.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1945,7 +1948,7 @@ importers: version: 10.1.0 '@testing-library/jest-dom': specifier: ^6.4.6 - version: 6.4.6(@jest/globals@29.7.0(supports-color@8.1.1))(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.11)(supports-color@8.1.1))(vitest@3.0.4) + version: 6.4.6(@jest/globals@29.7.0(supports-color@8.1.1))(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.11)(supports-color@8.1.1))(vitest@3.0.4(@types/node@20.12.11)(@vitest/ui@3.0.4)(jsdom@20.0.3(supports-color@8.1.1))(msw@2.4.11(typescript@5.5.2))(sass@1.72.0)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.19.3)(yaml@2.4.5)) '@testing-library/react': specifier: ^16.0.0 version: 16.0.0(@testing-library/dom@10.1.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1975,7 +1978,7 @@ importers: version: link:../api-types next-router-mock: specifier: ^0.9.13 - version: 0.9.13(next@14.2.21(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react@18.2.0) + version: 0.9.13(next@14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react@18.2.0) typescript: specifier: ~5.5.0 version: 5.5.2 @@ -2233,10 +2236,6 @@ packages: resolution: {integrity: sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.9': - resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} - engines: {node: '>=6.9.0'} - '@babel/generator@7.24.7': resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} engines: {node: '>=6.9.0'} @@ -7433,6 +7432,7 @@ packages: resolution: {integrity: sha512-t0q23FIpvHDTtnORW+bDJziGsal5uh9RJTJ1fyH8drd4lICOoXhJ5pLMUZ5C0VQei6dNmwTzzoTRgMkO9JgHEQ==} peerDependencies: eslint: '>= 5' + bundledDependencies: [] eslint-plugin-import@2.29.1: resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} @@ -13462,27 +13462,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/core@7.26.9(supports-color@8.1.1)': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.10 - '@babel/helper-compilation-targets': 7.26.5 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9(supports-color@8.1.1))(supports-color@8.1.1) - '@babel/helpers': 7.26.10 - '@babel/parser': 7.26.10 - '@babel/template': 7.26.9 - '@babel/traverse': 7.26.10(supports-color@8.1.1) - '@babel/types': 7.26.10 - convert-source-map: 2.0.0 - debug: 4.4.0(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/generator@7.24.7': dependencies: '@babel/types': 7.26.7 @@ -13580,16 +13559,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9(supports-color@8.1.1))(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.26.9(supports-color@8.1.1) - '@babel/helper-module-imports': 7.25.9(supports-color@8.1.1) - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.7(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/helper-plugin-utils@7.24.8': {} '@babel/helper-plugin-utils@7.26.5': @@ -17300,7 +17269,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0(supports-color@8.1.1))(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.11)(supports-color@8.1.1))(vitest@3.0.4)': + '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0(supports-color@8.1.1))(@types/jest@29.5.5)(jest@29.7.0(@types/node@20.12.11)(supports-color@8.1.1))(vitest@3.0.4(@types/node@20.12.11)(@vitest/ui@3.0.4)(jsdom@20.0.3(supports-color@8.1.1))(msw@2.4.11(typescript@5.5.2))(sass@1.72.0)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.19.3)(yaml@2.4.5))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.7 @@ -17952,14 +17921,6 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - '@vercel/flags@2.6.0(next@14.2.21(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': - dependencies: - jose: 5.2.1 - optionalDependencies: - next: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@vercel/og@0.6.2': dependencies: '@resvg/resvg-wasm': 2.4.0 @@ -17977,7 +17938,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@2.1.8(supports-color@8.1.1)(vitest@3.0.4)': + '@vitest/coverage-v8@2.1.8(supports-color@8.1.1)(vitest@3.0.4(@types/node@22.13.10)(@vitest/ui@3.0.4)(jsdom@20.0.3(supports-color@8.1.1))(msw@2.4.11(typescript@5.5.2))(sass@1.72.0)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.19.3)(yaml@2.4.5))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 0.2.3 @@ -18962,7 +18923,7 @@ snapshots: code-red@1.0.4: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 + '@types/estree': 1.0.5 acorn: 8.14.1 estree-walker: 3.0.3 periscopic: 3.1.0 @@ -19889,7 +19850,7 @@ snapshots: debug: 4.4.0(supports-color@8.1.1) enhanced-resolve: 5.17.1 eslint: 8.57.0(supports-color@8.1.1) - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-plugin-import@2.29.1)(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1))(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1) fast-glob: 3.3.2 get-tsconfig: 4.7.2 @@ -19901,7 +19862,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-plugin-import@2.29.1)(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1))(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: @@ -19928,7 +19889,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0(supports-color@8.1.1) eslint-import-resolver-node: 0.3.9(supports-color@8.1.1) - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint-plugin-import@2.29.1)(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1))(eslint@8.57.0(supports-color@8.1.1))(supports-color@8.1.1) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -23404,12 +23365,12 @@ snapshots: neo-async@2.6.2: {} - next-contentlayer2@0.4.6(contentlayer2@0.4.6(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.1)(markdown-wasm@1.2.0)(next@14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(supports-color@8.1.1): + next-contentlayer2@0.4.6(contentlayer2@0.4.6(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.1)(markdown-wasm@1.2.0)(next@14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(supports-color@8.1.1): dependencies: '@contentlayer2/core': 0.4.3(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1) '@contentlayer2/utils': 0.4.3 contentlayer2: 0.4.6(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1) - next: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + next: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) transitivePeerDependencies: @@ -23423,7 +23384,7 @@ snapshots: '@contentlayer2/core': 0.5.3(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1) '@contentlayer2/utils': 0.5.3 contentlayer2: 0.5.3(esbuild@0.25.1)(markdown-wasm@1.2.0)(supports-color@8.1.1) - next: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + next: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) transitivePeerDependencies: @@ -23452,14 +23413,9 @@ snapshots: next: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) react: 18.2.0 - next-router-mock@0.9.13(next@14.2.21(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react@18.2.0): - dependencies: - next: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) - react: 18.2.0 - next-seo@6.5.0(next@14.2.21(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: - next: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + next: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -23496,34 +23452,6 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0): - dependencies: - '@next/env': 14.2.21 - '@swc/helpers': 0.5.5 - busboy: 1.6.0 - caniuse-lite: 1.0.30001695 - graceful-fs: 4.2.11 - postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(@babel/core@7.26.9(supports-color@8.1.1))(react@18.2.0) - optionalDependencies: - '@next/swc-darwin-arm64': 14.2.21 - '@next/swc-darwin-x64': 14.2.21 - '@next/swc-linux-arm64-gnu': 14.2.21 - '@next/swc-linux-arm64-musl': 14.2.21 - '@next/swc-linux-x64-gnu': 14.2.21 - '@next/swc-linux-x64-musl': 14.2.21 - '@next/swc-win32-arm64-msvc': 14.2.21 - '@next/swc-win32-ia32-msvc': 14.2.21 - '@next/swc-win32-x64-msvc': 14.2.21 - '@opentelemetry/api': 1.9.0 - '@playwright/test': 1.49.1 - sass: 1.72.0 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - nice-try@1.0.5: {} no-case@3.0.4: @@ -23676,7 +23604,7 @@ snapshots: nuqs@1.19.1(next@14.2.21(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0)): dependencies: mitt: 3.0.1 - next: 14.2.21(@babel/core@7.26.9(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) + next: 14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0) nuqs@2.4.1(next@14.2.21(@babel/core@7.24.7(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.49.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.72.0))(react@18.2.0): dependencies: @@ -25866,13 +25794,6 @@ snapshots: optionalDependencies: '@babel/core': 7.24.7(supports-color@8.1.1) - styled-jsx@5.1.1(@babel/core@7.26.9(supports-color@8.1.1))(react@18.2.0): - dependencies: - client-only: 0.0.1 - react: 18.2.0 - optionalDependencies: - '@babel/core': 7.26.9(supports-color@8.1.1) - stylis@4.3.1: {} sucrase@3.34.0: @@ -25919,7 +25840,7 @@ snapshots: '@ampproject/remapping': 2.3.0 '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 - '@types/estree': 1.0.6 + '@types/estree': 1.0.5 acorn: 8.14.1 aria-query: 5.3.2 axobject-query: 4.1.0 @@ -26986,7 +26907,7 @@ snapshots: webpack@5.94.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.5 '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 @@ -27016,7 +26937,7 @@ snapshots: webpack@5.94.0(esbuild@0.25.1): dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.5 '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 diff --git a/turbo.json b/turbo.json index ba28942aff..44da74d3c3 100644 --- a/turbo.json +++ b/turbo.json @@ -89,6 +89,8 @@ "NEXT_PUBLIC_VERCEL_ENV", "NEXT_PUBLIC_VERCEL_BRANCH_URL", "NEXT_PUBLIC_API_URL", + "NEXT_PUBLIC_HCAPTCHA_SITE_KEY", + "HCAPTCHA_SECRET_KEY", "NODE_ENV", // These envs are used in the packages "NEXT_PUBLIC_STORAGE_KEY",