HEX
Server: Apache/2.4.65 (Debian)
System: Linux kubikelcreative 5.10.0-35-amd64 #1 SMP Debian 5.10.237-1 (2025-05-19) x86_64
User: www-data (33)
PHP: 8.4.13
Disabled: NONE
Upload Files
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;