2014-09-20 61 views
0

这是一个艰难的(对我来说)和罗嗦之一:保护我的非规范化的流星评级系统

我来这整个蒙戈非规范化的东西条款。我创建了评分系统,让用户评价彼此的视频。要获得视频的平均分数,每次用户“查看”视频文档(在名为“条目”的集合中),将0到10之间的数字直接添加到视频文档中的分数字段中(使用meteor.methods upsert )。当然,一个条目的平均得分是所有这些评分的总和除以总评论数。无论如何,我都会将每个评论记录在单独的收藏集中。

我的问题是......我不知道如何安全地写这个。没有什么可以阻止某人添加大于10或小于0的数字(或重复添加可接受的数字)。

你能帮忙吗?也许如果我说过“如果您尝试更新评论总数(在条目文档中)的新号码不等于存储在评论集合中的此条目的所有评论的总和,则抛出错误。 ..加上你的最新成绩。“但是,如果这是正确的,那么书面的问题如何?

这里的共享客户机/服务器代码:

//update reviews 
Meteor.methods({ 
    reviewUpsert: function(id, doc) { 
    if (!this.userId) { 
     throw new Meteor.Error(403, "You must be logged in to do that."); 
    } 
    if (Meteor.users.findOne(this.userId).emails[0].verified !== true) { 
     throw new Meteor.Error(403, "Your email must be verified to review. Check your email inbox.") 
    } 
    if (Meteor.user().status === "suspended") { 
     throw new Meteor.Error(403, "Cannot perform this action while account is suspended.") 
    } 
    var review = Reviews.findOne(id); 
    if (review && doc.reviewer !== this.userId) { 
     throw new Meteor.Error(403, "You don't own that review."); 
    } 
    if (doc.reviewer !== this.userId) { 
     throw new Meteor.Error(403, "Cannot create a review for someone else."); 
     // alternatively, just set doc.owner = this.userId 
    } 
    Reviews.upsert(id, doc); 
    } 
}); 

//update entry score 
Meteor.methods({ 
    entryScoreUpdate: function(id, doc) { 
     Entries.update(id, doc); 
    } 
}); 

下面是相关的客户端代码:

Meteor.call('reviewUpsert', 
    Reviews.findOne({unique_review: reviewer_and_entry}, {}, function(err, result){ 
     if (result) { 
     return result._id; 
     } 
     if (!result) { 
     return null; 
     } 
    }), 
    {date: new Date(), reviewer: Meteor.userId(), entry: Session.get('entryId'), title: entrytitle.title, unique_review: reviewer_and_entry, reviewername: Meteor.user().username, review: reviewfield, score: parseInt(scorefield)}, function(err){ 
     if (err) 
     Alerts.add('Review error: ' + err.reason, 'warning'); 
     else { 
      var reviewAdd = parseInt(scorefield) - lastscore; 
      Meteor.call('entryScoreUpdate',   
      {_id: Session.get('entryId')}, {$inc: {reviewsum: reviewAdd, reviewcount: incCount}}, 
      function(err){ 
       if (err) 
       Alerts.add('Review error: ' + err.reason, 'warning'); 
       else { 
        var entryforavg = Entries.findOne(Session.get('entryId')); 
        Meteor.call('entryScoreUpdate',   
        {_id: Session.get('entryId')}, {$set: {avgScore: Number(((entryforavg.reviewsum/entryforavg.reviewcount)*10).toFixed(2))}}, 
        function(err){ 
         if (err) 
         Alerts.add('Review error: ' + err.reason, 'warning'); 
         else { 
         Alerts.add('Review has been updated.', 'success'), 
         Session.set("formStatus", 'oldForm'); 
         } 
        } 
       ); 
       } 
      } 
     ); 
     } 
    } 
); 

回答

1

如何:

Meteor.methods({ 
    reviewUpsert : function(id, doc){ 
     ... 
     if((doc.rating > 10) || (doc.rating < 0)){ 
      throw new Meteor.Error(...) 
     } 
    } 
}) 

至于停止同一用户反复输入评分时,您必须跟踪哪些用户对哪些视频进行了评分并更新了他们的评分而不是简单地添加新的评分。

+0

感谢这部分。我跟踪上面代码中的用户评分,但为了获得平均值并显示这些平均值的被动列表,我需要在视频文档中复制该列表。要做到这一点,我必须允许用户访问视频文件。这就是安全问题开始的地方。除非您要将视频文档中的每个评分存储在数组中,并且不要仅收集评分。 – Quin 2014-09-20 20:59:53

+0

也许在您的收视率集合中,您还可以包含与每个评分相关联的userIds?这通常是我将标记放在白板上并找出哪个解决方案最少的地方。 ;) – rkstar 2014-09-21 17:01:01

0

我终于明白了。我不需要将entries.update作为自己的Meteor.method来在客户端上调用。我可以在“reviewsupsert”方法内的服务器上运行Entries.update。这样,我永远不会授予用户编辑其他用户视频的权限。他们只是编辑他们的评论,服务器编辑视频的平均水平。