Skip to content

Commit

Permalink
Merge branch 'main' into session
Browse files Browse the repository at this point in the history
  • Loading branch information
Sourabh782 authored Oct 28, 2024
2 parents 83b0d4b + 6d21841 commit aae2662
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 26 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,20 @@ We extend our heartfelt gratitude to all the amazing contributors who have made


<!-- ALL-CONTRIBUTORS-LIST:END -->
---
## Stargazers ❤️

<div align='left'>

[![Stargazers repo roster for RamakrushnaBiswal/PlayCafe](https://reporoster.com/stars/RamakrushnaBiswal/PlayCafe)](https://github.com/RamakrushnaBiswal/PlayCafe/stargazers)

</div>

## Forkers ❤️

[![Forkers repo roster for RamakrushnaBiswal/PlayCafe](https://reporoster.com/forks/RamakrushnaBiswal/PlayCafe)](https://github.com/RamakrushnaBiswal/PlayCafe/network/members)

---

## ⭐ Support

Expand Down
31 changes: 30 additions & 1 deletion backend/config/nodemailer.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,33 @@ exports.sendVerificationMail = async (email, verificationCode) => {
}
}

}
}


exports.sendRegisterVerificationMail = async (email, verificationCode) => {
const emailText = `
Dear Customer,
Please use this verification code for verifying your account. Here's your code':
RCode: ${verificationCode}
Thank you for choosing our service. We are happy to help you.
Best regards,
PlayCafe
`;

try {
await transporter.sendMail({
from: process.env.EMAIL_USER,
to: email,
subject: 'Your OTP Verification Code',
text: emailText,
});
} catch (error) {
console.error("Error sending OTP email:", error);
throw new Error("Failed to send OTP email");
}
}

82 changes: 63 additions & 19 deletions backend/controller/customer.controller.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* eslint-disable no-unused-vars */
const bcrypt = require("bcrypt");
const crypto = require('crypto');
const { z } = require("zod");
const Customer = require("../models/customer.model");
const jwt = require("jsonwebtoken");
const { sendRegisterVerificationMail } = require("../config/nodemailer");

// Define the schema
const customerSchema = z.object({
Expand All @@ -12,9 +14,7 @@ const customerSchema = z.object({
});

async function createCustomer(req, res) {
// Validate the request body
const validation = customerSchema.safeParse(req.body);

if (!validation.success) {
return res.status(400).json({ error: validation.error.errors });
}
Expand All @@ -25,67 +25,109 @@ async function createCustomer(req, res) {
}

try {

const otp = crypto.randomInt(100000, 999999).toString();
const otpExpiry = new Date(Date.now() + 5 * 60 * 1000); // 5 mins from now

const hashedPassword = await bcrypt.hash(req.body.password, 10);
const customer = new Customer({
name: req.body.name,
email: req.body.email,
password: hashedPassword,
otp,
otpExpiry,
isVerified: false,
});
await customer.save();
res.status(201).json({ message: "Customer created successfully" });

await sendRegisterVerificationMail(req.body.email, otp);

res.status(201).json({ message: "OTP sent to your email. Verify to complete registration." });
} catch (error) {
console.error("Error creating customer:", error);
res.status(500).json({ error: "Internal server error" });
}
}


async function verifyOtp(req, res) {
const { email, otp } = req.body;

try {
const customer = await Customer.findOne({ email });


if (!customer || customer.isVerified) {
return res.status(400).json({ error: "Invalid request or already verified" });
}


if (customer.otp !== otp) {
return res.status(400).json({ error: "Invalid OTP" });
}
if (new Date() > customer.otpExpiry) {
return res.status(400).json({ error: "OTP expired. Please register again." });
}


customer.isVerified = true;
customer.otp = undefined;
customer.otpExpiry = undefined;
await customer.save();

res.status(200).json({ message: "Registration successful!" });
} catch (error) {
console.error("Error verifying OTP:", error);
res.status(500).json({ error: "Internal server error" });
}
}


async function loginCustomer(req, res) {
const customerLoginSchema = z.object({
email: z.string().email("Invalid email address"),
password: z.string().min(6, "Password must be at least 6 characters long"),
});
// Validate the request body


const validation = customerLoginSchema.safeParse(req.body);
if (!validation.success) {
return res.status(400).json({ error: validation.error.errors });
}

try {
const customer = await Customer.findOne({ email: req.body.email });
console.log("1");

if (!customer) {
return res.status(401).json({ error: "Invalid email or password" });
}
const validPassword = await bcrypt.compare(
req.body.password,
customer.password
);
console.log("2");
if (!customer.isVerified) {
return res.status(403).json({ error: "Account not verified. Please verify your email." });
}

const validPassword = await bcrypt.compare(req.body.password, customer.password);

if (!validPassword) {
return res.status(401).json({ error: "Invalid email or password" });
}

const payload = {
sub: customer._id, // User ID
sub: customer._id,
name: customer.name, // Optional
role: "customer", // Optional
email: customer.email, // Optional
};
console.log("3");

const token = jwt.sign(
payload,
process.env.JWT_SECRET,
{ expiresIn: "1h" } // Expires in 1 hour
);
console.log("4");
console.log(req.session);

req.session.user = {
id: customer._id,
name: customer.name,
};
console.log("5");

res.cookie("authToken", token, {
maxAge: 1000 * 60 * 60,
Expand All @@ -104,12 +146,13 @@ async function loginCustomer(req, res) {
},
});
} catch (error) {
console.log(error);
console.error("Error during login:", error);

res.status(500).json({ error: "Internal server error" });
}
}


async function resetPassword(req, res) {
const customerResetPasswordSchema = z.object({
email: z.string().email("Invalid email address"),
Expand Down Expand Up @@ -148,5 +191,6 @@ module.exports = {
createCustomer,
loginCustomer,
resetPassword,
logout
logout,
verifyOtp
};
12 changes: 12 additions & 0 deletions backend/models/customer.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ const customerSchema = new Schema(
verificationCode: {
type: String,
default: "",

},
otp: {
type: String,
},
otpExpiry: {
type: Date,
},
isVerified: {
type: Boolean,
default: false,

},
role: {
type: String,
Expand Down
4 changes: 2 additions & 2 deletions backend/routes/customerRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const {
createCustomer,
resetPassword,
logout,
verifyOtp,
} = require("../controller/customer.controller");
const authenticateCustomer = require("../middlewares/authCustomer");
const passport = require("../config/passport.config");
Expand All @@ -28,9 +29,8 @@ router.get(
);

router.post("/register", createCustomer);

router.post("/logout", logout)

router.post("/verify", verifyOtp);
router.get(
"/auth/google",
passport.authenticate("google", { scope: ["email"] })
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/components/Pages/Signup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const Signup = () => {
const handleSubmit = async (e) => {
e.preventDefault();
setIsLoading(true);

// Input validation
if (!data.email || !data.password || !data.name) {
setError('Please fill in all fields');
setIsLoading(false);
Expand All @@ -45,25 +47,33 @@ const Signup = () => {
setIsLoading(false);
return;
}

try {
const response = await fetch(`${API_URL}/api/user/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();

if (!response.ok) {
setIsLoading(false);
setError(result.error);
return;
}
alert('Registered successfully! Please log in.');
navigate('/');


alert('OTP sent to your email. Verify to complete registration.');
navigate('/otp-verify');

} catch (error) {
setError(error.message);
console.error('Error:', error);
} finally {
setIsLoading(false); // Ensure loading state is reset after request
}
};


useEffect(() => {
window.scrollTo(0, 0);
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/Pages/VerifyOtp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ const VerifyOtp = () => {
onChange={(e) => handleChange(e)}
/>



<button
type="submit"
className="button-confirm mx-auto mt-12 px-4 w-30 h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] cursor-pointer active:shadow-none active:translate-x-[3px] active:translate-y-[3px]"
Expand Down
Loading

0 comments on commit aae2662

Please sign in to comment.