javascriptnode.jshandlebars.jspassport.jsexpress-handlebars

Display username in express partial after login


So I've been looking for a solution for a while now and nothing works for my problem.

So I have a homepage ('/'), a profile page ('/profile') and a login/register page. I am using passport with local, twitter and google for accounts. What I want to do is display the users name and profile picture inside the navbar anywhere they go on the site.

This is what the partial looks like:

partials/_nav.hbs

{{#if isAuthenticated}}
             <div class="dropdown">
                <button type="button" class="btn btn-primary dropdown-toggle dropdown-button"
                 data-toggle="dropdown">
                 <img class="user-avatar" src="{{image}}" alt="{{username}}'s' avatar">{{username}}
                </button>
                    <div class="dropdown-menu">
                        <a class="dropdown-item user-dropdown" href="/profile">My Profile</a>
                        <a class="dropdown-item user-dropdown" href="#">User Settings</a>
                        <a class="dropdown-item user-dropdown" href="/logout">Logout</a>
                    </div>
                </div>
                {{else}}
                <a href="/register" class="account-button text-nowrap">Register/Login
                </a>
        {{/if}}

routes/index.js -- And to display the user name and image, on my routes page I have:

// Login
router.get('/', (req, res, user) => {
  res.render('index', {
    username: req.user.username, // <-- line 10 and if I remove this it goes to line 11
    image: req.user.image,
  });
});

// Profile
router.get('/profile', ensureAuth, (req, res) => {
  res.render('profile', {
    username: req.user.username,
    image: req.user.image,
  });
});

So now onto my problem. The homepage and profile route actually work and display the username and image. The problem is when I try to logout, when I try to logout I get this error:

TypeError: Cannot read property 'username' of undefined
    at C:\Users\Desktop\Code\site\routes\index.js:10:20 // look in code above for this line

I have tried to solve this by instead passing the req.user object and then doing user.username for example inside my partial.

I'm kinda new to express but I think the problem may be that when I log out, username doesn't exist anymore and that's why it gives an error. However if that is the case, it should display the login/register button that's in my partial.

Just to note I registered isAuthenticated as a local variable in my server.js and if you need, this is my ensureAuth code:

middleware/auth.js

  module.exports = {
  ensureAuth: function (req, res, next) {
    if (req.isAuthenticated()) {
      return next();
    }
    res.redirect('/login');
  },
};

Solution

  • So I found out the solution. In my answer I was passing req.user.username without checking if it actually existed. So I asked on reddit and someone helped me come to this answer:

    const { user: { username, image } = {} } = req;
    

    What this does is it destructures the user object and either returns username and image, or nothing ({}).

    The get request looks something like this:

    router.get('/', (req, res) => {
      const { user: { username, image } = {} } = req;
      res.render('index', {
        username,
        image,
      });
    });