Files
talk/middleware/payload-filter.js
T
2016-12-16 16:46:15 -07:00

75 lines
2.0 KiB
JavaScript

// The maximum depth to recurse into nested objects checking for mongoose
// objects.
const maxRecursion = 3;
/**
* Middleware to wrap the `res.json` function to ensure that we can filter the
* payload response first based on user and role.
*/
module.exports = (req, res, next) => {
/**
* Updates the original document based on filtering out for roles.
* @param {Mixed} o original object to be modified
* @param {Integer} l current level of depth in the first object
* @return {Mixed} (possibly) modified object
*/
const wrap = (o, d = 0) => {
if (d > maxRecursion) {
return o;
}
// If this is an array, we need to walk over all the object's elements.
if (Array.isArray(o)) {
// Map each of the array elements.
return o.map((ob) => wrap(ob, d + 1));
} else if (o && o.constructor && o.constructor.name === 'model') {
// The object here is definitly a mongoose model.
// Check to see if it has a `filterForUser` method.
if (typeof o.filterForUser === 'function') {
// The object here actually has the `filterForUser` function, so filter
// the object!
o = o.filterForUser(req.user);
}
} else if (typeof o === 'object') {
// Iterate over the props, find only properties owned by the object.
for (let prop in o) {
// If and only if the object owns the property do we actually pull the
// property out.
if (typeof o.hasOwnProperty === 'function' && o.hasOwnProperty(prop)) {
// Wrap the property with one more layer down.
o[prop] = wrap(o[prop], d + 1);
}
}
}
return o;
};
// Save a reference to the original json function.
const json = res.json;
// Override the original json function.
res.json = (payload) => {
// Restore the old pointer.
res.json = json;
// Send it down the pipe after we've filtered it.
res.json(wrap(payload));
};
// Now that we've overridden the `res.json`, let's hand it down.
next();
};