From 80a00338c6d33dd291029033b190af0bf3ec991c Mon Sep 17 00:00:00 2001 From: BIG2EYEZ Date: Thu, 21 Dec 2023 20:35:54 +0800 Subject: [PATCH] UPDATE ADMIN CAN MANUALLY UPDATE PASSWORD OF USER --- Sean/inusers.js | 156 +++++++++++++++++---- Sean/server.js | 65 ++++++++- Sean/views/inusers.ejs | 250 ++++++++++++++++++++-------------- Sean/views/reset-password.ejs | 40 +++--- Sean/views/success.ejs | 15 ++ 5 files changed, 372 insertions(+), 154 deletions(-) create mode 100644 Sean/views/success.ejs diff --git a/Sean/inusers.js b/Sean/inusers.js index a2f8062..e29bcd2 100644 --- a/Sean/inusers.js +++ b/Sean/inusers.js @@ -1,30 +1,136 @@ -// inusers.js +const allUsers = <%- JSON.stringify(allUsers) %>; -const express = require('express'); -const router = express.Router(); +document.getElementById('downloadButton').addEventListener('click', function () { + console.log('Download button clicked'); + downloadExcel(allUsers); +}); -// Middleware to check if the user is authenticated -function isAuthenticated(req, res, next) { - if (req.session && req.session.authenticated) { - return next(); - } else { - res.redirect('/login'); +document.getElementById('addUserLink').addEventListener('click', function () { + document.getElementById('downloadButtonContainer').style.display = 'none'; + document.getElementById('userDataContainer').style.display = 'none'; + document.getElementById('createUserForm').style.display = 'block'; +}); + +document.getElementById('userDataLink').addEventListener('click', function () { + document.getElementById('downloadButtonContainer').style.display = 'block'; + document.getElementById('userDataContainer').style.display = 'block'; + document.getElementById('createUserForm').style.display = 'none'; +}); + +document.getElementById('userForm').addEventListener('submit', function (event) { + event.preventDefault(); + + // Use FormData directly + const formData = new FormData(document.getElementById('userForm')); + + // Check password complexity + const password = formData.get('password'); + const confirmPassword = formData.get('confirmPassword'); + + if (!isStrongPassword(password)) { + alert('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; + } + + // Check if passwords match + if (password !== confirmPassword) { + alert('Passwords do not match. Please enter the same password in both fields.'); + return; + } + + // Make a fetch request + fetch('/createUser', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: formData.get('name'), + username: formData.get('username'), + email: formData.get('email'), + password: password, // Use the validated password + jobTitle: formData.get('jobTitle'), + }), + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.json(); + }) + .then(data => { + console.log('Success:', data); + + // Show an alert with the received data + alert(`User Registered!`); + + // Optionally, you can clear the form or take other actions after registration + document.getElementById('userForm').reset(); + }) + .catch(error => { + console.error('Fetch Error:', error); + }); + }); + + // Function to validate password complexity + function isStrongPassword(password) { + // Password must be at least 10 characters long + if (password.length < 10) { + return false; + } + + // Password must contain at least one uppercase letter + if (!/[A-Z]/.test(password)) { + return false; + } + + // Password must contain at least one lowercase letter + if (!/[a-z]/.test(password)) { + return false; + } + + // Password must contain at least one digit + if (!/\d/.test(password)) { + return false; + } + + // Password must contain at least one symbol + if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) { + return false; + } + + return true; } -} -// InUsers route (renders the InUsers tab) -router.get('/', isAuthenticated, (req, res) => { - res.render('inusers'); -}); -// User Data route -router.get('/userdata', isAuthenticated, (req, res) => { - res.render('user-data'); -}); - -// Edit User Data route -router.get('/edituserdata', isAuthenticated, (req, res) => { - res.render('edit-user-data'); -}); - -module.exports = router; + function downloadExcel(allUsers) { + if (allUsers && allUsers.length > 0) { + const workbook = new ExcelJS.Workbook(); + const worksheet = workbook.addWorksheet('All Users'); + const headers = ['Name', 'Username', 'Email', 'Password', 'Last Login', 'Job Title']; + worksheet.addRow(headers); + allUsers.forEach(user => { + const rowData = [ + user.name || '', + user.username || '', + user.email || '', + user.password || '', + user.lastLogin ? new Date(user.lastLogin).toLocaleString('en-US', { timeZone: 'Asia/Singapore' }) : '', + user.jobTitle || '' + ]; + worksheet.addRow(rowData); + }); + workbook.xlsx.writeBuffer().then(buffer => { + const currentDate = new Date(); + const formattedDate = currentDate.toISOString().split('T')[0]; + const formattedTime = currentDate.toTimeString().split(' ')[0].replace(/:/g, '-'); + const fileName = `user_data_${formattedDate}_${formattedTime}.xlsx`; + const blob = new Blob([buffer], { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + }); + saveAs(blob, fileName); + }); + } else { + console.error('No data available for download.'); + } + } diff --git a/Sean/server.js b/Sean/server.js index 816fef8..472d6d3 100644 --- a/Sean/server.js +++ b/Sean/server.js @@ -332,7 +332,6 @@ app.post('/forgot-password', (req, res) => { }); }); // Handle Reset Password request -// Handle Reset Password request app.post('/reset-password/:token', async (req, res) => { const { token } = req.params; const { password, confirmPassword } = req.body; @@ -373,13 +372,16 @@ app.post('/reset-password/:token', async (req, res) => { // Pass the error to the template when rendering the reset-password page res.render('reset-password', { token, resetError: 'Error updating password' }); } else { - // Pass the success message to the template when rendering the reset-password page - res.render('reset-password', { token, resetError: null, success: 'Password changed successfully' }); + // Redirect to the success page upon successful password reset + res.redirect('/success'); } }); }); }); +app.get('/success', (req, res) => { + res.render('success'); +}); app.get('/reset-password/:token', (req, res) => { @@ -389,7 +391,64 @@ app.get('/reset-password/:token', (req, res) => { res.render('reset-password', { token, passwordValidationError: null, resetError: null, success: null }); }); +app.post('/reset-password', async (req, res) => { + const { username, password, confirmPassword } = req.body; + // Check if passwords match + if (password !== confirmPassword) { + return res.status(400).json({ error: 'Passwords do not match' }); + } + + // Check if the new password meets complexity requirements + if (!isStrongPassword(password)) { + 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.' + }); + } + + // Hash the new password + const hashedPassword = await bcrypt.hash(password, 10); + + // Check if the user exists in the database before updating the password + const userExists = await checkIfUserExists(username); + + if (!userExists) { + return res.status(404).json({ error: 'User does not exist' }); + } + + // Update user's password based on the username + const updateQuery = 'UPDATE users SET password = ? WHERE username = ?'; + mysqlConnection.query(updateQuery, [hashedPassword, username], (updateErr, updateResults) => { + if (updateErr) { + console.error('Error updating password:', updateErr); + return res.status(500).json({ error: 'Error updating password' }); + } + + // Check if the update affected any rows + if (updateResults.affectedRows > 0) { + // 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. No rows affected.' }); + } + }); +}); +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) => { + const query = 'SELECT * FROM users WHERE username = ?'; + mysqlConnection.query(query, [username], (err, results) => { + if (err) { + reject(err); + } else { + resolve(results.length > 0); + } + }); + }); +} app.use(express.static('views')); app.listen(PORT, () => { diff --git a/Sean/views/inusers.ejs b/Sean/views/inusers.ejs index 48edaea..da9f62a 100644 --- a/Sean/views/inusers.ejs +++ b/Sean/views/inusers.ejs @@ -27,6 +27,7 @@ User Data Add User Delete User + Reset Password Home @@ -106,8 +107,36 @@ + div id="createUserForm" class="user-creation-container" style="display: none;"> + - + + @@ -120,109 +149,32 @@ diff --git a/Sean/views/reset-password.ejs b/Sean/views/reset-password.ejs index f507ebb..1b521f6 100644 --- a/Sean/views/reset-password.ejs +++ b/Sean/views/reset-password.ejs @@ -10,33 +10,25 @@
- <% if (resetError) { %> -
<%= resetError %>
- <% } else if (success) { %> -
<%= success %>
-

Password changed successfully. Click here to log in.

- <% } else { %> - <% if (passwordValidationError) { %> +
+
+ + +
+
+ + +
+ + <% if (resetError) { %> +
<%= resetError %>
+ <% } else if (passwordValidationError) { %>
<%= passwordValidationError %>
<% } %> - -
- - -
-
- - -
- -
- <% } %> + + +
- - - - - diff --git a/Sean/views/success.ejs b/Sean/views/success.ejs new file mode 100644 index 0000000..3741e3e --- /dev/null +++ b/Sean/views/success.ejs @@ -0,0 +1,15 @@ + + + + + + Password Reset Success + + + +
+
Password changed successfully.
+

Thank you for updating your password. You can now log in with your new password.

+
+ +