【问题标题】:Meteor: Best practice for modifying document data with user dataMeteor:使用用户数据修改文档数据的最佳实践
【发布时间】:2017-03-13 00:08:08
【问题描述】:

感谢您查看我的问题。对于在生产中使用过 Meteor 的人来说应该很容易,我仍处于学习阶段。

所以我的流星设置是我有一堆文档,ownedBy_id 反映了哪个用户拥有每个文档(https://github.com/rgstephens/base/tree/extendDoc 是完整的 github,请注意它是 extendDoc 分支而不是 master 分支)。

我现在想修改我的 API,以便我可以显示文档每个所有者的真实姓名。在服务器端,我可以使用 Meteor.users.findOne({ownedBy}) 访问它,但在客户端,我发现由于 Meteor 安全协议(用户无权访问其他用户的数据),我无法执行此操作。

所以我有两个选择:

  1. 以某种方式修改我发布的结果以在服务器端包含用户的真实姓名

  2. 以某种方式将完整的用户数据推送到客户端,并将_id映射到客户端的真实姓名

这里的最佳做法是什么?我都试过了,这是我目前的结果:

  1. 我在这里失败了。我知道这是非常“节点”的想法。我可以在客户端访问用户数据,但 Meteor 坚持我的出版物必须返回 cursors 而不是 JSON 对象。如何将 JSON 对象转换为游标或以其他方式规避此 publish 限制?奇怪的是,谷歌对这个话题保持沉默。

    Meteor.publish('documents.listAll', function docPub() { 
       let documents = Documents.find({}).fetch();
       documents = documents.map((x) => {
         const userobject = Meteor.users.findOne({ _id: x.ownedBy });
         const x2 = x;
         if (userobject) {
           x2.userobject = userobject.profile;
         }
         return x2;
       });
      return documents; //this causes error due to not being a cursor
   }
  1. 我在这里取得了成功,但我怀疑是以一个巨大的安全漏洞为代价的。我只是将我的发布修改为一个游标数组,如下所示:

    Meteor.publish('documents.listAll', function docPub() { 
      return [Documents.find({}),
        Meteor.users.find({}),
      ];
    });

我真的很想做 1,因为我感觉 2 有一个很大的安全漏洞,但请告诉我应该怎么做?非常感谢。

【问题讨论】:

    标签: javascript mongodb meteor


    【解决方案1】:

    是的,您不想将完整的用户对象发布到客户端是正确的。但是您当然可以使用选项上的“字段”发布完整用户对象的子集,这是 find() 的第二个参数。在我的项目中,我为每个用户创建了一个“公共档案”区域;这使得我们可以轻松了解用户的哪些信息可以发布给其他用户。

    有几种方法可以将这些数据提供给客户端。您已经找到了一个:从发布中返回多个游标。

    在下面的示例中,我将返回所有文档,以及拥有这些文档的所有用户对象的子集。此示例假定用户名以及您决定为“公共”的任何其他信息都位于名为 publicInfo 的字段中,该字段是 Meteor.user 对象的一部分:

    Meteor.publish('documents.listAll', function() {
        let documentCursor = Documents.find({});
    
        let ownerIds = documentCursor.map(function(d) {
            return d.ownedBy;
        });
    
        let uniqueOwnerIds = _.uniq(ownerIds);
    
        let profileCursor = Meteor.users.find(
            {
                _id: {$in: uniqueOwnerIds}
            },
            {
                fields: {publicInfo: 1}
            });
    
        return [documentCursor, profileCursor];
    });
    

    【讨论】:

    • 你的例子做得很好,像我这样的笨蛋可以立即理解。谢谢你!所以在你的情况下,你已经充实了我在做用户数据映射客户端的情况下应该做什么。我分别收到了另一个可能有助于在服务器端进行映射的答案(如下),我将尝试一下。无论如何都支持你的。
    • 将您标记为正确答案,因为我正在探索的另一条路线一无所获。
    【解决方案2】:

    在 MeteorChef slack 频道中,@distalx 如此回应:

    嗨,您正在使用 fetchfetch 将所有匹配的文档作为数组返回。 我想如果你只使用find - w/o fetch 就可以了。

    Meteor.publish('documents.listAll', function docPub() { 
       let cursor = Documents.find({});
       let DocsWithUserObject = cursor.filter((doc) => {
         const userobject = Meteor.users.findOne({ _id: doc.ownedBy });
         if (userobject) {
           doc.userobject = userobject.profile;
           return doc
         }
    
       });
      return DocsWithUserObject;
    }
    

    我要试试这个。

    【讨论】:

    • 没用。 cursor 对象没有过滤方法:所以我得到了 TypeError: cursor.filter is not a function
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 2014-02-06
    • 2021-07-26
    • 2010-11-06
    • 2016-10-23
    • 2011-10-31
    • 1970-01-01
    相关资源
    最近更新 更多