Iron:router landing page AFTER login


#1

Hi Folks,

I’m sure there is a simple answer, but I am struggling a bit. Using iron:router, and accounts. The goal is to always have a user routed to the same route, once he/she logs in. I have the “welcome” page down for when a user is unauthenticated, but once a user is first logged-in I want to invalidate any previous routes that might be pending (IE. this.next()).

My Code:

26 var requireLogin = function() {
27 if (! Meteor.user()) {
28 if (Meteor.loggingIn()) {
29 this.render(this.loadingTemplate);
30 } else {
31 this.render(‘welcomeButLogin’);
32 }
33 } else {
34 this.next();
35 }
36 }

48 Router.onBeforeAction(requireLogin, {except: [‘blah’]});

I have tried to do a check on “first-login” status and added a call to a route in the “this.next()” else block, but in some cases get a meteor error that says the expected route was not rendered.

Your guidance would be much appreciated.

Thanks!

Gene.


#2

Instead of rendering the ‘welcomeButLogin’ template, make a new route for that and then redirect the user to that route.

  } else {
    this.redirect('nameOfRoute');
  }

#3

Thank you bmanturner.

I have 2 scenarios,

1st for unauthenticated users, they are directed to the “welcomeButLogin” landing page, which works well.

Secondly, I have users that might have used the application, is currently on a page, IE. ‘postList’, and then sign out. If they subsequently log back in, the this.next() behavior will reload the ‘postList’ page in this example. What I would like to accomplish is, that regardless what page the previously logged-in user signed out of the application, they always be directed to a single pre-specified route (IE. ‘dashboard’) as a landing page once they log back in.

I hope this clarifies.

Thanks again.
Gene.


#4

Oh. Yeah, that seems a bit trickier…

One solution may be to use mizzao:user-status to perform a function on users that are logging in while connecting.

UserStatus.events.on("connectionLogin", function(fields) { ... })

#5

Folks, I am making progress, but I am certain that there is a better, more elegant way to accomplish this functionality. As before, I want users to “always” be directed to a welcome page once they log into the application, even if they were previously signed-out at a different page. What trips me up is the “this.next()” requirement for iron Router’s onBeforeAction.

Briefly a scenario:

  1. User navigates to the application and is prompted with a “Welcome but please sign-in/up” page.

  2. User signs in, and the router directs the user to a “welcome to the application” page

  3. User navigates through the application to “pageOne” and then decides to sign out, and is again presented with the “Welcome but please sign-in/up” page being rendered. (However, the URL still reads http://xxx.xxx.xxx.xxx/pageOne)

  4. User signs-in again, where now the application should instead of rendering the “pageOne” page, which is the behavior of this.next(), be presented with the “welcome to the application” page.

I was able to get to this functionality with the code below:

Router.configure({
layoutTemplate: ‘layout’,
});

Router.route(’/’, {name: ‘welcome’});
Router.route(’/pageOne’, {name: ‘pageOne’});
Router.route(’/pageTwo’, {name: ‘pageTwo’});

var requireLogin = function() {
if (! Meteor.user()) {
if (Meteor.loggingIn()) {
Router.go(‘welcome’);
} else {
this.render(‘welcomeButLogin’);
}
} else {
this.next();
}
}

Router.onBeforeAction(requireLogin, {except: [‘blah’]});

This works, but I am getting a warning message of:

Route dispatch never rendered. Did you forget to call this.next() in an onBeforeAction?

Thank you for taking the time, any feedback would be much appreciated.

Gene.


#6

I think your first approach was good, you just need to check for first login in the else block with a session variable and redirect instead of render:

var requireLogin = function() {
  if (! Meteor.user()) {
    if (Meteor.loggingIn()) {
      this.render('Loading');
    } else {
      this.render('WelcomeButLogin');
      Session.set('firstLogin', true);
    }
  } else {
    if(Session.equals('firstLogin', true)) {
      this.redirect('/');
      Session.set('firstLogin', false);
    } else {
      this.next();
    }
  }
}

See it working here: http://meteorpad.com/pad/qHPaShpM4mJwu9xCg/routetest

Edit: I wasn’t able to set ‘firstLogin’ on the Accounts.onLogin callback (Session object doesn’t exist yet) so I just put it in the else block for users not logged in.


#7

Thank you for suggested changes solarc. I have made these changes, and the functionality works as expected, but however I am still getting the:

Route dispatch never rendered. Did you forget to call this.next() in an onBeforeAction?

warning message. It seems that the “onBeforeAction” will always require the “this.next()” method be called (also in the iron:router guide). I think I might be looking for some method that can be called in order to “abandon” the current route (on which the onBeforeAction is called), and move to the newly specified one, in our case “/”.

Thanks again!


#8

Problem solved! Thanks again solarc.

I changed:

Router.onBeforeAction(requireLogin, {except: [‘blah’]});

to:

Router.onBeforeAction(requireLogin);

per your suggested code. I don’t quite understand how this changes the routing specific behavior, since I interpreted that “{except” [‘blah’]}" would mean all routes since I did not have a “blah” route. I’ll investigate further, but for now it works as expected, and I am not getting the warning message.

Thanks!


#9

If you have direct control on the login/logout calls and you don’t mind having to dedicated routes for it, you can also do something like this:

Meteor.loginWithPassword(user, password, function(err){
  if (!err) {
    Router.go('dashboard');
  }
});
Meteor.logout(function(err){
  if (!err) {
    Router.go('WelcomeButLogin');
  }
});