项目作者: jalik

项目描述 :
A roles and permissions security layer for Meteor
高级语言: JavaScript
项目地址: git://github.com/jalik/meteor-jalik-roles.git
创建时间: 2015-06-30T09:19:00Z
项目社区:https://github.com/jalik/meteor-jalik-roles

开源协议:MIT License

下载


jalik:roles

This package adds a simple and flexible permissions system that allows you to control what users can do or cannot do in your Meteor apps.
The code is well tested with the mocha testing framework.

Donate

Installation

To install the package, execute this command in the root of your project :

  1. meteor add jalik:roles

If later you want to remove the package :

  1. meteor remove jalik:roles

Creating roles

You first need to define the roles of your app.
A role can be assigned to one or more users, but a user can only have one role.

Create the default roles when the app starts.
The roles collection is accessible via Meteor.roles which is a Mongo.Collection object.

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. if (Meteor.isServer) {
  4. if (Meteor.roles.find({}).count() === 0) {
  5. // Define administrator role
  6. Meteor.roles.insert({
  7. name: "Administrator",
  8. permissions: ['administrate']
  9. });
  10. // Define member role
  11. Meteor.roles.insert({
  12. name: "Member",
  13. permissions: ['vote', 'comment']
  14. });
  15. }
  16. }

Note that by default, all operations (insert, update, remove) on the roles collection are not allowed on the client.
If you want to interact with the collection, create your own Meteor.methods or set permissions with Meteor.roles.allow() or Meteor.roles.deny().

Adding permissions to a role

To add one or more permissions to a role, use Roles.addRolePerms(permission, roleId).

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. if (Meteor.isServer) {
  4. let role = Meteor.roles.findOne({name: "Administrator"});
  5. Roles.addRolePerms('administrate', role._id);
  6. Roles.addRolePerms(['create', 'delete'], role._id);
  7. }

Removing permissions from a role

To remove one or more permissions from a role, use Roles.removeRolePerms(permission, roleId).

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. if (Meteor.isServer) {
  4. let role = Meteor.roles.findOne({name: "Administrator"});
  5. Roles.removeRolePerms('administrate', role._id);
  6. Roles.removeRolePerms(['create', 'delete'], role._id);
  7. }

Getting permissions of a role

To get all permissions of a role, use Roles.getRolePerms(roleId).

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. if (Meteor.isServer) {
  4. let role = Meteor.roles.findOne({name: "Administrator"});
  5. let perms = Roles.getRolePerms(role._id);
  6. console.log(perms);
  7. }

Assigning a role to a user

To assign a role, use the Roles.setUserRole(userId, roleId) method.
The role will be stored on the user object, in the roleId attribute.

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. if (Meteor.isServer) {
  4. let user = Meteor.users.findOne({name: "karl"});
  5. let role = Meteor.roles.findOne({name: "Administrator"});
  6. // Set user's role
  7. Roles.setUserRole(user._id, role._id);
  8. }

Removing a role from a user

To remove a role from a user, use the Roles.setUserRole(userId, null) method.

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. if (Meteor.isServer) {
  4. let user = Meteor.users.findOne({name: "karl"});
  5. // Remove user's role by setting null
  6. Roles.setUserRole(user._id, null);
  7. }

Getting the role of a user

To get the role of a user, call the Roles.getUserRole(userId) or Roles.getUserRoleId(userId).
On the client, there you can use Meteor.role() or Meteor.roleId().

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. if (Meteor.isClient) {
  4. // Get the current role ID
  5. let roleId = Meteor.roleId();
  6. // Get the current role object
  7. let role = Meteor.role();
  8. }
  9. if (Meteor.isServer) {
  10. let user = Meteor.users.findOne({name: "karl"});
  11. // Get the role ID of this user
  12. let roleId = Roles.getUserRoleId(user._id);
  13. // Get the role of this user
  14. let role = Roles.getUserRole(user._id);
  15. }

NOTE : on the client, you should make sure that roles are loaded via subscriptions.

Checking permissions

To check if a user has one or more permissions, use Roles.userCan(permission, userId).
You can do the same with a role using the Roles.roleCan(permission, userId).

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. if (Meteor.isClient) {
  4. // do stuff if the current user can comment
  5. if (Roles.userCan('comment')) {
  6. }
  7. // equivalent to above
  8. if (Roles.userCan('comment', Meteor.userId())) {
  9. }
  10. // do stuff if the current user has all this permissions, not only one
  11. if (Roles.userCan(['edit', 'delete'])) {
  12. }
  13. }
  14. if (Meteor.isServer) {
  15. let user = Meteor.users.findOne({name: "karl"});
  16. let role = Meteor.roles.findOne({name: "Member"});
  17. // userId is required on server
  18. if (Roles.userCan('comment', user._id)) {
  19. }
  20. // do stuff if the user has all this permissions
  21. if (Roles.userCan(['edit', 'delete'], user._id)) {
  22. }
  23. // do stuff if the role can comment
  24. if (Roles.roleCan('comment', role._id)) {
  25. }
  26. }

You can throw an error if the role or the user does not have the permissions.

  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. let user = Meteor.users.findOne({name: "karl"});
  4. let role = Meteor.roles.findOne({name: "Member"});
  5. // Throw a 'forbidden' error if the checks fail
  6. Roles.checkUserPerms('send_comment', user._id);
  7. Roles.checkRolePerms('comment', role._id);
  8. // If the user cannot edit, the code below won't be reached
  9. console.log('sending comment...');

Publishing roles

Do not forget to publish/subscribe to the roles collection to make them accessible on clients.
You can create your own publications or use the package’s default publications.

  1. import {Roles} from 'meteor/jalik:roles';
  2. // Creates the 'role' publication
  3. Roles.publishRole();
  4. // Creates the 'roles' publication
  5. Roles.publishRoles();
  6. // Creates the 'userRole' publication
  7. // This one is important if you want to auto-subscribe to the current user's role
  8. // It can be used in combination of the Roles.autoLoadUserRole() method
  9. Roles.publishUserRole();
  1. import {Meteor} from 'meteor/meteor';
  2. import {Roles} from 'meteor/jalik:roles';
  3. // Subscribe to the publication you need on the client
  4. Meteor.startup(function() {
  5. // Load a single role
  6. Meteor.subscribe('role', roleId);
  7. // Load all roles with the "delete" permission
  8. Meteor.subscribe('roles', {permissions: {$in: ['delete']}}, {sort: {name: 1}});
  9. // Load the role of the current user (manually)
  10. Meteor.subscribe('userRole');
  11. // Automatically subscribe to the role of the current user
  12. // re-subscribe if user change or if role change.
  13. Roles.autoLoadUserRole();
  14. });

Adding template helpers

To add blaze template helpers, call the Roles.addBlazeHelpers() method, which will execute the code below :

  1. Template.registerHelper('userCan', function (permissions) {
  2. return Roles.userCan(permissions);
  3. });

After what the following helper will be available in your templates.

  1. {{#if userCan 'comment'}}
  2. {{> commentForm}}
  3. {{/if}}

Changelog

v0.2.2

  • Removes templating dependency to improve compatibility with non-blaze applications

v0.2.1

  • Fixes this scope in Roles.addBlazeHelpers()

v0.2.0

  • Uses ES6 module import and export syntax
  • Adds Roles.addBlazeHelpers() to manually add a userCan template helper
  • Adds Roles.addRolePerms(permission, roleId) to add permission to a role
  • Adds Roles.autoLoadUserRole() to load user’s role automatically on the client
  • Adds Roles.getRolePerms(roleId) to get the permissions of a role
  • Adds Roles.getUserRoleId(userId) to get the role ID of a user
  • Adds Roles.publishRole() on the server to publish a single role
  • Adds Roles.publishRoles() on the server to publish the roles collection
  • Adds Roles.publishUserRole() on the server to publish the current user’s role
  • Adds Roles.removeRolePerms(permission, roleId) to remove permission from a role
  • Adds Roles.roleExists(roleId) to check if a role exists
  • Adds Roles.setRolePerms(permissions, roleId) to replace permissions of a role
  • Adds unit tests to eliminate bugs
  • Removes automatic declaration of the userCan template helper
  • Modifies Roles.getUserRole(userId) to return the role object instead of the role ID

License

This project is released under the MIT License.