gitlab-org--gitlab-foss/app/finders/labels_finder.rb
Eugenia Grieff 6ff7788d4c Fix labels finder to filter visible issuables
Use project scopes to filter project labels

Add changelog file

Check  issuables visibility in  LabelsFinder

Add specs for issuables visibility cases

Rename Project method to reuse in LabelsFinder

Remove commented code

Improve changelog title
2019-10-22 17:00:56 +01:00

197 lines
4.6 KiB
Ruby

# frozen_string_literal: true
class LabelsFinder < UnionFinder
prepend FinderWithCrossProjectAccess
include FinderMethods
include Gitlab::Utils::StrongMemoize
requires_cross_project_access unless: -> { project? }
def initialize(current_user, params = {})
@current_user = current_user
@params = params
end
def execute(skip_authorization: false)
@skip_authorization = skip_authorization
items = find_union(label_ids, Label) || Label.none
items = with_title(items)
items = by_subscription(items)
items = by_search(items)
sort(items)
end
private
attr_reader :current_user, :params, :skip_authorization
# rubocop: disable CodeReuse/ActiveRecord
def label_ids
label_ids = []
if project?
if project
if project.group.present?
labels_table = Label.arel_table
group_ids = group_ids_for(project.group)
label_ids << Label.where(
labels_table[:type].eq('GroupLabel').and(labels_table[:group_id].in(group_ids)).or(
labels_table[:type].eq('ProjectLabel').and(labels_table[:project_id].eq(project.id))
)
)
else
label_ids << project.labels
end
end
else
if group?
group = Group.find(params[:group_id])
label_ids << Label.where(group_id: group_ids_for(group))
end
label_ids << Label.where(group_id: projects.group_ids)
label_ids << Label.where(project_id: ids_user_can_read_labels(projects)) unless only_group_labels?
end
label_ids
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def sort(items)
if params[:sort]
items.order_by(params[:sort])
else
items.reorder(title: :asc)
end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def with_title(items)
return items if title.nil?
return items.none if title.blank?
items.where(title: title)
end
# rubocop: enable CodeReuse/ActiveRecord
def by_search(labels)
return labels unless search?
labels.search(params[:search])
end
def by_subscription(labels)
labels.optionally_subscribed_by(subscriber_id)
end
def subscriber_id
current_user&.id if subscribed?
end
def subscribed?
params[:subscribed] == 'true'
end
# Gets redacted array of group ids
# which can include the ancestors and descendants of the requested group.
def group_ids_for(group)
strong_memoize(:group_ids) do
groups = groups_to_include(group)
groups_user_can_read_labels(groups).map(&:id)
end
end
def groups_to_include(group)
groups = [group]
groups += group.ancestors if include_ancestor_groups?
groups += group.descendants if include_descendant_groups?
groups
end
def include_ancestor_groups?
params[:include_ancestor_groups]
end
def include_descendant_groups?
params[:include_descendant_groups]
end
def group?
params[:group_id].present?
end
def project?
params[:project].present? || params[:project_id].present?
end
def projects?
params[:project_ids]
end
def only_group_labels?
params[:only_group_labels]
end
def search?
params[:search].present?
end
def title
params[:title] || params[:name]
end
def project
return @project if defined?(@project)
if project?
@project = params[:project] || Project.find(params[:project_id])
@project = nil unless authorized_to_read_labels?(@project)
else
@project = nil
end
@project
end
# rubocop: disable CodeReuse/ActiveRecord
def projects
return @projects if defined?(@projects)
@projects = if skip_authorization
Project.all
else
ProjectsFinder.new(params: { non_archived: true }, current_user: current_user).execute # rubocop: disable CodeReuse/Finder
end
@projects = @projects.in_namespace(params[:group_id]) if group?
@projects = @projects.where(id: params[:project_ids]) if projects?
@projects = @projects.reorder(nil)
@projects
end
# rubocop: enable CodeReuse/ActiveRecord
def authorized_to_read_labels?(label_parent)
return true if skip_authorization
Ability.allowed?(current_user, :read_label, label_parent)
end
def groups_user_can_read_labels(groups)
DeclarativePolicy.user_scope do
groups.select { |group| authorized_to_read_labels?(group) }
end
end
# rubocop: disable CodeReuse/ActiveRecord
def ids_user_can_read_labels(projects)
Project.where(id: projects.select(:id)).ids_with_issuables_available_for(current_user)
end
# rubocop: enable CodeReuse/ActiveRecord
end