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:
所以我有两个选择:
-
somehow modify the result of what I am publishing to include the user's real name on the server side
以某种方式修改我发布的结果,在服务器端包含用户的真实姓名
-
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:
这里最好的做法是什么?我试过了两个,到目前为止我的结果是:
- 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.
我在这里失败了。这是我所知道的非常“节点”的想法。我可以在客户端访问用户数据,但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
}
- 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:
我在这里取得了成功,但我怀疑是以一个巨大的安全漏洞为代价的。我只是将我的发布修改为一个游标数组,如下所示:
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.
我要试试这个。