I’m taking a look at the open sourced apps that Slava posted here, and checking some security things. One of them is the way that people are handling inserts, updates and deletes. I like to use Allow and Deny since it is cleaner to use Collection.insert() on client, for me. But I’m reconsidering that, and I would love to hear your experiences about that, taking security and performance in consideration.
I exclusively use calls Meteor.methods helps keep a separation of concerns, and prevents insert/update/delete logic from being duplicated in various event handlers.
Had I the opportunity to write it again - I would probably put another layer below Meteor.methods - rather than using them as my top level “API”. eg. So I could re-use them outside meteor, or test them better.
@Peppe_LG, thanks, that answer is very good. In fact, it made me think that maybe I can continue using Allow & Deny for now, and in a new version switch to other stuff (or not).
But what about performance, did anyone had some tests?
We’ve had this conversation before: “Should we allow developers to read/write tables directly or through stored procedures?”
The bottom line is that People.insert() is as natural and correct as People.find().
If you don’t create a ceremony for People.find(), why do you feel the need to add the ceremony to perform the exact equivalent of People.insert()? Any argument you use for People.insert() can also be used for People.find()
In a typical application, a read operation is a single line of code (People.find()) whereas a write operation is composed of a full page of sensitive security/access/permission checks following by the insert line (People.insert()). I find it reassuring to put together, in the same block of code, the full page of check and the write operation.
I hardly ever use allow and deny. Mostly sooner than later most of my apps require some code that calls for the flexibility that methods bring to the table. I don’t find them harder to use, and I am not comfortable with all the thinking I have to do when using allow/deny and trying to determine which case gets allowed and which is denied.
I don’t like that both allow and deny exists (one of them is enough!), but I always try to use them in favor of methods. They’re great for insert and remove operations (quite easy to write), but for update operations they’re not optimal. Usually, one have many different update queries, and writing one update query on the client that later needs to be validated on the server feels like duplicating the code. Using a method for each update query is much simpler.
I like to use the package ongoworks:security for doing the security logic of my app, it prevent me from overwriting insert/update/remove code in others pieces of the code.
I agree with @deb. With latency compensation being one of the 7 principles of meteor, I believe that the insert/update/remove with allow/deny rules most closely aligns with the goals of Meteor.
That being said, the allow/deny rules are much more complicated than a Meteor.method is, and I think there are use cases for both ways of doing it. But I think that allow/deny should be used when possible to most closely align with the principles of Meteor.
If you call Meteor.methods on both the server and the client, the methods on the client are called stubs (simulations). When you invoke a method on the client, it will run the stub for the method directly and send the request to run it on the server. The client will later adapt to what actually happened on the server.
It is really useful if you for example want to make sure that two inserts happens (for example, if you have one collection for all the threads in a forum and another one for all the posts in the forum, you want to make sure that when the user creates a thread, he must also also create a post in it).
I have such a method on the server with many validations and client I have the same method but all it does is update without any validations. It is incredibly fast