web-dev-qa-db-fra.com

Redirection des utilisateurs non connectés avec iron-router ... Encore une fois

Je me bats avec le besoin courant de rediriger un utilisateur vers une page de connexion s'il n'est pas connecté (Meteor v0.8.0 sur Windows 7).

Il y a plusieurs questions similaires sur stackoverflow, mais aucune réponse ne semble fonctionner pour moi.

Ne fonctionnera pas # 1: render ()

De la documentation :

onBeforeAction: function () {
  if (!Meteor.user()) {
    // render the login template but keep the url in the browser the same
    this.render('login');

    // stop the rest of the before hooks and the action function 
    this.stop();
  }
},

Deux questions ici:

1- La documentation est obsolète. Il n'y a plus de fonction this.stop(). Comme indiqué ici , le code devrait être:

onBeforeAction: function (pause) {
  if (!Meteor.user()) {
    // render the login template but keep the url in the browser the same
    this.render('login');

    // stop the rest of the before hooks and the action function 
    pause();
  }
},

2- Cela ne fonctionne que si la route n'a pas de layoutTemplate. S'il en possède un, le modèle login est rendu dans le {{>yield}} de la layoutTemplate. Ce n'est généralement pas ce que vous voulez pour une page de connexion.

Ne fonctionnera pas # 2: Router.go () ou this.redirect ()

Définir un itinéraire pour la page de connexion semble naturel. Vous pouvez alors faire:

Router.onBeforeAction(function(pause) {
    if (!Meteor.user()) {
        pause();
        Router.go('\login');
    }
}, {except: ['login']});

Ou:

Router.onBeforeAction(function() {
    if (!Meteor.user())
        this.redirect('\login');
}, {except: ['login']});

Mais étrangement, il existe toujours un problème si la route d'origine (avant la redirection) a une variable layoutTemplate: le modèle /login est rendu à l'intérieur du {{yield}}. Ce qui encore n'est pas ce que vous voulez habituellement (et certainement pas ce que vous attendez, car le modèle /login n'a pas de variable layoutTemplate définie).

J'ai trouvé un moyen de résoudre partiellement ceci:

Router.onBeforeAction(function() {
    if (!Meteor.user()) {
        var that = this;
        setTimeout(function() { that.redirect('\login'); }, 0);
    }
}, {except: ['login']});

Maintenant tout va bien: le modèle /login s'affiche sous forme de page vierge ... Sauf que la variable layoutTemplate de l'itinéraire d'origine clignote brièvement avant l'affichage du modèle /login.

Avez-vous le même problème?

20
steph643

Ok, il semble donc que la fonction de rendu sur une route ne rende un modèle que dans la présentation actuelle. Pour rendre un modèle dans une présentation différente, vous devez appeler this.setLayout('templateName'). Le seul inconvénient semble être que vous devrez redéfinir la disposition après la connexion.

onBeforeAction: function(pause) {
    var routeName = this.route.name;

    if (_.include(['login'], routeName))
        return;

    if (! Meteor.userId()) {
        this.setLayout("newLayout");
        this.render('login');

        //if you have named yields it the login form
        this.render('loginForm', {to:"formRegion"});

        //and finally call the pause() to prevent further actions from running
        pause();
    }else{
        this.setLayout(this.lookupLayoutTemplate());
    }
}

Vous pouvez également simplement rendre le modèle de connexion sous la forme si votre modèle de connexion est tout ce dont vous avez besoin en appelant this.setLayout('login').

9
Kelly Copley

Vous pouvez insérer un assistant de modèle if ou un dans le modèle de présentation.

{{#unless currentUser}}
  {{> loginPage}}
 {{else}}
  {{> yield}}
{{/unless}}
20
LakeEffect

Il semble que cela ait quelque chose à voir avec l'attente des abonnements dans waitOn.

Ce qui suit résout les problèmes de rendu de mise en page pour moi:

Router.onBeforeAction(function() {
    if (!Meteor.user() && this.ready())
        return this.redirect('/login');
}, {except: ['login']}); 
3
Eelco

Il vous suffit de renvoyer le résultat de render() depuis votre onBeforeAction()

onBeforeAction: function () {

  if (_.include(['login'], this.route.name)){
    return;
  }

  if (!Meteor.userId()) {

    return this.render('login');

  }
}

Notez également que j'ai changé Meteor.user() en Meteor.userId(). Cela empêche le raccordement d'être réexécuté chaque fois que le document des utilisateurs actuels est modifié.

0
Kelly Copley

Sur Meteor 0.8.3 pour moi fonctionne:

Router.onBeforeAction(function () { 
  if (_.include(['formLogin'], this.route.name)){
    return;
  }

  if (!Meteor.userId()) {
    this.redirect('formLogin');
    return;
  }

});
0
pwldp