2014-09-20 79 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。這樣,我永遠不會授予用戶編輯其他用戶視頻的權限。他們只是編輯他們的評論,服務器編輯視頻的平均水平。