Files

239 lines
6.4 KiB
JavaScript

const express = require('express');
const router = express.Router();
const User = require('../models/User');
const crypto = require('crypto');
const bcrypt = require('bcryptjs');
// Login page
router.get('/login', (req, res) => {
if (req.session.isAuthenticated) {
return res.redirect('/admin/dashboard');
}
res.render('auth/login', {
title: 'Login',
layout: false
});
});
// Login handle
router.post('/login', async (req, res) => {
const { username, password } = req.body;
try {
// Check database user
const user = await User.findOne({ username });
if (!user) {
req.flash('error_msg', 'Invalid username or password');
return res.redirect('/auth/login');
}
const isMatch = await user.comparePassword(password);
if (!isMatch) {
req.flash('error_msg', 'Invalid username or password');
return res.redirect('/auth/login');
}
// Login success
req.session.user = {
id: user._id,
username: user.username,
email: user.email,
name: user.name,
role: user.role
};
req.session.isAuthenticated = true;
req.flash('success_msg', 'Login successful');
res.redirect('/admin/dashboard');
} catch (err) {
console.error(err);
req.flash('error_msg', 'An error occurred during login');
res.redirect('/auth/login');
}
});
// Register page
router.get('/register', (req, res) => {
if (req.session.isAuthenticated) {
return res.redirect('/admin/dashboard');
}
res.render('auth/register', {
title: 'Create Account',
layout: false
});
});
// Register handle
router.post('/register', async (req, res) => {
const { username, email, password, confirm_password, name } = req.body;
let errors = [];
if (!username || !email || !password || !confirm_password || !name) {
errors.push({ msg: 'Please enter all fields' });
}
if (password !== confirm_password) {
errors.push({ msg: 'Passwords do not match' });
}
if (password.length < 6) {
errors.push({ msg: 'Password must be at least 6 characters' });
}
if (errors.length > 0) {
res.render('auth/register', {
errors,
username,
email,
name,
title: 'Create Account',
layout: false
});
} else {
try {
// Check if user exists
const existingUser = await User.findOne({ $or: [{ email }, { username }] });
if (existingUser) {
errors.push({ msg: 'Email or Username already exists' });
return res.render('auth/register', {
errors,
username,
email,
name,
title: 'Create Account',
layout: false
});
}
const newUser = new User({
username,
email,
name,
password
});
await newUser.save();
req.flash('success_msg', 'You are now registered and can log in');
res.redirect('/auth/login');
} catch (err) {
console.error(err);
errors.push({ msg: 'An error occurred during registration' });
res.render('auth/register', {
errors,
username,
email,
name,
title: 'Create Account',
layout: false
});
}
}
});
// Change Password Page
router.get('/change-password', (req, res) => {
res.render('auth/change-password', {
title: 'Change Password',
layout: false
});
});
// Change Password Handle
router.post('/change-password', async (req, res) => {
const { email } = req.body;
try {
const user = await User.findOne({ email });
if (!user) {
req.flash('error_msg', 'No account with that email address exists.');
return res.redirect('/auth/change-password');
}
const token = crypto.randomBytes(20).toString('hex');
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
await user.save();
// Direct flow as requested: Enter email -> Submit -> Enter new password
// Redirect directly to the reset password page with the generated token
res.redirect(`/auth/reset-password/${token}`);
} catch (err) {
console.error(err);
req.flash('error_msg', 'Error processing request');
res.redirect('/auth/change-password');
}
});
// Reset Password Page
router.get('/reset-password/:token', async (req, res) => {
try {
const user = await User.findOne({
resetPasswordToken: req.params.token,
resetPasswordExpires: { $gt: Date.now() }
});
if (!user) {
req.flash('error_msg', 'Password reset token is invalid or has expired.');
return res.redirect('/auth/change-password');
}
res.render('auth/reset-password', {
title: 'Reset Password',
layout: false,
token: req.params.token
});
} catch (err) {
console.error(err);
res.redirect('/auth/change-password');
}
});
// Reset Password Handle
router.post('/reset-password/:token', async (req, res) => {
try {
const user = await User.findOne({
resetPasswordToken: req.params.token,
resetPasswordExpires: { $gt: Date.now() }
});
if (!user) {
req.flash('error_msg', 'Password reset token is invalid or has expired.');
return res.redirect('/auth/change-password');
}
if (req.body.password !== req.body.confirm_password) {
req.flash('error_msg', 'Passwords do not match.');
return res.redirect('back');
}
user.password = req.body.password;
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
await user.save();
req.flash('success_msg', 'Success! Your password has been changed.');
res.redirect('/auth/login');
} catch (err) {
console.error(err);
res.redirect('back');
}
});
router.get('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
console.error('Error when logout:', err);
}
res.redirect('/');
});
});
module.exports = router;