diff options
Diffstat (limited to 'app/finders/issuable_finder.rb')
-rw-r--r-- | app/finders/issuable_finder.rb | 381 |
1 files changed, 62 insertions, 319 deletions
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 6d5b1ca3bc5..5687b375cf0 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -38,19 +38,14 @@ class IssuableFinder include CreatedAtFilter include Gitlab::Utils::StrongMemoize - requires_cross_project_access unless: -> { project? } - - # This is used as a common filter for None / Any - FILTER_NONE = 'none' - FILTER_ANY = 'any' - - # This is used in unassigning users - NONE = '0' + requires_cross_project_access unless: -> { params.project? } NEGATABLE_PARAMS_HELPER_KEYS = %i[include_subgroups in].freeze attr_accessor :current_user, :params + delegate(*%i[assignee milestones], to: :params) + class << self def scalar_params @scalar_params ||= %i[ @@ -91,9 +86,13 @@ class IssuableFinder end end + def params_class + IssuableFinder::Params + end + def initialize(current_user, params = {}) @current_user = current_user - @params = params + @params = params_class.new(params, current_user, klass) end def execute @@ -161,7 +160,7 @@ class IssuableFinder # of a CTE. The CTE will not be used if the sort doesn't support it, # but will always be used for the counts here as we ignore sorting # anyway. - labels_count = label_names.any? ? label_names.count : 1 + labels_count = params.label_names.any? ? params.label_names.count : 1 labels_count = 1 if use_cte_for_search? finder.execute.reorder(nil).group(:state_id).count.each do |key, value| @@ -174,192 +173,10 @@ class IssuableFinder end # rubocop: enable CodeReuse/ActiveRecord - def group - return @group if defined?(@group) - - @group = - if params[:group_id].present? - Group.find(params[:group_id]) - else - nil - end - end - - def related_groups - if project? && project && project.group && Ability.allowed?(current_user, :read_group, project.group) - project.group.self_and_ancestors - elsif group - [group] - elsif current_user - Gitlab::ObjectHierarchy.new(current_user.authorized_groups, current_user.groups).all_objects - else - [] - end - end - - def project? - params[:project_id].present? - end - - def project - return @project if defined?(@project) - - project = Project.find(params[:project_id]) - project = nil unless Ability.allowed?(current_user, :"read_#{klass.to_ability_name}", project) - - @project = project - end - - def projects - return @projects if defined?(@projects) - - return @projects = [project] if project? - - projects = - if current_user && params[:authorized_only].presence && !current_user_related? - current_user.authorized_projects(min_access_level) - else - projects_public_or_visible_to_user - end - - @projects = projects.with_feature_available_for_user(klass, current_user).reorder(nil) # rubocop: disable CodeReuse/ActiveRecord - end - - def projects_public_or_visible_to_user - projects = - if group - if params[:projects] - find_group_projects.id_in(params[:projects]) - else - find_group_projects - end - elsif params[:projects] - Project.id_in(params[:projects]) - else - Project - end - - projects.public_or_visible_to_user(current_user, min_access_level) - end - - def find_group_projects - return Project.none unless group - - if params[:include_subgroups] - Project.where(namespace_id: group.self_and_descendants) # rubocop: disable CodeReuse/ActiveRecord - else - group.projects - end - end - def search params[:search].presence end - def milestones? - params[:milestone_title].present? - end - - def milestones - return @milestones if defined?(@milestones) - - @milestones = - if milestones? - if project? - group_id = project.group&.id - project_id = project.id - end - - group_id = group.id if group - - search_params = - { title: params[:milestone_title], project_ids: project_id, group_ids: group_id } - - MilestonesFinder.new(search_params).execute # rubocop: disable CodeReuse/Finder - else - Milestone.none - end - end - - def labels? - params[:label_name].present? - end - - def filter_by_no_label? - downcased = label_names.map(&:downcase) - - downcased.include?(FILTER_NONE) - end - - def filter_by_any_label? - label_names.map(&:downcase).include?(FILTER_ANY) - end - - def labels - return @labels if defined?(@labels) - - @labels = - if labels? && !filter_by_no_label? - LabelsFinder.new(current_user, project_ids: projects, title: label_names).execute(skip_authorization: true) # rubocop: disable CodeReuse/Finder - else - Label.none - end - end - - def assignee_id? - params[:assignee_id].present? - end - - def assignee_username? - params[:assignee_username].present? - end - - def assignee - assignees.first - end - - # rubocop: disable CodeReuse/ActiveRecord - def assignees - strong_memoize(:assignees) do - if assignee_id? - User.where(id: params[:assignee_id]) - elsif assignee_username? - User.where(username: params[:assignee_username]) - else - User.none - end - end - end - # rubocop: enable CodeReuse/ActiveRecord - - def author_id? - params[:author_id].present? && params[:author_id] != NONE - end - - def author_username? - params[:author_username].present? && params[:author_username] != NONE - end - - def no_author? - # author_id takes precedence over author_username - params[:author_id] == NONE || params[:author_username] == NONE - end - - # rubocop: disable CodeReuse/ActiveRecord - def author - return @author if defined?(@author) - - @author = - if author_id? - User.find_by(id: params[:author_id]) - elsif author_username? - User.find_by_username(params[:author_username]) - else - nil - end - end - # rubocop: enable CodeReuse/ActiveRecord - def use_cte_for_search? strong_memoize(:use_cte_for_search) do next false unless search @@ -370,10 +187,6 @@ class IssuableFinder end end - def releases? - params[:release_tag].present? - end - private def force_cte? @@ -431,7 +244,7 @@ class IssuableFinder # rubocop: disable CodeReuse/ActiveRecord def by_scope(items) - return items.none if current_user_related? && !current_user + return items.none if params.current_user_related? && !current_user case params[:scope] when 'created_by_me', 'authored' @@ -480,16 +293,13 @@ class IssuableFinder # rubocop: disable CodeReuse/ActiveRecord def by_project(items) - items = - if project? - items.of_projects(projects).references_project - elsif projects - items.merge(projects.reorder(nil)).join_project - else - items.none - end - - items + if params.project? + items.of_projects(params.projects).references_project + elsif params.projects + items.merge(params.projects.reorder(nil)).join_project + else + items.none + end end # rubocop: enable CodeReuse/ActiveRecord @@ -519,42 +329,34 @@ class IssuableFinder def sort(items) # Ensure we always have an explicit sort order (instead of inheriting # multiple orders when combining ActiveRecord::Relation objects). - params[:sort] ? items.sort_by_attribute(params[:sort], excluded_labels: label_names) : items.reorder(id: :desc) + params[:sort] ? items.sort_by_attribute(params[:sort], excluded_labels: params.label_names) : items.reorder(id: :desc) end # rubocop: enable CodeReuse/ActiveRecord - def filter_by_no_assignee? - params[:assignee_id].to_s.downcase == FILTER_NONE - end - - def filter_by_any_assignee? - params[:assignee_id].to_s.downcase == FILTER_ANY - end - # rubocop: disable CodeReuse/ActiveRecord def by_author(items) - if author - items = items.where(author_id: author.id) - elsif no_author? - items = items.where(author_id: nil) - elsif author_id? || author_username? # author not found - items = items.none + if params.author + items.where(author_id: params.author.id) + elsif params.no_author? + items.where(author_id: nil) + elsif params.author_id? || params.author_username? # author not found + items.none + else + items end - - items end # rubocop: enable CodeReuse/ActiveRecord def by_assignee(items) - return items.assigned_to(assignees) if not_query? && assignees.any? + return items.assigned_to(params.assignees) if not_query? && params.assignees.any? - if filter_by_no_assignee? + if params.filter_by_no_assignee? items.unassigned - elsif filter_by_any_assignee? + elsif params.filter_by_any_assignee? items.assigned - elsif assignee - items.assigned_to(assignee) - elsif assignee_id? || assignee_username? # assignee not found + elsif params.assignee + items.assigned_to(params.assignee) + elsif params.assignee_id? || params.assignee_username? # assignee not found items.none else items @@ -563,106 +365,56 @@ class IssuableFinder # rubocop: disable CodeReuse/ActiveRecord def by_milestone(items) - if milestones? - if filter_by_no_milestone? - items = items.left_joins_milestones.where(milestone_id: [-1, nil]) - elsif filter_by_any_milestone? - items = items.any_milestone - elsif filter_by_upcoming_milestone? - upcoming_ids = Milestone.upcoming_ids(projects, related_groups) - items = items.left_joins_milestones.where(milestone_id: upcoming_ids) - elsif filter_by_started_milestone? - items = items.left_joins_milestones.merge(Milestone.started) - else - items = items.with_milestone(params[:milestone_title]) - end + return items unless params.milestones? + + if params.filter_by_no_milestone? + items.left_joins_milestones.where(milestone_id: [-1, nil]) + elsif params.filter_by_any_milestone? + items.any_milestone + elsif params.filter_by_upcoming_milestone? + upcoming_ids = Milestone.upcoming_ids(params.projects, params.related_groups) + items.left_joins_milestones.where(milestone_id: upcoming_ids) + elsif params.filter_by_started_milestone? + items.left_joins_milestones.merge(Milestone.started) + else + items.with_milestone(params[:milestone_title]) end - - items end # rubocop: enable CodeReuse/ActiveRecord def by_release(items) - return items unless releases? + return items unless params.releases? - if filter_by_no_release? + if params.filter_by_no_release? items.without_release - elsif filter_by_any_release? + elsif params.filter_by_any_release? items.any_release else items.with_release(params[:release_tag], params[:project_id]) end end - def filter_by_no_milestone? - # Accepts `No Milestone` for compatibility - params[:milestone_title].to_s.downcase == FILTER_NONE || params[:milestone_title] == Milestone::None.title - end - - def filter_by_any_milestone? - # Accepts `Any Milestone` for compatibility - params[:milestone_title].to_s.downcase == FILTER_ANY || params[:milestone_title] == Milestone::Any.title - end - - def filter_by_upcoming_milestone? - params[:milestone_title] == Milestone::Upcoming.name - end - - def filter_by_started_milestone? - params[:milestone_title] == Milestone::Started.name - end - - def filter_by_no_release? - params[:release_tag].to_s.downcase == FILTER_NONE - end - - def filter_by_any_release? - params[:release_tag].to_s.downcase == FILTER_ANY - end - def by_label(items) - return items unless labels? - - items = - if filter_by_no_label? - items.without_label - elsif filter_by_any_label? - items.any_label - else - items.with_label(label_names, params[:sort], not_query: not_query?) - end + return items unless params.labels? - items - end - - def by_my_reaction_emoji(items) - if params[:my_reaction_emoji].present? && current_user - items = - if filter_by_no_reaction? - items.not_awarded(current_user) - elsif filter_by_any_reaction? - items.awarded(current_user) - else - items.awarded(current_user, params[:my_reaction_emoji]) - end + if params.filter_by_no_label? + items.without_label + elsif params.filter_by_any_label? + items.any_label + else + items.with_label(params.label_names, params[:sort], not_query: not_query?) end - - items - end - - def filter_by_no_reaction? - params[:my_reaction_emoji].to_s.downcase == FILTER_NONE end - def filter_by_any_reaction? - params[:my_reaction_emoji].to_s.downcase == FILTER_ANY - end + def by_my_reaction_emoji(items) + return items unless params[:my_reaction_emoji] && current_user - def label_names - if labels? - params[:label_name].is_a?(String) ? params[:label_name].split(',') : params[:label_name] + if params.filter_by_no_reaction? + items.not_awarded(current_user) + elsif params.filter_by_any_reaction? + items.awarded(current_user) else - [] + items.awarded(current_user, params[:my_reaction_emoji]) end end @@ -670,15 +422,6 @@ class IssuableFinder params[:non_archived].present? ? items.non_archived : items end - def current_user_related? - scope = params[:scope] - scope == 'created_by_me' || scope == 'authored' || scope == 'assigned_to_me' - end - - def min_access_level - ProjectFeature.required_minimum_access_level(klass) - end - def not_query? !!params[:not_query] end |