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?
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')
.
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}}
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']});
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é.
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;
}
});