Home

Awesome

Roles

The most advanced roles package for meteor.

This roles package introduces a new way of thinking about roles. It makes you think first about actions and then define the different responses for each role to that action and makes it very easy to add more roles later.

Project sponsored by Orion Hosting - Hosting for Meteor

Installing

meteor add nicolaslopezj:roles

Basic use

You can use roles as a normal roles package

Attach roles to users

Only on server

To add roles to a user.

Roles.addUserToRoles(userId, roles)

To set roles.

Roles.setUserRoles(userId, roles)

To remove roles from a user

Roles.removeUserFromRoles(userId, roles)

Check if a user has a role

Roles.userHasRole(userId, role)

Users collection helpers

Roles also attach helpers to the Meteor.users collection.

Get user roles

var user = Meteor.user();
var roles = user.roles;

Check if a user has a role

var user = Meteor.user();
var hasRole = user.hasRole();

Advanced features

Roles allows you to define actions and have different responses for each role on that action.

Creating a role

If you use Roles as the basic way this is not necessary, but if you want to use actions, this is needed.

myRole = new Roles.Role(name)

Adding rules

Now, to set responses of a role on an action

Allow

myRole.allow(action, func)

Deny

myRole.deny(action, func)

Check permissions

Now that we have our allow/deny rules we want to check if the user has permissions. Note that a user can have more than one role, so Roles will check every action. If a role doesn't have allow/deny rules for an action they won't be considered.

Check allow

To check if a user is allowed to perform an action. Roles will check all the roles the user has and if at least one role return true on an action, this function will return true.

Roles.allow(userId, action, [extra])

Check deny

To check if a user is denied to perform an action. Roles will check all the roles the user has and if at least one role return true on an action, this function will return true.

Roles.deny(userId, action, [extra])

Check combined

This function will return true if the user is allowed and not denied to perform an action.

Roles.userHasPermission(userId, action, [extra])

To throw an error if the user doesn't have permission (useful for methods)

Roles.checkPermission(userId, action, [extra])

GraphQL Integration

To check a permission in GraphQL resolvers you can use the @Roles.graphQLAction decorator

Example:

import {Roles} from 'meteor/nicolaslopezj:roles'

const role = new Roles.Role('role')

role.allow('viewPostStats', function (post, params) {
  return post.createdBy === this.userId
})

// Resolvers
{
  Post: {
    @Roles.action('viewPostStats')
    stats (post, params, context) {
      return postStats
    }
  }
}

Debug

Set Roles.debug = true; log details.

Example

We will create a collection and create an action to update it.

// We create the collection
Posts = new Mongo.Collection('posts');

// Use the action
Posts.allow({
  update: function (userId, doc, fields, modifier) {
    return Roles.allow(userId, 'posts.update', userId, doc, fields, modifier);
  },
});
Posts.deny({
  update: function (userId, doc, fields, modifier) {
    return Roles.deny(userId, 'posts.update', userId, doc, fields, modifier);
  },
});

// Create a new role
EditorRole = new Roles.Role('editor');

// Set the allow/deny rules
EditorRole.allow('posts.update', function(userId, doc, fields, modifier) {
  return doc.userId === userId; // Will be allowed to edit his own posts
})
EditorRole.deny('posts.update', function(userId, doc, fields, modifier) {
  return !_.contains(fields, 'userId') // Can't update userId field.
})

Now, we will create a publication only for editors.


// Register the action
Roles.registerAction('posts.subscribeToMyPosts');

// Create the publication
if (Meteor.isServer) {
  Meteor.publish('myPosts', function () {
    // Roles.userHasPermission checks allow and deny rules
    if (!Roles.userHasPermission(this.userId, 'posts.subscribeToMyPosts')) {
      return [];
    } else {
      return Posts.find({ userId: this.userId })
    }
  });
}

// Now we will allow editor to subscribe to their posts
EditorRole.allow('posts.subscribeToMyPosts', true)

Helper for collections

Instead of registering and implementing the actions for a collection, there is a helper that do that for you.

myCollection.attachRoles('myCollectionRolesPrefix')

That code will register the following actions:

myCollectionRolesPrefix.insert
myCollectionRolesPrefix.update
myCollectionRolesPrefix.remove

And automatically attach the allow/deny rules to the collection.

Template Helpers

Check if the logged in has permissions over an action

<template name="myTemplate">
  {{# if userHasPermission 'myCollection.insert' }}
    <h1>Insert a document</h1>
  {{ else }}
    <p>You don't have permissions!</p>
  {{/ if }}
</template>

Check if roles are ready

<template name="myTemplate">
  {{# if rolesIsReady }}
    <p>Roles are loaded</p>
  {{ else }}
    <p>We don't know if you have permissions yet...</p>
  {{/ if }}
</template>

Version 2.0 Breaking Changes

Now roles are saved in the users collection. You need to migrate the db to update. The api is the same.

To migrate run:

Meteor.call('nicolaslopezj_roles_migrate');