Skip to content

Commit

Permalink
add only one registration per email
Browse files Browse the repository at this point in the history
  • Loading branch information
kamini08 committed Sep 22, 2024
1 parent 6118ede commit f4b1db8
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 220 deletions.
127 changes: 80 additions & 47 deletions app/(default)/api/registration/recruitment/route.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { db } from "@/Firebase";
import {
createCSRFToken,
getSessionIdFromRequest,
verifyCSRFToken,
} from "@/lib/server/csrf";

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

import {
Expand All @@ -20,19 +16,39 @@ import { NextResponse } from "next/server";
export async function POST(request: Request) {
const formData = await request.json();
const { recaptcha_token, ...data } = formData;
const { email } = formData;

// Only one Registration per Email

const q = query(
collection(db, "recruitment2024"),
where("email", "==", email)
);
const querySnapshot = await getDocs(q);

console.log(!querySnapshot.empty);

if (!querySnapshot.empty) {
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!",
Expand All @@ -44,58 +60,75 @@ export async function POST(request: Request) {
}
);
}
if (!phoneSnapshot.empty) {
return NextResponse.json(
{
message: "Whatsapp No. is already registered!",
error: "Whatsapp No. is already registered!",
},

const recaptchaToken = recaptcha_token;
if (!recaptchaToken) {
{
status: 500,
}
);
}
if (!collegeIdSnapshot.empty) {
return NextResponse.json(
{
message: "reCAPTCHA token not found! Refresh and try again",
error: "reCAPTCHA token not found!",
message: "College Id is already registered!",
error: "College Id is already registered!",
},

{
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();
const recaptchaToken = recaptcha_token;

console.log(recaptchaResult);
if (!recaptchaResult.success) {
return NextResponse.json({
message: "reCAPTCHA verification failed",
error: true,
});
}
const sessionId = getSessionIdFromRequest(request);
const csrfToken = createCSRFToken(sessionId);
const details = {
event: {
token: recaptchaToken,
siteKey: process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY,
},
};

// Verify the CSRF token
if (!verifyCSRFToken(sessionId, csrfToken)) {

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

// Validate the data
const val = recruitValidate(data);
// 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",
body: JSON.stringify(details),
}
);

if (!Array.isArray(data)) {
const recaptchaResult = await recaptchaResponse.json();
console.log(recaptchaResult.riskAnalysis.score);
if (recaptchaResult.riskAnalysis.score < 0.7) {
return NextResponse.json({
message: "Expected an array of JSON objects",
error: true,
message: "reCAPTCHA validation failed",
error: recaptchaResult["error-codes"],
});
}

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

if (val.error) {
return NextResponse.json(
{ message: "Validation error", error: val.error },
Expand Down
17 changes: 0 additions & 17 deletions app/(default)/api/registration/secure-data/route.ts

This file was deleted.

2 changes: 2 additions & 0 deletions app/(default)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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 @@ -25,6 +26,7 @@ export default function DefaultLayout({

return (
<>

<main className="grow">

{children}
Expand Down
6 changes: 3 additions & 3 deletions app/(default)/recruitment/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ const RegisterPage = () => {
// }
// });
// });\
useEffect(() => {
router.push("/");
})
// useEffect(() => {
// router.push("/");
// })
return (
<div className="w-50 mt-16 mx-auto flex flex-col items-center justify-center">
<div className="form-container my-2">
Expand Down
46 changes: 27 additions & 19 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
import "./css/style.css";
import { Inter } from "next/font/google";
import Header from "@/components/ui/header";
import "@fortawesome/fontawesome-svg-core/styles.css";
import { config } from "@fortawesome/fontawesome-svg-core";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import Script from "next/script";

import './css/style.css'
import { Inter } from 'next/font/google'
import Header from '@/components/ui/header'
import '@fortawesome/fontawesome-svg-core/styles.css'
import { config } from '@fortawesome/fontawesome-svg-core'
import { ThemeProvider as NextThemesProvider } from 'next-themes'

config.autoAddCss = false
config.autoAddCss = false;

const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
display: 'swap'
})
subsets: ["latin"],
variable: "--font-inter",
display: "swap",
});

export const metadata = {
title: 'Point Blank',
description: 'Hello World',
}
title: "Point Blank",
description: "Hello World",
};

export default function RootLayout({
children,
}: {
children: React.ReactNode
children: React.ReactNode;
}) {
return (
<html lang="en" className="dark" style={{ colorScheme: 'dark' }}>
<body className={`${inter.variable} font-inter antialiased bg-black text-white tracking-tight`}>
<html lang="en" className="dark" style={{ colorScheme: "dark" }}>
<head>
<Script
src={`https://www.google.com/recaptcha/enterprise.js?render=${process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}`}
strategy="lazyOnload" // Set reCAPTCHA ready state when the script is loaded
/>
</head>
<body
className={`${inter.variable} font-inter antialiased bg-black text-white tracking-tight`}
>
<NextThemesProvider>
<div className="flex flex-col min-h-screen overflow-hidden supports-[overflow:clip]:overflow-clip">
<Header />
Expand All @@ -35,5 +43,5 @@ export default function RootLayout({
</NextThemesProvider>
</body>
</html>
)
);
}
33 changes: 0 additions & 33 deletions components/forms/reCaptcha.tsx

This file was deleted.

31 changes: 13 additions & 18 deletions components/forms/recruitmentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import "../../app/css/additional-styles/theme.css";
import { useState } from "react";
import { useForm, SubmitHandler } from "react-hook-form";
import { years, branches } from "@/lib/constants/dropdownOptions";
import {
GoogleReCaptchaProvider,
GoogleReCaptcha,
} from "react-google-recaptcha-v3";
import Success from "./success";
import toast from "react-hot-toast";
import { getErrorMessage, fetchCsrfToken } from "@/lib/client/clientUtils";
Expand All @@ -17,8 +13,6 @@ const RecruitmentForm: React.FC = () => {
const [mode, setMode] = useState<boolean>(false);
const [display, setDisplay] = useState<boolean>(false);
const [token, setToken] = useState("");
const [refreshReCaptcha, setRefreshReCaptcha] = useState(false);
const [csrfToken, setCsrfToken] = useState<string>("");


const {
Expand All @@ -37,26 +31,28 @@ const RecruitmentForm: React.FC = () => {
},
});

const setTokenFunc = (getToken: string) => {
setToken(getToken);
};
const changeMode = (e: any) => {
console.log(e.target.value);
if (e.target.value === "1st year") setMode(true);
else setMode(false);
setDisplay(true);
};

const onSubmit: SubmitHandler<any> = async (data: any) => {

try {
const csrftoken = await fetchCsrfToken();
setCsrfToken(csrftoken);
try {
grecaptcha.enterprise.ready(async () => {
const token = await grecaptcha.enterprise.execute(
process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY
);
setTokenFunc(token);
});

data.recaptcha_token = token;

const response = await fetch("/api/registration/recruitment", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken,
},

body: JSON.stringify(data),
});

Expand All @@ -70,7 +66,6 @@ try {

setSuccess(true);
} catch (error) {
setRefreshReCaptcha(!refreshReCaptcha);
console.error("Error submitting form:", error);
toast.error(getErrorMessage(error));
}
Expand Down Expand Up @@ -269,9 +264,9 @@ try {
)}
</div>


<button
type="submit"
disabled={isSuccess}
className="bg-green-500 text-white rounded-lg py-2 px-4 hover:bg-green-600 "
>
Submit
Expand Down
1 change: 1 addition & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare var grecaptcha: any;
Loading

0 comments on commit f4b1db8

Please sign in to comment.