forked from UKSOURCE/cms.hailearning.edu.vn
feat: implement user authentication with database integration
This commit is contained in:
214
routes/auth.js
214
routes/auth.js
@@ -1,8 +1,8 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
const ADMIN_USERNAME = 'admin';
|
||||
const ADMIN_PASSWORD = 'admin1234';
|
||||
const User = require('../models/User');
|
||||
const crypto = require('crypto');
|
||||
const bcrypt = require('bcryptjs');
|
||||
|
||||
// Login page
|
||||
router.get('/login', (req, res) => {
|
||||
@@ -16,24 +16,216 @@ router.get('/login', (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
// Login handle
|
||||
router.post('/login', async (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
if (username === ADMIN_USERNAME && password === ADMIN_PASSWORD) {
|
||||
|
||||
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 = {
|
||||
username: ADMIN_USERNAME,
|
||||
email: 'admin@ggcamp.org',
|
||||
name: 'Administrator',
|
||||
role: 'admin'
|
||||
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');
|
||||
} else {
|
||||
req.flash('error_msg', 'Invalid username or password');
|
||||
|
||||
} 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
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Forgot Password Page
|
||||
router.get('/forgot-password', (req, res) => {
|
||||
res.render('auth/forgot-password', {
|
||||
title: 'Forgot Password',
|
||||
layout: false
|
||||
});
|
||||
});
|
||||
|
||||
// Forgot Password Handle
|
||||
router.post('/forgot-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/forgot-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/forgot-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/forgot-password');
|
||||
}
|
||||
|
||||
res.render('auth/reset-password', {
|
||||
title: 'Reset Password',
|
||||
layout: false,
|
||||
token: req.params.token
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.redirect('/auth/forgot-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/forgot-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) {
|
||||
@@ -43,4 +235,4 @@ router.get('/logout', (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user