update with user deleteion and logging

This commit is contained in:
BIG2EYEZ 2023-12-29 16:45:16 +08:00
parent 3913d0d2f7
commit d73147d1a8
2 changed files with 262 additions and 71 deletions

View File

@ -140,7 +140,6 @@ 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 = const loginsQuery =
"SELECT username, lastLogin FROM users ORDER BY lastLogin DESC LIMIT 10"; "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);
@ -531,17 +530,26 @@ app.post("/reset-password/:token", async (req, res) => {
// Update user's password and clear reset token // Update user's password and clear reset token
const updateQuery = const updateQuery =
"UPDATE users SET password = ?, reset_token = NULL, reset_token_expiry = NULL WHERE reset_token = ?"; "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], async (updateErr, updateResults) => {
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", { res.render("reset-password", {
token, token,
resetError: "Error updating password", resetError: "Error updating password",
}); });
} else { } else {
// Redirect to the success page upon successful password reset // Log password reset activity
res.redirect("/success"); const username = selectResults[0].username; // Assuming 'username' is the column name
const logQuery = "INSERT INTO user_logs (username, activity, timestamp) VALUES (?, 'Password Reseted successfully', NOW())";
connection.query(logQuery, [username], (logErr) => {
if (logErr) {
console.error("Error logging password reset:", logErr);
// You might want to handle the logging error here
}
});
// Redirect to the success page upon successful password reset
res.redirect("/success");
} }
}); });
}); });
@ -563,70 +571,159 @@ app.get("/reset-password/:token", (req, res) => {
}); });
}); });
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;
const creatorUsername = req.session.username;
// 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: 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.", "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);
// Check if the user exists in the database before updating the password // Check if the user exists in the database before updating the password
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( connection.query(updateQuery, [hashedPassword, username], async (updateErr, updateResults) => {
updateQuery, if (updateErr) {
[hashedPassword, username], console.error("Error updating password:", updateErr);
(updateErr, updateResults) => { return res.status(500).json({ error: "Error updating password" });
if (updateErr) { }
console.error("Error updating password:", updateErr);
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 // Log password reset activity
return res const logQuery = "INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, NOW())";
.status(200) const logActivity = `Password has been reset for ${username}`;
.json({ success: "Password updated successfully" }); connection.query(logQuery, [creatorUsername, logActivity], (logErr) => {
} else { if (logErr) {
return res console.error("Error logging password reset:", logErr);
.status(404) // You might want to handle the logging error here
.json({ }
error: "User not found or password not updated.",
}); // Password update successful
} return res.status(200).json({ success: "Password updated successfully" });
} });
); } else {
return res.status(404).json({
error: "User not found or password not updated.",
});
}
});
}); });
async function checkIfUserExists(username) { async function checkIfUserExists(username) {
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);
} else { } else {
resolve(results.length > 0); resolve(results.length > 0);
} }
}); });
}); });
} }
app.get('/searchUser', (req, res) => {
const { username } = req.query;
const query = 'SELECT * FROM users WHERE username = ?';
connection.query(query, [username], (err, results) => {
if (err) {
console.error('MySQL query error:', err);
res.status(500).json({ success: false, error: 'Internal Server Error' });
} else if (results.length === 0) {
// No user found with the given username
res.status(404).json({ success: false, error: 'User not found' });
} else {
res.json(results);
}
});
});
app.get('/api/users', (req, res) => {
const query = 'SELECT * FROM users';
connection.query(query, (err, results) => {
if (err) {
console.error('MySQL query error:', err);
res.status(500).json({ success: false, error: 'Internal Server Error' });
} else {
res.json(results);
}
});
});
// Route to search for a user by username
app.get('/api/searchUser', (req, res) => {
const { username } = req.query;
const query = 'SELECT * FROM users WHERE username = ?';
connection.query(query, [username], (err, results) => {
if (err) {
console.error('MySQL query error:', err);
res.status(500).json({ success: false, error: 'Internal Server Error' });
} else {
res.json(results);
}
});
});
// Route to delete a user by username
app.delete('/api/deleteUser/:username', async (req, res) => {
const { username } = req.params;
const query = 'DELETE FROM users WHERE username = ?';
const creatorUsername = req.session.username;
try {
// Log deletion activity to USER_LOGS
const deletionActivity = `User ${username} has been successfully deleted`;
const logQuery = 'INSERT INTO USER_LOGS (USERNAME, ACTIVITY, TIMESTAMP) VALUES (?, ?, CURRENT_TIMESTAMP)';
await executeQuery(logQuery, [creatorUsername, deletionActivity]);
// Perform user deletion
const results = await executeQuery(query, [username]);
if (results.affectedRows === 0) {
res.status(404).json({ success: false, error: 'User not found' });
} else {
res.json({ success: true, message: 'User deleted successfully' });
}
} catch (error) {
console.error('MySQL query error:', error);
res.status(500).json({ success: false, error: 'Internal Server Error', details: error.message });
}
});
async function executeQuery(sql, values) {
return new Promise((resolve, reject) => {
connection.query(sql, values, (err, results) => {
if (err) {
reject(err);
} else {
resolve(results);
}
});
});
}
app.use(express.static("views")); app.use(express.static("views"));

View File

@ -44,7 +44,6 @@
<th>Name</th> <th>Name</th>
<th>Username</th> <th>Username</th>
<th>Email</th> <th>Email</th>
<th>Password</th>
<th>Last Login</th> <th>Last Login</th>
<th>Job Title</th> <th>Job Title</th>
</tr> </tr>
@ -56,7 +55,6 @@
<td><%= user.name %></td> <td><%= user.name %></td>
<td><%= user.username %></td> <td><%= user.username %></td>
<td><%= user.email %></td> <td><%= user.email %></td>
<td><%= user.password %></td>
<td><%= new Date(user.lastLogin).toLocaleString('en-US', { timeZone: 'Asia/Singapore' }) %></td> <td><%= new Date(user.lastLogin).toLocaleString('en-US', { timeZone: 'Asia/Singapore' }) %></td>
<td><%= user.jobTitle %></td> <td><%= user.jobTitle %></td>
</tr> </tr>
@ -134,7 +132,17 @@
</div> </div>
</div> </div>
</div> </div>
<div id="deleteUserContainer" style="display: none;">
<h3>Delete User</h3>
<div class="search-container">
<input type="text" id="searchUserInput" placeholder="Search by username">
<button id="searchUserButton">Search</button>
</div>
<div id="searchResultsContainer" style="display: none;">
<h4>Search Results</h4>
<ul id="searchResultsList"></ul>
</div>
</div>
<!-- Your existing script tags --> <!-- Your existing script tags -->
@ -153,6 +161,7 @@ $(document).ready(function () {
$('#createUserForm').hide(); $('#createUserForm').hide();
$('#userDataContainer').hide(); $('#userDataContainer').hide();
$('#downloadButtonContainer').hide(); $('#downloadButtonContainer').hide();
$('#deleteUserContainer').hide();
}); });
$('#addUserLink').on('click', function () { $('#addUserLink').on('click', function () {
@ -160,6 +169,7 @@ $(document).ready(function () {
$('#createUserForm').show(); $('#createUserForm').show();
$('#userDataContainer').hide(); $('#userDataContainer').hide();
$('#downloadButtonContainer').hide(); $('#downloadButtonContainer').hide();
$('#deleteUserContainer').hide();
}); });
$('#userDataLink').on('click', function () { $('#userDataLink').on('click', function () {
@ -167,26 +177,110 @@ $(document).ready(function () {
$('#createUserForm').hide(); $('#createUserForm').hide();
$('#userDataContainer').show(); $('#userDataContainer').show();
$('#downloadButtonContainer').show(); $('#downloadButtonContainer').show();
$('#deleteUserContainer').hide();
}); });
$('#searchUserButton').on('click', function () {
console.log('Search button clicked');
const searchUsername = $('#searchUserInput').val();
// Call the function to search for the user
searchUser(searchUsername);
});
$('#deleteUserLink').on('click', function () {
$('#deleteUserContainer').show();
$('#resetPasswordFormContainer').hide();
$('#createUserForm').hide();
$('#userDataContainer').hide();
$('#downloadButtonContainer').hide();
}); });
$('#downloadButton').on('click', function () { $('#downloadButton').on('click', function () {
// Call the downloadExcel function with the allUsers data // Call the downloadExcel function with the allUsers data
downloadExcel(allUsers); downloadExcel(allUsers);
}); });
});
function searchUser(username) {
fetch(`/api/searchUser?username=${username}`) // Add the /api prefix here
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error(`HTTP error! Status: ${response.status}`);
}
})
.then(users => {
// Display search results
displaySearchResults(users);
})
.catch(error => {
console.error('Search error:', error);
// Handle errors, e.g., display an alert
});
}
// Function to display search results
function displaySearchResults(users) {
const searchResultsList = $('#searchResultsList');
// Clear previous results
searchResultsList.empty();
if (users && users.length > 0) {
users.forEach(user => {
const listItem = `<li>${user.username} - <button class="deleteUserButton" data-username="${user.username}">Delete</button></li>`;
searchResultsList.append(listItem);
});
// Show the search results container
$('#searchResultsContainer').show();
} else {
// Hide the search results container if no results
$('#searchResultsContainer').hide();
}
}
// Event listener for delete user button in search results
$('#searchResultsList').on('click', '.deleteUserButton', function () {
const usernameToDelete = $(this).data('username');
console.log('Before fetch for user deletion');
// Make a fetch request to delete the user
fetch(`/api/deleteUser/${usernameToDelete}`, {
method: 'DELETE',
})
.then(response => {
console.log('Inside fetch response handler');
if (response.ok) {
// Assuming your server sends a JSON response
return response.json();
} else {
throw new Error(`HTTP error! Status: ${response.status}`);
}
})
.then(data => {
console.log('User deletion success:', data);
alert('User deleted successfully');
$('#searchResultsContainer').hide();
})
.catch(error => {
console.error('User deletion error:', error);
alert('Failed to delete user. Please try again.');
// Handle errors, e.g., display an alert
});
});
function downloadExcel(allUsers) { function downloadExcel(allUsers) {
if (allUsers && allUsers.length > 0) { if (allUsers && allUsers.length > 0) {
const workbook = new ExcelJS.Workbook(); const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('All Users'); const worksheet = workbook.addWorksheet('All Users');
const headers = ['Name', 'Username', 'Email', 'Password', 'Last Login', 'Job Title']; const headers = ['Name', 'Username', 'Email', 'Last Login', 'Job Title'];
worksheet.addRow(headers); worksheet.addRow(headers);
allUsers.forEach(user => { allUsers.forEach(user => {
const rowData = [ const rowData = [
user.name || '', user.name || '',
user.username || '', user.username || '',
user.email || '', user.email || '',
user.password || '',
user.lastLogin ? new Date(user.lastLogin).toLocaleString('en-US', { timeZone: 'Asia/Singapore' }) : '', user.lastLogin ? new Date(user.lastLogin).toLocaleString('en-US', { timeZone: 'Asia/Singapore' }) : '',
user.jobTitle || '' user.jobTitle || ''
]; ];