This commit is contained in:
newtbot 2023-12-27 16:58:51 +08:00
parent 84e6b42cb7
commit 45747af260
4 changed files with 567 additions and 454 deletions

View File

@ -10,11 +10,9 @@
/* /*
1) generate random data for each sensor 1) generate random data for each sensor
3) send the coap request to the server 2) pass to mqtt broker
*/ */
const { isNumber } = require("../../Web-Server/functions/validateData");
let region = ["central", "north-east", "north", "east", "west"]; let region = ["central", "north-east", "north", "east", "west"];
function generateRandomData() { function generateRandomData() {

19
Sean/modules/mysql.js Normal file
View File

@ -0,0 +1,19 @@
const mysqlConfig = {
host: process.env.host,
user: process.env.user,
password: process.env.password,
database: process.env.database,
timezone: "Z", // Set the timezone to UTC
};
const connection = mysql.createConnection(mysqlConfig);
connection.connect((err) => {
if (err) {
console.error("Error connecting to MySQL:", err);
return;
}
console.log("Connected to MySQL");
});
module.exports = { connection , mysqlConfig };

View File

@ -0,0 +1,13 @@
const transporter = nodemailer.createTransport({
service: 'gmail',
host: 'smtp.gmail.com',
port: 587, // use the appropriate port for your SMTP server
secure: false, // true for 465, false for other ports
auth: {
user: process.env.euser,
pass: process.env.epass
},
});
module.exports = { transporter } ;

View File

@ -1,113 +1,95 @@
const express = require('express'); const express = require("express");
const session = require('express-session'); const session = require("express-session");
const mysql = require('mysql'); const mysql = require("mysql");
const bodyParser = require('body-parser'); const bodyParser = require("body-parser");
const bcrypt = require('bcrypt'); const bcrypt = require("bcrypt");
const crypto = require('crypto'); const crypto = require("crypto");
const nodemailer = require('nodemailer'); const nodemailer = require("nodemailer");
const transporter = require("../modules/nodeMailer");
const { mysqlConfig , connection } = require("../modules/mysql");
const app = express(); const app = express();
app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json()); app.use(bodyParser.json());
const PORT = process.env.PORT || 3000; const PORT = process.env.PORT || 3000;
require('dotenv').config(); require("dotenv").config();
const mysqlConfig = {
host: process.env.host,
user: process.env.user,
password: process.env.password,
database: process.env.database,
timezone: 'Z', // Set the timezone to UTC
};
const connection = mysql.createConnection(mysqlConfig);
connection.connect((err) => {
if (err) {
console.error('Error connecting to MySQL:', err);
return;
}
console.log('Connected to MySQL');
});
const transporter = nodemailer.createTransport({
service: 'gmail',
host: 'smtp.gmail.com',
port: 587, // use the appropriate port for your SMTP server
secure: false, // true for 465, false for other ports
auth: {
user: process.env.euser,
pass: process.env.epass
},
});
app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.urlencoded({ extended: true }));
app.use(session({ secret: 'your_session_secret', resave: false, saveUninitialized: true })); app.use(
app.set('view engine', 'ejs'); session({
secret: "your_session_secret",
resave: false,
saveUninitialized: true,
})
);
app.set("view engine", "ejs");
function isAuthenticated(req, res, next) { function isAuthenticated(req, res, next) {
if (req.session && req.session.authenticated) { if (req.session && req.session.authenticated) {
return next(); return next();
} else { } else {
res.redirect('/login'); res.redirect("/login");
} }
} }
app.get('/login', (req, res) => { app.get("/login", (req, res) => {
// Pass an initial value for the error variable // Pass an initial value for the error variable
res.render('login', { error: null }); res.render("login", { error: null });
}); });
const logActivity = async (username, success) => { const logActivity = async (username, success) => {
try { try {
const activity = success ? 'successful login' : 'unsuccessful login due to invalid password or username'; const activity = success
const logSql = 'INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)'; ? "successful login"
: "unsuccessful login due to invalid password or username";
const logSql =
"INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)";
const logParams = [username, activity]; const logParams = [username, activity];
//const connection = mysql.createConnection(mysqlConfig);
//connection.connect();
connection.query(logSql, logParams, (error, results) => { connection.query(logSql, logParams, (error, results) => {
if (error) { if (error) {
console.error('Error logging activity:', error); console.error("Error logging activity:", error);
// Handle error (you may want to log it or take other appropriate actions) // Handle error (you may want to log it or take other appropriate actions)
} else { } else {
console.log('Activity logged successfully'); console.log("Activity logged successfully");
} }
//connection.end(); // Close the connection after logging activity
}); });
} catch (error) { } catch (error) {
console.error('Error in logActivity function:', error); console.error("Error in logActivity function:", error);
// Handle error (you may want to log it or take other appropriate actions) // Handle error (you may want to log it or take other appropriate actions)
} }
}; };
app.post("/login", async (req, res) => {
app.post('/login', async (req, res) => {
try { try {
let { username, password } = req.body; let { username, password } = req.body;
username = username.trim(); username = username.trim();
const loginSql = 'SELECT * FROM users WHERE username = ?'; const loginSql = "SELECT * FROM users WHERE username = ?";
const updateLastLoginSql = 'UPDATE users SET lastLogin = CURRENT_TIMESTAMP WHERE username = ?'; const updateLastLoginSql =
"UPDATE users SET lastLogin = CURRENT_TIMESTAMP WHERE username = ?";
//const connection = mysql.createConnection(mysqlConfig); console.log("Login Query:", loginSql);
//connection.connect(); console.log("Query Parameters:", [username]);
console.log('Login Query:', loginSql);
console.log('Query Parameters:', [username]);
connection.query(loginSql, [username], async (error, results) => { connection.query(loginSql, [username], async (error, results) => {
console.log('Login Results:', results); console.log("Login Results:", results);
if (error) { if (error) {
console.error('Error executing login query:', error); console.error("Error executing login query:", error);
res.status(500).send('Internal Server Error'); res.status(500).send("Internal Server Error");
//connection.end(); // Close the connection in case of an error
return; return;
} }
const isLoginSuccessful = results.length > 0 && (await bcrypt.compare(password, results[0].password)); const isLoginSuccessful =
results.length > 0 &&
(await bcrypt.compare(password, results[0].password));
// Log login attempt // Log login attempt
await logActivity(username, isLoginSuccessful); await logActivity(username, isLoginSuccessful);
@ -116,80 +98,83 @@ app.post('/login', async (req, res) => {
const user = results[0]; const user = results[0];
// Update lastLogin field for the user // Update lastLogin field for the user
connection.query(updateLastLoginSql, [username], (updateError, updateResults) => { connection.query(
updateLastLoginSql,
[username],
(updateError, updateResults) => {
if (updateError) { if (updateError) {
console.error('Error updating lastLogin:', updateError); console.error("Error updating lastLogin:", updateError);
res.status(500).send('Internal Server Error'); res.status(500).send("Internal Server Error");
//connection.end(); // Close the connection in case of an error
return; return;
} }
// Check if the update affected any rows // Check if the update affected any rows
if (updateResults.affectedRows > 0) { if (updateResults.affectedRows > 0) {
// Set session data for authentication // Set session data for authentication
req.session.regenerate(err => { req.session.regenerate((err) => {
if (err) { if (err) {
console.error('Error regenerating session:', err); console.error("Error regenerating session:", err);
} }
console.log('Session regenerated successfully'); console.log("Session regenerated successfully");
req.session.authenticated = true; req.session.authenticated = true;
req.session.username = username; req.session.username = username;
res.redirect('/home'); res.redirect("/home");
//connection.end();
}); });
} else { } else {
// Pass the error to the template // Pass the error to the template
res.render('login', { error: 'Error updating lastLogin. No rows affected.' }); res.render("login", {
//connection.end(); // Close the connection when not needed anymore error: "Error updating lastLogin. No rows affected.",
});
} }
}); }
);
} else { } else {
// Pass the error to the template // Pass the error to the template
res.render('login', { error: 'Invalid username or password' }); res.render("login", { error: "Invalid username or password" });
//connection.end(); // Close the connection when not needed anymore
} }
}); });
} catch (error) { } catch (error) {
console.error('Error in login route:', error); console.error("Error in login route:", error);
res.status(500).send('Internal Server Error'); res.status(500).send("Internal Server Error");
} }
}); });
// Update your /home route to retrieve the overall last 10 logins for all users // Update your /home route to retrieve the overall last 10 logins for all users
app.get('/home', isAuthenticated, (req, res) => { app.get("/home", isAuthenticated, (req, res) => {
// Retrieve the overall last 10 logins for all users // Retrieve the overall last 10 logins for all users
const loginsQuery = 'SELECT username, lastLogin FROM users ORDER BY lastLogin DESC LIMIT 10'; const loginsQuery =
"SELECT username, lastLogin FROM users ORDER BY lastLogin DESC LIMIT 10";
connection.query(loginsQuery, (error, loginResults) => { connection.query(loginsQuery, (error, loginResults) => {
if (error) { if (error) {
console.error('Error executing login logs query:', error); console.error("Error executing login logs query:", error);
res.status(500).send('Internal Server Error'); res.status(500).send("Internal Server Error");
return; return;
} }
// Log the results on the server side // Log the results on the server side
console.log('Login Logs on Server:', loginResults); console.log("Login Logs on Server:", loginResults);
// Render the home page with login logs data // Render the home page with login logs data
res.render('home', { username: req.session.username, loginLogs: loginResults }); res.render("home", {
username: req.session.username,
loginLogs: loginResults,
});
}); });
}); });
app.get('/inusers', isAuthenticated, (req, res) => { app.get("/inusers", isAuthenticated, (req, res) => {
// Fetch all user data from the database // Fetch all user data from the database
const allUsersQuery = 'SELECT * FROM users'; const allUsersQuery = "SELECT * FROM users";
connection.query(allUsersQuery, (error, allUsers) => { connection.query(allUsersQuery, (error, allUsers) => {
if (error) { if (error) {
console.error('Error fetching all users:', error); console.error("Error fetching all users:", error);
res.status(500).send('Internal Server Error'); res.status(500).send("Internal Server Error");
return; return;
} }
// Render the inusers page with JSON data // Render the inusers page with JSON data
res.render('inusers', { allUsers }); res.render("inusers", { allUsers });
}); });
}); });
function isStrongPassword(password) { function isStrongPassword(password) {
@ -223,8 +208,11 @@ function isStrongPassword(password) {
const logUserCreationActivity = async (creatorUsername, success, message) => { const logUserCreationActivity = async (creatorUsername, success, message) => {
try { try {
const activity = success ? 'successful user creation' : `unsuccessful user creation: ${message}`; const activity = success
const logSql = 'INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)'; ? "successful user creation"
: `unsuccessful user creation: ${message}`;
const logSql =
"INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)";
const logParams = [creatorUsername, activity]; const logParams = [creatorUsername, activity];
const connection = mysql.createConnection(mysqlConfig); const connection = mysql.createConnection(mysqlConfig);
@ -233,21 +221,21 @@ const logUserCreationActivity = async (creatorUsername, success, message) => {
connection.query(logSql, logParams, (error, results) => { connection.query(logSql, logParams, (error, results) => {
if (error) { if (error) {
console.error('Error logging user creation activity:', error); console.error("Error logging user creation activity:", error);
// Handle error (you may want to log it or take other appropriate actions) // Handle error (you may want to log it or take other appropriate actions)
} else { } else {
console.log('User creation activity logged successfully'); console.log("User creation activity logged successfully");
} }
connection.end(); // Close the connection after logging activity connection.end(); // Close the connection after logging activity
}); });
} catch (error) { } catch (error) {
console.error('Error in logUserCreationActivity function:', error); console.error("Error in logUserCreationActivity function:", error);
// Handle error (you may want to log it or take other appropriate actions) // Handle error (you may want to log it or take other appropriate actions)
} }
}; };
app.post('/createUser', async (req, res) => { app.post("/createUser", async (req, res) => {
try { try {
const { name, username, email, password, jobTitle } = req.body; const { name, username, email, password, jobTitle } = req.body;
@ -256,71 +244,112 @@ app.post('/createUser', async (req, res) => {
// Validate password complexity // Validate password complexity
if (!isStrongPassword(password)) { if (!isStrongPassword(password)) {
return res.status(400).json({ error: 'Password does not meet complexity requirements' }); return res
.status(400)
.json({ error: "Password does not meet complexity requirements" });
} }
// Check if the username is already taken // Check if the username is already taken
const checkUsernameQuery = 'SELECT * FROM users WHERE username = ?'; const checkUsernameQuery = "SELECT * FROM users WHERE username = ?";
connection.query(checkUsernameQuery, [username], (usernameQueryErr, usernameResults) => { connection.query(
checkUsernameQuery,
[username],
(usernameQueryErr, usernameResults) => {
if (usernameQueryErr) { if (usernameQueryErr) {
console.error('Error checking username:', usernameQueryErr); console.error("Error checking username:", usernameQueryErr);
return res.status(500).json({ error: 'Internal Server Error' }); return res.status(500).json({ error: "Internal Server Error" });
} }
if (usernameResults.length > 0) { if (usernameResults.length > 0) {
// Log unsuccessful user creation due to username taken // Log unsuccessful user creation due to username taken
logUserCreationActivity(creatorUsername, false, 'username taken'); logUserCreationActivity(creatorUsername, false, "username taken");
return res.status(400).json({ error: 'Username is already taken', message: 'Username is already taken. Please choose a different username.' }); return res
.status(400)
.json({
error: "Username is already taken",
message:
"Username is already taken. Please choose a different username.",
});
} }
// Check if the email is already taken // Check if the email is already taken
const checkEmailQuery = 'SELECT * FROM users WHERE email = ?'; const checkEmailQuery = "SELECT * FROM users WHERE email = ?";
connection.query(checkEmailQuery, [email], (emailQueryErr, emailResults) => { connection.query(
checkEmailQuery,
[email],
(emailQueryErr, emailResults) => {
if (emailQueryErr) { if (emailQueryErr) {
console.error('Error checking email:', emailQueryErr); console.error("Error checking email:", emailQueryErr);
return res.status(500).json({ error: 'Internal Server Error' }); return res.status(500).json({ error: "Internal Server Error" });
} }
if (emailResults.length > 0) { if (emailResults.length > 0) {
// Log unsuccessful user creation due to email taken // Log unsuccessful user creation due to email taken
logUserCreationActivity(creatorUsername, false, 'email taken'); logUserCreationActivity(creatorUsername, false, "email taken");
return res.status(400).json({ error: 'Email is already in use', message: 'Email is already in use. Please choose another email.' }); return res
.status(400)
.json({
error: "Email is already in use",
message:
"Email is already in use. Please choose another email.",
});
} }
// Hash the password before storing it in the database // Hash the password before storing it in the database
bcrypt.hash(password, 10, (hashError, hashedPassword) => { bcrypt.hash(password, 10, (hashError, hashedPassword) => {
if (hashError) { if (hashError) {
console.error('Error hashing password:', hashError); console.error("Error hashing password:", hashError);
return res.status(500).json({ error: 'Internal Server Error' }); return res.status(500).json({ error: "Internal Server Error" });
} }
// Start a transaction // Start a transaction
connection.beginTransaction((transactionErr) => { connection.beginTransaction((transactionErr) => {
if (transactionErr) { if (transactionErr) {
console.error('Error starting transaction:', transactionErr); console.error("Error starting transaction:", transactionErr);
return res.status(500).json({ error: 'Internal Server Error' }); return res
.status(500)
.json({ error: "Internal Server Error" });
} }
// Define the insert query // Define the insert query
const insertUserQuery = 'INSERT INTO users (name, username, email, password, lastLogin, jobTitle) VALUES (?, ?, ?, ?, NULL, ?)'; const insertUserQuery =
"INSERT INTO users (name, username, email, password, lastLogin, jobTitle) VALUES (?, ?, ?, ?, NULL, ?)";
// Log the query and its parameters // Log the query and its parameters
console.log('Insert Query:', insertUserQuery); console.log("Insert Query:", insertUserQuery);
console.log('Query Parameters:', [name, username, email, hashedPassword, jobTitle]); console.log("Query Parameters:", [
name,
username,
email,
hashedPassword,
jobTitle,
]);
// Execute the query with user data // Execute the query with user data
connection.query(insertUserQuery, [name, username, email, hashedPassword, jobTitle], (queryErr, results) => { connection.query(
insertUserQuery,
[name, username, email, hashedPassword, jobTitle],
(queryErr, results) => {
if (queryErr) { if (queryErr) {
console.error('Error executing query:', queryErr); console.error("Error executing query:", queryErr);
// Rollback the transaction in case of an error // Rollback the transaction in case of an error
connection.rollback((rollbackErr) => { connection.rollback((rollbackErr) => {
if (rollbackErr) { if (rollbackErr) {
console.error('Error rolling back transaction:', rollbackErr); console.error(
"Error rolling back transaction:",
rollbackErr
);
} }
// Log unsuccessful user creation due to an error // Log unsuccessful user creation due to an error
logUserCreationActivity(creatorUsername, false, 'internal error'); logUserCreationActivity(
return res.status(500).json({ error: 'Internal Server Error' }); creatorUsername,
false,
"internal error"
);
return res
.status(500)
.json({ error: "Internal Server Error" });
}); });
return; return;
} }
@ -328,187 +357,237 @@ app.post('/createUser', async (req, res) => {
// Commit the transaction // Commit the transaction
connection.commit((commitErr) => { connection.commit((commitErr) => {
if (commitErr) { if (commitErr) {
console.error('Error committing transaction:', commitErr); console.error(
"Error committing transaction:",
commitErr
);
// Log unsuccessful user creation due to an error // Log unsuccessful user creation due to an error
logUserCreationActivity(creatorUsername, false, 'internal error'); logUserCreationActivity(
return res.status(500).json({ error: 'Internal Server Error' }); creatorUsername,
false,
"internal error"
);
return res
.status(500)
.json({ error: "Internal Server Error" });
} }
// Log successful user creation // Log successful user creation
logUserCreationActivity(creatorUsername, true, 'user created successfully'); logUserCreationActivity(
creatorUsername,
true,
"user created successfully"
);
// Log the results of the query // Log the results of the query
console.log('Query Results:', results); console.log("Query Results:", results);
// Respond with a success message // Respond with a success message
res.status(201).json({ message: 'User created successfully' }); res
}); .status(201)
}); .json({ message: "User created successfully" });
}); });
}); }
);
}); });
}); });
}
);
}
);
} catch (error) { } catch (error) {
console.error('Error creating user:', error); console.error("Error creating user:", error);
// Log unsuccessful user creation due to an error // Log unsuccessful user creation due to an error
logUserCreationActivity(req.session.username, false, 'internal error'); // Adjust this based on how you store the creator's username in your session logUserCreationActivity(req.session.username, false, "internal error"); // Adjust this based on how you store the creator's username in your session
res.status(500).json({ error: 'Internal Server Error' }); res.status(500).json({ error: "Internal Server Error" });
} }
}); });
app.get("/forgot-password", (req, res) => {
res.render("forgot-password"); // Assuming you have an EJS template for this
app.get('/forgot-password', (req, res) => {
res.render('forgot-password'); // Assuming you have an EJS template for this
}); });
app.get('/forgot-password', (req, res) => { app.get("/forgot-password", (req, res) => {
res.render('forgot-password', { error: null, success: null }); res.render("forgot-password", { error: null, success: null });
}); });
// Handle the submission of the forgot password form // Handle the submission of the forgot password form
app.post('/forgot-password', (req, res) => { app.post("/forgot-password", (req, res) => {
const { usernameOrEmail } = req.body; const { usernameOrEmail } = req.body;
// Perform the logic for sending the reset password email // Perform the logic for sending the reset password email
// This is a simplified example; you should implement your own logic here
// Check if the username or email exists in the database // Check if the username or email exists in the database
const checkUserQuery = 'SELECT * FROM users WHERE username = ? OR email = ?'; const checkUserQuery = "SELECT * FROM users WHERE username = ? OR email = ?";
connection.query(checkUserQuery, [usernameOrEmail, usernameOrEmail], (checkError, checkResults) => { connection.query(
checkUserQuery,
[usernameOrEmail, usernameOrEmail],
(checkError, checkResults) => {
if (checkError) { if (checkError) {
console.error('Error checking user:', checkError); console.error("Error checking user:", checkError);
const error = 'An error occurred during the password reset process.'; const error = "An error occurred during the password reset process.";
res.render('forgot-password', { error, success: null }); res.render("forgot-password", { error, success: null });
} else if (checkResults.length === 0) { } else if (checkResults.length === 0) {
const error = 'Username or email not found.'; const error = "Username or email not found.";
res.render('forgot-password', { error, success: null }); res.render("forgot-password", { error, success: null });
} else { } else {
// Assuming the user exists, generate a reset token and send an email // Assuming the user exists, generate a reset token and send an email
const user = checkResults[0]; const user = checkResults[0];
const resetToken = crypto.randomBytes(20).toString('hex'); const resetToken = crypto.randomBytes(20).toString("hex");
const resetTokenExpiry = new Date(Date.now() + 3600000); // Token expires in 1 hour const resetTokenExpiry = new Date(Date.now() + 3600000); // Token expires in 1 hour
// Update user with reset token and expiry // Update user with reset token and expiry
const updateQuery = 'UPDATE users SET reset_token = ?, reset_token_expiry = ? WHERE id = ?'; const updateQuery =
connection.query(updateQuery, [resetToken, resetTokenExpiry, user.id], (updateError) => { "UPDATE users SET reset_token = ?, reset_token_expiry = ? WHERE id = ?";
connection.query(
updateQuery,
[resetToken, resetTokenExpiry, user.id],
(updateError) => {
if (updateError) { if (updateError) {
console.error('Error updating reset token:', updateError); console.error("Error updating reset token:", updateError);
const error = 'An error occurred during the password reset process.'; const error =
res.render('forgot-password', { error, success: null }); "An error occurred during the password reset process.";
res.render("forgot-password", { error, success: null });
} else { } else {
// Send email with reset link // Send email with reset link
const resetLink = `http://localhost:3000/reset-password/${resetToken}`; const resetLink = `http://localhost:3000/reset-password/${resetToken}`;
const mailOptions = { const mailOptions = {
to: user.email, to: user.email,
subject: 'Password Reset', subject: "Password Reset",
text: `Click on the following link to reset your password: ${resetLink}`, text: `Click on the following link to reset your password: ${resetLink}`,
}; };
transporter.sendMail(mailOptions, (emailError, info) => { transporter.sendMail(mailOptions, (emailError, info) => {
if (emailError) { if (emailError) {
console.error('Error sending email:', emailError); console.error("Error sending email:", emailError);
const error = 'An error occurred during the password reset process.'; const error =
res.render('forgot-password', { error, success: null }); "An error occurred during the password reset process.";
res.render("forgot-password", { error, success: null });
} else { } else {
console.log('Email sent: ' + info.response); console.log("Email sent: " + info.response);
const success = 'Password reset email sent successfully. Check your inbox.'; const success =
res.render('forgot-password', { error: null, success }); "Password reset email sent successfully. Check your inbox.";
res.render("forgot-password", { error: null, success });
// Log the successful sending of the reset link in the database // Log the successful sending of the reset link in the database
logPasswordResetActivity(user.username, 'link sent successfully'); logPasswordResetActivity(
user.username,
"link sent successfully"
);
} }
}); });
} }
});
} }
}); );
}
}
);
}); });
// Function to log the password reset activity in the database // Function to log the password reset activity in the database
function logPasswordResetActivity(username, activity) { function logPasswordResetActivity(username, activity) {
const logSql = 'INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)'; const logSql =
"INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)";
mysqlConnection.query(logSql, [username, activity], (error) => { mysqlConnection.query(logSql, [username, activity], (error) => {
if (error) { if (error) {
console.error('Error logging password reset activity:', error); console.error("Error logging password reset activity:", error);
} else { } else {
console.log('Password reset activity logged successfully'); console.log("Password reset activity logged successfully");
} }
}); });
} }
// Handle Reset Password request // Handle Reset Password request
app.post('/reset-password/:token', async (req, res) => { app.post("/reset-password/:token", async (req, res) => {
const { token } = req.params; const { token } = req.params;
const { password, confirmPassword } = req.body; const { password, confirmPassword } = req.body;
// Find user with matching reset token and not expired // Find user with matching reset token and not expired
const selectQuery = 'SELECT * FROM users WHERE reset_token = ? AND reset_token_expiry > NOW()'; const selectQuery =
"SELECT * FROM users WHERE reset_token = ? AND reset_token_expiry > NOW()";
connection.query(selectQuery, [token], async (selectErr, selectResults) => { connection.query(selectQuery, [token], async (selectErr, selectResults) => {
if (selectErr) { if (selectErr) {
console.error('Error querying reset token:', selectErr); console.error("Error querying reset token:", selectErr);
return res.status(500).json({ error: 'Error querying reset token' }); return res.status(500).json({ error: "Error querying reset token" });
} }
if (selectResults.length === 0) { if (selectResults.length === 0) {
// Pass the error to the template when rendering the reset-password page // Pass the error to the template when rendering the reset-password page
return res.render('reset-password', { token, resetError: 'Invalid or expired reset token' }); return res.render("reset-password", {
token,
resetError: "Invalid or expired reset token",
});
} }
// Check if passwords match // Check if passwords match
if (password !== confirmPassword) { if (password !== confirmPassword) {
// Pass the error to the template when rendering the reset-password page // Pass the error to the template when rendering the reset-password page
return res.render('reset-password', { token, resetError: 'Passwords do not match' }); return res.render("reset-password", {
token,
resetError: "Passwords do not match",
});
} }
// Check if the new password meets complexity requirements // Check if the new password meets complexity requirements
if (!isStrongPassword(password)) { if (!isStrongPassword(password)) {
// Pass the error to the template when rendering the reset-password page // Pass the error to the template when rendering the reset-password page
return res.render('reset-password', { token, resetError: 'Password does not meet complexity requirements. It must be at least 10 characters long and include at least one uppercase letter, one lowercase letter, one digit, and one symbol.' }); return res.render("reset-password", {
token,
resetError:
"Password does not meet complexity requirements. It must be at least 10 characters long and include at least one uppercase letter, one lowercase letter, one digit, and one symbol.",
});
} }
// Hash the new password // Hash the new password
const hashedPassword = await bcrypt.hash(password, 10); const hashedPassword = await bcrypt.hash(password, 10);
// Update user's password and clear reset token // Update user's password and clear reset token
const updateQuery = 'UPDATE users SET password = ?, reset_token = NULL, reset_token_expiry = NULL WHERE reset_token = ?'; const updateQuery =
"UPDATE users SET password = ?, reset_token = NULL, reset_token_expiry = NULL WHERE reset_token = ?";
connection.query(updateQuery, [hashedPassword, token], (updateErr) => { connection.query(updateQuery, [hashedPassword, token], (updateErr) => {
if (updateErr) { if (updateErr) {
console.error('Error updating password:', updateErr); console.error("Error updating password:", updateErr);
// Pass the error to the template when rendering the reset-password page // Pass the error to the template when rendering the reset-password page
res.render('reset-password', { token, resetError: 'Error updating password' }); res.render("reset-password", {
token,
resetError: "Error updating password",
});
} else { } else {
// Redirect to the success page upon successful password reset // Redirect to the success page upon successful password reset
res.redirect('/success'); res.redirect("/success");
} }
}); });
}); });
}); });
app.get('/success', (req, res) => { app.get("/success", (req, res) => {
res.render('success'); res.render("success");
}); });
app.get("/reset-password/:token", (req, res) => {
app.get('/reset-password/:token', (req, res) => {
const { token } = req.params; const { token } = req.params;
const error = req.query.error || null; // Get error from query parameter const error = req.query.error || null; // Get error from query parameter
// Assuming you have this line in your server code where you render the reset-password view // Assuming you have this line in your server code where you render the reset-password view
res.render('reset-password', { token, passwordValidationError: null, resetError: null, success: null }); res.render("reset-password", {
token,
passwordValidationError: null,
resetError: null,
success: null,
});
}); });
app.post('/reset-password', async (req, res) => { app.post("/reset-password", async (req, res) => {
const { username, password, confirmPassword } = req.body; const { username, password, confirmPassword } = req.body;
// Check if passwords match // Check if passwords match
if (password !== confirmPassword) { if (password !== confirmPassword) {
return res.status(400).json({ error: 'Passwords do not match' }); return res.status(400).json({ error: "Passwords do not match" });
} }
// Check if the new password meets complexity requirements // Check if the new password meets complexity requirements
if (!isStrongPassword(password)) { if (!isStrongPassword(password)) {
return res.status(400).json({ return res.status(400).json({
error: 'Password does not meet complexity requirements. It must be at least 10 characters long and include at least one uppercase letter, one lowercase letter, one digit, and one symbol.' error:
"Password does not meet complexity requirements. It must be at least 10 characters long and include at least one uppercase letter, one lowercase letter, one digit, and one symbol.",
}); });
} }
@ -519,33 +598,39 @@ app.post('/reset-password', async (req, res) => {
const userExists = await checkIfUserExists(username); const userExists = await checkIfUserExists(username);
if (!userExists) { if (!userExists) {
return res.status(404).json({ error: 'User does not exist' }); return res.status(404).json({ error: "User does not exist" });
} }
// Update user's password based on the username // Update user's password based on the username
const updateQuery = 'UPDATE users SET password = ? WHERE username = ?'; const updateQuery = "UPDATE users SET password = ? WHERE username = ?";
connection.query(updateQuery, [hashedPassword, username], (updateErr, updateResults) => { connection.query(
updateQuery,
[hashedPassword, username],
(updateErr, updateResults) => {
if (updateErr) { if (updateErr) {
console.error('Error updating password:', updateErr); console.error("Error updating password:", updateErr);
return res.status(500).json({ error: 'Error updating password' }); return res.status(500).json({ error: "Error updating password" });
} }
// Check if the update affected any rows // Check if the update affected any rows
if (updateResults.affectedRows > 0) { if (updateResults.affectedRows > 0) {
// Password update successful // Password update successful
return res.status(200).json({ success: 'Password updated successfully' }); return res
.status(200)
.json({ success: "Password updated successfully" });
} else { } else {
return res.status(404).json({ error: 'User not found or password not updated. No rows affected.' }); return res
} .status(404)
.json({
error: "User not found or password not updated. No rows affected.",
}); });
}
}
);
}); });
async function checkIfUserExists(username) { async function checkIfUserExists(username) {
// Example: Check if the user exists in your database
// You should replace this with your actual database query
// This is just a placeholder, and you need to implement it based on your database structure and connection
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const query = 'SELECT * FROM users WHERE username = ?'; const query = "SELECT * FROM users WHERE username = ?";
connection.query(query, [username], (err, results) => { connection.query(query, [username], (err, results) => {
if (err) { if (err) {
reject(err); reject(err);
@ -556,9 +641,7 @@ async function checkIfUserExists(username) {
}); });
} }
app.use(express.static("views"));
app.use(express.static('views'));
app.listen(PORT, () => { app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`); console.log(`Server is running on port ${PORT}`);