I’d like to be able to define Meteor methods for each Collection, that can be called the same way as dburles:collection-helpers, so I’ve made this function. It also fetches the user and document for you, as that’s something you always need for validation, and it also saves all actions to a log.
What do you guys think? I don’t think there should be any security issues, right?
Example usage
Todos.methods({
check(){
//this.doc and this.user are "secure" as they're fetched on the server
if(!_.includes(doc.owners, user._id){
throw new Error('denied')
} else if(_.find(this.doc.tasks, task => !task.done)){
throw new Error('all tasks are not done')
} else {
Todos.update(this.doc._id, {$set:{done:{user:this.user._id, date:new Date()}}})
}
},
updateDescription(description){
if(!_.includes(doc.owners, user._id){
throw new Error('denied')
} else {
Todos.update(this.doc._id, {$set:{description}})
}
}
})
Then you can call the helpers/methods on the client like this:
let todo = Todos.findOne()
todo.check()
todo.updateDescription('new description')
Here’s the code
//Create a meteor method and a collection helper for each "Collection method"
Mongo.Collection.prototype.methods = function(methods){
let collection = this
_.each(methods, (fn, name) => {
let methodName = collection._name + '-' + name
Meteor.methods({
[methodName](id, ...args){
//Meteor method, runs on both client and server
let doc = collection.findOne(id)
let user = Users.findOne(this.userId) //it always requires that the user is logged in, which is fine for my app
if(doc && user){
fn.call({doc, user}, ...args)
if(Meteor.isServer){
Log.insert({
date:new Date(),
userId:this.userId,
collection:collection._name,
action:name,
docId:id,
args:args
})
}
}
}
})
collection.helpers({
[name](...args){
//Collection helper which calls the method
Meteor.call(methodName, this._id, ...args)
}
})
})
}