diff --git a/backend/package-lock.json b/backend/package-lock.json index fa9e417..c4beaf7 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -25,9 +25,8 @@ "express": "^4.19.2", "express-rate-limit": "^7.4.0", "jsonwebtoken": "^9.0.2", - "leetcode-query": "^1.2.3", "multer": "^1.4.5-lts.1", - "nodemailer": "^6.9.13", + "nodemailer": "^6.9.14", "puppeteer": "^23.1.0", "uuid": "^9.0.1", "zod": "^3.23.8" @@ -345,20 +344,6 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" }, - "node_modules/@fetch-impl/cross-fetch": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@fetch-impl/cross-fetch/-/cross-fetch-1.0.0.tgz", - "integrity": "sha512-vNvwtCQ7yruvpYnp1i/4paVi/icrGYx9O4eHNDYorjTAFg78bhitO0l39opJSVfsTKqyWqj3+2+YenoGhZOCJA==", - "peerDependencies": { - "@fetch-impl/fetcher": "^1.0.0", - "cross-fetch": "*" - } - }, - "node_modules/@fetch-impl/fetcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@fetch-impl/fetcher/-/fetcher-1.0.0.tgz", - "integrity": "sha512-UPUN9Yfjnk513Vc08iNW8/9L1nSwQMsTx6nOvmjPNfU2Rtbew/2KgAbQDPuoL6PrNgEmEmmyeM29BkcVBpt3gQ==" - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -1382,14 +1367,6 @@ } } }, - "node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dependencies": { - "node-fetch": "^2.6.12" - } - }, "node_modules/crypto-js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", @@ -1654,11 +1631,6 @@ "node": ">= 0.6" } }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, "node_modules/express": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", @@ -2388,17 +2360,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/leetcode-query": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/leetcode-query/-/leetcode-query-1.2.3.tgz", - "integrity": "sha512-J73ehmjgIfDd3Ugg1ee83bDALNaGh78nQwDS5qyPOsgGahK55a2lcl9Q/iaByKi6AUMMxsHEyEsUNGBX4Lmn2Q==", - "dependencies": { - "@fetch-impl/cross-fetch": "^1.0.0", - "@fetch-impl/fetcher": "^1.0.0", - "cross-fetch": "^4.0.0", - "eventemitter3": "^5.0.1" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -2670,9 +2631,9 @@ } }, "node_modules/nodemailer": { - "version": "6.9.13", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.13.tgz", - "integrity": "sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==", + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz", + "integrity": "sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==", "engines": { "node": ">=6.0.0" } diff --git a/backend/package.json b/backend/package.json index 45c345f..dfe6ac6 100644 --- a/backend/package.json +++ b/backend/package.json @@ -29,7 +29,7 @@ "express-rate-limit": "^7.4.0", "jsonwebtoken": "^9.0.2", "multer": "^1.4.5-lts.1", - "nodemailer": "^6.9.13", + "nodemailer": "^6.9.14", "puppeteer": "^23.1.0", "uuid": "^9.0.1", "zod": "^3.23.8" diff --git a/backend/src/controller/auth.js b/backend/src/controller/auth.js index 667512b..2278380 100644 --- a/backend/src/controller/auth.js +++ b/backend/src/controller/auth.js @@ -1,36 +1,49 @@ import prisma from "../../db/db.config.js"; import bcrypt from "bcrypt"; -import jwt from "jsonwebtoken" ; +import jwt from "jsonwebtoken"; import transporter from "../utils/transporter.js"; import z from "zod"; +import nodemailer from "nodemailer"; -import { generateUniqueUsernames } from '../utils/generateUsernames.js'; +import { generateUniqueUsernames } from "../utils/generateUsernames.js"; const usersignUpSchema = z.object({ - username:z.string(), - email:z.string(), - password:z.string() -}) + username: z.string(), + email: z.string(), + password: z.string(), +}); const usersSignInSchema = z.object({ - email:z.string(), - password:z.string() -}) + email: z.string(), + password: z.string(), +}); - - - -const sendEmailVarification = async ({ userID, email }, res) => { +const sendEmailVarification = async ({ userID, username, email }, res) => { try { console.log(userID, email); const otp = `${Math.floor(1000 + Math.random() * 9000)}`; const hashOtp = await bcrypt.hash(otp, 10); - const mailOptions = { - from: process.env.AUTH_EMAIL, + // const mailOptions = { + // from: process.env.AUTH_EMAIL, + // to: email, + // subject: "Varify Your Email", + // text: `Your OTP code for quIET is: ${otp}. It will expire in 3 minutes`, + // }; + + let transporter = nodemailer.createTransport({ + service: "gmail", + auth: { + user: process.env.AUTH_EMAIL, + pass: process.env.AUTH_PASS, + }, + }); + + let mailOptions = { to: email, subject: "Varify Your Email", text: `Your OTP code for quIET is: ${otp}. It will expire in 3 minutes`, + html: `

Your OTP code for quIET with the username ${username} is ${otp}. It will expire in 3 minutes.`, }; transporter.sendMail(mailOptions, async (error, info) => { @@ -79,12 +92,12 @@ const sendEmailVarification = async ({ userID, email }, res) => { const signup = async (req, res) => { try { const validity = usersignUpSchema.safeParse(req.body); - if(!validity.success) + if (!validity.success) res.status(500).json({ - message:"Wrong Inputs", - error:validity.error - }) - + message: "Wrong Inputs", + error: validity.error, + }); + const { username, email, password } = req.body; if (username == "" || email == "" || password == "") { res.json({ message: "Credentials cannot be empty" }); @@ -94,49 +107,62 @@ const signup = async (req, res) => { var token = jwt.sign({ email: email }, process.env.SECRET_KEY, { expiresIn: "1d", }); - + const isuser = await prisma.user.findFirst({ where: { - OR:[ + OR: [ { - username + username, }, { - email: email - } - ] - } + email: email, + }, + ], + }, }); - if (isuser) { + let newUser; + if ((isuser && isuser.isVarified)|| (isuser && !isuser.isVarified && isuser.email!=email)) { res.status(400).json({ res: "User Already Exists" }); + return; + } else if (isuser && !isuser.isVarified && isuser.email==email) { + newUser = await prisma.user.update({ + where:{ + username: isuser.username + }, + data:{ + username, + password: hashPass, + } + }) + + } else { - const newUser = await prisma.user.create({ + newUser = await prisma.user.create({ data: { username: username, email: email, password: hashPass, }, }); - console.log(newUser); - await sendEmailVarification(newUser, res); } + console.log(newUser); + await sendEmailVarification(newUser, res); } catch (error) { console.log(error); res.json({ - msg:"Some Error Occured", - error + msg: "Some Error Occured", + error, }); } }; - - -const varifyOtp = async (req, res) => { +const varifyOtp = async (req, res) => { try { // console.log("Remaining = "+(req.rateLimit.remaining)); - if(req.rateLimit.remaining <= 1) - { - return res.status(425).send({message:"Too Many requests, please try again after some minutes"}); + if (req.rateLimit.remaining <= 1) { + return res.status(425).send({ + message: "Too Many requests, please try again after some minutes", + }); } const { userID, otp, email } = req.body; if (userID == "" || otp == "") { @@ -165,9 +191,13 @@ const varifyOtp = async (req, res) => { return res.status(401).json({ msg: "Invalid Otp" }); } - var token = jwt.sign({ userId:userID,email: email }, process.env.SECRET_KEY, { - expiresIn: 24 * 60 * 60, - }); + var token = jwt.sign( + { userId: userID, email: email }, + process.env.SECRET_KEY, + { + expiresIn: 24 * 60 * 60, + } + ); const updateUser = await prisma.user.update({ where: { userID: userID, @@ -183,12 +213,15 @@ const varifyOtp = async (req, res) => { }, }); - return res.cookie(updateUser.userID, token, { - path: "/", - expires: new Date(Date.now() + 1000 * 1 * 24 * 60 * 60), - httpOnly: true, - sameSite: "lax", - }).status(202).send(email); + return res + .cookie(updateUser.userID, token, { + path: "/", + expires: new Date(Date.now() + 1000 * 1 * 24 * 60 * 60), + httpOnly: true, + sameSite: "lax", + }) + .status(202) + .send(email); } } catch (error) { console.log(error); @@ -251,10 +284,11 @@ const updatePassword = async (req, res) => { const signin = async (req, res) => { try { - if(req.rateLimit.remaining <= 1) - { - return res.status(425).send({message:"Too Many requests, please try again after some minutes"}); - } + if (req.rateLimit.remaining <= 1) { + return res.status(425).send({ + message: "Too Many requests, please try again after some minutes", + }); + } const { username, email, password } = req.body; const user = await prisma.user.findFirst({ @@ -270,26 +304,32 @@ const signin = async (req, res) => { console.log(user); if (!user) { - return res.status(401).json({ msg: "Incorrect Credentials or User not found" }); + return res + .status(401) + .json({ msg: "Incorrect Credentials or User not found" }); } - var token = jwt.sign({ userId:user.userID,email: user.email }, process.env.SECRET_KEY, { - expiresIn: 24 * 60 * 60, - }); + var token = jwt.sign( + { userId: user.userID, email: user.email }, + process.env.SECRET_KEY, + { + expiresIn: 24 * 60 * 60, + } + ); console.log(token); const hashPass = user.password; const isVarified = user.isVarified; const validPass = bcrypt.compareSync(password, hashPass); console.log(validPass); + if (!isVarified) { + res.status(403).send({ msg: "User is not varified!" }); + } if (!validPass) { return res.status(401).json({ msg: "Incorrect Credentials" }); } - if (!isVarified) { - res.status(403).send({ msg: "User is not varified!" }); - } res .cookie(user.userID, token, { @@ -305,8 +345,6 @@ const signin = async (req, res) => { } }; - - const refreshSignIn = async (req, res) => { try { if (req.headers.cookie) { @@ -341,7 +379,7 @@ const logout = async (req, res) => { where: { email: payload.email }, }); // console.log(user?.email); - if(!user) return res.status(400).send("User not Found"); + if (!user) return res.status(400).send("User not Found"); res .clearCookie(user?.userID, "", { path: "/", @@ -354,14 +392,12 @@ const logout = async (req, res) => { // console.log(req.body.email); } catch (error) { res.status(500).json({ - msg:"Server Issue", - error - }) + msg: "Server Issue", + error, + }); } }; - - const testing = async (req, res) => { const deleteUsers = await prisma.user.deleteMany({ where: { @@ -380,18 +416,26 @@ const testing = async (req, res) => { res.json({ msg: "deleted" }); }; - -const generateUsername=async(req,res)=>{ - +const generateUsername = async (req, res) => { try { const usernames = await generateUniqueUsernames(); res.status(201).json({ usernames }); } catch (error) { - res.status(500).json({ error: 'Failed to generate username options' }); + res.status(500).json({ error: "Failed to generate username options" }); } - }; -const authController={signup, signin, logout, varifyOtp , resendOtp, resetPassword, updatePassword, refreshSignIn,generateUsername,testing} +const authController = { + signup, + signin, + logout, + varifyOtp, + resendOtp, + resetPassword, + updatePassword, + refreshSignIn, + generateUsername, + testing, +}; -export default authController \ No newline at end of file +export default authController; diff --git a/backend/src/controller/search.js b/backend/src/controller/search.js index 5a0cc89..5413a4d 100644 --- a/backend/src/controller/search.js +++ b/backend/src/controller/search.js @@ -1,7 +1,6 @@ import prisma from "../../db/db.config.js"; import CryptoJS from "crypto-js"; import axios from "axios"; -import { LeetCode } from "leetcode-query"; export const getUsers = async (req, res) => { try { @@ -215,7 +214,8 @@ export const getLCdata = async (req, res) => { const user = data.matchedUser; if (!user) { - res.status(404).send({ status: "error" }); + res.status(404).send("user not found"); + return } const solved = user.submitStats.acSubmissionNum; diff --git a/frontend/src/components/LeetCode.jsx b/frontend/src/components/LeetCode.jsx index 1c78b0f..a4ac773 100644 --- a/frontend/src/components/LeetCode.jsx +++ b/frontend/src/components/LeetCode.jsx @@ -54,23 +54,23 @@ const LeetCode = () => { const encUsername = CryptoJS.AES.encrypt(user.leetcode, import.meta.env.VITE_LC_SECRETKEY).toString(); - - let res = await axios.post(`${baseAddress}search/getLCdata/`, {username: encUsername}); if (res.status==200) { setlcdata(res.data); - } else { - console.log("Some error occured!"); - toast.error("Some error occured!") - } } catch (error) { - console.log(error); + if(error.response.status==404){ + console.log("user not found"); + toast.error("User not found!"); + + }else{ + console.log(error); + } } setisLoading(false) @@ -93,7 +93,7 @@ const LeetCode = () => { if (user?.leetcode) { getLC() } - }, [user]) + }, []) return ( diff --git a/frontend/src/pages/Signin.jsx b/frontend/src/pages/Signin.jsx index a85c1da..760558c 100644 --- a/frontend/src/pages/Signin.jsx +++ b/frontend/src/pages/Signin.jsx @@ -71,8 +71,8 @@ const Signin = () => { if(error.response.status==401){ toast.error("Invalid Credentials") }else if(error.response.status==403){ - toast.error("User is not Varified! Varify your email.") - Navigate("/varifyaccount") + toast.error("User doesn't exists. Please Sign Up") + Navigate("/signup") } else if(error.response.status == 425) { diff --git a/frontend/src/pages/Signup.jsx b/frontend/src/pages/Signup.jsx index 35f9ec4..e3c891a 100644 --- a/frontend/src/pages/Signup.jsx +++ b/frontend/src/pages/Signup.jsx @@ -17,6 +17,8 @@ import baseAddress from "../utils/localhost"; import { login } from '../redux/login'; import { getUserData } from '../App'; import { show } from '../redux/welcome'; +import { v4 as uuidv4 } from 'uuid'; + @@ -290,9 +292,9 @@ const Signup = () => {

- {Array.from(usrnmList).map(username => <> -
handleSelect(username)} className=' rounded-xl px-2 cursor-pointer bg-[#b1b390] text-gray-900'>{username}
- + {Array.from(usrnmList).map(username =>( +
handleSelect(username)} className=' rounded-xl px-2 cursor-pointer bg-[#b1b390] text-gray-900'>{username}
+ ) )}
{isLoading ? : handleClick()} className=' font-semibold text-xl' />}