Meteor:使用用户数据修改文档数据的最佳实践

时间:2023-01-18 16:29:43

Thanks for looking at my question. It should be easy for anyone who has used Meteor in production, I am still at the learning stage.

谢谢你看我的问题。任何在生产中使用Meteor的人都应该很容易,我还处于学习阶段。

So my meteor setup is I have a bunch of documents with ownedBy _id's reflecting which user owns each document (https://github.com/rgstephens/base/tree/extendDoc is the full github, note that it is the extendDoc branch and not the master branch).

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

I now want to modify my API such that I can display the real name of each owner of the document. On the server side I can access this with Meteor.users.findOne({ownedBy}) but on the client side I have discovered that I cannot do this due to Meteor security protocols (a user doesnt have access to another user's data).

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

So I have two options:

所以我有两个选择:

  1. somehow modify the result of what I am publishing to include the user's real name on the server side

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

  2. somehow push the full user data to the clientside and do the mapping of the _id to the real names on the clientside

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

what is the best practice here? I have tried both and here are my results so far:

这里最好的做法是什么?我试过了两个,到目前为止我的结果是:

  1. I have failed here. This is very 'Node' thinking I know. I can access user data on clientside but Meteor insists that my publications must return cursors and not JSON objects. How do I transform JSON objects into cursors or otherwise circumvent this publish restriction? Google is strangely silent on this topic.
  2. 我在这里失败了。这是我所知道的非常“节点”的想法。我可以在客户端访问用户数据,但Meteor坚持认为我的出版物必须返回游标而不是JSON对象。如何将JSON对象转换为游标或以其他方式绕过此发布限制?谷歌在这个话题上非常沉默。

    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. I have succeeded here but I suspect at the cost of a massive security hole. I simply modified my publish to be an array of cursors, as below:
  2. 我在这里取得了成功,但我怀疑是以一个巨大的安全漏洞为代价的。我只是将我的发布修改为一个游标数组,如下所示:

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

I would really like to do 1 because I sense there is a big security hole in 2, but please advise on how I should do it? thanks very much.

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

2 个解决方案

#1


2  

yes, you are right to not want to publish full user objects to the client. but you can certainly publish a subset of the full user object, using the "fields" on the options, which is the 2nd argument of find(). on my project, i created a "public profile" area on each user; that makes it easy to know what things about a user we can publish to other users.

是的,您不想将完整的用户对象发布到客户端。但你可以使用选项上的“字段”发布完整用户对象的子集,这是find()的第二个参数。在我的项目中,我为每个用户创建了一个“公开个人资料”区域;这使我们可以轻松了解用户可以向其他用户发布的内容。

there are several ways to approach getting this data to the client. you've already found one: returning multiple cursors from a publish.

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

in the example below, i'm returning all the documents, and a subset of all the user object who own those documents. this example assumes that the user's name, and whatever other info you decide is "public," is in a field called publicInfo that's part of the Meteor.user object:

在下面的示例中,我将返回所有文档,以及拥有这些文档的所有用户对象的子集。此示例假定用户的名称以及您决定的其他任何“公共”信息位于名为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


0  

In the MeteorChef slack channel, @distalx responded thusly:

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

Hi, you are using fetch and fetch return all matching documents as an Array. I think if you just use find - w/o fetch it will do it.

嗨,您正在使用fetch和fetch将所有匹配的文档作为数组返回。我想如果你只是使用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;
}

I am going to try this.

我要试试这个。

#1


2  

yes, you are right to not want to publish full user objects to the client. but you can certainly publish a subset of the full user object, using the "fields" on the options, which is the 2nd argument of find(). on my project, i created a "public profile" area on each user; that makes it easy to know what things about a user we can publish to other users.

是的,您不想将完整的用户对象发布到客户端。但你可以使用选项上的“字段”发布完整用户对象的子集,这是find()的第二个参数。在我的项目中,我为每个用户创建了一个“公开个人资料”区域;这使我们可以轻松了解用户可以向其他用户发布的内容。

there are several ways to approach getting this data to the client. you've already found one: returning multiple cursors from a publish.

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

in the example below, i'm returning all the documents, and a subset of all the user object who own those documents. this example assumes that the user's name, and whatever other info you decide is "public," is in a field called publicInfo that's part of the Meteor.user object:

在下面的示例中,我将返回所有文档,以及拥有这些文档的所有用户对象的子集。此示例假定用户的名称以及您决定的其他任何“公共”信息位于名为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


0  

In the MeteorChef slack channel, @distalx responded thusly:

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

Hi, you are using fetch and fetch return all matching documents as an Array. I think if you just use find - w/o fetch it will do it.

嗨,您正在使用fetch和fetch将所有匹配的文档作为数组返回。我想如果你只是使用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;
}

I am going to try this.

我要试试这个。