We know that it is possible to define filters both directly, e.g. “field1 == 123” and via Filter type, e.g. Filter.eq(‘field1’,123). The latter is the recommended/preferred way. Could someone explain the benefits of using Filter? Thanks.
IMO, the 2 biggest benefits of using C3’s
Filter helper are:
Filter.eq('name', spec.searchQuery).and.intersects('id', idsArray)
vs. B :
'name == "' + spec.searchQuery + '" && intersects(id, ["' + idsArray.join('","') + '"])'
String concatenation like this is very prone to mistakes with mismatching single/double quotes, parentheses, and square brackets. And what if
idsArray is empty?
JSON.stringify(idsArray) could solve that, but we’d still have to rely on string concatenation.
Proper escaping of quote characters
In the above example, if
spec.searchQuery or any value in
idsArray contains a double quote character, the filter will be invalid and an exception will be thrown. In fact, the proper way (without any C3 helpers) to write filter B above is:
'name == "' + spec.searchQuery.replace('"', '\\"') + '" && intersects(id, ' + JSON.stringify(idsArray) + ')
'name == ' + JSON.stringify(spec.searchQuery) + ' && intersects(id, ' + JSON.stringify(idsArray) + ')
This is especially important if you use user input in filter expressions, as improper handling of quotes can be exploited in a manner similar to SQL injection (e.g.
spec.searchQuery = 'whatever" || 1 == 1 || name == "') to return unintended data*.
Filter helper makes writing non-trivial filter expressions painless, and for consistency’s sake I use it for trivial expressions too.
* Note that
fetch will only ever return data in your tag**, and it would not be a security issue per se since you should have implemented ACLs to properly protect sensitive information, but such a filter would be buggy nonetheless.
** Ignoring facaded types
Constructing good filters using Filter