CleverStack/clever-roles

View on GitHub
controllers/PermissionController.js

Summary

Maintainability
C
1 day
Test Coverage
var injector = require('injector');

module.exports = function(async, _, Controller, PermissionService) {
  var AccountController = null;

  var PermissionController = Controller.extend(
  {  
    service: PermissionService,

    route: [
      '[POST] /account/:AccountId/permission/?',
      '/account/:AccountId/permission/:id/?',
      '/account/:AccountId/permission/:id/:action/?',
      '/account/:AccountId/permissions/?',
      '/account/:AccountId/permissions/:action/?'
    ],

    autoRouting: [
      function(req, res, next) {
        return PermissionController.requiresPermission({
          all: 'Permission.$action'
        })(req, res, next);
      },

      function(req, res, next) {
        if (AccountController === null) {
          AccountController = injector.getInstance('AccountController');
        }

        AccountController.addAccountIdToRequest({
          all             : false,
          listAction      : true,
          getAction       : true,
          postAction      : true,
          putAction       : true,
          deleteAction    : true
        })(req, res, next);
      }
    ],

    /*
      PermissionController.requiresPermission('Some.permission');
      // or
      PermissionController.requiresPermission(['Some.permission', 'Another.permission']);
    */
    requiresPermission: function(requiredPermissions) {
      if (requiredPermissions instanceof Array) {
        requiredPermissions = {
          all: requiredPermissions
        }
      } else if (typeof requiredPermissions !== 'object') {
        requiredPermissions = {
          all: [requiredPermissions]
        }
      }

      return function(req, res, next) {
        var user    = req.user
          , method  = req.method.toLowerCase()
          , id      = req.params.id
          , action  = req.params.action || id;

        if (!!id && !!action && action === 'list') {
          action = 'get'
          req.params.action = 'get';
        } else if (!action && method === 'get' && /^\/.*\/(.*\/?)$/ig.test(req.url)) {
          action = 'list';
        } else if (/^[0-9a-fA-F]{24}$/.test(action) || !isNaN(action)) {
          action = 'get';
        } else {
          if (req.params.action) {
            action = req.params.action;
          } else if (method === 'get' && !id) {
            action = 'list';
          } else {
            action = method;
          }
        }

        async.waterfall(
          [

            function determinePermissions(callback) {
              var actionName = (!!action ? action : method) + 'Action'
                , permissions = [];
              
              if (typeof requiredPermissions[actionName] !== 'undefined') {
                if (requiredPermissions[actionName] !== null) {
                  if (requiredPermissions[actionName] instanceof Array) {
                    permissions = permissions.concat(requiredPermissions[actionName]);
                  } else {
                    permissions.push(requiredPermissions[actionName]);
                  }
                }
              } else if (typeof requiredPermissions.all !== 'undefined') {
                if (requiredPermissions.all !== null) {
                  permissions = requiredPermissions.all instanceof Array ? requiredPermissions.all : [requiredPermissions.all];
                }
              }

              callback(null, permissions);
            },

            function userRoleHasPermission(permissions, callback) {
              var hasPermission = true;

              if (!!permissions.length && !req.isAuthenticated()) {
                return callback('User is not authenticated!');
              }

              permissions.every(function(requiredPermission) {
                if (/^([^\$]+)\.\$action/.test(requiredPermission)) {
                  requiredPermission = RegExp.$1 + '.';

                  switch(action) {
                  
                  case 'get':
                    requiredPermission += 'view';
                    break;
                  case 'post':
                    requiredPermission += 'create';
                    break;
                  case 'put':
                    requiredPermission += 'edit';
                    break;
                  default:
                    requiredPermission += action;
                    break;
                  }
                }

                if (requiredPermission !== 'requiresLogin' && _.findWhere([].slice.call(user.Role.Permissions), { action: requiredPermission }) === undefined) {
                  callback('Logged in user does not have ' + requiredPermission + ' permission.');
                  hasPermission = false;
                  return false;
                }
                return true;
              });

              if (!!hasPermission) {
                callback(null);
              }
            }
          ],
          function(err) {
            if (err === null) {
              next();
            } else {
              console.dir(err);
              res.send(401, { statusCode: 401, message: err });
            }
          }

       );
      }
    }
  },
  {
    
  });

  return PermissionController;
}