From b76ae638462ab0f673e5915986070518dd3f9ad3 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 19 Aug 2021 09:08:42 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-2-stable-ee --- app/finders/alert_management/alerts_finder.rb | 2 +- app/finders/ci/pipelines_finder.rb | 10 ++++++ app/finders/error_tracking/errors_finder.rb | 37 ++++++++++++++++++++++ app/finders/group_members_finder.rb | 9 ++++++ app/finders/groups_finder.rb | 10 ++++++ app/finders/issuable_finder.rb | 3 +- app/finders/issuable_finder/params.rb | 28 +++++++++++----- app/finders/issues_finder.rb | 20 ++++++++---- app/finders/issues_finder/params.rb | 8 ++++- app/finders/lfs_pointers_finder.rb | 36 +++++++++++++++++++++ app/finders/merge_requests_finder.rb | 13 ++------ app/finders/packages/pypi/packages_finder.rb | 7 ++-- .../members/effective_access_level_finder.rb | 10 ++++-- .../effective_access_level_per_user_finder.rb | 20 ++++++++++++ app/finders/security/jobs_finder.rb | 19 +---------- 15 files changed, 178 insertions(+), 54 deletions(-) create mode 100644 app/finders/error_tracking/errors_finder.rb create mode 100644 app/finders/lfs_pointers_finder.rb create mode 100644 app/finders/projects/members/effective_access_level_per_user_finder.rb (limited to 'app/finders') diff --git a/app/finders/alert_management/alerts_finder.rb b/app/finders/alert_management/alerts_finder.rb index b4f66a38faa..1fbc1a4a258 100644 --- a/app/finders/alert_management/alerts_finder.rb +++ b/app/finders/alert_management/alerts_finder.rb @@ -46,7 +46,7 @@ module AlertManagement def by_status(collection) values = AlertManagement::Alert.status_names & Array(params[:status]) - values.present? ? collection.for_status(values) : collection + values.present? ? collection.with_status(values) : collection end def by_search(collection) diff --git a/app/finders/ci/pipelines_finder.rb b/app/finders/ci/pipelines_finder.rb index d9fe5c23a7e..a79840216da 100644 --- a/app/finders/ci/pipelines_finder.rb +++ b/app/finders/ci/pipelines_finder.rb @@ -29,6 +29,9 @@ module Ci items = by_username(items) items = by_yaml_errors(items) items = by_updated_at(items) + + items = by_source(items) if Feature.enabled?(:pipeline_source_filter, project, default_enabled: :yaml) + sort_items(items) end @@ -87,6 +90,12 @@ module Ci end # rubocop: enable CodeReuse/ActiveRecord + def by_source(items) + return items unless ::Ci::Pipeline.sources.key?(params[:source]) + + items.with_pipeline_source(params[:source]) + end + # rubocop: disable CodeReuse/ActiveRecord def by_ref(items) if params[:ref].present? @@ -107,6 +116,7 @@ module Ci end # rubocop: enable CodeReuse/ActiveRecord + # This method is deprecated and will be removed in 14.3 # rubocop: disable CodeReuse/ActiveRecord def by_name(items) if params[:name].present? diff --git a/app/finders/error_tracking/errors_finder.rb b/app/finders/error_tracking/errors_finder.rb new file mode 100644 index 00000000000..fb2d4b14dfa --- /dev/null +++ b/app/finders/error_tracking/errors_finder.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module ErrorTracking + class ErrorsFinder + def initialize(current_user, project, params) + @current_user = current_user + @project = project + @params = params + end + + def execute + return ErrorTracking::Error.none unless authorized? + + collection = project.error_tracking_errors + collection = by_status(collection) + + # Limit collection until pagination implemented + collection.limit(20) + end + + private + + attr_reader :current_user, :project, :params + + def by_status(collection) + if params[:status].present? && ErrorTracking::Error.statuses.key?(params[:status]) + collection.for_status(params[:status]) + else + collection + end + end + + def authorized? + Ability.allowed?(current_user, :read_sentry_issue, project) + end + end +end diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb index 982234f7506..75623d33ef5 100644 --- a/app/finders/group_members_finder.rb +++ b/app/finders/group_members_finder.rb @@ -3,6 +3,7 @@ class GroupMembersFinder < UnionFinder RELATIONS = %i(direct inherited descendants).freeze DEFAULT_RELATIONS = %i(direct inherited).freeze + INVALID_RELATION_TYPE_ERROR_MSG = "is not a valid relation type. Valid relation types are #{RELATIONS.join(', ')}." RELATIONS_DESCRIPTIONS = { direct: 'Members in the group itself', @@ -42,6 +43,8 @@ class GroupMembersFinder < UnionFinder attr_reader :user, :group def groups_by_relations(include_relations) + check_relation_arguments!(include_relations) + case include_relations.sort when [:inherited] group.ancestors @@ -86,6 +89,12 @@ class GroupMembersFinder < UnionFinder def members_of_groups(groups) GroupMember.non_request.of_groups(groups) end + + def check_relation_arguments!(include_relations) + unless include_relations & RELATIONS == include_relations + raise ArgumentError, "#{(include_relations - RELATIONS).first} #{INVALID_RELATION_TYPE_ERROR_MSG}" + end + end end GroupMembersFinder.prepend_mod_with('GroupMembersFinder') diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb index 4b6b2716c64..7ea3362fba1 100644 --- a/app/finders/groups_finder.rb +++ b/app/finders/groups_finder.rb @@ -11,6 +11,7 @@ # parent: Group # all_available: boolean (defaults to true) # min_access_level: integer +# search: string # exclude_group_ids: array of integers # include_parent_descendants: boolean (defaults to false) - includes descendant groups when # filtering by parent. The parent param must be present. @@ -33,6 +34,7 @@ class GroupsFinder < UnionFinder item = by_parent(item) item = by_custom_attributes(item) item = exclude_group_ids(item) + item = by_search(item) item end @@ -94,6 +96,14 @@ class GroupsFinder < UnionFinder end # rubocop: enable CodeReuse/ActiveRecord + # rubocop: disable CodeReuse/ActiveRecord + def by_search(groups) + return groups unless params[:search].present? + + groups.search(params[:search], include_parents: params[:parent].blank?) + end + # rubocop: enable CodeReuse/ActiveRecord + def owned_groups current_user&.owned_groups || Group.none end diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 086dadcf5b7..9f3ca385d93 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -15,7 +15,8 @@ # state: 'opened' or 'closed' or 'locked' or 'all' # group_id: integer # project_id: integer -# milestone_title: string +# milestone_title: string (cannot be simultaneously used with milestone_wildcard_id) +# milestone_wildcard_id: 'none', 'any', 'upcoming', 'started' (cannot be simultaneously used with milestone_title) # release_tag: string # author_id: integer # author_username: string diff --git a/app/finders/issuable_finder/params.rb b/app/finders/issuable_finder/params.rb index 51e12dde51d..595f4e4cf8a 100644 --- a/app/finders/issuable_finder/params.rb +++ b/app/finders/issuable_finder/params.rb @@ -4,9 +4,11 @@ class IssuableFinder class Params < SimpleDelegator include Gitlab::Utils::StrongMemoize - # This is used as a common filter for None / Any + # This is used as a common filter for None / Any / Upcoming / Started FILTER_NONE = 'none' FILTER_ANY = 'any' + FILTER_STARTED = 'started' + FILTER_UPCOMING = 'upcoming' # This is used in unassigning users NONE = '0' @@ -42,25 +44,35 @@ class IssuableFinder end def milestones? - params[:milestone_title].present? + params[:milestone_title].present? || params[:milestone_wildcard_id].present? 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 + # Usage of `No Milestone` and `none`/`None` in milestone_title to be deprecated + # https://gitlab.com/gitlab-org/gitlab/-/issues/336044 + params[:milestone_title].to_s.downcase == FILTER_NONE || + params[:milestone_title] == Milestone::None.title || + params[:milestone_wildcard_id].to_s.downcase == FILTER_NONE 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 + # Usage of `Any Milestone` and `any`/`Any` in milestone_title to be deprecated + # https://gitlab.com/gitlab-org/gitlab/-/issues/336044 + params[:milestone_title].to_s.downcase == FILTER_ANY || + params[:milestone_title] == Milestone::Any.title || + params[:milestone_wildcard_id].to_s.downcase == FILTER_ANY end def filter_by_upcoming_milestone? - params[:milestone_title] == Milestone::Upcoming.name + # Usage of `#upcoming` in milestone_title to be deprecated + # https://gitlab.com/gitlab-org/gitlab/-/issues/336044 + params[:milestone_title] == Milestone::Upcoming.name || params[:milestone_wildcard_id].to_s.downcase == FILTER_UPCOMING end def filter_by_started_milestone? - params[:milestone_title] == Milestone::Started.name + # Usage of `#started` in milestone_title to be deprecated + # https://gitlab.com/gitlab-org/gitlab/-/issues/336044 + params[:milestone_title] == Milestone::Started.name || params[:milestone_wildcard_id].to_s.downcase == FILTER_STARTED end def filter_by_no_release? diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb index 40d6730d232..7595b1c7a15 100644 --- a/app/finders/issues_finder.rb +++ b/app/finders/issues_finder.rb @@ -11,7 +11,8 @@ # state: 'opened' or 'closed' or 'all' # group_id: integer # project_id: integer -# milestone_title: string +# milestone_title: string (cannot be simultaneously used with milestone_wildcard_id) +# milestone_wildcard_id: 'none', 'any', 'upcoming', 'started' (cannot be simultaneously used with milestone_title) # assignee_id: integer # search: string # in: 'title', 'description', or a string joining them with comma @@ -25,7 +26,7 @@ # updated_after: datetime # updated_before: datetime # confidential: boolean -# issue_types: array of strings (one of Issue.issue_types) +# issue_types: array of strings (one of WorkItem::Type.base_types) # class IssuesFinder < IssuableFinder CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::REPORTER @@ -46,17 +47,22 @@ class IssuesFinder < IssuableFinder # rubocop: disable CodeReuse/ActiveRecord def with_confidentiality_access_check - return Issue.all if params.user_can_see_all_confidential_issues? + return Issue.all if params.user_can_see_all_issues? + + # Only admins can see hidden issues, so for non-admins, we filter out any hidden issues + issues = Issue.without_hidden + + return issues.all if params.user_can_see_all_confidential_issues? # If already filtering by assignee we can skip confidentiality since a user # can always see confidential issues assigned to them. This is just an # optimization since a very common usecase of this Finder is to load the # count of issues assigned to the user for the header bar. - return Issue.all if current_user && assignee_filter.includes_user?(current_user) + return issues.all if current_user && assignee_filter.includes_user?(current_user) - return Issue.where('issues.confidential IS NOT TRUE') if params.user_cannot_see_confidential_issues? + return issues.where('issues.confidential IS NOT TRUE') if params.user_cannot_see_confidential_issues? - Issue.where(' + issues.where(' issues.confidential IS NOT TRUE OR (issues.confidential = TRUE AND (issues.author_id = :user_id @@ -111,7 +117,7 @@ class IssuesFinder < IssuableFinder def by_issue_types(items) issue_type_params = Array(params[:issue_types]).map(&:to_s) return items if issue_type_params.blank? - return Issue.none unless (Issue.issue_types.keys & issue_type_params).sort == issue_type_params.sort + return Issue.none unless (WorkItem::Type.base_types.keys & issue_type_params).sort == issue_type_params.sort items.with_issue_type(params[:issue_types]) end diff --git a/app/finders/issues_finder/params.rb b/app/finders/issues_finder/params.rb index 1de117216f8..2edd8a6f099 100644 --- a/app/finders/issues_finder/params.rb +++ b/app/finders/issues_finder/params.rb @@ -32,7 +32,7 @@ class IssuesFinder if parent Ability.allowed?(current_user, :read_confidential_issues, parent) else - Ability.allowed?(current_user, :read_all_resources) + user_can_see_all_issues? end end end @@ -42,6 +42,12 @@ class IssuesFinder current_user.blank? end + + def user_can_see_all_issues? + strong_memoize(:user_can_see_all_issues) do + Ability.allowed?(current_user, :read_all_resources) + end + end end end diff --git a/app/finders/lfs_pointers_finder.rb b/app/finders/lfs_pointers_finder.rb new file mode 100644 index 00000000000..7e621002f1e --- /dev/null +++ b/app/finders/lfs_pointers_finder.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class LfsPointersFinder + def initialize(repository, path) + @repository = repository + @path = path + end + + def execute + return [] unless ref + + blob_ids = tree.blobs.map(&:id) + + # When current endpoint is a Blob then `tree.blobs` will be empty, it means we need to analyze + # the current Blob in order to determine if it's a LFS object + blob_ids = Array.wrap(current_blob&.id) if blob_ids.empty? + + Gitlab::Git::Blob.batch_lfs_pointers(repository, blob_ids).map(&:id) + end + + private + + attr_reader :repository, :path + + def ref + repository.root_ref + end + + def tree + repository.tree(ref, path) + end + + def current_blob + repository.blob_at(ref, path) + end +end diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb index e23fa3f7f68..13696add965 100644 --- a/app/finders/merge_requests_finder.rb +++ b/app/finders/merge_requests_finder.rb @@ -154,16 +154,9 @@ class MergeRequestsFinder < IssuableFinder # WIP is deprecated in favor of Draft. Currently both options are supported def wip_match(table) - items = - table[:title].matches('WIP:%') - .or(table[:title].matches('WIP %')) - .or(table[:title].matches('[WIP]%')) - - # Let's keep this FF around until https://gitlab.com/gitlab-org/gitlab/-/issues/232999 - # is implemented - return items unless Feature.enabled?(:merge_request_draft_filter, default_enabled: true) - - items + table[:title].matches('WIP:%') + .or(table[:title].matches('WIP %')) + .or(table[:title].matches('[WIP]%')) .or(table[:title].matches('Draft - %')) .or(table[:title].matches('Draft:%')) .or(table[:title].matches('[Draft]%')) diff --git a/app/finders/packages/pypi/packages_finder.rb b/app/finders/packages/pypi/packages_finder.rb index 642ca2cf2e6..47cfb59944b 100644 --- a/app/finders/packages/pypi/packages_finder.rb +++ b/app/finders/packages/pypi/packages_finder.rb @@ -3,11 +3,8 @@ module Packages module Pypi class PackagesFinder < ::Packages::GroupOrProjectPackageFinder - def execute! - results = packages.with_normalized_pypi_name(@params[:package_name]) - raise ActiveRecord::RecordNotFound if results.empty? - - results + def execute + packages.with_normalized_pypi_name(@params[:package_name]) end private diff --git a/app/finders/projects/members/effective_access_level_finder.rb b/app/finders/projects/members/effective_access_level_finder.rb index 2880d6667ce..c1e3842a9e4 100644 --- a/app/finders/projects/members/effective_access_level_finder.rb +++ b/app/finders/projects/members/effective_access_level_finder.rb @@ -59,8 +59,8 @@ module Projects # @return [Array<[user_id, access_level]>] def user_ids_and_access_levels_from_all_memberships strong_memoize(:user_ids_and_access_levels_from_all_memberships) do - all_possible_avenues_of_membership.flat_map do |relation| - relation.pluck(*USER_ID_AND_ACCESS_LEVEL) # rubocop: disable CodeReuse/ActiveRecord + all_possible_avenues_of_membership.flat_map do |members| + apply_scopes(members).pluck(*USER_ID_AND_ACCESS_LEVEL) # rubocop: disable CodeReuse/ActiveRecord end end end @@ -86,7 +86,7 @@ module Projects members << Member.from_union(members_per_batch) end - members.flatten + Member.from_union(members) end def project_owner_acting_as_maintainer @@ -120,6 +120,10 @@ module Projects Arel.sql(column_alias) ) end + + def apply_scopes(members) + members + end end end end diff --git a/app/finders/projects/members/effective_access_level_per_user_finder.rb b/app/finders/projects/members/effective_access_level_per_user_finder.rb new file mode 100644 index 00000000000..f367b4ca451 --- /dev/null +++ b/app/finders/projects/members/effective_access_level_per_user_finder.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Projects + module Members + class EffectiveAccessLevelPerUserFinder < EffectiveAccessLevelFinder + def initialize(project, user) + @project = project + @user = user + end + + private + + attr_reader :user + + def apply_scopes(members) + super.where(user_id: user.id) # rubocop: disable CodeReuse/ActiveRecord + end + end + end +end diff --git a/app/finders/security/jobs_finder.rb b/app/finders/security/jobs_finder.rb index 99bcf97f43c..6c2090e0509 100644 --- a/app/finders/security/jobs_finder.rb +++ b/app/finders/security/jobs_finder.rb @@ -38,11 +38,7 @@ module Security def execute return [] if @job_types.empty? - if Feature.enabled?(:ci_build_metadata_config, pipeline.project, default_enabled: :yaml) - find_jobs - else - find_jobs_legacy - end + find_jobs end private @@ -51,19 +47,6 @@ module Security @pipeline.builds.with_secure_reports_from_config_options(@job_types) end - def find_jobs_legacy - # the query doesn't guarantee accuracy, so we verify it here - legacy_jobs_query.select do |job| - @job_types.find { |job_type| job.options.dig(:artifacts, :reports, job_type) } - end - end - - def legacy_jobs_query - @job_types.map do |job_type| - @pipeline.builds.with_secure_reports_from_options(job_type) - end.reduce(&:or) - end - def valid_job_types?(job_types) (job_types - self.class.allowed_job_types).empty? end -- cgit v1.2.3