all files / express-stormpath/lib/middleware/ groups-required.js

92.5% Statements 37/40
86.36% Branches 19/22
100% Functions 11/11
92.5% Lines 37/40
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                                                                                                                           
'use strict';
 
var helpers = require('../helpers');
 
/**
 * Assert that a user is a member of one or more groups before allowing the user
 * to continue. If the user is not logged in, they will be redirected to the
 * login page. If the user does not meet the group requirements, they will be
 * shown an unauthorized page letting them know they do not have the required
 * permissions.
 *
 * @param {String[]} groups - List of groups to assert membership for. Groups
 *   must be specified by group name.
 * @param {Boolean} [all=true] - Whether membership is required in one group or all.
 *
 * @returns {Function} Returns an express middleware which asserts a user's
 *   group membership, and only allows the user to continue if the assertions
 *   are true.
 */
module.exports = function (groups, all) {
  all = all === false ? false : true;
 
  return function (req, res, next) {
    var config = req.app.get('stormpathConfig');
    var logger = req.app.get('stormpathLogger');
 
    function redirectToLoginPage() {
      var url = config.web.login.uri + '?next=' + encodeURIComponent(req.originalUrl);
      return res.redirect(302, url);
    }
 
    function isUserInGroups(callback) {
      var isInGroup = false;
      var done = groups.length;
 
      req.user.getGroups(function (err, userGroups) {
        Iif (err) {
          logger.info('Could not fetch user ' + req.user.email + '\'s groups.');
          return callback(null, false);
        }
 
        // Iterate through each group on the user's account, checking to see
        // whether or not it's one of the required groups.
        userGroups.each(
          function (group, iterateNext) {
            Eif (groups.indexOf(group.name) > -1) {
              if (!all || --done === 0) {
                isInGroup = true;
              }
            }
            iterateNext();
          },
          function () {
            callback(null, isInGroup);
          }
        );
      });
    }
 
    function handleJsonRequest() {
      if (!req.user) {
        return helpers.writeJsonError(res, new Error('You are not authenticated. Please log in to access this resource.'), 401);
      }
 
      isUserInGroups(function (err, isInGroup) {
        Iif (err) {
          return helpers.writeJsonError(res, new Error('An internal error occurred. Please contact support.'), 500);
        }
 
        if (!isInGroup) {
          return helpers.writeJsonError(res, new Error('You do not have sufficient permissions to access this resource.'), 403);
        }
 
        next();
      });
    }
 
    function handleTextHtmlRequest() {
      if (!req.user) {
        return redirectToLoginPage();
      }
 
      isUserInGroups(function (err, isInGroup) {
        if (err || !isInGroup) {
          res.status(403);
          return helpers.render(req, res, 'unauthorized');
        }
 
        next();
      });
    }
 
    helpers.handleAcceptRequest(req, res, {
      'text/html': handleTextHtmlRequest,
      'application/json': handleJsonRequest
    }, handleTextHtmlRequest);
  };
};