backend_adaptive_learning/controllers/auth.js

202 lines
5.5 KiB
JavaScript
Raw Normal View History

2024-08-12 02:44:06 +00:00
import response from "../response.js";
import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
import nodemailer from 'nodemailer';
import models from "../models/index.js";
const transporter = nodemailer.createTransport({
service: 'gmail', // Anda bisa menggunakan layanan email lainnya
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
export const registerUser = async (req, res) => {
const { name, email, password, confirmPassword } = req.body;
let roles = "student";
if (!name) {
return res.status(400).json({ message: "Name is required!" });
}
if (!email) {
return res.status(400).json({ message: "Email is required!" });
}
if (!password) {
return res.status(400).json({ message: "Password is required!" });
}
if (!confirmPassword) {
return res.status(400).json({ message: "Confirm Password is required!" });
}
if (password !== confirmPassword) {
return res.status(400).json({ message: "Passwords do not match!" });
}
try {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const newUser = await models.User.create({
name,
email,
password: hashedPassword,
roles,
});
res.status(200).json({ message: "Registration success", result: newUser });
} catch (error) {
console.log(error);
// Check for unique constraint error on email
if (error.name === "SequelizeUniqueConstraintError") {
return res.status(400).json({ message: "Email already registered!" });
}
res.status(500).json({ message: "Internal Server Error" });
}
};
export const loginUser = async (req, res) => {
const { email, password } = req.body;
if (!email) {
return response(400, null, "Email is required!", res);
}
if (!password) {
return response(400, null, "Password is required!", res);
}
try {
const user = await models.User.findOne({ where: { email } });
if (!user) {
return response(404, null, "User data not found!", res);
}
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) {
return response(401, null, "The password you entered is incorrect!", res);
}
const accessToken = jwt.sign(
{ id: user.id },
process.env.ACCESS_TOKEN_SECRET
);
// Set tokens as HTTP-only cookies
res.cookie("accessToken", accessToken, {
httpOnly: true,
secure: process.env.NODE_ENV === "production", // Use secure cookies in production
});
// Selectively pick fields to send in the response
const userResponse = {
id: user.id,
name: user.name,
email: user.email,
roles: user.roles,
};
response(200, userResponse, "Success", res);
} catch (error) {
console.log(error);
res.status(500).json({ message: "Internal Server Error" });
}
};
export const logoutUser = (req, res) => {
res.clearCookie("accessToken", {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
});
res.status(200).json({ message: "You have successfully logged out." });
};
export const forgotPassword = async (req, res) => {
const { email } = req.body;
if (!email) {
return response(400, null, "Email is required!", res);
}
try {
const user = await models.User.findOne({ where: { email } });
if (!user) {
return response(404, null, "Email is not registered!", res);
}
const resetToken = jwt.sign({ id: user.id }, process.env.RESET_PASSWORD_SECRET, {
expiresIn: '1h', // Token valid for 1 hour
});
const resetLink = `http://localhost:${process.env.APP_PORT}/resetPassword/${resetToken}`;
const mailOptions = {
from: process.env.EMAIL_USER,
to: user.email,
subject: 'Password Reset',
text: `You are receiving this because you (or someone else) have requested the reset of the password for your account.
Please click on the following link, or paste this into your browser to complete the process:
${resetLink}
If you did not request this, please ignore this email and your password will remain unchanged.`,
};
await transporter.sendMail(mailOptions);
response(200, null, "Password reset email sent successfully!", res);
} catch (error) {
console.log(error);
res.status(500).json({ message: "Internal Server Error" });
}
};
export const resetPassword = async (req, res) => {
const { token, newPassword, confirmNewPassword } = req.body;
if (!token) {
return response(400, null, "Token is required!", res);
}
if (!newPassword) {
return response(400, null, "New password is required!", res);
}
if (!confirmNewPassword) {
return response(400, null, "Confirm new password is required!", res);
}
if (newPassword !== confirmNewPassword) {
return response(400, null, "Passwords do not match!", res);
}
try {
const decoded = jwt.verify(token, process.env.RESET_PASSWORD_SECRET);
const user = await models.User.findOne({ where: { id: decoded.id } });
if (!user) {
return response(404, null, "User data not found!", res);
}
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(newPassword, salt);
user.password = hashedPassword;
await user.save();
response(200, null, "Password has been reset successfully!", res);
} catch (error) {
console.log(error);
if (error.name === "TokenExpiredError") {
return response(400, null, "Reset token has expired!", res);
} else {
return res.status(500).json({ message: "Internal Server Error" });
}
}
};