Server Allow / Client Deny for same Collection Operation


#1

Please take a look at the following code. Is it possible to allow an insert from server code and deny the same from client code ? This is intended to stop an insert from being entered via the browser, whereas the same would execute if it is placed in a meteor directory that is not client or server.

The following code anyway inserts the record twice, so not my expected behaviour.

//------------- test code below
// the following code runs on both server and client
nameValuePair = new Mongo.Collection(“NameValuePair”);

Schemas = {};

Schemas.NameValuePair = new SimpleSchema({
name: {
type: String
},
value: {
type: String
}
});

nameValuePair.attachSchema(Schemas.NameValuePair);

if (Meteor.isServer) {
Meteor.publish(“namevalues”, function nameValuePublish(){
return nameValuePair.find();
});
}

if (Meteor.isClient) {
Meteor.subscribe(“namevalues”);
}

if (Meteor.isServer) {
nameValuePair.allow({
‘insert’: function() {
return true;
}
});
}

if (Meteor.isClient) {
nameValuePair.deny({
‘insert’: function() {
return true;
}
});
}

console.log(“inserting”);

// required behaviour is that the following insert statement is executed only once… although the console logs will be run twice…
nameValuePair.insert({name: “booboo”, “value”: “coolguy”});

console.log(“inserted”);
// ---------------- end of test code


Proof that no one uses Allow/Deny
#2

As far as I know, the allow/deny rules are only applied to the client.

The server is allowed to do what he wants, always. Wouldn’t really make much sense if it was otherwise.

Also, your code shows a bit of confusion as to which statement goes where.

Take a look at the docs again - it states pretty explicitly what goes where.


#3

Actually, my point is that the allow/deny rules should have scope in both client and server, where the same operation is allowed in server and denied in client. This behaviour will be controlled by using the Meteor.isClient or Meteor.isServer in the common code.

Note that the required behaviour will still have the record inserted, though it fails on the client. The insert operation, namely,

nameValuePair.insert({name: “booboo”, “value”: “coolguy”});

will succeed on the server, and thanks to the Meteor.publish, will eventually reach the client. Hope this makes sense.


#4

If allow/deny could be used on the client with any authority, wouldn’t that defeat the purpose of restricting the client?

If your goal is to prevent the untampered client from wasting a round-trip to the server to figure out whether or not it can do something, you can write error-checking/obstacle code on the client to prevent the client from making unnecessary server calls. IIRC, all inserts on the client are denied by default…


#5

Can you explain more what this means? So you want something which is like a server-only method, such that it doesn’t optimistically update the client, but is called via Collection#insert? Why not just define a method?


#6

Thanks @sashko. Yes that is pretty much what I want. However, without having to create a Meteor.method and doing a Meteor.call for it.

Why use the same old client stub pattern in an isomorphic world, huh? :smiley:

As it is, Meteor instruments a lot of code, we should further remove the distinction between client code and server code. How about just using Meteor.isClient as a basis of that distinction? Along with allow/deny…

This may be hard to provide as a feature of Meteor I presume. Hope this makes sense… Thanks again!


#7

To summarise, maybe Meteor can make every JS function defined in the common area as a Meteor.method. Hope that will work. Thanks!


#8

Sorry, I think the best practices and our recommendations are moving in the other direction - app developers should be aware of exactly what lies on the boundary between client and server, rather than blurring the distinction. That’s why explicitly defining methods and validating their arguments is the best choice.


#9

This boundary can be explicitly specified by the coder using isClient and isServer.

Methods will just be pure JS methods defined in the common area not the boilerplate Meteor.methods.

Same point I am making here.