Подтвердить что ты не робот

Перенаправление не зарегистрированных пользователей с железным маршрутизатором... Снова

Я борюсь с общей необходимостью перенаправлять пользователя на страницу входа в систему, если он не вошел в систему (Meteor v0.8.0 в Windows 7).

Есть несколько похожих вопросов о stackoverflow, но ответ не работает для меня.

Не будет работать # 1: render()

Из документация:

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();
  }
},

Два вопроса здесь:

1- Документация устарела. Функция this.stop() больше отсутствует. Как указано здесь, код должен быть:

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- Это работает, только если маршрут не имеет значения layoutTemplate. Если он имеет один, шаблон login отображается в {{>yield}} layoutTemplate. Обычно это не то, что вы хотите для страницы входа.

Не будет работать # 2: Router.go() или this.redirect()

Определение маршрута для страницы входа звучит как естественный путь. Затем вы можете:

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

Или:

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

Но, как ни странно, по-прежнему существует проблема, если исходный маршрут (перед перенаправлением) имеет layoutTemplate: шаблон /login отображается внутри {{yield}}. Что опять же не то, что вы обычно хотите (и определенно не то, что вы ожидаете, так как шаблон /login не имеет layoutTemplate).

Я нашел способ частично решить эту проблему:

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

Теперь все в порядке: шаблон /login отображается как чистая страница... За исключением того, что layoutTemplate исходного маршрута кратковременно мигает до отображения шаблона /login.

У вас есть эта же проблема?

4b9b3361

Ответ 1

Итак, кажется, что функция рендеринга на маршруте только отображает шаблон в текущий макет. Чтобы отобразить шаблон в другом макете, вы должны вызвать this.setLayout('templateName'). Кажется, что одно предупреждение - вам нужно будет установить макет после входа в систему.

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());
    }
}

Вы также можете просто визуализировать шаблон входа в качестве макета, если вам нужен шаблон входа в систему, вызывая this.setLayout('login')

Ответ 2

Вы можете поместить в шаблон макета if или if template.

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

Ответ 3

Похоже, что это связано с ожиданием подписок в waitOn.

Ниже перечислены проблемы с отображением макета для меня:

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

Ответ 4

Вам просто нужно вернуть результат render() из onBeforeAction()

onBeforeAction: function () {

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

  if (!Meteor.userId()) {

    return this.render('login');

  }
}

Также обратите внимание, что я изменил Meteor.user() на Meteor.userId(). Это препятствует повторному запуску крючка каждый раз, когда текущий документ пользователя работает.

Ответ 5

В Meteor 0.8.3 для меня работает:

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

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

});