From 36a59d088eca61b834191dacea009677a96c052f Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 19 May 2022 07:33:21 +0000 Subject: Add latest changes from gitlab-org/gitlab@15-0-stable-ee --- app/finders/alert_management/alerts_finder.rb | 2 - app/finders/error_tracking/errors_finder.rb | 46 ------- app/finders/group_descendants_finder.rb | 2 +- app/finders/group_members_finder.rb | 4 + .../base.rb | 35 +++++ .../on_direct_membership_finder.rb | 36 +++++ .../on_transfer_finder.rb | 17 +++ app/finders/groups_finder.rb | 4 +- .../incident_management/timeline_events_finder.rb | 37 +++++ app/finders/issuable_finder.rb | 4 +- app/finders/issues_finder.rb | 7 +- app/finders/issues_finder/params.rb | 4 - app/finders/packages/build_infos_finder.rb | 46 +++++-- .../build_infos_for_many_packages_finder.rb | 92 ------------- app/finders/personal_access_tokens_finder.rb | 2 - .../projects/serverless/functions_finder.rb | 153 --------------------- app/finders/releases_finder.rb | 14 -- app/finders/tags_finder.rb | 4 - app/finders/user_recent_events_finder.rb | 7 +- 19 files changed, 177 insertions(+), 339 deletions(-) delete mode 100644 app/finders/error_tracking/errors_finder.rb create mode 100644 app/finders/groups/projects_requiring_authorizations_refresh/base.rb create mode 100644 app/finders/groups/projects_requiring_authorizations_refresh/on_direct_membership_finder.rb create mode 100644 app/finders/groups/projects_requiring_authorizations_refresh/on_transfer_finder.rb create mode 100644 app/finders/incident_management/timeline_events_finder.rb delete mode 100644 app/finders/packages/build_infos_for_many_packages_finder.rb delete mode 100644 app/finders/projects/serverless/functions_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 1fbc1a4a258..11c0f37a79c 100644 --- a/app/finders/alert_management/alerts_finder.rb +++ b/app/finders/alert_management/alerts_finder.rb @@ -66,5 +66,3 @@ module AlertManagement end end end - -AlertManagement::AlertsFinder.prepend_mod_with('AlertManagement::AlertsFinder') diff --git a/app/finders/error_tracking/errors_finder.rb b/app/finders/error_tracking/errors_finder.rb deleted file mode 100644 index c361d6e2fc2..00000000000 --- a/app/finders/error_tracking/errors_finder.rb +++ /dev/null @@ -1,46 +0,0 @@ -# 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) - collection = sort(collection) - - collection.keyset_paginate(cursor: params[:cursor], per_page: limit) - 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 - - def sort(collection) - params[:sort] ? collection.sort_by_attribute(params[:sort]) : collection.order_id_desc - end - - def limit - # Restrict the maximum limit at 100 records. - [(params[:limit] || 20).to_i, 100].min - end - end -end diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb index 40d6be03a17..42cd06c8066 100644 --- a/app/finders/group_descendants_finder.rb +++ b/app/finders/group_descendants_finder.rb @@ -112,7 +112,7 @@ class GroupDescendantsFinder group_ids = base_for_ancestors.except(:select, :sort).select(:id) groups = Group.where(id: group_ids) - if Feature.enabled?(:linear_group_descendants_finder_upto, current_user, default_enabled: :yaml) + if Feature.enabled?(:linear_group_descendants_finder_upto, current_user) groups.self_and_ancestors(upto: parent_group.id) else Gitlab::ObjectHierarchy.new(groups).base_and_ancestors(upto: parent_group.id) diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb index 4213a3f1965..048e25046da 100644 --- a/app/finders/group_members_finder.rb +++ b/app/finders/group_members_finder.rb @@ -60,6 +60,10 @@ class GroupMembersFinder < UnionFinder members = members.filter_by_2fa(params[:two_factor]) end + if params[:access_levels].present? + members = members.by_access_level(params[:access_levels]) + end + members = apply_additional_filters(members) by_created_at(members) diff --git a/app/finders/groups/projects_requiring_authorizations_refresh/base.rb b/app/finders/groups/projects_requiring_authorizations_refresh/base.rb new file mode 100644 index 00000000000..c719e6ba903 --- /dev/null +++ b/app/finders/groups/projects_requiring_authorizations_refresh/base.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Groups + module ProjectsRequiringAuthorizationsRefresh + class Base + def initialize(group) + @group = group + end + + private + + def ids_of_projects_in_hierarchy_and_project_shares(group) + project_ids = Set.new + + ids_of_projects_in_hierarchy = group.all_projects.pluck(:id) # rubocop: disable CodeReuse/ActiveRecord + ids_of_projects_in_project_shares = ids_of_projects_shared_with_self_and_descendant_groups(group) + + project_ids.merge(ids_of_projects_in_hierarchy) + project_ids.merge(ids_of_projects_in_project_shares) + + project_ids + end + + def ids_of_projects_shared_with_self_and_descendant_groups(group, batch_size: 50) + project_ids = Set.new + + group.self_and_descendants_ids.each_slice(batch_size) do |group_ids| + project_ids.merge(ProjectGroupLink.in_group(group_ids).pluck(:project_id)) # rubocop: disable CodeReuse/ActiveRecord + end + + project_ids + end + end + end +end diff --git a/app/finders/groups/projects_requiring_authorizations_refresh/on_direct_membership_finder.rb b/app/finders/groups/projects_requiring_authorizations_refresh/on_direct_membership_finder.rb new file mode 100644 index 00000000000..f6b8b999b99 --- /dev/null +++ b/app/finders/groups/projects_requiring_authorizations_refresh/on_direct_membership_finder.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +# Groups::ProjectsRequiringAuthorizationsRefresh::OnDirectMembershipFinder +# +# Given a group, this finder can be used to obtain a list of Project IDs of projects +# that requires their `project_authorizations` records to be refreshed in the event where +# a member has been added/removed/updated in the group. + +module Groups + module ProjectsRequiringAuthorizationsRefresh + class OnDirectMembershipFinder < Base + def execute + project_ids = Set.new + + project_ids.merge(ids_of_projects_in_hierarchy_and_project_shares(@group)) + project_ids.merge(ids_of_projects_in_hierarchy_and_project_shares_of_shared_groups(@group)) + + project_ids.to_a + end + + private + + def ids_of_projects_in_hierarchy_and_project_shares_of_shared_groups(group, batch_size: 10) + project_ids = Set.new + + group.shared_groups.each_batch(of: batch_size) do |shared_groups_batch| + shared_groups_batch.each do |shared_group| + project_ids.merge(ids_of_projects_in_hierarchy_and_project_shares(shared_group)) + end + end + + project_ids + end + end + end +end diff --git a/app/finders/groups/projects_requiring_authorizations_refresh/on_transfer_finder.rb b/app/finders/groups/projects_requiring_authorizations_refresh/on_transfer_finder.rb new file mode 100644 index 00000000000..781e1222287 --- /dev/null +++ b/app/finders/groups/projects_requiring_authorizations_refresh/on_transfer_finder.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +# Groups::ProjectsRequiringAuthorizationsRefresh::OnTransferFinder +# +# Given a group, this finder can be used to obtain a list of Project IDs of projects +# that requires their `project_authorizations` records to be refreshed in the event where +# the group has been transferred. + +module Groups + module ProjectsRequiringAuthorizationsRefresh + class OnTransferFinder < Base + def execute + ids_of_projects_in_hierarchy_and_project_shares(@group).to_a + end + end + end +end diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb index 7cb3e7a5d7f..9a8bc74f435 100644 --- a/app/finders/groups_finder.rb +++ b/app/finders/groups_finder.rb @@ -54,7 +54,7 @@ class GroupsFinder < UnionFinder groups = [] if current_user - if Feature.enabled?(:use_traversal_ids_groups_finder, current_user, default_enabled: :yaml) + if Feature.enabled?(:use_traversal_ids_groups_finder, current_user) groups << current_user.authorized_groups.self_and_ancestors groups << current_user.groups.self_and_descendants else @@ -81,7 +81,7 @@ class GroupsFinder < UnionFinder .groups .where('members.access_level >= ?', params[:min_access_level]) - if Feature.enabled?(:use_traversal_ids_groups_finder, current_user, default_enabled: :yaml) + if Feature.enabled?(:use_traversal_ids_groups_finder, current_user) groups.self_and_descendants else Gitlab::ObjectHierarchy diff --git a/app/finders/incident_management/timeline_events_finder.rb b/app/finders/incident_management/timeline_events_finder.rb new file mode 100644 index 00000000000..09de46bb79f --- /dev/null +++ b/app/finders/incident_management/timeline_events_finder.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module IncidentManagement + class TimelineEventsFinder + def initialize(user, incident, params = {}) + @user = user + @incident = incident + @params = params + end + + def execute + return ::IncidentManagement::TimelineEvent.none unless allowed? + + collection = incident.incident_management_timeline_events + collection = by_id(collection) + sort(collection) + end + + private + + attr_reader :user, :incident, :params + + def allowed? + Ability.allowed?(user, :read_incident_management_timeline_event, incident) + end + + def by_id(collection) + return collection unless params[:id] + + collection.id_in(params[:id]) + end + + def sort(collection) + collection.order_occurred_at_asc + end + end +end diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index bf7b2265ded..fe07a52cbf0 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -348,7 +348,7 @@ class IssuableFinder params[:in].blank? && klass.try(:pg_full_text_searchable_columns).present? && params[:search] =~ FULL_TEXT_SEARCH_TERM_REGEX && - Feature.enabled?(:issues_full_text_search, params.project || params.group, default_enabled: :yaml) + Feature.enabled?(:issues_full_text_search, params.project || params.group) end # rubocop: disable CodeReuse/ActiveRecord @@ -489,7 +489,7 @@ class IssuableFinder def or_filters_enabled? strong_memoize(:or_filters_enabled) do - Feature.enabled?(:or_issuable_queries, feature_flag_scope, default_enabled: :yaml) + Feature.enabled?(:or_issuable_queries, feature_flag_scope) end end diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb index a7eaaddd187..7929c36906d 100644 --- a/app/finders/issues_finder.rb +++ b/app/finders/issues_finder.rb @@ -20,7 +20,6 @@ # sort: string # my_reaction_emoji: string # public_only: boolean -# include_hidden: boolean # due_date: date or '0', '', 'overdue', 'week', or 'month' # created_after: datetime # created_before: datetime @@ -48,6 +47,8 @@ class IssuesFinder < IssuableFinder # rubocop: disable CodeReuse/ActiveRecord def with_confidentiality_access_check + 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 @@ -75,9 +76,7 @@ class IssuesFinder < IssuableFinder private def init_collection - if params.include_hidden? - Issue.all - elsif params.public_only? + if params.public_only? Issue.public_only else with_confidentiality_access_check diff --git a/app/finders/issues_finder/params.rb b/app/finders/issues_finder/params.rb index 57bfb35f1b8..7f8acb79ed6 100644 --- a/app/finders/issues_finder/params.rb +++ b/app/finders/issues_finder/params.rb @@ -6,10 +6,6 @@ class IssuesFinder params.fetch(:public_only, false) end - def include_hidden? - user_can_see_all_issues? - end - def filter_by_any_due_date? due_date? && params[:due_date] == Issue::AnyDueDate.name end diff --git a/app/finders/packages/build_infos_finder.rb b/app/finders/packages/build_infos_finder.rb index 92ad5888eb9..a346c3d754b 100644 --- a/app/finders/packages/build_infos_finder.rb +++ b/app/finders/packages/build_infos_finder.rb @@ -2,33 +2,55 @@ module Packages class BuildInfosFinder + include ActiveRecord::ConnectionAdapters::Quoting + MAX_PAGE_SIZE = 100 - def initialize(package, params) - @package = package + def initialize(package_ids, params) + @package_ids = package_ids @params = params end def execute - build_infos = @package.build_infos.without_empty_pipelines - build_infos = apply_order(build_infos) - build_infos = apply_limit(build_infos) - apply_cursor(build_infos) + return Packages::BuildInfo.none if @package_ids.blank? + + # This is a highly custom query that + # will not be re-used elsewhere + # rubocop: disable CodeReuse/ActiveRecord + query = Packages::Package.id_in(@package_ids) + .select('build_infos.*') + .from([Packages::Package.arel_table, lateral_query.arel.lateral.as('build_infos')]) + .order('build_infos.id DESC') + + # We manually select build_infos fields from the lateral query. + # Thus, we need to instruct ActiveRecord that returned rows are + # actually Packages::BuildInfo objects + Packages::BuildInfo.find_by_sql(query.to_sql) + # rubocop: enable CodeReuse/ActiveRecord end private - def apply_order(build_infos) - order_direction = :desc - order_direction = :asc if last + def lateral_query + order_direction = last ? :asc : :desc - build_infos.order_by_pipeline_id(order_direction) + # This is a highly custom query that + # will not be re-used elsewhere + # rubocop: disable CodeReuse/ActiveRecord + where_condition = Packages::BuildInfo.arel_table[:package_id] + .eq(Arel.sql("#{Packages::Package.table_name}.id")) + build_infos = ::Packages::BuildInfo.without_empty_pipelines + .where(where_condition) + .order(id: order_direction) + .limit(max_rows_per_package_id) + # rubocop: enable CodeReuse/ActiveRecord + apply_cursor(build_infos) end - def apply_limit(build_infos) + def max_rows_per_package_id limit = [first, last, max_page_size, MAX_PAGE_SIZE].compact.min limit += 1 if support_next_page - build_infos.limit(limit) + limit end def apply_cursor(build_infos) diff --git a/app/finders/packages/build_infos_for_many_packages_finder.rb b/app/finders/packages/build_infos_for_many_packages_finder.rb deleted file mode 100644 index 8f9805f51d0..00000000000 --- a/app/finders/packages/build_infos_for_many_packages_finder.rb +++ /dev/null @@ -1,92 +0,0 @@ -# frozen_string_literal: true - -module Packages - # TODO rename to BuildInfosFinder when cleaning up packages_graphql_pipelines_resolver - # https://gitlab.com/gitlab-org/gitlab/-/issues/358432 - class BuildInfosForManyPackagesFinder - include ActiveRecord::ConnectionAdapters::Quoting - - MAX_PAGE_SIZE = 100 - - def initialize(package_ids, params) - @package_ids = package_ids - @params = params - end - - def execute - return Packages::BuildInfo.none if @package_ids.blank? - - # This is a highly custom query that - # will not be re-used elsewhere - # rubocop: disable CodeReuse/ActiveRecord - query = Packages::Package.id_in(@package_ids) - .select('build_infos.*') - .from([Packages::Package.arel_table, lateral_query.arel.lateral.as('build_infos')]) - .order('build_infos.id DESC') - - # We manually select build_infos fields from the lateral query. - # Thus, we need to instruct ActiveRecord that returned rows are - # actually Packages::BuildInfo objects - Packages::BuildInfo.find_by_sql(query.to_sql) - # rubocop: enable CodeReuse/ActiveRecord - end - - private - - def lateral_query - order_direction = last ? :asc : :desc - - # This is a highly custom query that - # will not be re-used elsewhere - # rubocop: disable CodeReuse/ActiveRecord - where_condition = Packages::BuildInfo.arel_table[:package_id] - .eq(Arel.sql("#{Packages::Package.table_name}.id")) - build_infos = ::Packages::BuildInfo.without_empty_pipelines - .where(where_condition) - .order(id: order_direction) - .limit(max_rows_per_package_id) - # rubocop: enable CodeReuse/ActiveRecord - apply_cursor(build_infos) - end - - def max_rows_per_package_id - limit = [first, last, max_page_size, MAX_PAGE_SIZE].compact.min - limit += 1 if support_next_page - limit - end - - def apply_cursor(build_infos) - if before - build_infos.with_pipeline_id_greater_than(before) - elsif after - build_infos.with_pipeline_id_less_than(after) - else - build_infos - end - end - - def first - @params[:first] - end - - def last - @params[:last] - end - - def max_page_size - @params[:max_page_size] - end - - def before - @params[:before] - end - - def after - @params[:after] - end - - def support_next_page - @params[:support_next_page] - end - end -end diff --git a/app/finders/personal_access_tokens_finder.rb b/app/finders/personal_access_tokens_finder.rb index be266045951..7d356c1014c 100644 --- a/app/finders/personal_access_tokens_finder.rb +++ b/app/finders/personal_access_tokens_finder.rb @@ -79,8 +79,6 @@ class PersonalAccessTokensFinder tokens.active when 'inactive' tokens.inactive - when 'active_or_expired' - tokens.not_revoked.expired.or(tokens.active) else tokens end diff --git a/app/finders/projects/serverless/functions_finder.rb b/app/finders/projects/serverless/functions_finder.rb deleted file mode 100644 index f8ccea6b820..00000000000 --- a/app/finders/projects/serverless/functions_finder.rb +++ /dev/null @@ -1,153 +0,0 @@ -# frozen_string_literal: true - -module Projects - module Serverless - class FunctionsFinder - include Gitlab::Utils::StrongMemoize - include ReactiveCaching - - attr_reader :project - - self.reactive_cache_key = ->(finder) { finder.cache_key } - self.reactive_cache_work_type = :external_dependency - self.reactive_cache_worker_finder = ->(_id, *args) { from_cache(*args) } - - MAX_CLUSTERS = 10 - - def initialize(project) - @project = project - end - - def execute - knative_services.flatten.compact - end - - def knative_installed - return knative_installed_from_cluster?(*cache_key) if available_environments.empty? - - states = services_finders.map do |finder| - finder.knative_detected.tap do |state| - return state if state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] # rubocop:disable Cop/AvoidReturnFromBlocks - end - end - - states.any? { |state| state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['installed'] } - end - - def service(environment_scope, name) - knative_service(environment_scope, name)&.first - end - - def invocation_metrics(environment_scope, name) - environment = finders_for_scope(environment_scope).first&.environment - - if environment.present? && environment.prometheus_adapter&.can_query? - func = ::Serverless::Function.new(project, name, environment.deployment_namespace) - environment.prometheus_adapter.query(:knative_invocation, func) - end - end - - def has_prometheus?(environment_scope) - finders_for_scope(environment_scope).any? do |finder| - finder.cluster.integration_prometheus_available? - end - end - - def self.from_cache(project_id) - project = Project.find(project_id) - - new(project) - end - - def cache_key(*args) - [project.id] - end - - def calculate_reactive_cache(*) - # rubocop: disable CodeReuse/ActiveRecord - project.all_clusters.enabled.take(MAX_CLUSTERS).any? do |cluster| - cluster.kubeclient.knative_client.discover - rescue Kubeclient::ResourceNotFoundError - next - end - end - - private - - def knative_installed_from_cluster?(*cache_key) - cached_data = with_reactive_cache_memoized(*cache_key) { |data| data } - - return ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] if cached_data.nil? - - cached_data ? true : false - end - - def with_reactive_cache_memoized(*cache_key) - strong_memoize(:reactive_cache) do - with_reactive_cache(*cache_key) { |data| data } - end - end - - def knative_service(environment_scope, name) - finders_for_scope(environment_scope).map do |finder| - services = finder - .services - .select { |svc| svc["metadata"]["name"] == name } - - attributes = add_metadata(finder, services).first - next unless attributes - - Gitlab::Serverless::Service.new(attributes) - end - end - - def knative_services - services_finders.map do |finder| - attributes = add_metadata(finder, finder.services) - - attributes&.map do |attributes| - Gitlab::Serverless::Service.new(attributes) - end - end - end - - def add_metadata(finder, services) - return if services.nil? - - add_pod_count = services.one? - - services.each do |s| - s["environment_scope"] = finder.cluster.environment_scope - s["environment"] = finder.environment - s["cluster"] = finder.cluster - - if add_pod_count - s["podcount"] = finder - .service_pod_details(s["metadata"]["name"]) - .length - end - end - end - - def services_finders - strong_memoize(:services_finders) do - available_environments.map(&:knative_services_finder).compact - end - end - - def available_environments - @project.environments.available.preload_cluster - end - - def finders_for_scope(environment_scope) - services_finders.select do |finder| - environment_scope == finder.cluster.environment_scope - end - end - - def id - nil - end - end - end -end diff --git a/app/finders/releases_finder.rb b/app/finders/releases_finder.rb index 0d72d6ffc6b..78240e0a050 100644 --- a/app/finders/releases_finder.rb +++ b/app/finders/releases_finder.rb @@ -29,28 +29,14 @@ class ReleasesFinder Release.where(project_id: projects).where.not(tag: nil) # rubocop: disable CodeReuse/ActiveRecord end - def include_subgroups? - params.fetch(:include_subgroups, false) - end - def projects strong_memoize(:projects) do if parent.is_a?(Project) Ability.allowed?(current_user, :read_release, parent) ? [parent] : [] - elsif parent.is_a?(Group) - Ability.allowed?(current_user, :read_release, parent) ? accessible_projects : [] end end end - def accessible_projects - if include_subgroups? - Project.for_group_and_its_subgroups(parent) - else - parent.projects - end - end - # rubocop: disable CodeReuse/ActiveRecord def by_tag(releases) return releases unless params[:tag].present? diff --git a/app/finders/tags_finder.rb b/app/finders/tags_finder.rb index 6bc5419e704..16bba62f766 100644 --- a/app/finders/tags_finder.rb +++ b/app/finders/tags_finder.rb @@ -1,10 +1,6 @@ # frozen_string_literal: true class TagsFinder < GitRefsFinder - def initialize(repository, params) - super(repository, params) - end - def execute(gitaly_pagination: false) tags = if gitaly_pagination repository.tags_sorted_by(sort, pagination_params) diff --git a/app/finders/user_recent_events_finder.rb b/app/finders/user_recent_events_finder.rb index 64903c67573..0f7bf893bb2 100644 --- a/app/finders/user_recent_events_finder.rb +++ b/app/finders/user_recent_events_finder.rb @@ -74,7 +74,12 @@ class UserRecentEventsFinder return Event.none if users.empty? if Feature.enabled?(:optimized_followed_users_queries, current_user) - query_builder_params = event_filter.in_operator_query_builder_params(users) + array_data = { + scope_ids: users, + scope_model: User, + mapping_column: :author_id + } + query_builder_params = event_filter.in_operator_query_builder_params(array_data) Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder .new(**query_builder_params) -- cgit v1.2.3