The Broad Strokes of Meteor Permissions in Meteor js
Let’s talk permissions. In particular, how Meteor js handles permissions and how you can use them to:
- Secure your content so that people only see what they are allowed to see.
- Avoid performance issues by only loading for the user stuff that he needs to see at that given moment (and not the entire universe of information).
The way Meteor does this is actually rather elegant. If you are familiar with Drupal, the closest equivalent would be a menu_hook. If you’re not familiar with Drupal, it’s not too complicated. Basically, in your server code (the code that the client can’t see), you define a series of values in a couple functions that tell the client what he is allowed to store in his local MogoDB.
But before I get ahead of myself, let’s first break out how Meteor is storing the data your user is seeing.
Autopublish, The Insecure Module and Client-Side Database Querying
If you’ve watched any of the Meteor tutorials, you’ll see that you can actually query your database from Firebug right in the browser (from the client). Once you get past how cool this is, you then start thinking how terrifying it is.
“So...like...users can query *anything* from the client??”.
Well, Yes. And no.
By default, when you’re developing your application, you’ll probably have the insecure and autopublish modules enabled. This means that anyone can see and query anything, which isn’t a big deal because it’s just you and/or your team in there.
But as your application migrates to production or you start getting lots of data in there, you start wanting to protect this data from prying eyes, and avoiding the scenario where you have a bazillion records loaded by your poor overworked and ridiculously slow browser - resulting in a performance issue.
You define the publishing parameters
The thing is, Meteor doesn’t *actually* let the user/client query everything willy nilly. It lets it search *what’s in the client mongoDB* at will. But that doesn’t necessarily mean that the data match what’s in your server mongoDB. One of the really slick things about meteor is that although it may appear that the client is querying from the server database, it actually is not. Rather, it has its own local version of the mongo db (with data that the server specifies it is allowed to have) and as both the server and client make changes to their respective databases, Meteor works in the background to keep them properly in sync.
Let’s think about that for a second. It’s almost like you’re in a kitchen cooking a meal, and you just have one drawer. And every time you open that drawer, the utensils and ingredients you need for exactly that step in your cooking process *magically* appear. When you close the drawer and reopen it, you have new stuff that you need and the old stuff goes away. It’s beautiful - as anyone who has ever sifted through a drawer full of crap to find the one thing they need rightfully knows. To take the analogy just a tad further (but no further, I promise), if you suddenly decide that you want to make an entirely new dish - just open the drawer again. Everything you need is there and ready to begin for the next plate.
I suspect that Meteor employs the same gremlins to do this syncing as the ones that hide your extra socks because 1) you never see it happen and 2) you know that it always will happen. But I digress! (I apologize in advance for these horrible jokes. They are bad, but don’t let that stop me.)
So what’s beautiful about this is that from the client perspective, you just know that you’ll always have the stuff you need to do what you need to do client-side. And from the server perspective, the client will only be given / synced with data that you explicitly declare (once you turn off insecure mode / autopublish).
You declare these permissions in two ways
A ‘publish’ function allows you to essentially create something similar to an rss feed from the server to the client. The client ‘subscribes’ to a callback on the server, which then keeps the results of the callback (what’s returned) in the client db. In this blog, you'll notice that I am implying that 'publishing' is the same thing as 'permissions'. Technically, it's not - it just returns back stuff you can see. But in a way, it kind of is at the same time (as you can't see what you aren't allowed to see). I just make this distinction for you nitpickers out there (you know who you are...picking all those nits).
Here’s an example of a publish function:
This will return to the client all of the cat records that have my userId in the record (which obviously means that when you created the Cats collection, and inserted into it Cat records, that you should have been pushing a userId along with it. Note that this is not publishing cats that do not belong to me. Who knows how many cats are actually there!
The one-two punch of the security permissions though is your ‘allow’ function. Here you define the parameters of the operations that are permitted by the client on your Collection (in other words, what people can ‘update’, ‘insert’ and ‘remove’). If you do not define anything and you do not have the insecure module enabled, then the client will be able to do nothing.
So let’s look at an example:
Now of course, these are pretty broad strokes. You can get as granular as you see fit. Note that with each of the update parameters, you get a number of variables related to the call, which can be used to make an intelligent decision about permissions.
And there you have it
This is not intended to be an in-depth crash course about permissions. There are Meteor docs for that! But it should give you a broad understanding of the principles behind what otherwise might be a fairly intimidating concept (probably not for you though because you’re very smart. But other folks, at least).
If you have any questions, feel free to reach out. We consider ourselves fairly savvy with Meteor and we are also happy to help out where we can.