diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 6c422b98b..42aeda176 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -50,6 +50,8 @@ class SearchController < ApplicationController }, ].freeze + VALID_SORT_DIRECTIONS = %i[asc desc].freeze + def tags result = Search::Tag.search_documents(term: params[:name]) render json: { result: result } @@ -196,6 +198,14 @@ class SearchController < ApplicationController # nil differently. This is a helper method to remove any params that are # blank before passing it to Elasticsearch. def sanitize_params - params.delete_if { |_k, v| v.blank? } + params.compact_blank! + remove_invalid_sort_directions + end + + def remove_invalid_sort_directions + return unless params.key?(:sort_direction) + + direction = params[:sort_direction].downcase.to_sym + params.delete(:sort_direction) unless direction.in?(VALID_SORT_DIRECTIONS) end end diff --git a/app/queries/homepage/articles_query.rb b/app/queries/homepage/articles_query.rb index eb8f62cb7..ae2fc2537 100644 --- a/app/queries/homepage/articles_query.rb +++ b/app/queries/homepage/articles_query.rb @@ -17,7 +17,9 @@ module Homepage ].freeze DEFAULT_PER_PAGE = 60 MAX_PER_PAGE = 100 + SORT_PARAMS = %i[hotness_score public_reactions_count published_at].freeze + DEFAULT_SORT_DIRECTION = :desc def self.call(...) new(...).call @@ -44,7 +46,7 @@ module Homepage @tags = tags.presence || [] @sort_by = sort_by - @sort_direction = sort_direction + @sort_direction = sort_direction || DEFAULT_SORT_DIRECTION @page = page.to_i + 1 @per_page = [(per_page || DEFAULT_PER_PAGE).to_i, MAX_PER_PAGE].min diff --git a/app/services/search/article.rb b/app/services/search/article.rb index c32a6bbbb..b0e372f25 100644 --- a/app/services/search/article.rb +++ b/app/services/search/article.rb @@ -23,7 +23,7 @@ module Search # By skipping ordering, we rely on the custom ranking defined in the article's tsvector document return relation if term.present? && sort_by.blank? - return relation.reorder(sort_by => sort_direction) if sort_by&.to_sym == :published_at + return relation.reorder(sort_by => sort_direction) if sort_by&.to_sym == :published_at && sort_direction relation.reorder(DEFAULT_SORT_BY) end diff --git a/spec/requests/search_spec.rb b/spec/requests/search_spec.rb index 61eb2090d..6000969b8 100644 --- a/spec/requests/search_spec.rb +++ b/spec/requests/search_spec.rb @@ -157,6 +157,21 @@ RSpec.describe "Search", type: :request, proper_status: true do expect(Search::Article).to have_received(:search_documents) end + + it "nullifies invalid sort directions" do + allow(Search::Article).to receive(:search_documents).and_call_original + article = create(:article) + + get search_feed_content_path( + class_name: "Article", page: 0, per_page: 1, search_fields: article.title, + sort_by: :published_at, sort_direction: :invalid + ) + + expect(response.parsed_body["result"].first["id"]).to eq(article.id) + expect(Search::Article) + .to have_received(:search_documents) + .with(hash_including(sort_direction: nil)) + end end context "when searching for comments" do