Skip to content

Commit

Permalink
odata-filter: handle unsupported functions (#1236)
Browse files Browse the repository at this point in the history
  • Loading branch information
alxndrsn authored Oct 30, 2024
1 parent 1090748 commit 8b9db34
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 4 deletions.
13 changes: 9 additions & 4 deletions lib/data/odata-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ const odataFilter = (expr, odataToColumnMap) => {
// I don't want to pass it to all of them.

const extractFunctions = ['year', 'month', 'day', 'hour', 'minute', 'second'];
const methodCall = (fn, params) => {
const methodCall = (node) => {
// n.b. odata-v4-parser appears to already validate function name and arity.
const fn = node.value.method;
const lowerName = fn.toLowerCase();
if (extractFunctions.includes(lowerName))
const params = node.value.parameters;
if (extractFunctions.includes(lowerName)) {
return sql`extract(${raw(lowerName)} from ${op(params[0])})`; // eslint-disable-line no-use-before-define
else if (fn === 'now')
} else if (fn === 'now') {
return sql`now()`;
} else {
throw Problem.internal.unsupportedODataExpression({ at: node.position, type: node.type, text: node.raw });
}
};
const binaryOp = (left, right, operator) =>
// always use parens to ensure the original AST op precedence.
Expand All @@ -51,7 +56,7 @@ const odataFilter = (expr, odataToColumnMap) => {
: (/^'.*'$/.test(node.raw)) ? node.raw.slice(1, node.raw.length - 1)
: node.raw; // eslint-disable-line indent
} else if (node.type === 'MethodCallExpression') {
return methodCall(node.value.method, node.value.parameters);
return methodCall(node);
} else if (node.type === 'EqualsExpression') {
return binaryOp(node.value.left, node.value.right, 'is not distinct from');
} else if (node.type === 'NotEqualsExpression') {
Expand Down
8 changes: 8 additions & 0 deletions test/assertions.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,14 @@ should.Assertion.add('FormAttachment', function() {
if (this.obj.updatedAt != null) this.obj.updatedAt.should.be.an.isoDate();
});

should.Assertion.add('Problem', function() {
this.params = { operator: 'to be a Problem' };

this.obj.should.be.a.Error();
Object.keys(this.obj).should.containDeep([ 'problemCode', 'problemDetails' ]);
this.obj.problemCode.should.be.a.Number();
});

should.Assertion.add('Project', function() {
this.params = { operator: 'to be a Project' };

Expand Down
9 changes: 9 additions & 0 deletions test/unit/data/odata-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ describe('OData filter query transformer', () => {
return true;
});
});

it('should reject unrecognized function names', () => {
assert.throws(() => { odataFilter('123 eq trim(\' 123 \')'); }, (err) => {
err.should.be.a.Problem();
err.problemCode.should.equal(501.4);
err.message.should.equal('The given OData filter expression uses features not supported by this server: MethodCallExpression at 7 ("trim(\' 123 \')")');
return true;
});
});
});

describe('OData orderby/sort query transformer', () => {
Expand Down

0 comments on commit 8b9db34

Please sign in to comment.