我有一个运行良好的流星应用原型,但截至目前非常不安全:我需要向当前登录用户显示匹配用户列表。对于初学者,我决定发布所有用户,将字段限制为在客户端过滤用户列表所需的字段。
Meteor.publish('users', function () {
return Meteor.users.find({}, {
fields: {
'profile.picture': 1,
'profile.likes': 1,
'profile.friends': 1,
'profile.type': 1
}
});
});
然后在我的路由器中,我会请求只在客户端显示我想要的内容:
Router.map(function() {
this.route('usersList', {
path: '/users',
waitOn: function () {
return Meteor.subscribe('users');
},
data: function () {
var user = Meteor.user();
return {
users: Meteor.users.find({ $and: [
{_id: {$ne : user._id}},
{'profile.type': user.profile.interest}
]})
};
}
});
});
在上面的代码中,我查询不是当前用户且其类型符合当前用户兴趣的所有用户。我还使用此客户端助手在我们的“profile.friends”数组中将用户的照片显示在某个边框上:
Template.userItem.helpers({
getClass: function(userId) {
var user = Meteor.user();
var lookedup = Meteor.users.findOne({_id: userId});
if ($.inArray(user._id, lookedup.profile.friends) !== -1)
return "yes";
return "no";
}
});
现在这一切都很有效,但通过这种设置,每个客户都可以查询每个用户并获取他们的类型,图片,朋友列表和喜欢的数量。如果我在MVC中,则只能在服务器端访问此信息。所以我决定我的下一次迭代是安全的。我会将我的查询从路由器文件移动到publication文件。这就是麻烦开始的地方......
Meteor.publish('users', function () {
var user = Meteor.users.findOne({_id: this.userId});
var interest = user.profile.interest;
// retrieve all users, with their friends for now
allUsers = Meteor.users.find({ $and: [
{'_id': {$ne: user._id}},
{'profile.type':interest}
]},
{ fields: {'profile.picture': 1, 'profile.friends': 1}}
);
return allUsers;
});
在路由器中:
Router.map(function() {
this.route('usersList', {
path: '/users',
waitOn: function () {
return Meteor.subscribe('users');
},
data: function () {
var user = Meteor.user();
return {users: Meteor.users.find({_id: {$ne : user._id}})};
}
});
});
(请注意,我仍然需要从路由器查询中排除当前用户,因为当前用户始终完全发布)
这有效,但:
Router.go('usersList')
时,用户列表不会更新。只有当我刷新浏览器时,我的列表才会根据用户的新兴趣进行更新。不知道为什么。这个问题让我对流星适用于安全应用的赞美感到怀疑......这在Rails或其他人中很容易实现!
编辑:根据要求,这是我到目前为止将“匹配”检查过渡到服务器的代码:
Meteor.publish('users', function () {
var user = Meteor.users.findOne({_id: this.userId});
var interest = user.profile.interest;
// retrieve all users, with their friends for now
allUsers = Meteor.users.find({ $and: [
{'_id': {$ne: user._id}},
{'profile.type':interest}
]},
{ fields: {'profile.picture': 1, 'profile.friends': 1}}
);
// ------------- ADDED ---------------
allUsers.forEach(function (lookedup) {
if (_.contains(lookedup.profile.friends, user._id))
lookedup.profile.relation = "yes";
else
lookedup.profile.relation = "no";
lookedup.profile.friends = undefined;
return lookedup;
});
// ------------- END ---------------
return allUsers;
});
显然这段代码根本不起作用,因为我无法在foreach循环中修改游标值。但它给出了我想要实现的目标:给客户端一个方法来了解朋友是否匹配,而无需访问客户端的所有用户的朋友列表。 (并且,避免在显示期间每个用户必须执行一个请求,以询问服务器此特定用户是否与此特定用户匹配)