Skip to content

Commit b649f11

Browse files
pimped the xss hook to accept dot syntax and work on after and before hooks
1 parent 1b36d49 commit b649f11

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

server/hooks/xss.js

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
const { getByDot, setByDot, getItems, replaceItems } = require('feathers-hooks-common');
12
const sanitizeHtml = require('sanitize-html');
23
// const embedToAnchor = require('quill-url-embeds/dist/embed-to-anchor');
3-
const _ = require('lodash');
4+
const { isEmpty } = require('lodash');
45
const cheerio = require('cheerio');
56

67
const embedToAnchor = (content) => {
@@ -14,6 +15,10 @@ const embedToAnchor = (content) => {
1415
};
1516

1617
function clean (dirty) {
18+
if (!dirty) {
19+
return dirty;
20+
}
21+
1722
// Convert embeds to a-tags
1823
dirty = embedToAnchor(dirty);
1924
dirty = sanitizeHtml(dirty, {
@@ -42,7 +47,7 @@ function clean (dirty) {
4247
s: 'strike'
4348
// 'img': function (tagName, attribs) {
4449
// let src = attribs.src;
45-
// if (_.isEmpty(hook.result)) {
50+
// if (isEmpty(hook.result)) {
4651
// const config = hook.app.get('thumbor');
4752
// if (config && src.indexOf(config < 0)) {
4853
// // download image
@@ -74,26 +79,37 @@ function clean (dirty) {
7479
return dirty;
7580
}
7681

82+
// iterate through all fields and clean the values
83+
function cleanAllFields (items, fields) {
84+
if (!items) {
85+
return items;
86+
}
87+
88+
if (Array.isArray(items)) {
89+
// items is an array so fall this function for all items
90+
items.forEach((item, key) => {
91+
items[key] = cleanAllFields(items[key], fields);
92+
});
93+
} else {
94+
// clean value for all fields on the single given item
95+
fields.forEach((field) => {
96+
// get item by dot notation
97+
const value = getByDot(items, field);
98+
// set cleaned item by dot notation
99+
setByDot(items, field, clean(value));
100+
});
101+
}
102+
return items;
103+
}
104+
77105
module.exports = function (options = { fields: [] }) {
78106
return function (hook) {
79107
return new Promise(resolve => {
80-
options.fields.forEach(field => {
81-
try {
82-
if (!_.isEmpty(hook.result) && !_.isEmpty(hook.result[field])) {
83-
hook.result[field] = clean(hook.result[field], hook);
84-
} else if (!_.isEmpty(hook.result) && !_.isEmpty(hook.result.data)) {
85-
hook.result.data.forEach((result, i) => {
86-
if (!_.isEmpty(hook.result.data[i][field])) {
87-
hook.result.data[i][field] = clean(hook.result.data[i][field], hook);
88-
}
89-
});
90-
} else if (!_.isEmpty(hook.data) && !_.isEmpty(hook.data[field])) {
91-
hook.data[field] = clean(hook.data[field]);
92-
}
93-
} catch (err) {
94-
hook.app.error(err);
95-
}
96-
});
108+
const isFindOrGet = ['find', 'get'].includes(hook.method);
109+
const items = getItems(hook);
110+
if (!isEmpty(items) && !(isFindOrGet && hook.type === 'before')) {
111+
replaceItems(hook, cleanAllFields(items, options.fields));
112+
}
97113
resolve(hook);
98114
});
99115
};

0 commit comments

Comments
 (0)