From ef34d70c21e7a789f0fe1b2979e988f165799927 Mon Sep 17 00:00:00 2001 From: vishal Date: Wed, 31 Jul 2024 15:10:10 +0530 Subject: [PATCH] Added invisible captcha --- apps/web/app/api/submission/route.ts | 33 ++++++++++++++++++-- apps/web/app/components/ProblemSubmitBar.tsx | 15 ++++++--- k8s/5-web/configmap.yml | 3 +- k8s/5-web/deployment.yml | 21 +++++++++++-- k8s/5-web/secret.yml | 2 ++ packages/common/zod/submissionInput.ts | 2 +- 6 files changed, 64 insertions(+), 12 deletions(-) diff --git a/apps/web/app/api/submission/route.ts b/apps/web/app/api/submission/route.ts index 28fb489..225054e 100644 --- a/apps/web/app/api/submission/route.ts +++ b/apps/web/app/api/submission/route.ts @@ -10,6 +10,8 @@ import { isRequestAllowed } from "@/app/lib/redis"; const JUDGE0_URI = process.env.JUDGE0_URI; +const CLOUDFLARE_TURNSTILE_SECRET_KEY = process.env.CLOUDFLARE_TURNSTILE_SECRET_KEY!; +const CLOUDFLARE_TURNSTILE_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify"; export async function POST(req: NextRequest) { @@ -36,6 +38,7 @@ export async function POST(req: NextRequest) { }; + //get and check the submission input const submissionInput = SubmissionInput.safeParse(await req.json()); if (!submissionInput.success) { @@ -47,6 +50,30 @@ export async function POST(req: NextRequest) { ); }; + if (process.env.NODE_ENV === "production") { + let formData = new FormData(); + formData.append("secret", CLOUDFLARE_TURNSTILE_SECRET_KEY!); + formData.append("response", submissionInput.data.token); + + const result = await fetch(CLOUDFLARE_TURNSTILE_URL, { + body: formData, + method: 'POST', + }); + + const outcome = await result.json(); + + if (!outcome.success && process.env.NODE_ENV == "production") { + return NextResponse.json( + { + message: "Please try again! something went wrong", + status: 403, + } + ); + } + } + + + //get the problem const dbProblem = await db.problem.findUnique({ where: { @@ -89,7 +116,7 @@ export async function POST(req: NextRequest) { })), } ); - + //create the submission in the database const submission = await db.submission.create({ @@ -153,7 +180,7 @@ export async function GET(req: NextRequest) { }, }); - if(submission?.status === "AC"){ + if (submission?.status === "AC") { const updatedProblem = await db.problem.update({ where: { id: submission.problemId, @@ -174,7 +201,7 @@ export async function GET(req: NextRequest) { ); } } - + if (!submission) { return NextResponse.json( { diff --git a/apps/web/app/components/ProblemSubmitBar.tsx b/apps/web/app/components/ProblemSubmitBar.tsx index 3d03aea..1ed32a3 100644 --- a/apps/web/app/components/ProblemSubmitBar.tsx +++ b/apps/web/app/components/ProblemSubmitBar.tsx @@ -20,7 +20,7 @@ import { signIn, useSession } from "next-auth/react"; import { submissions as SubmissionsType } from "@prisma/client"; import { Turnstile } from "@marsidev/react-turnstile"; -const TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY || "0x4AAAAAAAc4qhUEsytXspC_"; +const TURNSTILE_SITE_KEY = process.env.NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY || "0x4AAAAAAAgE_1Uk6Lva-ewz"; enum SubmitStatus { SUBMIT = "SUBMIT", @@ -106,6 +106,7 @@ function SubmitProblem({ setCode(defaultCode); }, [problem]); + async function pollWithBackoff(id: string, retries: number) { if (retries === 0) { @@ -144,16 +145,16 @@ function SubmitProblem({ languageId: language, problemId: problem.id, activeContestId: contestId, - token: token, + token: token }); - if(response.status === 429){ + if (response.status === 429) { setStatus(SubmitStatus.FAILED); toast.error("Try again after sometime"); return; }; - if(response.status != 200){ + if (response.status != 200) { setStatus(SubmitStatus.FAILED); toast.error("Failed to submit"); return; @@ -204,6 +205,12 @@ function SubmitProblem({ />
+ {process.env.NODE_ENV === "production" && ( + setToken(token)} + siteKey={TURNSTILE_SITE_KEY} + /> + )};