UNPKG

fakeblock

Version:

Field-level ACL library for Node.js and NoSql document stores

181 lines (155 loc) 4.98 kB
/** * Copyright 2014 GetHuman LLC * Author: Jeff Whelpley * Date: 2/17/14 * * A few data manipulation utility functions used by fakeblock to apply * filters (both restrictive and permissive) on data given a list of fields */ var _ = require('lodash'); /** * Remove items from a list * @param list * @param itemsToRemove * @returns {Array} */ function removeItemsFromList(list, itemsToRemove) { var result = []; _.each(list, function (item) { var valid = true; for (var i = 0; i < itemsToRemove.length; i++) { // if the item match one of the items to remove don't includ it in the result list if (item.indexOf(itemsToRemove[i]) === 0) { valid = false; break; } } if (valid) { result.push(item); } }); return result; } /** * Get all items from a list that match specified items. * @param list * @param itemsToGet * @returns {Array} */ function getItemsFromList(list, itemsToGet) { var result = []; _.each(list, function (item) { for (var i = 0; i < itemsToGet.length; i++) { if (item.indexOf(itemsToGet[i]) === 0) { result.push(item); } } }); return result; } /** * Remove all specified fields from a given object based on input * of field paths. The field path must match a object field to * be removed. * @param data Data to be changed * @param fieldsToRemove An array of field paths * @returns {{}} */ function removeFieldsFromObj(data, fieldsToRemove) { _.each(fieldsToRemove, function (fieldToRemove) { // if field to remove is in the data, just remove it and go to the next one if (data[fieldToRemove]) { delete data[fieldToRemove]; return true; } var fieldParts = fieldToRemove.split('.'); var fieldPart; var dataPointer = data; var len = fieldParts.length; for (var i = 0; i < len; i++) { fieldPart = fieldParts[i]; // if the field doesn't exist, break out of the loop if (!dataPointer[fieldPart]) { break; } // if we are at the end then delete the item from the updatedData else if (i === (len - 1)) { delete dataPointer[fieldPart]; } // else move the pointer down the object tree and go to the next iteration else { dataPointer = dataPointer[fieldPart]; } } return true; }); return data; } /** * Get all fields specified from an object * @param data * @param fieldsToGet An array of fields where each field is dot notation * @returns {{}} */ function getFieldsFromObj(data, fieldsToGet) { var newObj = {}; _.each(fieldsToGet, function (fieldToGet) { // if the field to get is in the data, then just transfer it over and that is it if (data.hasOwnProperty(fieldToGet)) { newObj[fieldToGet] = data[fieldToGet]; return true; } var fieldParts = fieldToGet.split('.'); var len = fieldParts.length; var dataPointer = data; var tempPointer = newObj; var fieldPart, i; for (i = 0; i < len; i++) { fieldPart = fieldParts[i]; // if doesn't exist, then break out of loop as there is no value in data for this if (typeof dataPointer[fieldPart] === 'undefined') { break; } // else we are at the end, so copy this value to the newObj else if (i === (len - 1)) { tempPointer[fieldPart] = dataPointer[fieldPart]; } else { dataPointer = dataPointer[fieldPart]; tempPointer = tempPointer[fieldPart] = tempPointer[fieldPart] || {}; } } return true; }); return newObj; } /** * Apply the appropriate filter based on the input data * * @param data * @param restrictedFields * @param allowedFields * @returns {{}} */ function applyFilter(data, restrictedFields, allowedFields) { var filterFunc; // if string, something like a sort where each word should be a value var isString = _.isString(data); if (isString) { data = data.split(' '); } if (restrictedFields) { filterFunc = _.isArray(data) ? removeItemsFromList : removeFieldsFromObj; data = filterFunc(data, restrictedFields); } else if (allowedFields) { filterFunc = _.isArray(data) ? getItemsFromList : getFieldsFromObj; data = filterFunc(data, allowedFields); } return isString ? data[0] : data; } module.exports = { removeItemsFromList: removeItemsFromList, getItemsFromList: getItemsFromList, removeFieldsFromObj: removeFieldsFromObj, getFieldsFromObj: getFieldsFromObj, applyFilter: applyFilter };