diff --git a/packages/features/auth/src/captcha/server/verify-captcha.tsx b/packages/features/auth/src/captcha/server/verify-captcha.tsx index 21cb27b21..bf306612c 100644 --- a/packages/features/auth/src/captcha/server/verify-captcha.tsx +++ b/packages/features/auth/src/captcha/server/verify-captcha.tsx @@ -3,20 +3,26 @@ import 'server-only'; const verifyEndpoint = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'; -const secret = process.env.CAPTCHA_SECRET_TOKEN; +const CAPTCHA_SECRET_TOKEN = process.env.CAPTCHA_SECRET_TOKEN; /** - * Verify the CAPTCHA token with the CAPTCHA service - * @param token + * @name verifyCaptchaToken + * @description Verify the CAPTCHA token with the CAPTCHA service + * @param token - The CAPTCHA token to verify */ export async function verifyCaptchaToken(token: string) { - if (!secret) { + if (!CAPTCHA_SECRET_TOKEN) { throw new Error('CAPTCHA_SECRET_TOKEN is not set'); } + const formData = new FormData(); + + formData.append('secret', CAPTCHA_SECRET_TOKEN); + formData.append('response', token); + const res = await fetch(verifyEndpoint, { method: 'POST', - body: `secret=${encodeURIComponent(secret)}&response=${encodeURIComponent(token)}`, + body: formData, headers: { 'content-type': 'application/x-www-form-urlencoded', }, diff --git a/packages/next/src/actions/index.ts b/packages/next/src/actions/index.ts index 1b2a8b5a6..c71e13e0d 100644 --- a/packages/next/src/actions/index.ts +++ b/packages/next/src/actions/index.ts @@ -13,13 +13,6 @@ import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-clie import { captureException, zodParseFactory } from '../utils'; /** - * @name IS_CAPTCHA_SETUP - * @description Check if the CAPTCHA is setup - */ -const IS_CAPTCHA_SETUP = !!process.env.CAPTCHA_SECRET_TOKEN; - -/** - * * @name enhanceAction * @description Enhance an action with captcha, schema and auth checks */ @@ -48,9 +41,25 @@ export function enhanceAction< type UserParam = Config['auth'] extends false ? undefined : User; const requireAuth = config.auth ?? true; - let user: UserParam = undefined as UserParam; + // validate the schema passed in the config if it exists + const data = config.schema + ? zodParseFactory(config.schema)(params) + : params; + + // by default, the CAPTCHA token is not required + const verifyCaptcha = config.captcha ?? false; + + // verify the CAPTCHA token. It will throw an error if the token is invalid. + if (verifyCaptcha) { + const token = (data as Args & { captchaToken: string }).captchaToken; + + // Verify the CAPTCHA token. It will throw an error if the token is invalid. + await verifyCaptchaToken(token); + } + + // verify the user is authenticated if required if (requireAuth) { // verify the user is authenticated if required const auth = await requireUser(getSupabaseServerActionClient()); @@ -63,35 +72,23 @@ export function enhanceAction< user = auth.data as UserParam; } - // validate the schema - const data = config.schema - ? zodParseFactory(config.schema)(params) - : params; - - // verify captcha unless it's explicitly disabled - // verify the captcha token if required - const verifyCaptcha = config.captcha ?? IS_CAPTCHA_SETUP; - - if (verifyCaptcha) { - const token = (data as Args & { captchaToken: string }).captchaToken; - - // Verify the CAPTCHA token. It will throw an error if the token is invalid. - await verifyCaptchaToken(token); - } - // capture exceptions if required const shouldCaptureException = config.captureException ?? true; + // if the action should capture exceptions, wrap the action in a try/catch block if (shouldCaptureException) { try { + // pass the data to the action return await fn(data, user); } catch (error) { + // capture the exception await captureException(error); + // re-throw the error throw error; } } else { - // pass the data to the action + // no need to capture exceptions, just pass the data to the action return fn(data, user); } }; diff --git a/packages/next/src/routes/index.ts b/packages/next/src/routes/index.ts index 0a6744f95..c2bee0830 100644 --- a/packages/next/src/routes/index.ts +++ b/packages/next/src/routes/index.ts @@ -19,12 +19,6 @@ interface HandlerParams { body: Body; } -/** - * @name IS_CAPTCHA_SETUP - * @description Check if the CAPTCHA is setup - */ -const IS_CAPTCHA_SETUP = !!process.env.CAPTCHA_SECRET_TOKEN; - /** * Enhanced route handler function. * @@ -69,7 +63,8 @@ export const enhanceRouteHandler = < * This function takes a request object as an argument and returns a response object. */ return async function routeHandler(request: NextRequest) { - const shouldVerifyCaptcha = params?.captcha ?? IS_CAPTCHA_SETUP; + // Check if the captcha token should be verified + const shouldVerifyCaptcha = params?.captcha ?? false; // Verify the captcha token if required and setup if (shouldVerifyCaptcha) {