How to make FlowRouter wait for users collection o

2019-07-09 23:26发布

问题:

I'm writing a section of my app which requires the user to have the 'operator' role. I'm checking for this in FlowRouter's triggersEnter function. I want that the user which doesn't have the operator role to be shown a restricted access page.

I use FlowRouter, Roles and brettle:accounts-deluxe which auto logs in as guest every visitor.

Here is my code, routes.js:

FlowRouter.route('/switchboard', {
  name: 'switchboard',
  triggersEnter: [function (context, redirect, stop) {
    if (!Roles.userIsInRole(Meteor.userId(), ['operator'])) {
      BlazeLayout.render('main', {
        content: 'restrictedAccess'
      });           
      stop();
    }
  }],
  action: function () {
    BlazeLayout.render('main', {
        content: 'switchboard'
    });
  }
});

Everything works as expected on localhost, but when the app is deployed using mup, on a server, at the time triggersEnter is ran, Meteor.user() is undefined (Meteor.userId() returns ok), and the result of Roles.userIsInRole call is false, although looking in the database it's clear the user has the operator role.

I think the users subscription is not available at the time triggersEnter is ran meaning that the users collection is not published on the client. I have this feeling because if i access the route by clicking on a link the userIsInRole result is ok, but if I refresh the page I get the problem described. I would like to know why is this happening only on the server and how can I fix it.

回答1:

The reason is that FlowRouter triggersEnter is not blocking templates from rendering and it makes checking roles before Roles collections are subscribed. Solution is to use FlowRouter.wait() on app init and then make the global subscription for Roles (you need it global - not tied to template level) collection and call FlowRouter.initialize() when its ready.

That way FlowRouter will wait for your collection and will be initialized after it's ready to check.

Update

On localhost there is much less latency between local db and app. When your app is deployed is takes more time for client to fetch data from database. In result on localhost your collection is ready when FlowRouter initializes and on deployed app it isn't.



回答2:

Use the Template.subscriptionsReady flag

<template name="blogPost">
  <a href="/">Back</a>
  {{#if Template.subscriptionsReady}}
    {{#with post}}
      <h3>{{title}}</h3>
      <p>{{content}}</p>
    {{/with}}
  {{else}}
      <p>Loading...</p>
  {{/if}}
</template>

check full doc here: https://kadira.io/academy/meteor-routing-guide/content/subscriptions-and-data-management/with-blaze to see how to handle individual subscriptions