update where no duplicate username and email can be created
This commit is contained in:
parent
a5be62cc46
commit
1db32e3c7a
184
Sean/server.js
184
Sean/server.js
@ -207,57 +207,80 @@ app.post('/createUser', (req, res) => {
|
||||
return res.status(400).json({ error: 'Password does not meet complexity requirements' });
|
||||
}
|
||||
|
||||
// Hash the password before storing it in the database
|
||||
bcrypt.hash(password, 10, (hashError, hashedPassword) => {
|
||||
if (hashError) {
|
||||
console.error('Error hashing password:', hashError);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
return;
|
||||
// Check if the username is already taken
|
||||
const checkUsernameQuery = 'SELECT * FROM users WHERE username = ?';
|
||||
mysqlConnection.query(checkUsernameQuery, [username], (usernameQueryErr, usernameResults) => {
|
||||
if (usernameQueryErr) {
|
||||
console.error('Error checking username:', usernameQueryErr);
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
|
||||
// Start a transaction
|
||||
mysqlConnection.beginTransaction((transactionErr) => {
|
||||
if (transactionErr) {
|
||||
console.error('Error starting transaction:', transactionErr);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
return;
|
||||
if (usernameResults.length > 0) {
|
||||
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
|
||||
const checkEmailQuery = 'SELECT * FROM users WHERE email = ?';
|
||||
mysqlConnection.query(checkEmailQuery, [email], (emailQueryErr, emailResults) => {
|
||||
if (emailQueryErr) {
|
||||
console.error('Error checking email:', emailQueryErr);
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
|
||||
// Define the insert query
|
||||
const insertUserQuery = 'INSERT INTO users (name, username, email, password, lastLogin, jobTitle) VALUES (?, ?, ?, ?, NULL, ?)';
|
||||
if (emailResults.length > 0) {
|
||||
return res.status(400).json({ error: 'Email is already in use', message: 'Email is already in use. Please choose another email.' });
|
||||
}
|
||||
|
||||
// Log the query and its parameters
|
||||
console.log('Insert Query:', insertUserQuery);
|
||||
console.log('Query Parameters:', [name, username, email, hashedPassword, jobTitle]);
|
||||
|
||||
// Execute the query with user data
|
||||
mysqlConnection.query(insertUserQuery, [name, username, email, hashedPassword, jobTitle], (queryErr, results) => {
|
||||
if (queryErr) {
|
||||
console.error('Error executing query:', queryErr);
|
||||
|
||||
// Rollback the transaction in case of an error
|
||||
mysqlConnection.rollback((rollbackErr) => {
|
||||
if (rollbackErr) {
|
||||
console.error('Error rolling back transaction:', rollbackErr);
|
||||
}
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
});
|
||||
return;
|
||||
// Hash the password before storing it in the database
|
||||
bcrypt.hash(password, 10, (hashError, hashedPassword) => {
|
||||
if (hashError) {
|
||||
console.error('Error hashing password:', hashError);
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
mysqlConnection.commit((commitErr) => {
|
||||
if (commitErr) {
|
||||
console.error('Error committing transaction:', commitErr);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
return;
|
||||
// Start a transaction
|
||||
mysqlConnection.beginTransaction((transactionErr) => {
|
||||
if (transactionErr) {
|
||||
console.error('Error starting transaction:', transactionErr);
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
|
||||
// Log the results of the query
|
||||
console.log('Query Results:', results);
|
||||
// Define the insert query
|
||||
const insertUserQuery = 'INSERT INTO users (name, username, email, password, lastLogin, jobTitle) VALUES (?, ?, ?, ?, NULL, ?)';
|
||||
|
||||
// Respond with a success message
|
||||
res.status(201).json({ message: 'User created successfully' });
|
||||
// Log the query and its parameters
|
||||
console.log('Insert Query:', insertUserQuery);
|
||||
console.log('Query Parameters:', [name, username, email, hashedPassword, jobTitle]);
|
||||
|
||||
// Execute the query with user data
|
||||
mysqlConnection.query(insertUserQuery, [name, username, email, hashedPassword, jobTitle], (queryErr, results) => {
|
||||
if (queryErr) {
|
||||
console.error('Error executing query:', queryErr);
|
||||
|
||||
// Rollback the transaction in case of an error
|
||||
mysqlConnection.rollback((rollbackErr) => {
|
||||
if (rollbackErr) {
|
||||
console.error('Error rolling back transaction:', rollbackErr);
|
||||
}
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
mysqlConnection.commit((commitErr) => {
|
||||
if (commitErr) {
|
||||
console.error('Error committing transaction:', commitErr);
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
|
||||
// Log the results of the query
|
||||
console.log('Query Results:', results);
|
||||
|
||||
// Respond with a success message
|
||||
res.status(201).json({ message: 'User created successfully' });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -268,6 +291,82 @@ app.post('/createUser', (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.post('/check-username-email', (req, res) => {
|
||||
try {
|
||||
const { username, email } = req.body;
|
||||
|
||||
// Check if the username is already taken
|
||||
const checkUsernameQuery = 'SELECT * FROM users WHERE username = ?';
|
||||
mysqlConnection.query(checkUsernameQuery, [username], (usernameQueryErr, usernameResults) => {
|
||||
if (usernameQueryErr) {
|
||||
console.error('Error checking username:', usernameQueryErr);
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
|
||||
// Check if the email is already taken
|
||||
const checkEmailQuery = 'SELECT * FROM users WHERE email = ?';
|
||||
mysqlConnection.query(checkEmailQuery, [email], (emailQueryErr, emailResults) => {
|
||||
if (emailQueryErr) {
|
||||
console.error('Error checking email:', emailQueryErr);
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
|
||||
if (usernameResults.length === 0 && emailResults.length === 0) {
|
||||
// Both username and email are available
|
||||
return res.status(200).json({ available: true });
|
||||
} else {
|
||||
// Either username or email is already taken
|
||||
return res.status(400).json({ error: 'Username or email already taken' });
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error checking username and email:', error);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.post('/check-username', (req, res) => {
|
||||
const { username } = req.body;
|
||||
|
||||
const checkUsernameQuery = 'SELECT * FROM users WHERE username = ?';
|
||||
mysqlConnection.query(checkUsernameQuery, [username], (error, results) => {
|
||||
if (error) {
|
||||
console.error('Error checking username:', error);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
} else {
|
||||
const isAvailable = results.length === 0;
|
||||
res.json({ available: isAvailable });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Assuming you have an instance of express named 'app'
|
||||
app.post('/check-email', (req, res) => {
|
||||
const { email } = req.body;
|
||||
|
||||
// Check if the email is already taken in the database
|
||||
const checkEmailQuery = 'SELECT * FROM users WHERE email = ?';
|
||||
mysqlConnection.query(checkEmailQuery, [email], (error, results) => {
|
||||
if (error) {
|
||||
console.error('Error checking email:', error);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
return;
|
||||
}
|
||||
|
||||
// If results.length is greater than 0, it means the email is already taken
|
||||
const isEmailAvailable = results.length === 0;
|
||||
|
||||
// Return a JSON response indicating whether the email is available or not
|
||||
res.json({ available: isEmailAvailable });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.get('/forgot-password', (req, res) => {
|
||||
res.render('forgot-password'); // Assuming you have an EJS template for this
|
||||
});
|
||||
@ -449,6 +548,9 @@ async function checkIfUserExists(username) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
app.use(express.static('views'));
|
||||
|
||||
app.listen(PORT, () => {
|
||||
|
@ -145,7 +145,7 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/exceljs/4.2.1/exceljs.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
const allUsers = <%- JSON.stringify(allUsers) %>;
|
||||
const allUsers = <%- JSON.stringify(allUsers) %>;
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#resetPasswordLink').on('click', function () {
|
||||
@ -169,134 +169,234 @@ $(document).ready(function () {
|
||||
$('#downloadButtonContainer').show();
|
||||
});
|
||||
});
|
||||
|
||||
$('#downloadButton').on('click', function () {
|
||||
// Call the downloadExcel function with the allUsers data
|
||||
downloadExcel(allUsers);
|
||||
});
|
||||
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.');
|
||||
}
|
||||
}
|
||||
// Call the downloadExcel function with the allUsers data
|
||||
downloadExcel(allUsers);
|
||||
});
|
||||
|
||||
function isStrongPassword(password) {
|
||||
// Password must be at least 10 characters long
|
||||
if (password.length < 10) {
|
||||
return false;
|
||||
}
|
||||
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.');
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
function isStrongPassword(password) {
|
||||
// Password must be at least 10 characters long
|
||||
if (password.length < 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$('#resetPasswordForm').on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
// Password must contain at least one uppercase letter
|
||||
if (!/[A-Z]/.test(password)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get values from the form
|
||||
const username = $('#resetUsername').val();
|
||||
const password = $('#resetPassword').val();
|
||||
const confirmPassword = $('#resetConfirmPassword').val();
|
||||
// Password must contain at least one lowercase letter
|
||||
if (!/[a-z]/.test(password)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('Username:', username);
|
||||
console.log('New Password:', password);
|
||||
// Password must contain at least one digit
|
||||
if (!/\d/.test(password)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate passwords
|
||||
if (password !== confirmPassword) {
|
||||
// Password must contain at least one symbol
|
||||
if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function resetFormFields() {
|
||||
$('#name').val('');
|
||||
$('#username').val('');
|
||||
$('#email').val('');
|
||||
$('#password').val('');
|
||||
$('#confirmPassword').val('');
|
||||
$('#jobTitle').val('');
|
||||
}
|
||||
|
||||
|
||||
$('#userForm').on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const name = $('#name').val();
|
||||
const username = $('#username').val();
|
||||
const email = $('#email').val();
|
||||
const password = $('#password').val();
|
||||
const confirmPassword = $('#confirmPassword').val();
|
||||
const jobTitle = $('#jobTitle').val();
|
||||
|
||||
if (password !== confirmPassword) {
|
||||
alert('Passwords do not match. Please enter the same password in both fields.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the new password meets complexity requirements
|
||||
if (!isStrongPassword(password)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Make a fetch request
|
||||
fetch('/reset-password', {
|
||||
fetch('/createUser', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: username,
|
||||
password: password,
|
||||
confirmPassword: confirmPassword,
|
||||
name: name,
|
||||
username: username,
|
||||
email: email,
|
||||
password: password,
|
||||
jobTitle: jobTitle,
|
||||
}),
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
if (response.status === 201) {
|
||||
// Status 201 indicates successful creation
|
||||
return response.json();
|
||||
} else {
|
||||
return response.json().then(data => {
|
||||
throw new Error(data.error || `HTTP error! Status: ${response.status}`);
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
console.log('Success:', data);
|
||||
|
||||
// Show an alert with the received data
|
||||
alert(data.success || data.error || 'Password change status unknown');
|
||||
|
||||
// Optionally, you can clear the form or take other actions after the password change
|
||||
$('#resetUsername').val('');
|
||||
$('#resetPassword').val('');
|
||||
$('#resetConfirmPassword').val('');
|
||||
|
||||
// You might want to hide the reset password form after submission
|
||||
$('#resetPasswordFormContainer').hide();
|
||||
console.log('User registration success:', data);
|
||||
alert('User registered successfully!');
|
||||
resetFormFields();
|
||||
})
|
||||
.catch(error => {
|
||||
// Handle 404 error separately to show an alert
|
||||
if (error.message.includes('HTTP error! Status: 404')) {
|
||||
alert('User not found. Please enter a valid username.');
|
||||
} else {
|
||||
console.error('Fetch Error:', error);
|
||||
}
|
||||
console.error('User registration error:', error);
|
||||
handleRegistrationError(error);
|
||||
});
|
||||
});
|
||||
|
||||
function handleRegistrationError(error) {
|
||||
console.error('Registration error:', error); // Log the full error object for debugging
|
||||
|
||||
let errorMessage;
|
||||
|
||||
if (typeof error === 'string') {
|
||||
errorMessage = error;
|
||||
} else if (error instanceof Error) {
|
||||
errorMessage = error.message;
|
||||
} else if (error.response && error.response.data && error.response.data.error) {
|
||||
errorMessage = error.response.data.error;
|
||||
} else {
|
||||
errorMessage = 'Unknown error';
|
||||
}
|
||||
|
||||
if (errorMessage.includes('Username is already taken')) {
|
||||
alert('Username is already taken. Please choose a different username.');
|
||||
} else if (errorMessage.includes('Email is already in use')) {
|
||||
alert('Email is already in use. Please choose a different email.');
|
||||
} else if (errorMessage.includes('Password does not meet complexity requirements')) {
|
||||
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.');
|
||||
} else if (errorMessage.includes('User registration failed')) {
|
||||
alert('User registration failed. Please try again.');
|
||||
} else {
|
||||
alert(`Unknown error: ${errorMessage}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$('#resetPasswordForm').on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Get values from the form
|
||||
const username = $('#resetUsername').val();
|
||||
const password = $('#resetPassword').val();
|
||||
const confirmPassword = $('#resetConfirmPassword').val();
|
||||
|
||||
console.log('Username:', username);
|
||||
console.log('New Password:', password);
|
||||
|
||||
// Validate passwords
|
||||
if (password !== confirmPassword) {
|
||||
alert('Error: Passwords do not match. Please enter the same password in both fields.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the new password meets complexity requirements
|
||||
if (!isStrongPassword(password)) {
|
||||
alert('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.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a fetch request
|
||||
fetch('/reset-password', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: username,
|
||||
password: password,
|
||||
confirmPassword: confirmPassword,
|
||||
}),
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
return response.text().then(errorText => {
|
||||
throw new Error(`HTTP error! Status: ${response.status}, Error: ${errorText}`);
|
||||
});
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
console.log('Success:', data);
|
||||
|
||||
// Show an alert with the received data
|
||||
alert(data.success || data.error || 'Password change status unknown');
|
||||
|
||||
// Optionally, you can clear the form or take other actions after the password change
|
||||
$('#resetUsername').val('');
|
||||
$('#resetPassword').val('');
|
||||
$('#resetConfirmPassword').val('');
|
||||
|
||||
// You might want to hide the reset password form after submission
|
||||
$('#resetPasswordFormContainer').hide();
|
||||
})
|
||||
.catch(error => {
|
||||
// Handle 404 error separately to show an alert
|
||||
if (error.message.includes('HTTP error! Status: 404')) {
|
||||
alert('Error: User not found. Please enter a valid username.');
|
||||
} else {
|
||||
console.error('Fetch Error:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user