Auth Controller Register/Login/Logout with JWT


const db = require('../models');
const User = db.User;
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { body, validationResult } = require('express-validator');

// Register a new user
exports.register = [
  // Validation middleware
  body('name').notEmpty().withMessage('Name is required'),
  body('email').isEmail().withMessage('Invalid email format'),
  body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters long'),
  body('role').notEmpty().withMessage('Role is required'),
  
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    const { name, email, password, role, resellerId } = req.body;

    const transaction = await db.sequelize.transaction();
    try {
      // const hashedPassword = await bcrypt.hash(password, 10);
      const salt = await bcrypt.genSalt(10);
      const hashedPassword = await bcrypt.hash(password, salt);

      const newUser = await User.create({
        name,
        email,
        password: hashedPassword,
        role,
        resellerId
      }, { transaction });

      await transaction.commit();
      res.status(201).json({ user: newUser });
    } catch (error) {
      await transaction.rollback();
      console.error(error);
      res.status(500).json({ error: 'Something went wrong' });
    }
  }
];

// Login a user
exports.login = [
  body('email').isEmail().withMessage('Invalid email format'),
  body('password').notEmpty().withMessage('Password is required'),

  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      console.log('Validation errors:', errors.array());
      return res.status(400).json({
        status: 'error',
        message: 'Validation errors',
        errors: errors.array()
      });
    }

    const { email, password } = req.body;

    try {
      console.log('Looking for user with email:', email);
      const user = await User.findOne({ where: { email } });

      if (!user) {
        console.log('User not found');
        return res.status(404).json({
          status: 'error',
          message: 'User not found'
        });
      }

      const isMatch = await bcrypt.compare(password, user.password);

      if (!isMatch) {
        console.log('Invalid credentials');
        return res.status(400).json({
          status: 'error',
          message: 'Invalid credentials'
        });
      }

      const expiresIn = 3600; // 1 hour in seconds
      const token = jwt.sign({ id: user.id, role: user.role }, process.env.JWT_SECRET, { expiresIn });

      // res.cookie('token', token, {
      //   httpOnly: true,
      //   secure: false,
      //   sameSite: 'Lax',
      //   maxAge: expiresIn * 1000
      // });

      console.log('Login successful, token generated.');
      res.status(200).json({
        status: 'success',
        message: 'Login successful',
        data: {
          token: token,
          user: {
            id: user.id,
            email: user.email,
            name: user.name,
            role: user.role
          },
          expires_in: expiresIn
        }
      });
    } catch (error) {
      console.error('Login error:', error);
      res.status(500).json({
        status: 'error',
        message: 'Internal server error',
        error: error.message
      });
    }
  }
];

// Logout a user
exports.logout = async (req, res) => {
  // Menghapus cookie dengan token JWT
  res.clearCookie('token');
  res.json({ message: 'Logout successful' });
};

exports.verifyToken = (req, res) => {
  const token = req.cookies.token;
  if (!token) {
    return res.status(401).json({
      status: 'error',
      message: 'Unauthorized'
    });
  }

  jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
    if (err) {
      return res.status(401).json({
        status: 'error',
        message: 'Unauthorized'
      });
    }
    res.json({
      status: 'success',
      message: 'Token is valid', 
      user: decoded 
    });
  });
};