0

I want to find the logged in user, and set their info to app.locals so that I can use it in any view.

I'm setting it up in my server.js file like so:

app.use(ensureAuthenticated, function(req, res, next) {
  User.findOne({ _id: req.session.passport.user }, (err, user) => {
    console.log('user\n', user)
    app.locals.logged_in_user = user;
    next();
  })
});

console.log('user\n', user) confirms that the user has been found. Then, I should be able to use this user's info in any partial, such as in my layout.hbs file like so:

Currently, {{logged_in_user}} is logged in.

But, it's not working. The answer here suggested to use res.locals instead, but that didn't work. The example here uses static data, but I need dynamic data since user will depend on who's logged in.

Right now, I have to define the user variable in every route. Is there a way to globally define a user variable that can be used in any partial?

Farid
  • 1,557
  • 2
  • 21
  • 35
  • 1
    `res.locals` is the correct object to add dynamic information to, `app.locals` is for static (set once) information only. Is your middleware declared before the route(s) that render the templates? Inside those routes, just before calling `res.render()`, what is the value of `res.locals.logged_in_user`? – robertklep Jul 05 '17 at 06:15
  • I just took out `ensureAuthenticated` and it worked. But thanks for the reply! – Farid Jul 05 '17 at 07:20
  • 1
    Still, don't use `app.locals`. Or, if you do, expect that you can only have one active user at all times. – robertklep Jul 05 '17 at 07:21
  • You're right: I used `res.locals` and it worked as expected. But, it's good to know that I can use `app.locals` for static data. – Farid Jul 05 '17 at 07:25

1 Answers1

1

You're using passport judging from the code. The documentation states the following:

If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user.

Therefore you can do the following (or however you want to do it):

app.use((req, res, next) => {
  res.locals.user = req.user
  next()
}

This will pass the user object to all requests and the views.

Cisco
  • 20,972
  • 5
  • 38
  • 60
  • Thanks for the reply. Yes, I'm using passport. I think your answer makes sense if I wasn't looking up the user in my database. However, I'm running `User.findOne` to look the user up in my database. I then want to pass that user object that's returned from the db to a `res.locals` variable. So, `app.use((req, res, next) => { User.findOne({ _id: req.session.passport.user }, (err, user) => { res.locals.logged_in_user = user; next(); }) });` – Farid Jul 05 '17 at 04:47
  • @Farid with a proper Passport setup, `passport.deserializeUser` would have already looked up the user. – robertklep Jul 05 '17 at 06:16
  • Taking out `ensureAuthenticated` worked. Thanks guys. – Farid Jul 05 '17 at 07:20
  • I tried this again, but using `req.locals` instead of `res.locals`, and it doesn't seem to work. My app just hangs. Did you mean to write `res.locals`? Because that works. – Farid Jul 08 '17 at 11:49
  • @Farid you are correct. I've edited the answer. https://expressjs.com/en/4x/api.html#res.locals – Cisco Jul 08 '17 at 14:55