Roles-based authorization package for Meteor - compatible with built-in accounts package.
The example-app
directory contains a Meteor app which shows off the following features:
- Server-side publishing with authorization to secure sensitive data
- Client-side navigation with link visibility based on user permissions
- 'Sign-in required' app with up-front login page using
accounts-ui
- Client-side routing via
meteor-router
smart package
View online @ http://roles-example.meteor.com/
Run locally:
- install Meteorite
git clone https://github.com/alanning/meteor-roles.git
cd meteor-roles/example-app
mrt
- point browser to
http://localhost:3000
- User entries in the
Meteor.users
collection gain a new field namedroles
which is an array of strings corresponding to the user's roles. - A new collection
Meteor.roles
contains a global list of defined role names. - The currently logged-in user's
roles
field is automatically published under_roles_own_user_roles
. - Client javascript automatically subscribes to
_roles_own_user_roles
.
Add this smart package to your project:
- install Meteorite
mrt add roles
Here are some potential use cases:
-- Server --
Add users to roles:
var users = [
{name:"Normal User",email:"[email protected]",roles:[]},
{name:"View-Secrets User",email:"[email protected]",roles:['view-secrets']},
{name:"Manage-Users User",email:"[email protected]",roles:['manage-users']},
{name:"Admin User",email:"[email protected]",roles:['admin']}
];
_.each(users, function (user) {
var id;
id = Accounts.createUser({
email: user.email,
password: "apple1",
profile: { name: user.name }
});
if (user.roles.length > 0) {
Roles.addUsersToRoles(id, user.roles);
}
});
Check user roles before publishing sensitive data:
// server/publish.js
// Give authorized users access to sensitive data
Meteor.publish('secrets', function () {
if (Roles.userIsInRole(this.userId, ['view-secrets','admin'])) {
return Meteor.secrets.find();
} else {
// user not authorized. do not publish secrets
return;
}
});
Prevent non-authorized users from creating new users:
Accounts.validateNewUser(function (user) {
var loggedInUser = Meteor.user();
if (Roles.userIsInRole(loggedInUser, ['admin','manage-users'])) {
return true;
}
throw new Meteor.Error(403, "Not authorized to create new users");
});
-- Client --
Client javascript has access to all the same Roles functions as the server with the addition of a isInRole
handlebars helper which is automatically registered by the Roles package.
Like all Meteor applications, client-side checks are a convenience, rather than a true security implementation since Meteor bundles the same client-side code to all users. Providing the Roles functions client-side also allows for latency compensation during Meteor method calls.
NOTE: Any sensitive data needs to be controlled server-side to prevent unwanted disclosure. To be clear, Meteor sends all templates, client-side javascript, and published data to the client's browser. This is by design and is a good thing. The following example is just sugar to help improve the user experience for normal users. Those interested in seeing the 'admin_nav' template in the example below will still be able to do so by manually reading the bundled client.js
file. It won't be pretty but it is possible. But this is not a problem as long as the actual data is restricted server-side.
Online API docs found here: http://alanning.github.com/meteor-roles/
API docs generated using YUIDoc
To re-generate documentation:
- install YUIDoc
cd meteor-roles
yuidoc
To serve documentation locally:
- install YUIDoc
cd meteor-roles
yuidoc --server
- point browser at http://localhost:3000/
To run tests:
- install Meteorite
cd meteor-roles/roles
mrt
- point browser at http://localhost:3000/
NOTE: If you see an error message regarding 'roles package does not exist' that means you are trying to run 'mrt' in the wrong directory. See step 2.