diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-20 13:00:54 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-20 13:00:54 +0300 |
commit | 3cccd102ba543e02725d247893729e5c73b38295 (patch) | |
tree | f36a04ec38517f5deaaacb5acc7d949688d1e187 /app/finders | |
parent | 205943281328046ef7b4528031b90fbda70c75ac (diff) |
Add latest changes from gitlab-org/gitlab@14-10-stable-eev14.10.0-rc42
Diffstat (limited to 'app/finders')
-rw-r--r-- | app/finders/bulk_imports/entities_finder.rb | 17 | ||||
-rw-r--r-- | app/finders/bulk_imports/imports_finder.rb | 17 | ||||
-rw-r--r-- | app/finders/ci/jobs_finder.rb | 2 | ||||
-rw-r--r-- | app/finders/concerns/finder_methods.rb | 23 | ||||
-rw-r--r-- | app/finders/keys_finder.rb | 10 | ||||
-rw-r--r-- | app/finders/packages/build_infos_for_many_packages_finder.rb | 92 | ||||
-rw-r--r-- | app/finders/packages/group_packages_finder.rb | 6 | ||||
-rw-r--r-- | app/finders/packages/packages_finder.rb | 6 | ||||
-rw-r--r-- | app/finders/releases/group_releases_finder.rb | 44 | ||||
-rw-r--r-- | app/finders/user_recent_events_finder.rb | 16 | ||||
-rw-r--r-- | app/finders/users_finder.rb | 10 |
11 files changed, 173 insertions, 70 deletions
diff --git a/app/finders/bulk_imports/entities_finder.rb b/app/finders/bulk_imports/entities_finder.rb index 2947d155668..78446f104d0 100644 --- a/app/finders/bulk_imports/entities_finder.rb +++ b/app/finders/bulk_imports/entities_finder.rb @@ -2,10 +2,10 @@ module BulkImports class EntitiesFinder - def initialize(user:, bulk_import: nil, status: nil) + def initialize(user:, bulk_import: nil, params: {}) @user = user @bulk_import = bulk_import - @status = status + @params = params end def execute @@ -14,6 +14,7 @@ module BulkImports .by_user_id(user.id) .then(&method(:filter_by_bulk_import)) .then(&method(:filter_by_status)) + .then(&method(:sort)) end private @@ -23,13 +24,19 @@ module BulkImports def filter_by_bulk_import(entities) return entities unless bulk_import - entities.where(bulk_import_id: bulk_import.id) # rubocop: disable CodeReuse/ActiveRecord + entities.by_bulk_import_id(bulk_import.id) end def filter_by_status(entities) - return entities unless ::BulkImports::Entity.all_human_statuses.include?(status) + return entities unless ::BulkImports::Entity.all_human_statuses.include?(@params[:status]) - entities.with_status(status) + entities.with_status(@params[:status]) + end + + def sort(entities) + return entities unless @params[:sort] + + entities.order_by_created_at(@params[:sort]) end end end diff --git a/app/finders/bulk_imports/imports_finder.rb b/app/finders/bulk_imports/imports_finder.rb index b554bbfa5e7..d682080576f 100644 --- a/app/finders/bulk_imports/imports_finder.rb +++ b/app/finders/bulk_imports/imports_finder.rb @@ -2,13 +2,14 @@ module BulkImports class ImportsFinder - def initialize(user:, status: nil) + def initialize(user:, params: {}) @user = user - @status = status + @params = params end def execute - filter_by_status(user.bulk_imports) + imports = filter_by_status(user.bulk_imports) + sort(imports) end private @@ -16,9 +17,15 @@ module BulkImports attr_reader :user, :status def filter_by_status(imports) - return imports unless BulkImport.all_human_statuses.include?(status) + return imports unless BulkImport.all_human_statuses.include?(@params[:status]) - imports.with_status(status) + imports.with_status(@params[:status]) + end + + def sort(imports) + return imports unless @params[:sort] + + imports.order_by_created_at(@params[:sort]) end end end diff --git a/app/finders/ci/jobs_finder.rb b/app/finders/ci/jobs_finder.rb index 5fc9c0e1778..152eb271694 100644 --- a/app/finders/ci/jobs_finder.rb +++ b/app/finders/ci/jobs_finder.rb @@ -76,7 +76,7 @@ module Ci unknown_statuses = params[:scope] - ::CommitStatus::AVAILABLE_STATUSES raise ArgumentError, 'Scope contains invalid value(s)' unless unknown_statuses.empty? - builds.where(status: params[:scope]) # rubocop: disable CodeReuse/ActiveRecord + builds.with_statuses(params[:scope]) end def jobs_by_type(relation, type) diff --git a/app/finders/concerns/finder_methods.rb b/app/finders/concerns/finder_methods.rb index 193b52b1694..ce6001a01d7 100644 --- a/app/finders/concerns/finder_methods.rb +++ b/app/finders/concerns/finder_methods.rb @@ -13,16 +13,23 @@ module FinderMethods end # rubocop: enable CodeReuse/ActiveRecord + # rubocop: disable CodeReuse/ActiveRecord def find(*args) - raise_not_found_unless_authorized model.find(*args) + raise_not_found_unless_authorized execute.reorder(nil).find(*args) end + # rubocop: enable CodeReuse/ActiveRecord private def raise_not_found_unless_authorized(result) result = if_authorized(result) - raise(ActiveRecord::RecordNotFound, "Couldn't find #{model}") unless result + unless result + # This fetches the model from the `ActiveRecord::Relation` but does not + # actually execute the query. + model = execute.model + raise ActiveRecord::RecordNotFound, "Couldn't find #{model}" + end result end @@ -32,11 +39,7 @@ module FinderMethods # this is currently the case in the `MilestoneFinder` return result unless respond_to?(:current_user, true) - if can_read_object?(result) - result - else - nil - end + result if can_read_object?(result) end def can_read_object?(object) @@ -53,10 +56,4 @@ module FinderMethods # Not all objects define `#to_ability_name`, so attempt to derive it: object.model_name.singular end - - # This fetches the model from the `ActiveRecord::Relation` but does not - # actually execute the query. - def model - execute.model - end end diff --git a/app/finders/keys_finder.rb b/app/finders/keys_finder.rb index 9c357e12205..4b5cc02f012 100644 --- a/app/finders/keys_finder.rb +++ b/app/finders/keys_finder.rb @@ -52,11 +52,11 @@ class KeysFinder end def valid_fingerprint_param? - if fingerprint_type == "sha256" - Base64.decode64(fingerprint).length == 32 - else - fingerprint =~ /^(\h{2}:){15}\h{2}/ - end + return Base64.decode64(fingerprint).length == 32 if fingerprint_type == "sha256" + + return false if Gitlab::FIPS.enabled? + + fingerprint =~ /^(\h{2}:){15}\h{2}/ end def fingerprint_query diff --git a/app/finders/packages/build_infos_for_many_packages_finder.rb b/app/finders/packages/build_infos_for_many_packages_finder.rb new file mode 100644 index 00000000000..8f9805f51d0 --- /dev/null +++ b/app/finders/packages/build_infos_for_many_packages_finder.rb @@ -0,0 +1,92 @@ +# 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/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb index 23b0e71d836..1d1ae59674a 100644 --- a/app/finders/packages/group_packages_finder.rb +++ b/app/finders/packages/group_packages_finder.rb @@ -22,11 +22,11 @@ module Packages def packages_for_group_projects(installable_only: false) packages = ::Packages::Package - .preload_pipelines .including_project_route .including_tags .for_projects(group_projects_visible_to_current_user.select(:id)) .sort_by_attribute("#{params[:order_by]}_#{params[:sort]}") + packages = packages.preload_pipelines if preload_pipelines packages = filter_with_version(packages) packages = filter_by_package_type(packages) @@ -59,5 +59,9 @@ module Packages def exclude_subgroups? params[:exclude_subgroups] end + + def preload_pipelines + params.fetch(:preload_pipelines, true) + end end end diff --git a/app/finders/packages/packages_finder.rb b/app/finders/packages/packages_finder.rb index 3bc348c8dc8..b3d14e15953 100644 --- a/app/finders/packages/packages_finder.rb +++ b/app/finders/packages/packages_finder.rb @@ -14,9 +14,9 @@ module Packages def execute packages = project.packages - .preload_pipelines .including_project_route .including_tags + packages = packages.preload_pipelines if preload_pipelines packages = filter_with_version(packages) packages = filter_by_package_type(packages) @@ -32,5 +32,9 @@ module Packages def order_packages(packages) packages.sort_by_attribute("#{params[:order_by]}_#{params[:sort]}") end + + def preload_pipelines + params.fetch(:preload_pipelines, true) + end end end diff --git a/app/finders/releases/group_releases_finder.rb b/app/finders/releases/group_releases_finder.rb index d87ba8c0b03..8b1b0c552fd 100644 --- a/app/finders/releases/group_releases_finder.rb +++ b/app/finders/releases/group_releases_finder.rb @@ -6,9 +6,8 @@ module Releases # # order_by - only ordering by released_at is supported # filter by tag - currently not supported + # include_subgroups - always true for group releases finder class GroupReleasesFinder - include Gitlab::Utils::StrongMemoize - attr_reader :parent, :current_user, :params def initialize(parent, current_user = nil, params = {}) @@ -16,59 +15,34 @@ module Releases @current_user = current_user @params = params - params[:order_by] ||= 'released_at' params[:sort] ||= 'desc' - params[:page] ||= 0 - params[:per] ||= 30 end def execute(preload: true) return Release.none unless Ability.allowed?(current_user, :read_release, parent) - releases = get_releases(preload: preload) - - paginate_releases(releases) + releases = get_releases + releases.preloaded if preload + releases end private - def include_subgroups? - params.fetch(:include_subgroups, false) - end - - def accessible_projects_scope - if include_subgroups? - Project.for_group_and_its_subgroups(parent) - else - parent.projects - end - end - # rubocop: disable CodeReuse/ActiveRecord - def get_releases(preload: true) + def get_releases Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder.new( - scope: releases_scope(preload: preload), - array_scope: accessible_projects_scope.select(:id), + scope: releases_scope, + array_scope: Project.for_group_and_its_subgroups(parent).select(:id), array_mapping_scope: -> (project_id_expression) { Release.where(Release.arel_table[:project_id].eq(project_id_expression)) }, finder_query: -> (order_by, id_expression) { Release.where(Release.arel_table[:id].eq(id_expression)) } ) .execute end - def releases_scope(preload: true) - scope = Release.all - scope = order_releases(scope) - scope = scope.preloaded if preload - scope - end - - def order_releases(scope) - scope.sort_by_attribute("released_at_#{params[:sort]}").order(id: params[:sort]) + def releases_scope + Release.sort_by_attribute("released_at_#{params[:sort]}").order(id: params[:sort]) end - def paginate_releases(releases) - releases.page(params[:page].to_i).per(params[:per]) - end # rubocop: enable CodeReuse/ActiveRecord end end diff --git a/app/finders/user_recent_events_finder.rb b/app/finders/user_recent_events_finder.rb index 96120d9412f..64903c67573 100644 --- a/app/finders/user_recent_events_finder.rb +++ b/app/finders/user_recent_events_finder.rb @@ -73,10 +73,20 @@ class UserRecentEventsFinder return Event.none if users.empty? - if event_filter.filter == EventFilter::ALL - execute_optimized_multi(users) + if Feature.enabled?(:optimized_followed_users_queries, current_user) + query_builder_params = event_filter.in_operator_query_builder_params(users) + + Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder + .new(**query_builder_params) + .execute + .limit(limit) + .offset(params[:offset] || 0) else - event_filter.apply_filter(Event.where(author: users).limit_recent(limit, params[:offset] || 0)) + if event_filter.filter == EventFilter::ALL + execute_optimized_multi(users) + else + event_filter.apply_filter(Event.where(author: users).limit_recent(limit, params[:offset] || 0)) + end end end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb index b983882b272..9c2462b42a6 100644 --- a/app/finders/users_finder.rb +++ b/app/finders/users_finder.rb @@ -47,6 +47,7 @@ class UsersFinder users = by_without_projects(users) users = by_custom_attributes(users) users = by_non_internal(users) + users = by_without_project_bots(users) order(users) end @@ -54,7 +55,8 @@ class UsersFinder private def base_scope - User.all.order_id_desc + scope = current_user&.admin? ? User.all : User.without_forbidden_states + scope.order_id_desc end def by_username(users) @@ -138,6 +140,12 @@ class UsersFinder users.non_internal end + def by_without_project_bots(users) + return users unless params[:without_project_bots] + + users.without_project_bot + end + # rubocop: disable CodeReuse/ActiveRecord def order(users) return users unless params[:sort] |