Iron Router - 取决于租户的条件路由

Iron Router - Conditional routes depending on tenant

我正在开发一个多租户应用程序,我不确定如何有条件地加载路由。

我有:

   var tenant = resolveTenant();
   if (tenant === null) {

        Router.configure({
            layoutTemplate: 'main',
            notFoundTemplate: 'not-found'
        })
        Router.route('home', {
            path: '/'
        })

        Router.route('newClient', {
            path: 'signup'
        })
    } else {
        Router.configure({
            layoutTemplate: 'storeMain',
            notFoundTemplate: 'not-found'
        })
        Router.route('storeHome', {
            path: '/'
        })
    }

因此,如果无法解决租户问题,请加载主站点。

这工作得很好,不是很漂亮,但很好。但是,问题是当租户不存在时。

案例:

为此,我需要调用数据库。所以我将条件包装在一个带有回调的方法调用中:

    Router.configure({
        layoutTemplate: "loading"
    });
    var tenant = resolveTenant();
    Meteor.call("tenant.exists", tenant, function(err, exists) {
        if (tenant !== null && !exists) {
            Router.configure({
                layoutTemplate: 'noTenant'
            })
            Router.route('noTenant', {
                path: '/'
            })
        } else if (tenant === null) {

            Router.configure({
                layoutTemplate: 'main',
                notFoundTemplate: 'not-found'
            })
            Router.route('home', {
                path: '/'
            })

            Router.route('newClient', {
                path: 'signup'
            })
        } else {
            Router.configure({
                layoutTemplate: 'storeMain',
                notFoundTemplate: 'not-found'
            })
            Router.route('storeHome', {
                path: '/'
            })
        }
    })

问题是,它不会在调用完成后从加载模板配置中移动。如果我删除加载模板路由,我会得到 iron router 登陆页面。

为了完成,这里是 "tenant.exists" 方法:

  "tenant.exists": function(url){
    if(url === null){
      return false
    }
    return Tenants.find({"url": url}).count() > 0;
  },

关于如何实现这一点有什么想法吗?

编辑

我确实尝试从客户端的方法调用和 运行 查询中删除条件。然而,计数总是在不应该返回 0 时返回。

 if (tenant !== null && Tenants.find({"url": tenant}).count() === 0) {
      Router.configure({
          layoutTemplate: 'noTenant'
      })
      Router.route('noTenant', {
          path: '/'
      })
  } else if (tenant === null) {

      Router.configure({
          layoutTemplate: 'main',
          notFoundTemplate: 'not-found'
      })
      Router.route('home', {
          path: '/'
      })

      Router.route('newClient', {
          path: 'signup'
      })
  } else {
      Router.configure({
          layoutTemplate: 'storeMain',
          notFoundTemplate: 'not-found'
      })
      Router.route('storeHome', {
          path: '/'
      })
  }

请允许我提出一个更简单的方法,该方法还可以避免将所有租户的名称发布给每个客户端,同时还可以避免 Meteor.call():

的异步副作用
  1. 订阅租户订阅,将租户名称作为参数传递
  2. 在相应的发布中,只有return一个匹配的租户
  3. onBeforeAction 处理程序中,查看是否有租户记录,如果有则继续,否则呈现适当的页面。

路由器:

var tenant = resolveTenant();

Router.route('/',{
  name: 'storeHome',
  onBeforeAction: function(){
    if ( Tenants.findOne() ) this.next();
    else if ( tenant ) this.render('noTenant');
    else this.render('signup');
  },
  waitOn: function(){
    return Meteor.subscribe('tenant', tenant);
  }
});

服务器:

Meteor.publish('tenant',name,function(){
  check(name,String);
  return Tenants.find({ url: tenant });
});

取自模式here