ValidatedMethod vs Extending Mongo Collection + Allow


#1

I’ve done a fair bit of work recently with the mdg:validated-method to very much tie down what users can and cannot do.

The usual approach is something like this:

  • I attach a schema to the collection.
  • I simply deny every single client call to the collection.
  • I usually extend the collection to add some information such as who edited a record, but there is no validation
  • I use ‘validate:method’ for 100% of my manipulation on collections.
  • Every method is testing access rights before proceeding to manipulate the collections.

I’m continuously annoyed by the overhead of writing sometimes long validations for each and every. Even though I reuse predefined schemas.

So I have been looking at alternatives. One approach that appears a lot cleaner to me would be this:

  • Check for each user if they can update the collection within the deny/allow functions.
  • Attach a schema to the collection to enforce all actions to be valid.
  • Use the basic Meteor.Method simply to encapsulate actions that affect more than one collection or are otherwise complex beyond what I’m comfortable doing in helpers/events.

The flaw with this is quite obvious: allow / deny only affect the client. So if I don’t check the access rights within the Meteor Method, users might still be able to execute database change without sufficient authorization.
But this is exactly what’s annoying me about using mdg:validated:method. I keep rewriting the same usually 1 or 2 line validation code in each of them. In some cases my validation also changes based on the type of user

In almost all of my code, the access to a specific field in a collection is far more aligned to the collection than to the method calling it. So I’d like to override the Mongo.Collection with a bespoke Class doing all the checking.

I’d expect this to look something like this:

class MySpecificAuthorisedCollection extends Mongo.Collection{
  insert(doc, callback){ // deny would be very much the same + deleting relational dependencies. 
    // check user can insert
    // validate schema
    return super.insert(doc, callback); 
  }
  update(){
    // the update doc can be too complex to control so I just 
    // simply override the update to prevent users from calling it. 
  },
  myUpdate(id, params, callback){
    // check user can insert for each key in params. 
    // then update based on the keys that can be authorized by calling super.params. 
  }
}

Now I still believe this to be unsafe, as I’m assuming there would be something as simple as calling authorizedCollection.super.update() or similar. (Sorry if that’s not possible but I’m still trying to get to grips with ES6 and objects).

So my questions:

  • Is there a way to create secure access restrictions within something similar to an overridden Mongo.Collection where these restrictions are safely defined at collection level, instead of method level?
  • Is there any module that has been written for this purpose and takes the grunt of the work (or makes it secure - assuming my above suggestion is far from it).
  • What is the most similar approach?