Tidy up extended operator check

This commit is contained in:
Raymond Feng 2018-10-14 09:27:46 -07:00
parent f2e718639a
commit a761e0d114
2 changed files with 55 additions and 29 deletions

View File

@ -1477,6 +1477,7 @@ DataAccessObject._getSetting = function(key) {
}; };
var operators = { var operators = {
eq: '=',
gt: '>', gt: '>',
gte: '>=', gte: '>=',
lt: '<', lt: '<',
@ -1818,6 +1819,7 @@ DataAccessObject._coerce = function(where, options) {
// NOOP when not coercable into an array. // NOOP when not coercable into an array.
} }
var allowExtendedOperators = self._allowExtendedOperators(options);
// Coerce the array items // Coerce the array items
if (Array.isArray(val)) { if (Array.isArray(val)) {
for (var i = 0; i < val.length; i++) { for (var i = 0; i < val.length; i++) {
@ -1829,7 +1831,6 @@ DataAccessObject._coerce = function(where, options) {
} }
} else { } else {
if (val != null) { if (val != null) {
var allowExtendedOperators = self._allowExtendedOperators(options);
if (operator === null && val instanceof RegExp) { if (operator === null && val instanceof RegExp) {
// Normalize {name: /A/} to {name: {regexp: /A/}} // Normalize {name: /A/} to {name: {regexp: /A/}}
operator = 'regexp'; operator = 'regexp';
@ -1841,12 +1842,28 @@ DataAccessObject._coerce = function(where, options) {
} else if (allowExtendedOperators && typeof val === 'object') { } else if (allowExtendedOperators && typeof val === 'object') {
// Do not coerce object values when extended operators are allowed // Do not coerce object values when extended operators are allowed
} else { } else {
if (!allowExtendedOperators) {
var extendedOperators = Object.keys(val).filter(function(k) {
return k[0] === '$';
});
if (extendedOperators.length) {
const msg = g.f('Operators "' + extendedOperators.join(', ') + '" are not allowed in query');
const err = new Error(msg);
err.code = 'OPERATOR_NOT_ALLOWED_IN_QUERY';
err.statusCode = 400;
err.details = {
operators: extendedOperators,
where: where,
};
throw err;
}
}
val = DataType(val); val = DataType(val);
} }
} }
} }
// Rebuild {property: {operator: value}} // Rebuild {property: {operator: value}}
if (operator) { if (operator && operator !== 'eq') {
var value = {}; var value = {};
value[operator] = val; value[operator] = val;
if (exp.options) { if (exp.options) {

View File

@ -67,50 +67,59 @@ describe('allowExtendedOperators', () => {
} }
} }
function assertOperatorNotAllowed(err) {
should.exist(err);
err.message.should.match(/Operators "\$exists" are not allowed in query/);
err.code.should.equal('OPERATOR_NOT_ALLOWED_IN_QUERY');
err.statusCode.should.equal(400);
err.details.should.have.property('operators');
err.details.should.have.property('where');
}
describe('dataSource.settings.allowExtendedOperators', () => { describe('dataSource.settings.allowExtendedOperators', () => {
context('DAO.find()', () => { context('DAO.find()', () => {
it('converts extended operators to string value by default', () => { it('reports invalid operator by default', () => {
const TestModel = createTestModel(); const TestModel = createTestModel();
return TestModel.find(extendedQuery()).then((results) => { return TestModel.find(extendedQuery()).catch(err => {
should(results[0].value).eql('[object Object]'); assertOperatorNotAllowed(err);
}); });
}); });
it('preserves extended operators with allowExtendedOperators set', () => { it('preserves extended operators with allowExtendedOperators set', () => {
const TestModel = createTestModel({allowExtendedOperators: true}); const TestModel = createTestModel({allowExtendedOperators: true});
return TestModel.find(extendedQuery()).then((results) => { return TestModel.find(extendedQuery()).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });
it('`Model.settings.allowExtendedOperators` override data source settings - ' + it('`Model.settings.allowExtendedOperators` override data source settings - ' +
'converts extended operators', () => { 'reports invalid operator', () => {
const TestModel = createTestModel({allowExtendedOperators: true}, {allowExtendedOperators: false}); const TestModel = createTestModel({allowExtendedOperators: true}, {allowExtendedOperators: false});
return TestModel.find(extendedQuery()).then((results) => { return TestModel.find(extendedQuery()).catch(err => {
should(results[0].value).eql('[object Object]'); assertOperatorNotAllowed(err);
}); });
}); });
it('`Model.settings.allowExtendedOperators` override data source settings - ' + it('`Model.settings.allowExtendedOperators` override data source settings - ' +
'preserves extended operators', () => { 'preserves extended operators', () => {
const TestModel = createTestModel({allowExtendedOperators: false}, {allowExtendedOperators: true}); const TestModel = createTestModel({allowExtendedOperators: false}, {allowExtendedOperators: true});
return TestModel.find(extendedQuery()).then((results) => { return TestModel.find(extendedQuery()).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });
it('`options.allowExtendedOperators` override data source settings - ' + it('`options.allowExtendedOperators` override data source settings - ' +
'converts extended operators', () => { 'reports invalid operator', () => {
const TestModel = createTestModel({allowExtendedOperators: true}); const TestModel = createTestModel({allowExtendedOperators: true});
return TestModel.find(extendedQuery(), {allowExtendedOperators: false}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: false}).catch(err => {
should(results[0].value).eql('[object Object]'); assertOperatorNotAllowed(err);
}); });
}); });
it('`options.allowExtendedOperators` override data source settings - ' + it('`options.allowExtendedOperators` override data source settings - ' +
'preserves extended operators', () => { 'preserves extended operators', () => {
const TestModel = createTestModel({allowExtendedOperators: false}); const TestModel = createTestModel({allowExtendedOperators: false});
return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });
@ -168,37 +177,37 @@ describe('allowExtendedOperators', () => {
context('DAO.find()', () => { context('DAO.find()', () => {
it('preserves extended operators with allowExtendedOperators set', () => { it('preserves extended operators with allowExtendedOperators set', () => {
const TestModel = createTestModel({}, {allowExtendedOperators: true}); const TestModel = createTestModel({}, {allowExtendedOperators: true});
return TestModel.find(extendedQuery()).then((results) => { return TestModel.find(extendedQuery()).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });
it('`dataSource.settings.allowExtendedOperators` honor Model settings - ' + it('`dataSource.settings.allowExtendedOperators` honor Model settings - ' +
'converts extended operators', () => { 'reports invalid operator', () => {
const TestModel = createTestModel({allowExtendedOperators: true}, {allowExtendedOperators: false}); const TestModel = createTestModel({allowExtendedOperators: true}, {allowExtendedOperators: false});
return TestModel.find(extendedQuery()).then((results) => { return TestModel.find(extendedQuery()).catch(err => {
should(results[0].value).eql('[object Object]'); assertOperatorNotAllowed(err);
}); });
}); });
it('`dataSource.settings.allowExtendedOperators` honor Model settings - ' + it('`dataSource.settings.allowExtendedOperators` honor Model settings - ' +
'preserves extended operators', () => { 'preserves extended operators', () => {
const TestModel = createTestModel({allowExtendedOperators: false}, {allowExtendedOperators: true}); const TestModel = createTestModel({allowExtendedOperators: false}, {allowExtendedOperators: true});
return TestModel.find(extendedQuery()).then((results) => { return TestModel.find(extendedQuery()).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });
it('`options.allowExtendedOperators` override Model settings - converts extended operators', () => { it('`options.allowExtendedOperators` override Model settings - converts extended operators', () => {
const TestModel = createTestModel({allowExtendedOperators: true}); const TestModel = createTestModel({allowExtendedOperators: true});
return TestModel.find(extendedQuery(), {allowExtendedOperators: false}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: false}).catch(err => {
should(results[0].value).eql('[object Object]'); assertOperatorNotAllowed(err);
}); });
}); });
it('`options.allowExtendedOperators` Model settings - preserves extended operators', () => { it('`options.allowExtendedOperators` Model settings - preserves extended operators', () => {
const TestModel = createTestModel({allowExtendedOperators: false}); const TestModel = createTestModel({allowExtendedOperators: false});
return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });
@ -255,7 +264,7 @@ describe('allowExtendedOperators', () => {
context('DAO.find()', () => { context('DAO.find()', () => {
it('preserves extended operators with allowExtendedOperators set', () => { it('preserves extended operators with allowExtendedOperators set', () => {
const TestModel = createTestModel(); const TestModel = createTestModel();
return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });
@ -263,15 +272,15 @@ describe('allowExtendedOperators', () => {
it('`dataSource.settings.allowExtendedOperators` honor options settings - ' + it('`dataSource.settings.allowExtendedOperators` honor options settings - ' +
'converts extended operators', () => { 'converts extended operators', () => {
const TestModel = createTestModel({allowExtendedOperators: true}); const TestModel = createTestModel({allowExtendedOperators: true});
return TestModel.find(extendedQuery(), {allowExtendedOperators: false}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: false}).catch(err => {
should(results[0].value).eql('[object Object]'); assertOperatorNotAllowed(err);
}); });
}); });
it('`dataSource.settings.allowExtendedOperators` honor options settings - ' + it('`dataSource.settings.allowExtendedOperators` honor options settings - ' +
'preserves extended operators', () => { 'preserves extended operators', () => {
const TestModel = createTestModel({allowExtendedOperators: false}); const TestModel = createTestModel({allowExtendedOperators: false});
return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });
@ -279,15 +288,15 @@ describe('allowExtendedOperators', () => {
it('`Model.settings.allowExtendedOperators` honor options settings - ' + it('`Model.settings.allowExtendedOperators` honor options settings - ' +
'converts extended operators', () => { 'converts extended operators', () => {
const TestModel = createTestModel({}, {allowExtendedOperators: true}); const TestModel = createTestModel({}, {allowExtendedOperators: true});
return TestModel.find(extendedQuery(), {allowExtendedOperators: false}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: false}).catch(err => {
should(results[0].value).eql('[object Object]'); assertOperatorNotAllowed(err);
}); });
}); });
it('`Model.settings.allowExtendedOperators` honor options settings - ' + it('`Model.settings.allowExtendedOperators` honor options settings - ' +
'preserves extended operators', () => { 'preserves extended operators', () => {
const TestModel = createTestModel({}, {allowExtendedOperators: false}); const TestModel = createTestModel({}, {allowExtendedOperators: false});
return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then((results) => { return TestModel.find(extendedQuery(), {allowExtendedOperators: true}).then(results => {
should(results[0].value).eql({$exists: true}); should(results[0].value).eql({$exists: true});
}); });
}); });