Search code examples
javascriptmeteoripleaderboardvote

Limit Meteor Vote Once Per Day


I'm following the MeteorJS example for a leaderboard here: https://www.meteor.com/examples/leaderboard

I want to limit the votes to once per day (per IP address). What's the best way to do this?


Solution

  • The following solution assumes you are starting with a clean version of the leaderboard example.

    Step one: Declare a new collection to hold IP address and date information. This can be added just below the definition of Players.

    IPs = new Meteor.Collection('ips');
    

    Step two: Replace the increment event with a call to our new method givePoints.

    Template.leaderboard.events({
      'click input.inc': function() {
        var playerId = Session.get('selected_player');
        Meteor.call('givePoints', playerId, function(err) {
          if (err)
            alert(err.reason);
        });
      }
    });
    

    Step three: Define the givePoints method on the server (this.connection only works on the server). You can do this by inserting the following anywhere inside of the Meteor.isServer check or by creating a new file under the /server directory.

    Meteor.methods({
      givePoints: function(playerId) {
        check(playerId, String);
    
        // we want to use a date with a 1-day granularity
        var startOfDay = new Date;
        startOfDay.setHours(0, 0, 0, 0);
    
        // the IP address of the caller
        ip = this.connection.clientAddress;
    
        // check by ip and date (these should be indexed)
        if (IPs.findOne({ip: ip, date: startOfDay})) {
          throw new Meteor.Error(403, 'You already voted!');
        } else {
          // the player has not voted yet
          Players.update(playerId, {$inc: {score: 5}});
    
          // make sure she cannot vote again today
          IPs.insert({ip: ip, date: startOfDay});
        }
      }
    });
    

    The complete code can be seen in this gist.