File: /var/www/indoadvisory_new/web/webapp/routes/auth.js
const express = require('express');
const { body } = require('express-validator');
const {
validateLogin,
redirectIfAuth,
logAuditEvent,
generateJWT
} = require('../middleware/auth');
const {
validateEmail,
validatePassword,
checkValidationResult,
loginRateLimit
} = require('../middleware/security');
const router = express.Router();
// Login page
router.get('/login', redirectIfAuth, (req, res) => {
res.render('auth/login', {
title: res.locals.__('login_title'),
messages: req.flash()
});
});
// Login form submission
router.post('/login',
loginRateLimit,
[
validateEmail,
body('password').notEmpty().withMessage('Password is required')
],
checkValidationResult,
async (req, res) => {
try {
const { email, password } = req.body;
// Validate credentials
const result = await validateLogin(email, password, req);
if (!result.success) {
req.flash('error', result.message);
return res.redirect('/auth/login');
}
// Set session
req.session.user = result.user;
// Log successful login
await logAuditEvent(result.user.id, 'login_success', 'user', result.user.id, req);
req.flash('success', res.locals.__('login_success'));
// Redirect to intended page or admin dashboard
const redirectTo = req.session.returnTo || '/admin';
delete req.session.returnTo;
res.redirect(redirectTo);
} catch (error) {
console.error('Login error:', error);
req.flash('error', 'An error occurred during login. Please try again.');
res.redirect('/auth/login');
}
}
);
// Logout
router.post('/logout', async (req, res) => {
try {
const userId = req.session.user?.id;
if (userId) {
await logAuditEvent(userId, 'logout', 'user', userId, req);
}
req.session.destroy((err) => {
if (err) {
console.error('Session destruction error:', err);
}
res.clearCookie('sessionId');
res.redirect('/');
});
} catch (error) {
console.error('Logout error:', error);
res.redirect('/');
}
});
// API Login for mobile/API access
router.post('/api/login',
loginRateLimit,
[
validateEmail,
body('password').notEmpty().withMessage('Password is required')
],
async (req, res) => {
try {
const { email, password } = req.body;
// Check validation errors
const { validationResult } = require('express-validator');
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
success: false,
message: 'Validation failed',
errors: errors.array()
});
}
// Validate credentials
const result = await validateLogin(email, password, req);
if (!result.success) {
return res.status(401).json({
success: false,
message: result.message
});
}
// Generate JWT token
const token = generateJWT(result.user);
// Log successful API login
await logAuditEvent(result.user.id, 'api_login_success', 'user', result.user.id, req);
res.json({
success: true,
message: 'Login successful',
token: token,
user: {
id: result.user.id,
email: result.user.email,
name: result.user.name,
role: result.user.role
}
});
} catch (error) {
console.error('API login error:', error);
res.status(500).json({
success: false,
message: 'An error occurred during login'
});
}
}
);
// Change password (authenticated users)
router.get('/change-password', async (req, res) => {
if (!req.session.user) {
req.session.returnTo = req.originalUrl;
return res.redirect('/auth/login');
}
res.render('auth/change-password', {
title: 'Change Password'
});
});
router.post('/change-password',
[
body('current_password').notEmpty().withMessage('Current password is required'),
validatePassword.withMessage('New password must meet security requirements'),
body('confirm_password').custom((value, { req }) => {
if (value !== req.body.password) {
throw new Error('Password confirmation does not match');
}
return true;
})
],
checkValidationResult,
async (req, res) => {
try {
if (!req.session.user) {
return res.redirect('/auth/login');
}
const { current_password, password } = req.body;
const userId = req.session.user.id;
// Verify current password
const { db } = require('../config/database');
const bcrypt = require('bcryptjs');
const userResult = await db.query(
'SELECT password_hash FROM users WHERE id = $1',
[userId]
);
if (userResult.rows.length === 0) {
req.flash('error', 'User not found');
return res.redirect('/auth/change-password');
}
const isValidPassword = await bcrypt.compare(current_password, userResult.rows[0].password_hash);
if (!isValidPassword) {
req.flash('error', 'Current password is incorrect');
return res.redirect('/auth/change-password');
}
// Hash new password
const { hashPassword } = require('../middleware/auth');
const hashedPassword = await hashPassword(password);
// Update password
await db.query(
'UPDATE users SET password_hash = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2',
[hashedPassword, userId]
);
// Log password change
await logAuditEvent(userId, 'password_changed', 'user', userId, req);
req.flash('success', 'Password changed successfully');
res.redirect('/admin');
} catch (error) {
console.error('Change password error:', error);
req.flash('error', 'An error occurred while changing password');
res.redirect('/auth/change-password');
}
}
);
module.exports = router;