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;