skip to Main Content

I want to implement the function that checks if there is a token, verifies the token and grants access to the protected route but I dont know how to send user data to the next function.

authController.js file –

exports.protect = async (req, res, next) => {
  //1) Getting token and check if it's there
  let token;
  if (
    req.headers.authorization &&
    req.headers.authorization.startsWith("Bearer")
  ) {
    token = req.headers.authorization.split(" ")[1];
  } else if (req.cookies.jwt) {
    token = req.cookies.jwt;
  }

  if (!token) {
    res.status(401).json({
      status: "fail",
      message: "You are not logged in. Please login to get access",
    });
    next();
  }
  //2) Verificating the token

  //const decoded = await promisify(jwt.verify)(token, process.env.JWT_SECRET);
  
  const decoded = jwt.verify(token, process.env.JWT_SECRET);
  
  let currentUser;
  //3)Check if user still exists
  db.getConnection(async (err, connection) => {
    const sqlSearch = "SELECT * FROM users WHERE id = ?";
    const sqlQuery = mysql.format(sqlSearch, [decoded.id]);
    connection.query(sqlQuery, (err, result) => {
      connection.release();
      currentUser = result;
    });
  });
  if (!currentUser) {
    res.status(401).json({
      status: "fail",
      message: "The user belonging to this token does no longer exist",
    });
    next();
  }

  //GRANT ACCESS TO PROTECTED ROUTE
  req.user = currentUser;
  res.locals.user = currentUser;
  next();
};

courseRouter.js file –

const express = require('express');
const coursesController = require('../controllers/coursesController');
const authController = require('../controllers/authController');
const router = express.Router();

router.get('/', coursesController.getAllCourses);
router.post('/:slug', authController.protect, coursesController.buyCourse);

module.exports = router;

After connecting to the database i don’t know how to return user data to the buyCourse() function. The way I did it the "currentUser" is undefined.

2

Answers


  1. I would suggest using AsyncLocalStorage for storing the logged-in user on a context-based storage and granting access to any function down the chain. This would ensure that the logged-in user’s context is maintained across different function calls within the same execution context.

    You can refer to the Node.js documentation for usage: https://nodejs.org/api/async_context.html

    AsyncLocalStorage is a singleton instance, and you can use its run() method on every incoming request to set up the context and store the logged-in user information.

    Login or Signup to reply.
  2. Your use of response.locals.user looks pretty standard. Declare buyCourse to accept request and response objects like this:

    buyCourse(request, response) {
      // Use response.locals.user
    }
    

    But you are not awaiting the database results, so currentUser is still null when you set it. Try writing it like this instead:

    try {
      const connection = await db.getConnection();
      const sqlSearch = "SELECT * FROM users WHERE id = ?";
      const sqlQuery = mysql.format(sqlSearch, [decoded.id]);
      const result = await connection.query(sqlQuery);
      connection.release();
      currentUser = result;
    
      // Validation
    
      res.locals.user = currentUser;
    
    } catch(e) {
      // Handle errors
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search