Skip to content

Managing Roles and Permissions

Jixun Wu edited this page May 28, 2017 · 8 revisions

permissions

Creating Roles

By default, all new Users are given the registered role. There are two ways to create a new Role:

Let's say you want to create a new Role called collaborator, and assign it to User tjwebb:

  1. The same way you would create any other sails.js object:

    User.findOne({ username: 'tjwebb' })
      .then(function (user) {
        return Role.create({
          name: 'collaborator',
          users: [ user.id ]
        })
      .then(function (role) {
        console.log(role);
      })
      .catch(function (error) {
        console.error(error);
      });

    You can also use the sails.js blueprint endpoints to accomplish the same thing, e.g. GET /role/create?name=collaborator.

    Note: When using the REST endpoints, make sure you are authenticated as a user who has sufficient Permissions to create new Roles! By default, the only user allowed to do this is the admin user.

  2. Via the PermissionService helper method ’createRole’. Note that this method requires creating one or more Permission objects as part of the method call (see the 'permissions' key in the object passed into the createRole function below).

    PermissionService.createRole({ name: 'collaborator', users: 'tjwebb', 
                                   permissions: [{ model: 'mymodel', action: 'create' }, 
                                                 { model: 'myothermodel', action: 'read' }] })

Creating Permissions

Creating a Role is super easy. By default, new Roles have no Permissions. There are two ways to grant new Permissions to a Role:

Let's say you want to grant Users with the role collaborator with the ability to create and read all Project and Issue objects.

  1. Create Permission objects just like any other sails.js model, and associate it with a Role.

    Promise.bind({ }, Role.findOne({ name: 'collaborator' })
      .then(function (role) {
        this.role = role;
        return Model.find({ name: [ 'Project', 'Issue' ] });
      })
      .map(function (model) {
        return [
          Permission.create({
            model: model.id,
            action: 'create',
            role: this.role.id
          }),
          Permission.create({
            model: model.id,
            action: 'read',
            role: this.role.id
          })
        ];
      })
      .spread(function (createPermission, readPermission) {
        sails.log('new create permission', createPermission);
        sails.log('new read permission', readPermission);
      })
      .catch(sails.log.error);
  2. Use the PermissionService helper method ‘grant’.

    Promise.all([PermissionService.grant({ role: 'collaborator', model: 'Project', action: 'read'}),
                 PermissionService.grant({ role: 'collaborator', model: 'Project', action: 'create'}),
                 PermissionService.grant({ role: 'collaborator', model: 'Issue', action: 'read'}),
                 PermissionService.grant({ role: 'collaborator', model: 'Issue', action: 'create'}])
            .spread(function (projectRead, projectCreate, issueRead, issueCreate) {
                sails.log('new read Project permission', projectRead);
                sails.log('new create Project permission', projectCreate);
                sails.log('new read Issue permission', issueRead);
                sails.log('new create Issue permission', issueCreate);
            });

Revoking Permissions

Permissions are revoked simply by deleting the relevant Permission object, or by using the PermissionService helper method ‘revoke’.

Let's say we want to revoke the create Permission we just granted to the collaborator Role for Project.

Promise.bind({ }, Role.findOne({ name: 'collaborator' })
  .then(function (role) {
    this.role = role;
    return Model.findOne({ name: 'Project' });
  })
  .then(function (model) {
    return Permission.destroy({
      model: model.id,
      action: 'read',
      role: role.id,
    });
  })
  .then(function () {
    sails.log('revoked "read" from "collaborator" on "Project"');
  })
  .catch(sails.log.error);

There is also a helper method in PermissionService named ‘revoke’:

PermissionService.revoke({ model: 'project', action: 'read', role: 'collaborator', relation: 'role' })
    .then(function () {
        sails.log('revoked “read” from “collaborator” on “Project”');
    });

Role add/remove Users:

PermissionService has helpers to facilitate adding users to and removing users from a role. You can pass a single username or an array of usernames to these functions.

PermissionService.addUsersToRole('someusername', 'collaborator')
    .then(function () {
       sails.log('added “someusername” to role “collaborator”');
    });

PermissionService.removeUsersFromRole(['someusername', 'tjwebb'], 'collaborator')
    .then(function () {
        sails.log('removed “someusername” and “tjwebb” from role “collaborator”');
    });

Permission Criteria

Criteria are used to specify further conditions that must be met for a Permission to be valid. Criteria have two important fields, 'where' and 'blacklist'. The 'where' field uses waterline query syntax to specify a condition that must be true for a Permission to be valid.

For instance, a user may only have permission to update an Issue if it is a public issue (assume that Issue has a boolean field 'public'). The Criteria for this situation would look like this:

{ where: { public: true } }

This Criteria would be associated with a Permission granting the update action on the Issue model to some particular role.

The 'blacklist' field is used for attribute-level permissions. For update and create requests, it returns an error if a field in the blacklist is included in the request. For get requests, it filters the blacklisted fields from the response.

For the same Issue 'update' Permission, we could blacklist the 'public' field. This would prevent the role associated with this Permission from updating the value of the field.

To create this Permission, we can use the PermissionService helper:

PermissionService.grant({role: 'collaborator', model: 'Issue', action: 'update', 
                         criteria: { where: { public: true }, blacklist: ['public'] } })