Skip to content

Commit

Permalink
Merge pull request #69 from kamini08/main
Browse files Browse the repository at this point in the history
Add reCAPTCHA to Recruitment Form and Notifications for Error Handling
  • Loading branch information
SkySingh04 authored Sep 22, 2024
2 parents 95191e7 + f4b1db8 commit 8ff29df
Show file tree
Hide file tree
Showing 24 changed files with 810 additions and 502 deletions.
178 changes: 127 additions & 51 deletions app/(default)/api/registration/recruitment/route.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,153 @@
import { db } from "@/Firebase";
import { recruitValidate } from "@/lib/utils";
import { addDoc, collection, getDocs } from "firebase/firestore";

import { recruitValidate } from "@/lib/server/utils";

import {
addDoc,
collection,
getDocs,
limit,
query,
where,
} from "firebase/firestore";
import { NextResponse } from "next/server";

// Verify reCAPTCHA Token
async function verifyRecaptcha(token: string) {
const secretKey = process.env.RECAPTCHA_SECRET_KEY;
const response = await fetch(
`https://www.google.com/recaptcha/api/siteverify`,
// Add a new registration
export async function POST(request: Request) {
const formData = await request.json();
const { recaptcha_token, ...data } = formData;
const { email, whatsapp_number, college_id } = formData;

// Only one Registration per person

// Query for email
const emailQuery = query(
collection(db, "recruitment2024"),
where("email", "==", email)
);

// Query for phone number
const phoneQuery = query(
collection(db, "recruitment2024"),
where("whatsapp_number", "==", whatsapp_number)
);

// Query for college ID
const collegeIdQuery = query(
collection(db, "recruitment2024"),
where("college_id", "==", college_id)
);

// Fetch results from all queries
const [emailSnapshot, phoneSnapshot, collegeIdSnapshot] = await Promise.all([
getDocs(emailQuery),
getDocs(phoneQuery),
getDocs(collegeIdQuery)
]);


console.log(!emailSnapshot.empty);

if (!emailSnapshot.empty) {
return NextResponse.json(
{
message: "Email is already registered!",
error: "Email is already registered!",
},

{
status: 500,
}
);
}
if (!phoneSnapshot.empty) {
return NextResponse.json(
{
message: "Whatsapp No. is already registered!",
error: "Whatsapp No. is already registered!",
},

{
status: 500,
}
);
}
if (!collegeIdSnapshot.empty) {
return NextResponse.json(
{
message: "College Id is already registered!",
error: "College Id is already registered!",
},

{
status: 500,
}
);
}

const recaptchaToken = recaptcha_token;

const details = {
event: {
token: recaptchaToken,
siteKey: process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY,
},
};


if (!recaptchaToken) {
return NextResponse.json(
{
message: "reCAPTCHA token not found! Try again",
error: "reCAPTCHA token not found!",
},
{
status: 500,
}
);
}

// Verify the reCATPTCHA token

const recaptchaResponse = await fetch(
`https://recaptchaenterprise.googleapis.com/v1/projects/${process.env.RECAPTCHA_PROJECT}/assessments?key=${process.env.RECAPTCHA_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
secret: secretKey || "",
response: token,
}),
body: JSON.stringify(details),
}
);
const data = await response.json();
return data.success;
}

// Add a new registration
export async function POST(request: Request) {
const data = await request.json();
const recaptchaToken = data.recaptchaToken; // Extract the reCAPTCHA token from the request

// Verify the reCAPTCHA token
const isRecaptchaValid = await verifyRecaptcha(recaptchaToken);

if (!isRecaptchaValid) {
const recaptchaResult = await recaptchaResponse.json();
console.log(recaptchaResult.riskAnalysis.score);
if (recaptchaResult.riskAnalysis.score < 0.7) {
return NextResponse.json({
message: "reCAPTCHA verification failed",
error: true,
message: "reCAPTCHA validation failed",
error: recaptchaResult["error-codes"],
});
}

// Validate the data
const val = recruitValidate(data);

if (!Array.isArray(data)) {
return NextResponse.json({
message: "Expected an array of JSON objects",
error: true,
});
}

if (val.error) {
return NextResponse.json({ message: "Validation error", error: val.error });
return NextResponse.json(
{ message: "Validation error", error: val.error },
{ status: 500 }
);
}

// Save to Firebase

try {
// Save to Firebase
const docRef = await addDoc(collection(db, "recruitment2024"), data);
console.log("Document written with ID: ", docRef.id);
} catch (error) {
console.error(error);
return NextResponse.json({ message: "An error occurred", error });
return NextResponse.json(
{ message: "An error occurred", error },
{ status: 500 }
);
}
// Return a response
return NextResponse.json({ message: "Registration successful", data });
}

// Get all registrations
export async function GET() {
try {
// Get all registrations in recruitment2024 collection
const querySnapshot = await getDocs(collection(db, "recruitment2024"));
// Map the data to get only the data
const data = querySnapshot.docs.map((doc) => doc.data());
return NextResponse.json({ data });
} catch (error) {
console.error(error);
return NextResponse.json({ message: "An error occurred", error });
}
return NextResponse.json({ message: "Registration successful" });
}
146 changes: 93 additions & 53 deletions app/(default)/api/registration/sih/route.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,91 @@
import { db } from '@/Firebase';
import { sihValidate } from '@/lib/utils';
import { addDoc, collection, getDocs } from 'firebase/firestore';
import { NextResponse } from 'next/server';
import { db } from "@/Firebase";
import {
createCSRFToken,
getSessionIdFromRequest,
verifyCSRFToken,
} from "@/lib/server/csrf";
import { sihValidate } from "@/lib/server/utils";
import { addDoc, collection, getDocs, query, where } from "firebase/firestore";
import { NextResponse } from "next/server";

// Add a new registration
export async function POST(request: Request) {
const formData = await request.json();
const { recaptcha_token, ...data } = formData;

// Verify reCAPTCHA Token
// async function verifyRecaptcha(token: string) {
// const secretKey = process.env.RECAPTCHA_SECRET_KEY;
// const response = await fetch(`https://www.google.com/recaptcha/api/siteverify`, {
// method: 'POST',
// headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
// body: new URLSearchParams({
// secret: secretKey || '',
// response: token,
// }),
// });
// const data = await response.json();
// return data.success;
// }
console.log(formData);


// Only one Registration per Email

// Add a new registration
export async function POST(request: Request) {
const data = await request.json();
const recaptchaToken = data.recaptchaToken; // Extract the reCAPTCHA token from the request
const { team_info: { team_leader: { email } } } = data;
const q = query(
collection(db, "sih2024"),
where("team_info.team_leader.email", "==", email)
);
const querySnapshot = await getDocs(q);

console.log(!querySnapshot.empty);

if (!querySnapshot.empty) {
return NextResponse.json(
{
message: "Email is already registered!",
error: "Email is already registered!",
},

{
status: 500,
}
);
}

// Verify the reCAPTCHA token
// const isRecaptchaValid = await verifyRecaptcha(recaptchaToken);
const recaptchaToken = recaptcha_token;
if (!recaptchaToken) {
return NextResponse.json(
{
message: "reCAPTCHA token not found! Refresh and try again",
error: "reCAPTCHA token not found!",
},
{
status: 500,
}
);
}
const recaptchaSecretKey = process.env.RECAPTCHA_SECRET_KEY;

// Verify reCAPTCHA token
const recaptchaResponse = await fetch(
`https://www.google.com/recaptcha/api/siteverify?secret=${recaptchaSecretKey}&response=${recaptchaToken}`,
{ method: "POST" }
);
const recaptchaResult = await recaptchaResponse.json();

console.log(recaptchaResult);
if (!recaptchaResult.success) {
return NextResponse.json(
{
message: "reCAPTCHA validation failed",
error: recaptchaResult["error-codes"],
},
{
status: 500,
}
);
}

const sessionId = getSessionIdFromRequest(request);
const csrfToken = createCSRFToken(sessionId);

// Verify the CSRF token
if (!verifyCSRFToken(sessionId, csrfToken)) {
return NextResponse.json(
{ message: "Invalid CSRF token" },
{
status: 403,
}
);
}

// if (!isRecaptchaValid) {
// return NextResponse.json({ message: 'reCAPTCHA verification failed', error: true });
Expand All @@ -35,33 +94,14 @@ export async function POST(request: Request) {
// Validate the data
const val = sihValidate(data);

if (val.error) {
return NextResponse.json({ message: 'Validation error', error: val.error });
}

try {
console.log('Data:', data);
// Save to Firebase
const docRef = await addDoc(collection(db, "sih2024"), data);
console.log("Document written with ID: ", docRef.id);
} catch (error) {
console.error(error);
return NextResponse.json({ message: 'An error occurred', error });
}
// Return a response
return NextResponse.json({ message: 'Registration successful', data });
try {
// Save to Firebase
const docRef = await addDoc(collection(db, "sih2024"), data);
console.log("Document written with ID: ", docRef.id);
} catch (error) {
console.error(error);
return NextResponse.json({ message: "An error occurred", error });
}
// Return a response
return NextResponse.json({ message: "Registration successful" });
}

//get all registrations
export async function GET() {
try {
// Get all registrations in sih2024 collection
const querySnapshot = await getDocs(collection(db, "sih2024"));
// Map the data to get only the data
const data = querySnapshot.docs.map((doc) => doc.data());
return NextResponse.json({ data });
} catch (error) {
console.error(error);
return NextResponse.json({ message: 'An error occurred', error });
}
}
5 changes: 4 additions & 1 deletion app/(default)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import AOS from 'aos'
import 'aos/dist/aos.css'

import Footer from '@/components/ui/footer'
import { Toaster } from 'react-hot-toast'
import Script from 'next/script'

export default function DefaultLayout({
children,
Expand All @@ -24,10 +26,11 @@ export default function DefaultLayout({

return (
<>

<main className="grow">

{children}

<Toaster position='top-right' />
</main>

<Footer />
Expand Down
Loading

0 comments on commit 8ff29df

Please sign in to comment.