UNPKG

@coding-blocks/jsonapi-server

Version:

A config driven NodeJS framework implementing json:api

105 lines (92 loc) 3.41 kB
'use strict' const filter = module.exports = { } const _ = { assign: require('lodash.assign'), isEqual: require('lodash.isequal') } const debug = require('../debugging.js') filter.action = (request, response, callback) => { const filters = request.processedFilter if (!filters) return callback() if (Array.isArray(response.data)) { for (let j = 0; j < response.data.length; j++) { if (!filter._filterKeepObject(response.data[j], filters)) { debug.filter('removed', JSON.stringify(filters), JSON.stringify(response.data[j].attributes)) response.data.splice(j, 1) j-- } } } else if (response.data instanceof Object) { if (!filter._filterKeepObject(response.data, filters)) { debug.filter('removed', JSON.stringify(filters), JSON.stringify(response.data.attributes)) return callback({ // eslint-disable-line standard/no-callback-literal status: '404', code: 'ENOTFOUND', title: 'Requested resource does not exist', detail: `There is no ${request.params.type} with id ${request.params.id} which satisfies ${request.params.filter}` }) } } return callback() } filter._filterMatches = (filterElement, attributeValue) => { if (!filterElement.operator) { return _.isEqual(attributeValue, filterElement.value) } const filterFunction = { '>': function filterGreaterThan (attrValue, filterValue) { return attrValue > filterValue }, '<': function filterLessThan (attrValue, filterValue) { return attrValue < filterValue }, '~': function filterCaseInsensitiveEqual (attrValue, filterValue) { return attrValue.toLowerCase() === filterValue.toLowerCase() }, ':': function filterCaseInsensitiveContains (attrValue, filterValue) { return attrValue.toLowerCase().indexOf(filterValue.toLowerCase()) !== -1 } }[filterElement.operator] const result = filterFunction(attributeValue, filterElement.value) return result } filter._filterKeepObject = (someObject, filters) => { for (const filterName in filters) { const whitelist = filters[filterName] if (someObject.attributes.hasOwnProperty(filterName) || (filterName === 'id')) { let attributeValue = someObject.attributes[filterName] if (filterName === 'id') attributeValue = someObject.id const attributeMatches = filter._attributesMatchesOR(attributeValue, whitelist) if (!attributeMatches) return false } else if (someObject.relationships.hasOwnProperty(filterName)) { const relationships = someObject.relationships[filterName] const relationshipMatches = filter._relationshipMatchesOR(relationships, whitelist) if (!relationshipMatches) return false } else { return false } } return true } filter._attributesMatchesOR = (attributeValue, whitelist) => { let matchOR = false whitelist.forEach(filterElement => { if (filter._filterMatches(filterElement, attributeValue)) { matchOR = true } }) return matchOR } filter._relationshipMatchesOR = (relationships, whitelist) => { let matchOR = false let data = relationships.data if (!data) return false if (!(Array.isArray(data))) data = [ data ] data = data.map(relation => relation.id) whitelist.forEach(filterElement => { if (data.indexOf(filterElement.value) !== -1) { matchOR = true } }) return matchOR }