diff --git a/middleware/auth.js b/middleware/auth.js index 7deb650..5643839 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -7,14 +7,31 @@ export const authenticateToken = async (req, res, next) => { try { // TODO: Implement the authentication middleware // 1. Get the token from the request header + const token = req.headers["authorization"]?.split(" ")[1]; + if (!token) { + return res.status(401).json({ + success: false, + message: "No token provided", + }); + } + // 2. Verify the token + const decoded = jwt.verify(token, JWT_SECRET || "9f3c8a72b4e6d1a0c57e3f91d2b8a4e5"); // 3. Get the user from the database + const user = await prisma.user.findUnique({ + where: { id: decoded.id }, + }); // 4. If the user doesn't exist, throw an error + if (!user) { + return res.status(401).json({ + success: false, + message: "User not found", + }); + } // 5. Attach the user to the request object + req.user = user; // 6. Call the next middleware - - - + next(); } catch (error) { if (error.name === "JsonWebTokenError") { return res.status(401).json({ diff --git a/routes/auth.js b/routes/auth.js index 7a78cfc..2d5ad04 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -5,21 +5,51 @@ import prisma from "../lib/prisma.js"; import { authenticateToken } from "../middleware/auth.js"; const router = express.Router(); -const JWT_SECRET = process.env.JWT_SECRET || "your-secret-key"; +const JWT_SECRET = process.env.JWT_SECRET || "9f3c8a72b4e6d1a0c57e3f91d2b8a4e5"; // POST /api/auth/register - Register a new user router.post("/register", async (req, res) => { try { // TODO: Implement the registration logic // 1. Validate the input + const { email, password } = req.body; + if (!email || !password) { + return res.status(400).json({ + success: false, + message: "Email and password are required", + }); + } + // 2. Check if the user already exists + const existingUser = await prisma.user.findUnique({ + where: { email }, + }); + if (existingUser) { + return res.status(400).json({ + success: false, + message: "User already exists", + }); + } + // 3. Hash the password + const hashedPassword = await bcrypt.hash(password, 10); // 4. Create the user + const newUser = await prisma.user.create({ + data: { + email, + password: hashedPassword, + }, + }); // 5. Generate a JWT token + const token = jwt.sign({ id: newUser.id }, JWT_SECRET, { expiresIn: "1h" }); // 6. Return the user data and token - - - + res.json({ + success: true, + data: { + user: newUser, + token, + }, + }); } catch (error) { console.error("Registration error:", error); res.status(500).json({ @@ -35,12 +65,35 @@ router.post("/login", async (req, res) => { try { // TODO: Implement the login logic // 1. Validate the input + const { email, password } = req.body; // 2. Check if the user exists + const user = await prisma.user.findUnique({ + where: { email }, + }); + if (!user) { + return res.status(401).json({ + success: false, + message: "Invalid email or password", + }); + } // 3. Compare the password + const isMatch = await bcrypt.compare(password, user.password); + if (!isMatch) { + return res.status(401).json({ + success: false, + message: "Invalid email or password", + }); + } // 4. Generate a JWT token + const token = jwt.sign({ id: user.id }, JWT_SECRET, { expiresIn: "1h" }); // 5. Return the user data and token - - + res.json({ + success: true, + data: { + user, + token, + }, + }); } catch (error) { console.error("Login error:", error); res.status(500).json({ @@ -50,6 +103,148 @@ router.post("/login", async (req, res) => { }); } }); +//add email verification field +const emailVerificationField = async () => { + // Add email verification field to user model + await prisma.user.updateMany({ + where: { emailVerified: null }, + data: { emailVerified: false }, + }); +}; + +// create password reset endpoint +router.post("/reset-password", async (req, res) => { + const { email } = req.body; + if (!email) { + return res.status(400).json({ + success: false, + message: "Email is required", + }); + } + + // Check if the user exists + const user = await prisma.user.findUnique({ + where: { email }, + }); + if (!user) { + return res.status(404).json({ + success: false, + message: "User not found", + }); + } + + // Generate a password reset token + const token = generatePasswordResetToken(user.id); + sendPasswordResetEmail(email, token); + + res.json({ + success: true, + message: "Password reset email sent", + }); +}); + +//send reset email +const sendPasswordResetEmail = (email, token) => { + // In a real application, you would send the email here. + console.log(`Send password reset email to ${email} with token: ${token}`); +}; +//create reset password endpoint +router.post("/reset-password/:token", async (req, res) => { + const { token } = req.params; + const { newPassword } = req.body; + + if (!token || !newPassword) { + return res.status(400).json({ + success: false, + message: "Token and new password are required", + }); + } + + try { + const decoded = jwt.verify(token, JWT_SECRET); + const user = await prisma.user.findUnique({ + where: { id: decoded.id }, + }); + if (!user) { + return res.status(404).json({ + success: false, + message: "User not found", + }); + } + + // Update user's password + const hashedPassword = await bcrypt.hash(newPassword, 10); + await prisma.user.update({ + where: { id: user.id }, + data: { password: hashedPassword }, + }); + + res.json({ + success: true, + message: "Password reset successfully", + }); + } catch (error) { + console.error("Password reset error:", error); + res.status(500).json({ + success: false, + message: "Error resetting password", + error: error.message, + }); + } +}); + +//generate verification token +const generateVerificationToken = (userId) => { + return jwt.sign({ id: userId }, JWT_SECRET, { expiresIn: "1d" }); +}; + +//send verification token +const sendVerificationEmail = (email, token) => { + // In a real application, you would send the email here. + console.log(`Send verification email to ${email} with token: ${token}`); +}; + +//create verification endpoint +router.post("/verify-email", async (req, res) => { + const { token } = req.body; + if (!token) { + return res.status(400).json({ + success: false, + message: "Verification token is required", + }); + } + + try { + const decoded = jwt.verify(token, JWT_SECRET); + const user = await prisma.user.findUnique({ + where: { id: decoded.id }, + }); + if (!user) { + return res.status(404).json({ + success: false, + message: "User not found", + }); + } + + // Update user's email verification status + await prisma.user.update({ + where: { id: user.id }, + data: { emailVerified: true }, + }); + + res.json({ + success: true, + message: "Email verified successfully", + }); + } catch (error) { + console.error("Email verification error:", error); + res.status(500).json({ + success: false, + message: "Error verifying email", + error: error.message, + }); + } +}); // GET /api/auth/me - Get current user profile (protected route) router.get("/me", authenticateToken, async (req, res) => {