Mike
Mike

Reputation: 23

Allow collection to update from client in Meteor

Just hit an insanely frustrating roadblock in prototyping. I need to update and increment values an array inside of a collection. To do this, I'm accessing the collection using the MongoDB syntax like so:

 Players.update({_id: Session.get('p1_id'), 'opponents.$.id' : Session.get('p2_id')}, 
  {$inc: {
    'games_played' : 1
  }}
);

When this runs I get an error saying: Uncaught Error: Not permitted. Untrusted code may only update documents by ID. [403]

Now, I searched the hell out of this and I know that it came down in an update and why they only allow update by id's. But my problem is that I can't seem to find a way around it. I tried forcing it by adding this to if (Meteor.isServer):

Players.allow({
  insert: function(userId, doc, fields, modifier){
   return true;
  },
  update: function(userId, doc, fields, modifier){
    return true;
  },
  remove: function(userId, doc, fields, modifier){
    return true;
  }
});

Nothing seems to work, and all the examples I find talk about using a Meteor method (not really sure what that is) or are doing userId validation (I dont have any users and don't want to add them right now). I'm just prototyping/sketching and I'm not concerned about security. How can I proceed here?

Upvotes: 2

Views: 2658

Answers (2)

sclausen
sclausen

Reputation: 1719

You just got the update wrong. The first parameter of the update method should be the id. the second parameter is an object containing the modifiers.

Players.update(playerId, {$inc:{games_played:1}});

Optionally you can add a callback containing error as the first parameter and response as the second parameter.

Upvotes: 1

sbking
sbking

Reputation: 7680

Here's how you can make this into a method:

Meteor.methods({
  incrementGames: function (player1Id, player2Id) {
    check(player1Id, Meteor.Collection.ObjectID);
    check(player2Id, Meteor.Collection.ObjectID);

    Players.update({
      _id: player1Id,
      'opponents.$.id': player2Id
    }, {
      $inc: {
        'games_played' : 1
      }
    }, function(error, affectedDocs) {
      if (error) {
        throw new Meteor.Error(500, error.message);
      } else {
        return "Update Successful";
      }
    });
  }
});

And on your client:

Meteor.call("incrementGames", Session.get('p1_id'), Session.get('p2_id'), function(error, affectedDocs) {
  if (error) {
    console.log(error.message);
  } else {
    // Do whatever
  }
});

Upvotes: 1

Related Questions