All Projects → nicolaslopezj → Roles

nicolaslopezj / Roles

Licence: mit
The most advanced roles package for meteor

Programming Languages

javascript
184084 projects - #8 most used programming language

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)
  • userId String. The id of the user.
  • roles Array or String. The name of the roles you want to add to the user.

To set roles.

Roles.setUserRoles(userId, roles)
  • userId String. The id of the user.
  • roles Array or String. The name of the roles you want to set to the user.

To remove roles from a user

Roles.removeUserFromRoles(userId, roles)
  • userId String. The id of the user.
  • roles Array or String. The name of the roles you want to remove from the user.

Check if a user has a role

Roles.userHasRole(userId, role)
  • userId String. The id of the user.
  • role String. The name of the 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)
  • name String. The name of the new role.

Adding rules

Now, to set responses of a role on an action

Allow

myRole.allow(action, func)
  • action String. The name of the action.
  • func Function. Return true to allow the role to perform this action. You can get the user id using this.userId. To pass arguments to this function pass extra arguments when checking, example: Roles.allow(userId, action, arg1, arg2)

Deny

myRole.deny(action, func)
  • action String. The name of the action.
  • func Function. Return true to deny the role to perform this action. You can get the user id using this.userId. To pass arguments to this function pass extra arguments when checking, example: Roles.deny(userId, action, arg1, arg2)

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])
  • userId String. The id of the user.
  • action String. The name of the action.
  • [extra] Each argument that you add to this function will be passed to the allow/deny functions you defined.

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])
  • userId String. The id of the user.
  • action String. The name of the action.
  • [extra] Each argument that you add to this function will be passed to the allow/deny functions you defined.

Check combined

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

Roles.userHasPermission(userId, action, [extra])
  • userId String. The id of the user.
  • action String. The name of the action.
  • [extra] Each argument that you add to this function will be passed to the allow/deny functions you defined.

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');
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].