Prevent client side updates to database?


#1

So I currently have this code triggering on a click event:

Meteor.users.update({ _id: Meteor.userId() }, {$set: {voted: true}});

and then in the server:

Meteor.users.allow({ update: function (userId, doc) { return true; } });

Currently a user would be able to open up the console and update values in the database to whatever. I’ve removed insecure, but how would I go about preventing the users from updating the database while maintaining the current codes functionality?


#2

The code you’ve posted explicitly allows the user to modify the database directly.
You can’t retain that functionality while at the same time denying it be achieved via the console.

If you don’t want a user to be able to modify the database themselves directly, you will need to use a client side call & server side method.

With the allow/deny rules, you can put rules on how and what can be modified, but if you allow something - then it can be done via the console too.


#3

When I said retain functionality I meant just updating the DB, hence the thread =\ . Mmk so I wrote the server method and client call like this:

var userId = Meteor.userId(); Meteor.call('voted', userId, {$set: { voted: true }});

Meteor.methods({ voted: function (userId, voted) { Meteor.users.update(userId, voted); } });

So this works nicely and I cant seem to update the DB from the console :smile:. When this call and method is triggered though, I get an update failed: Access denied message in the console, even though it obviously went through because the database gets updated with the new value. Why is this message being printed out?


#4

Did you remove the insecure package? From Meteor’s Full API docs:

Meteor also has a special “insecure mode” for quickly prototyping new applications. In insecure mode, if you haven’t set up any allow or deny rules on a collection, then all users have full write access to the collection. This is the only effect of insecure mode. If you call allow or deny at all on a collection, even Posts.allow({}), then access is checked just like normal on that collection. New Meteor projects start in insecure mode by default. To turn it off just run $ meteor remove insecure.

At some point you should also remove the ‘autopublish’ package. For further info on them see http://docs.meteor.com/#/full/dataandsecurity


#5

Yea I already removed it.


#6

The method is executed both on the client and the server (latency compensation), and the client side execution rejects the update (no allow rule on the server finds it OK), which is why the error message is shown, but the update on the server is OK, so the update goes through.


#7

So whats the usual way to take care of it? Or is that just something normal that should be happening?


#8

Add

Meteor.methods({
voted: function (userId, voted) {
Meteor.users.update(userId, voted);
}
});

to the server only. But note that the clients are able to call this method in the console ( Meteor.call('voted') ).


#9

I think if you just remove your allow & deny rules then you shouldn’t see that error during simulation.
I only use methods now, and I never see that error pop up any more, the only thing I can think is that I haven’t got any allow/deny rules set (by default everything is denied).
Caveat - I still have a deny rule on users profile field, since that’s always allowed.


#10

Isn’t it possible to deny just the updating of the field role (or any field in Meteor.users you want to protect via console update)?

Like in this example from the Meteor documentation:

Posts.deny({
    update: function (userId, doc, fields, modifier) {
        // can't change role
        return _.contains(fields, 'role');
    }
});

I haven’t tested it myself, I’m just starting my second month with Meteor