improved restrictFields to work better with nested elements

This commit is contained in:
Theodor Diaconu 2016-10-26 10:28:09 +03:00
parent 8de2744e8c
commit 9b419de092
3 changed files with 94 additions and 30 deletions

View file

@ -14,42 +14,83 @@ export default function restrictFields(filters, options, restrictedFields) {
throw new Meteor.Error('invalid-parameters', 'Please specify an array of restricted fields.');
}
if (options.fields) {
options.fields = _.omit(options.fields, ...restrictedFields);
} else {
let restrictingRules = {};
_.each(restrictedFields, field => {
restrictingRules[field] = 0
});
if (restrictingRules.length) {
options.fields = _.extend({}, options.fields, restrictingRules)
}
}
if (options.fields && _.keys(options.fields).length === 0) {
_.extend(options.fields, {_id: 1});
}
if (options.sort) {
options.sort = _.omit(options.sort, ...restrictedFields);
}
cleanFilters(filters, restrictedFields);
cleanOptions(options, restrictedFields)
}
/**
* Deep cleans filters
*
* @param filters
* @param restrictedFields
*/
function cleanFilters(filters, restrictedFields) {
if (filters) {
_.each(restrictedFields, field => {
delete filters[field];
})
cleanObject(filters, restrictedFields);
}
deepFilterFieldsArray.forEach(field => {
if (filters[field]) {
filters[field].forEach(element => restrictFields(element, {}, restrictedFields));
filters[field].forEach(element => cleanFilters(element, restrictedFields));
}
});
deepFilterFieldsObject.forEach(field => {
if (filters[field]) {
restrictFields(filters[field], {}, restrictedFields);
cleanFilters(filters[field], restrictedFields);
}
});
}
/**
* Deeply cleans options
*
* @param options
* @param restrictedFields
*/
function cleanOptions(options, restrictedFields) {
if (options.fields) {
cleanObject(options.fields, restrictedFields);
if (_.keys(options.fields) === 0) {
_.extend(options.fields, {_id: 1})
}
} else {
options.fields = {_id: 1};
}
if (options.sort) {
cleanObject(options.sort, restrictedFields);
}
}
/**
* Cleans the object (not deeply)
*
* @param object
* @param restrictedFields
*/
function cleanObject(object, restrictedFields) {
_.each(object, (value, key) => {
restrictedFields.forEach((restrictedField) => {
if (matching(restrictedField, key)) {
delete object[key];
}
})
});
}
/**
* Returns true if field == subfield or if `${field}.` INCLUDED in subfield
* Example: "profile" and "profile.firstName" will be a matching field
* @param field
* @param subfield
* @returns {boolean}
*/
function matching(field, subfield) {
if (field === subfield) {
return true;
}
return subfield.slice(0, field.length + 1) === field + '.';
}

View file

@ -9,27 +9,33 @@ describe('Unit Tests', function () {
let filters = {
test: 1,
shouldRestrict: 1,
'shouldRestrict.this': 1,
shouldRestrict2: 1,
$and: [{
shouldRestrict: 1,
'shouldRestrict.this': 1,
test: 1,
}, {
test: 1,
shouldRestrict: 1
shouldRestrict: 1,
'shouldRestrict.this': 1
}],
$or: [{
$and: [{
test: 1,
shouldRestrict: 1
shouldRestrict: 1,
'shouldRestrict.this': 1
}]
}],
$nor: [{
test: 1,
shouldRestrict: 1
shouldRestrict: 1,
'shouldRestrict.this': 1
}],
$not: {
test: 1,
shouldRestrict: 1
shouldRestrict: 1,
'shouldRestrict.this': 1
}
};
@ -38,11 +44,13 @@ describe('Unit Tests', function () {
test: 1,
shouldRestrict: 1,
shouldRestrict2: 1,
'shouldRestrict.this': 1
},
fields: {
test: 1,
shouldRestrict: 1,
shouldRestrict2: 1
shouldRestrict2: 1,
'shouldRestrict.this': 1
}
};
@ -50,23 +58,34 @@ describe('Unit Tests', function () {
assert.lengthOf(_.keys(filters), 5);
assert.equal(filters.test, 1);
assert.isUndefined(filters.shouldRestrict);
assert.isUndefined(filters['shouldRestrict.this']);
assert.lengthOf(_.keys(options.sort), 1);
assert.equal(options.sort.test, 1);
assert.isUndefined(options.sort.shouldRestrict, 1);
assert.isUndefined(options.sort['shouldRestrict.this']);
assert.lengthOf(_.keys(options.fields), 1);
assert.equal(options.fields.test, 1);
assert.isUndefined(options.fields['shouldRestrict.this']);
assert.isUndefined(options.fields['shouldRestrict']);
assert.isDefined(filters.$not.test);
assert.isUndefined(filters.$not.shouldRestrict);
assert.isUndefined(filters.$not['shouldRestrict.this']);
assert.isDefined(filters.$nor[0].test);
assert.isUndefined(filters.$nor[0].shouldRestrict);
assert.isUndefined(filters.$nor[0]['shouldRestrict.this']);
assert.isDefined(filters.$and[0].test);
assert.isUndefined(filters.$and[0].shouldRestrict);
assert.isUndefined(filters.$and[0]['shouldRestrict.this']);
assert.isDefined(filters.$and[1].test);
assert.isUndefined(filters.$and[1].shouldRestrict);
assert.isUndefined(filters.$and[1]['shouldRestrict.this']);
assert.isDefined(filters.$or[0].$and[0].test);
assert.isUndefined(filters.$or[0].$and[0].shouldRestrict);
assert.isUndefined(filters.$or[0].$and[0]['shouldRestrict.this']);
});
it('Should restrict links # getLinks', function () {

View file

@ -46,6 +46,10 @@ function createNodes(root) {
root.add(fieldNode);
}
});
if (root.fieldNodes.length === 0) {
root.add(new FieldNode('_id', 1));
}
}
export default function (collection, body) {