0001-Gracefully-handle-invalid-query-parameters-for-custo.patch

Holger Just, 2021-05-25 20:04

Download (4.66 KB)

View differences:

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
326
-