diff --git a/app/(default)/api/registration/recruitment/route.ts b/app/(default)/api/registration/recruitment/route.ts index 94175db..aaee02e 100644 --- a/app/(default)/api/registration/recruitment/route.ts +++ b/app/(default)/api/registration/recruitment/route.ts @@ -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" }); } diff --git a/app/(default)/api/registration/sih/route.ts b/app/(default)/api/registration/sih/route.ts index b368caa..60c8e71 100644 --- a/app/(default)/api/registration/sih/route.ts +++ b/app/(default)/api/registration/sih/route.ts @@ -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 }); @@ -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 }); - } -} \ No newline at end of file diff --git a/app/(default)/layout.tsx b/app/(default)/layout.tsx index 83a7959..9ac7068 100644 --- a/app/(default)/layout.tsx +++ b/app/(default)/layout.tsx @@ -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, @@ -24,10 +26,11 @@ export default function DefaultLayout({ return ( <> +
{children} - +