3

我正在使用Alanning Roles为我的应用程序的用户维护一组组/角色。当用户创建“应用程序”时,我为他们生成一个新角色作为app_name + UUID,然后将其作为具有角色的组添加Admin到创建它的用户。然后,我可以使用生成的组名加上AdminorViewer角色的组合来确定哪些Applications用户有权查看和/或编辑。

我遇到的问题是我想不出一个好方法来让出版物只发布用户应该看到的东西。我知道,至少在默认情况下,发布不像客户端那样“反应性”,它们仅对返回的游标具有反应性。但是,在我的代码中,我首先创建组/角色,将其添加到用户,然后保存“应用程序”,我认为它会重新运行我的出版物,但它没有:

Meteor.publish('myApplications', function(groups) {
  if (this.userId) {
    console.log('Running myApplications publication...');
    console.log('Found roles for user ' + this.userId + ': ', Roles.getGroupsForUser(this.userId));
    return Applications.find({group: {$in: Roles.getGroupsForUser(this.userId)}});
  } else {
    //console.log("Skipping null user");
    return null;
  }
});

但是,与我认为会发生的情况相反(整个发布方法将重新运行),我猜真正发生的是只有 Cursor 是更新。因此,对于我的下一次尝试,我添加了 mrt:reactive-publications 包并简单地将光标移至用户的 Meteor.users 集合,认为这会“触发”当用户使用新的更新时重新运行发布组/角色,但这不起作用。

我最终通过简单地为用户传递组来工作:

Meteor.publish('myApplications', function(groups) {
  if (this.userId) {
    if (!groups || groups.length === 0) {
      groups = Roles.getGroupsForUser(this.userId);
    }
    console.log('Running myApplications publication...');
    console.log('Found roles for user ' + this.userId + ': ', Roles.getGroupsForUser(this.userId));
    return Applications.find({group: {$in: groups}});
  } else {
    //console.log("Skipping null user");
    return null;
  }
});

然后我只是像Meteor.subscribe('myApplications', Roles.getGroupsForUser(Meteor.userId()))在我的路线中那样调用出版物waitOn,但这意味着任何客户都可以调用相同的出版物并传入他们喜欢的任何组,并可能看到他们不打算看到的文档。这似乎是一个相当大的安全漏洞。

有没有更好的方法来实现这一点,这样客户就无法哄骗他们看到不属于他们的东西?我认为唯一真正的方法是在发布方面聚集小组,但这会破坏反应性。

4

1 回答 1

2

在筛选了一堆文档和一些非常有用的堆栈帖子之后,这是我想出的替代方案。奇迹般有效!

我的目标是向组管理员发布“来宾”用户的信息,以批准/拒绝增强权限。

Meteor.publish('groupAdmin', function(groupId) {
  // only publish guest users info to group admins
  if(Roles.userIsInRole(this.userId, ['group-admin'], groupId)) {
    // I can't explain it but it works!
    var obj = {key: {$in: ['guest']}};
    var query = {};
    var key = ('roles.' + groupId);
    query[key] = {$in: ['guest']};
    return Meteor.users.find(query, {
        fields: {
          createdAt: 1,
          profile: 1
        }
      });
  } else {
    this.stop();
    return;
  }
});

参考:如何从变量中设置 mongo 字段 以及如何在 Meteor 的 Mongo 查询中使用变量作为字段名?

于 2015-08-31T04:00:20.280 回答