-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invalid filters return unfiltered results #62
Comments
This appears to be the case because I have worked around this for now by pre-validating filter and sort params, basing the logic on how |
Hmm, I don't think @NeilSlater-Clixifix would you be kind to share a better example of what do you think |
Well the issue to me is that bad filter params (that don't work with the chosen filter library) are being silently ignored, whilst a well-behaved API should respond with a 400 error. This becomes important when considering that the filter params using Ransack are constructed, so a client application should get some kind of feedback when they have been constructed incorrectly. I think this became clear to me when writing documentation for the API (in my case using Given the param validation, then having two components that understand how Ransack has been adjusted to work within My validation methods are implemented in a Rails helper module that looks a bit like the code below. I have adjusted some things here as I also have error helpers and error renderer in my api controller base class that are no relevant to this conversation. The undefined Exception class ApiError stands in for that. module ApiListParamValidators
def api_validate_filter_and_sort(allowed_filters)
validate_filters(params[:filter], allowed_filters)
validate_sort(params[:sort], allowed_filters)
end
private
def validate_filters(filter_params, allowed_filters)
return if filter_params.blank?
unless filter_params.is_a? ActionController::Parameters
raise ApiError, 'Filter Parameter Error', 400, 'filter must be an object'
end
filter_params.each_key do |filter_command|
validate_filter_syntax(filter_command, allowed_filters)
end
end
def validate_filter_syntax(filter_command, allowed_filters)
predicates = []
to_process = filter_command.to_s.dup
while Ransack::Predicate.detect_from_string(to_process).present?
predicates << Ransack::Predicate.detect_and_strip_from_string!(to_process)
end
if predicates.blank?
raise ApiError, 'Filter Parameter Error', 400, "filter[#{filter_command}] not supported, unrecognised predicate"
end
validate_filter_attribute_names(filter_command, to_process, allowed_filters)
end
def validate_filter_attribute_names(filter_command, command_without_predicates, allowed_filters)
command_without_predicates.split(/_and_|_or_/).each do |attribute|
unless allowed_filters.include?(attribute)
raise ApiError, 'Filter Parameter Error', 400, "filter[#{filter_command}] unsupported attribute '#{attribute}'"
end
end
end
def validate_sort(sort_param, allowed_filters)
return if sort_param.blank?
unless sort_param.is_a?(String)
raise ApiError, 'Sort Parameter Error', 400, 'sort must be a string of comma-separated attributes'
end
sort_param.split(/\s*,\s*/).each do |sort_field|
attribute = sort_field.sub(/\A-/, '')
unless allowed_filters.include?(attribute)
raise ApiError, 'Sort Parameter Error', 400, "sort by unsupported attribute '#{attribute}'"
end
end
end
end I have similar business logic for validating |
Thanks @NeilSlater-Clixifix Though I'm still unsure how Btw, consider using the built-in error renderer instead of returning arbitrary error payloads. Eg.
|
Well the issue from a code design point of view is that I am using the error renderers by handling exceptions in the base controller and calling |
If there was come kind of callbacks for filter and sort params, similar to Service developer could then add validation and some kind of 40x response, and |
Nice!
Hmm, so Obviously PRs are welcome! |
Expected Behavior
When making requests with an invalid filter, I would expect to have an error raised.
This can be set on Ransack with the following configuration:
Although this does not seem to work.
Actual Behavior
When making a request with an invalid filter, the filter is not applied at all,
payments?filter[id_eqblabla]=1,2,3,4,5
will return all payments. This is far from ideal.This happens regardless of the configuration above.
JSONAPI::Filtering
configures the opposite value (not sure what value has precedence over the other):jsonapi.rb/lib/jsonapi/patches.rb
Lines 3 to 6 in a28f6d4
I have tried to change that line and see what happens as well without success.
Not sure if this is an issue with the way JSONAPI integrates with Ransack, or something not working as expected on Ransack.
Steps
Specifications
The text was updated successfully, but these errors were encountered: