Meteor multiple dependent collections and their permissions - what's the best practice?


Hello meteor community!

I’m starting my first meteor project and have stuck in how to organize collections and publish permissions.
To simplify things - let’s say I have users (built-in), teams, projects and tasks.
The rules:

  • A user can be in multiple teams
  • Each team has access only to their projects
  • Each project can have multiple tasks (which can be accessed only by the team members)

Right now:

  • I have three separate collections - Teams, Projects and Tasks
  • Teams collection stores the team name and members array with ID’s
  • Projects store project data and the teamID to which it belongs
  • Tasks store task data and the project to which it belongs

For projects my current setup is something like this:

// Permissions check
hasTeamAccess = function(teamId,userId) {
  return Teams.findOne({_id:teamId,members:userId}) === undefined ? false : true;

// Projects publications
Meteor.publish('projects', function(teamId) {
   if(this.userId && hasTeamAccess(teamId,this.userId)){
      return Projects.find({team:teamId});
   } else {

// Projects route
Router.route('/routetoteamprojects/:id', {
   template: 'projects',
   waitOn: function() {
      return [
   data: function() {
      return {
         projects: Projects.find({}),
         team: Teams.findOne(

And that’s basically where I’m stuck :confused: What is the most elegant way to go further? Do I need to go in deeper permissions check all the way up all like:

hasProjectAccess = function(projectId,userId) {
   var project = Projects.findOne({_id:projectId);
   return hasTeamAccess(project.teamId,userId));

hasTaskAccess = function(taskId,userId) {
   var task = Projects.findOne({_id:taskId);

      var project = Projects.findOne({_id:task.projectId);
      return hasTeamAccess(project.teamId,userId));

hasTaskCommentAccess = function(taskId,userId) {
   var comment = Comments.findOne({_id:taskId);
      var task = Comments.findOne({_id:comment.taskId);
         var project = Projects.findOne({_id:task.projectId);
         return hasTeamAccess(project.teamId,userId));

And so on. Or are there more elegant ways to do that? What are your suggestions?