Patch #35312 ยป 0001-Gracefully-handle-invalid-query-parameters-for-custo.patch
| app/controllers/application_controller.rb | ||
|---|---|---|
| 725 | 725 |
render_error l(:error_query_statement_invalid) |
| 726 | 726 |
end |
| 727 | 727 | |
| 728 |
def query_error(exception) |
|
| 729 |
Rails.logger.debug "#{exception.class.name}: #{exception.message}"
|
|
| 730 |
Rails.logger.debug " #{exception.backtrace.join("\n ")}"
|
|
| 731 | ||
| 732 |
render_404 |
|
| 733 |
end |
|
| 734 | ||
| 728 | 735 |
# Renders a 204 response for successful updates or deletions via the API |
| 729 | 736 |
def render_api_ok |
| 730 | 737 |
render_api_head :no_content |
| app/controllers/issues_controller.rb | ||
|---|---|---|
| 29 | 29 |
accept_api_auth :index, :show, :create, :update, :destroy |
| 30 | 30 | |
| 31 | 31 |
rescue_from Query::StatementInvalid, :with => :query_statement_invalid |
| 32 |
rescue_from Query::QueryError, :with => :query_error |
|
| 32 | 33 | |
| 33 | 34 |
helper :journals |
| 34 | 35 |
helper :projects |
| ... | ... | |
| 470 | 471 | |
| 471 | 472 |
private |
| 472 | 473 | |
| 474 |
def query_error(exception) |
|
| 475 |
session.delete(:issue_query) |
|
| 476 |
super |
|
| 477 |
end |
|
| 478 | ||
| 473 | 479 |
def retrieve_previous_and_next_issue_ids |
| 474 | 480 |
if params[:prev_issue_id].present? || params[:next_issue_id].present? |
| 475 | 481 |
@prev_issue_id = params[:prev_issue_id].presence.try(:to_i) |
| app/controllers/timelog_controller.rb | ||
|---|---|---|
| 32 | 32 |
accept_api_auth :index, :show, :create, :update, :destroy |
| 33 | 33 | |
| 34 | 34 |
rescue_from Query::StatementInvalid, :with => :query_statement_invalid |
| 35 |
rescue_from Query::QueryError, :with => :query_error |
|
| 35 | 36 | |
| 36 | 37 |
helper :issues |
| 37 | 38 |
include TimelogHelper |
| ... | ... | |
| 303 | 304 |
def retrieve_time_entry_query |
| 304 | 305 |
retrieve_query(TimeEntryQuery, false, :defaults => @default_columns_names) |
| 305 | 306 |
end |
| 307 | ||
| 308 |
def query_error(exception) |
|
| 309 |
session.delete(:time_entry_query) |
|
| 310 |
super |
|
| 311 |
end |
|
| 306 | 312 |
end |
| app/models/query.rb | ||
|---|---|---|
| 239 | 239 |
class StatementInvalid < ::ActiveRecord::StatementInvalid |
| 240 | 240 |
end |
| 241 | 241 | |
| 242 |
class QueryError < StandardError |
|
| 243 |
end |
|
| 244 | ||
| 242 | 245 |
include Redmine::SubclassFactory |
| 243 | 246 | |
| 244 | 247 |
VISIBILITY_PRIVATE = 0 |
| ... | ... | |
| 1143 | 1146 |
assoc = $1 |
| 1144 | 1147 |
customized_key = "#{assoc}_id"
|
| 1145 | 1148 |
customized_class = queried_class.reflect_on_association(assoc.to_sym).klass.base_class rescue nil |
| 1146 |
raise "Unknown #{queried_class.name} association #{assoc}" unless customized_class
|
|
| 1149 |
raise QueryError, "Unknown #{queried_class.name} association #{assoc}" unless customized_class
|
|
| 1147 | 1150 |
end |
| 1148 | 1151 |
where = sql_for_field(field, operator, value, db_table, db_field, true) |
| 1149 | 1152 |
if /[<>]/.match?(operator) |
| ... | ... | |
| 1420 | 1423 |
when "$" |
| 1421 | 1424 |
sql = sql_contains("#{db_table}.#{db_field}", value.first, :ends_with => true)
|
| 1422 | 1425 |
else |
| 1423 |
raise "Unknown query operator #{operator}"
|
|
| 1426 |
raise QueryError, "Unknown query operator #{operator}"
|
|
| 1424 | 1427 |
end |
| 1425 | 1428 | |
| 1426 | 1429 |
return sql |
| test/integration/issues_test.rb | ||
|---|---|---|
| 322 | 322 |
assert_response 404 |
| 323 | 323 |
end |
| 324 | 324 |
end |
| 325 | ||
| 326 |
def test_invalid_operators_should_render_404 |
|
| 327 |
get '/projects/ecookbook/issues', :params => {
|
|
| 328 |
'set_filter' => '1', |
|
| 329 |
'f' => ['status_id', 'cf_9'], |
|
| 330 |
'op' => {'status_id' => 'o', 'cf_9' => '=6546546546'},
|
|
| 331 |
'v' => {'cf_9' => ['2021-05-25']}
|
|
| 332 |
} |
|
| 333 | ||
| 334 |
assert_response 404 |
|
| 335 |
end |
|
| 325 | 336 |
end |