From 8733975f13b4c366694b4770e062074ae03e1c97 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 17 Jun 2024 16:54:34 +0200 Subject: [PATCH] Fix being able to retrieve unusable hashtags through the API --- app/controllers/api/v1/tags_controller.rb | 2 ++ .../api/v1/timelines/tag_controller.rb | 2 +- app/lib/search_query_transformer.rb | 19 +++++++++++++++++++ app/services/statuses_search_service.rb | 8 +++++++- app/services/tag_search_service.rb | 2 +- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/v1/tags_controller.rb b/app/controllers/api/v1/tags_controller.rb index 672535a018..88cc1a9407 100644 --- a/app/controllers/api/v1/tags_controller.rb +++ b/app/controllers/api/v1/tags_controller.rb @@ -29,5 +29,7 @@ class Api::V1::TagsController < Api::BaseController return not_found unless Tag::HASHTAG_NAME_RE.match?(params[:id]) @tag = Tag.find_normalized(params[:id]) || Tag.new(name: Tag.normalize(params[:id]), display_name: params[:id]) + + not_found unless @tag.usable? end end diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 3bf8f374e1..9277921a8e 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -19,7 +19,7 @@ class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController end def load_tag - @tag = Tag.find_normalized(params[:id]) + @tag = Tag.usable.find_normalized(params[:id]) end def load_statuses diff --git a/app/lib/search_query_transformer.rb b/app/lib/search_query_transformer.rb index 927495eace..f38f5fd390 100644 --- a/app/lib/search_query_transformer.rb +++ b/app/lib/search_query_transformer.rb @@ -13,6 +13,8 @@ class SearchQueryTransformer < Parslet::Transform ).freeze class Query + attr_reader :keywords + def initialize(clauses, options = {}) raise ArgumentError if options[:current_account].nil? @@ -20,6 +22,7 @@ class SearchQueryTransformer < Parslet::Transform @options = options flags_from_clauses! + keywords_from_clauses! end def request @@ -42,6 +45,10 @@ class SearchQueryTransformer < Parslet::Transform @flags = clauses_by_operator.fetch(:flag, []).to_h { |clause| [clause.prefix, clause.term] } end + def keywords_from_clauses! + @keywords = must_clauses.flat_map(&:keywords).uniq + end + def must_clauses clauses_by_operator.fetch(:must, []) end @@ -128,6 +135,10 @@ class SearchQueryTransformer < Parslet::Transform { multi_match: { type: 'most_fields', query: @term, fields: ['text', 'text.stemmed'], operator: 'and' } } end end + + def keywords + @term.split + end end class PhraseClause @@ -141,6 +152,10 @@ class SearchQueryTransformer < Parslet::Transform def to_query { match_phrase: { text: { query: @phrase } } } end + + def keywords + @phrase.split + end end class PrefixClause @@ -193,6 +208,10 @@ class SearchQueryTransformer < Parslet::Transform end end + def keywords + [] + end + private def account_id_from_term(term) diff --git a/app/services/statuses_search_service.rb b/app/services/statuses_search_service.rb index ab8e28f61c..7d793c9063 100644 --- a/app/services/statuses_search_service.rb +++ b/app/services/statuses_search_service.rb @@ -25,6 +25,8 @@ class StatusesSearchService < BaseService private def status_search_results + return [] if contains_forbidden_terms? + request = parsed_query.request results = request.collapse(field: :id).order(id: { order: :desc }).limit(@limit).offset(@offset).objects.compact account_ids = results.map(&:account_id) @@ -37,7 +39,7 @@ class StatusesSearchService < BaseService end def parsed_query - SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query), current_account: @account) + @parsed_query ||= SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query), current_account: @account) end def convert_deprecated_options! @@ -60,4 +62,8 @@ class StatusesSearchService < BaseService @query = "#{@query} #{syntax_options.join(' ')}".strip if syntax_options.any? end + + def contains_forbidden_terms? + Tag.where(usable: false).matching_name(parsed_query.keywords).exists? + end end diff --git a/app/services/tag_search_service.rb b/app/services/tag_search_service.rb index 57400b76ad..06282d5140 100644 --- a/app/services/tag_search_service.rb +++ b/app/services/tag_search_service.rb @@ -41,7 +41,7 @@ class TagSearchService < BaseService normalized_query = Tag.normalize(@query) exact_match = results.find { |tag| tag.name.downcase == normalized_query } - exact_match ||= Tag.find_normalized(normalized_query) + exact_match ||= Tag.listable.find_normalized(normalized_query) unless exact_match.nil? results.delete(exact_match) results = [exact_match] + results