debian-mirror-gitlab/app/services/search_service.rb

175 lines
4.3 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2017-08-17 22:00:37 +05:30
class SearchService
include Gitlab::Allowable
2022-01-26 12:08:38 +05:30
include Gitlab::Utils::StrongMemoize
2017-08-17 22:00:37 +05:30
2020-05-24 23:13:21 +05:30
DEFAULT_PER_PAGE = Gitlab::SearchResults::DEFAULT_PER_PAGE
MAX_PER_PAGE = 200
2022-03-02 08:16:31 +05:30
attr_reader :params
2017-08-17 22:00:37 +05:30
def initialize(current_user, params = {})
@current_user = current_user
2022-08-13 15:12:31 +05:30
@params = Gitlab::Search::Params.new(params, detect_abuse: true)
2017-08-17 22:00:37 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2017-08-17 22:00:37 +05:30
def project
2022-01-26 12:08:38 +05:30
strong_memoize(:project) do
if params[:project_id].present? && valid_request?
2017-08-17 22:00:37 +05:30
the_project = Project.find_by(id: params[:project_id])
2017-09-10 17:25:29 +05:30
can?(current_user, :read_project, the_project) ? the_project : nil
2017-08-17 22:00:37 +05:30
end
2022-01-26 12:08:38 +05:30
end
2017-08-17 22:00:37 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2017-08-17 22:00:37 +05:30
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2017-08-17 22:00:37 +05:30
def group
2022-01-26 12:08:38 +05:30
strong_memoize(:group) do
if params[:group_id].present? && valid_request?
2017-08-17 22:00:37 +05:30
the_group = Group.find_by(id: params[:group_id])
can?(current_user, :read_group, the_group) ? the_group : nil
end
2022-01-26 12:08:38 +05:30
end
2017-08-17 22:00:37 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2017-08-17 22:00:37 +05:30
2021-09-04 01:27:46 +05:30
def projects
# overridden in EE
end
2022-01-26 12:08:38 +05:30
def global_search?
project.blank? && group.blank?
end
2017-08-17 22:00:37 +05:30
def show_snippets?
return @show_snippets if defined?(@show_snippets)
@show_snippets = params[:snippets] == 'true'
end
delegate :scope, to: :search_service
2022-01-26 12:08:38 +05:30
delegate :valid_terms_count?, :valid_query_length?, to: :params
2017-08-17 22:00:37 +05:30
def search_results
2022-01-26 12:08:38 +05:30
strong_memoize(:search_results) do
abuse_detected? ? Gitlab::EmptySearchResults.new : search_service.execute
end
2017-08-17 22:00:37 +05:30
end
2020-06-23 00:09:42 +05:30
def search_objects(preload_method = nil)
2021-01-29 00:20:46 +05:30
@search_objects ||= redact_unauthorized_results(
search_results.objects(scope, page: page, per_page: per_page, preload_method: preload_method)
)
2020-04-08 14:13:33 +05:30
end
2021-01-03 14:25:43 +05:30
def search_highlight
search_results.highlight_map(scope)
end
2020-04-08 14:13:33 +05:30
2021-12-11 22:18:48 +05:30
def search_aggregations
search_results.aggregations(scope)
end
2022-01-26 12:08:38 +05:30
def abuse_detected?
strong_memoize(:abuse_detected) do
params.abusive?
end
end
def abuse_messages
return [] unless params.abusive?
params.abuse_detection.errors.full_messages
end
def valid_request?
strong_memoize(:valid_request) do
params.valid?
end
end
2022-08-13 15:12:31 +05:30
def level
@level ||=
if project
'project'
elsif group
'group'
else
'global'
end
2022-01-26 12:08:38 +05:30
end
2022-08-13 15:12:31 +05:30
private
2021-01-29 00:20:46 +05:30
def page
[1, params[:page].to_i].max
end
2020-05-24 23:13:21 +05:30
def per_page
per_page_param = params[:per_page].to_i
2020-10-24 23:57:45 +05:30
return DEFAULT_PER_PAGE unless per_page_param > 0
2020-05-24 23:13:21 +05:30
[MAX_PER_PAGE, per_page_param].min
end
2020-04-08 14:13:33 +05:30
def visible_result?(object)
return true unless object.respond_to?(:to_ability_name) && DeclarativePolicy.has_policy?(object)
Ability.allowed?(current_user, :"read_#{object.to_ability_name}", object)
end
2020-04-22 19:07:51 +05:30
def redact_unauthorized_results(results_collection)
2020-06-23 00:09:42 +05:30
redacted_results = results_collection.reject { |object| visible_result?(object) }
if redacted_results.any?
redacted_log = redacted_results.each_with_object({}) do |object, memo|
memo[object.id] = { ability: :"read_#{object.to_ability_name}", id: object.id, class_name: object.class.name }
end
log_redacted_search_results(redacted_log.values)
2020-04-08 14:13:33 +05:30
2020-06-23 00:09:42 +05:30
return results_collection.id_not_in(redacted_log.keys) if results_collection.is_a?(ActiveRecord::Relation)
2020-04-08 14:13:33 +05:30
end
2020-06-23 00:09:42 +05:30
return results_collection if results_collection.is_a?(ActiveRecord::Relation)
2020-04-08 14:13:33 +05:30
2020-06-23 00:09:42 +05:30
permitted_results = results_collection - redacted_results
2020-04-08 14:13:33 +05:30
Kaminari.paginate_array(
permitted_results,
2020-04-22 19:07:51 +05:30
total_count: results_collection.total_count,
limit: results_collection.limit_value,
offset: results_collection.offset_value
2020-04-08 14:13:33 +05:30
)
end
def log_redacted_search_results(filtered_results)
logger.error(message: "redacted_search_results", filtered: filtered_results, current_user_id: current_user&.id, query: params[:search])
end
def logger
@logger ||= ::Gitlab::RedactedSearchResultsLogger.build
end
2017-08-17 22:00:37 +05:30
def search_service
@search_service ||=
if project
Search::ProjectService.new(project, current_user, params)
elsif show_snippets?
Search::SnippetService.new(current_user, params)
elsif group
Search::GroupService.new(current_user, group, params)
else
Search::GlobalService.new(current_user, params)
end
end
2022-03-02 08:16:31 +05:30
attr_reader :current_user
2017-08-17 22:00:37 +05:30
end
2019-12-04 20:38:33 +05:30
2021-06-08 01:23:25 +05:30
SearchService.prepend_mod_with('SearchService')