diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-18 13:50:51 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-18 13:50:51 +0300 |
commit | db384e6b19af03b4c3c82a5760d83a3fd79f7982 (patch) | |
tree | 34beaef37df5f47ccbcf5729d7583aae093cffa0 /app/finders | |
parent | 54fd7b1bad233e3944434da91d257fa7f63c3996 (diff) |
Add latest changes from gitlab-org/gitlab@16-3-stable-eev16.3.0-rc42
Diffstat (limited to 'app/finders')
24 files changed, 361 insertions, 152 deletions
diff --git a/app/finders/abuse_reports_finder.rb b/app/finders/abuse_reports_finder.rb index 6a6d0413194..43cebd16d92 100644 --- a/app/finders/abuse_reports_finder.rb +++ b/app/finders/abuse_reports_finder.rb @@ -3,9 +3,13 @@ class AbuseReportsFinder attr_reader :params, :reports - DEFAULT_STATUS_FILTER = 'open' - DEFAULT_SORT = 'created_at_desc' - ALLOWED_SORT = [DEFAULT_SORT, *%w[created_at_asc updated_at_desc updated_at_asc]].freeze + STATUS_OPEN = 'open' + + DEFAULT_SORT_STATUS_CLOSED = 'created_at_desc' + ALLOWED_SORT = [DEFAULT_SORT_STATUS_CLOSED, *%w[created_at_asc updated_at_desc updated_at_asc]].freeze + + DEFAULT_SORT_STATUS_OPEN = 'number_of_reports_desc' + SORT_BY_COUNT = [DEFAULT_SORT_STATUS_OPEN].freeze def initialize(params = {}) @params = params @@ -14,6 +18,7 @@ class AbuseReportsFinder def execute filter_reports + aggregate_reports sort_reports reports.with_users.page(params[:page]) @@ -22,20 +27,28 @@ class AbuseReportsFinder private def filter_reports - filter_by_user_id + if Feature.disabled?(:abuse_reports_list) + filter_by_user_id + return + end + filter_by_status filter_by_user filter_by_reporter - filter_by_status filter_by_category end + def filter_by_user_id + return unless params[:user_id].present? + + @reports = @reports.by_user_id(params[:user_id]) + end + def filter_by_status - return unless Feature.enabled?(:abuse_reports_list) return unless params[:status].present? status = params[:status] - status = DEFAULT_STATUS_FILTER unless status.in?(AbuseReport.statuses.keys) + status = STATUS_OPEN unless status.in?(AbuseReport.statuses.keys) case status when 'open' @@ -69,10 +82,13 @@ class AbuseReportsFinder @reports = @reports.by_reporter_id(user_id) end - def filter_by_user_id - return unless params[:user_id].present? + def sort_key + sort_key = params[:sort] - @reports = @reports.by_user_id(params[:user_id]) + return sort_key if sort_key.in?(ALLOWED_SORT + SORT_BY_COUNT) + return DEFAULT_SORT_STATUS_OPEN if status_open? + + DEFAULT_SORT_STATUS_CLOSED end def sort_reports @@ -81,13 +97,31 @@ class AbuseReportsFinder return end - sort_by = params[:sort] - sort_by = DEFAULT_SORT unless sort_by.in?(ALLOWED_SORT) + # let sub_query in aggregate_reports do the sorting if sorting by number of reports + return if sort_key.in?(SORT_BY_COUNT) - @reports = @reports.order_by(sort_by) + @reports = @reports.order_by(sort_key) end def find_user_id(username) User.by_username(username).pick(:id) end + + def status_open? + return unless Feature.enabled?(:abuse_reports_list) && params[:status].present? + + status = params[:status] + status = STATUS_OPEN unless status.in?(AbuseReport.statuses.keys) + + status == STATUS_OPEN + end + + def aggregate_reports + if status_open? + sort_by_count = sort_key.in?(SORT_BY_COUNT) + @reports = @reports.aggregated_by_user_and_category(sort_by_count) + end + + @reports + end end diff --git a/app/finders/admin/abuse_report_labels_finder.rb b/app/finders/admin/abuse_report_labels_finder.rb new file mode 100644 index 00000000000..f8ca40f77b2 --- /dev/null +++ b/app/finders/admin/abuse_report_labels_finder.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Admin + class AbuseReportLabelsFinder + def initialize(current_user, params = {}) + @current_user = current_user + @params = params + end + + def execute + return Admin::AbuseReportLabel.none unless current_user&.can_admin_all_resources? + + items = Admin::AbuseReportLabel.all + items = by_search(items) + + items.order(title: :asc) # rubocop: disable CodeReuse/ActiveRecord + end + + private + + attr_reader :current_user, :params + + def by_search(labels) + return labels unless search_term + + labels.search(search_term) + end + + def search_term + params[:search_term] + end + end +end diff --git a/app/finders/autocomplete/group_users_finder.rb b/app/finders/autocomplete/group_users_finder.rb new file mode 100644 index 00000000000..b24f3f7f032 --- /dev/null +++ b/app/finders/autocomplete/group_users_finder.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +# This finder returns all users that are related to a given group because: +# 1. They are members of the group, its sub-groups, or its ancestor groups +# 2. They are members of a group that is invited to the group, its sub-groups, or its ancestors +# 3. They are members of a project that belongs to the group +# 4. They are members of a group that is invited to the group's descendant projects +# +# These users are not necessarily members of the given group and may not have access to the group +# so this should not be used for access control +module Autocomplete + class GroupUsersFinder + include Gitlab::Utils::StrongMemoize + + def initialize(group:) + @group = group + end + + def execute + members = Member + .with(group_hierarchy_cte.to_arel) # rubocop:disable CodeReuse/ActiveRecord + .with(descendant_projects_cte.to_arel) # rubocop:disable CodeReuse/ActiveRecord + .from_union(member_relations, remove_duplicates: false) + + User + .id_in(members.select(:user_id)) + .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/420387") + end + + private + + def member_relations + [ + members_from_group_hierarchy.select(:user_id), + members_from_hierarchy_group_shares.select(:user_id), + members_from_descendant_projects.select(:user_id), + members_from_descendant_project_shares.select(:user_id) + ] + end + + def members_from_group_hierarchy + GroupMember + .with_source_id(group_hierarchy_ids) + .without_invites_and_requests + end + + def members_from_hierarchy_group_shares + invited_groups = GroupGroupLink.for_shared_groups(group_hierarchy_ids).select(:shared_with_group_id) + + GroupMember + .with_source_id(invited_groups) + .without_invites_and_requests + end + + def members_from_descendant_projects + ProjectMember + .with_source_id(descendant_project_ids) + .without_invites_and_requests + end + + def members_from_descendant_project_shares + descendant_project_invited_groups = ProjectGroupLink.for_projects(descendant_project_ids).select(:group_id) + + GroupMember + .with_source_id(descendant_project_invited_groups) + .without_invites_and_requests + end + + def group_hierarchy_cte + Gitlab::SQL::CTE.new(:group_hierarchy, @group.self_and_hierarchy.select(:id)) + end + strong_memoize_attr :group_hierarchy_cte + + def group_hierarchy_ids + Namespace.from(group_hierarchy_cte.table).select(:id) # rubocop:disable CodeReuse/ActiveRecord + end + + def descendant_projects_cte + Gitlab::SQL::CTE.new(:descendant_projects, @group.all_projects.select(:id)) + end + strong_memoize_attr :descendant_projects_cte + + def descendant_project_ids + Project.from(descendant_projects_cte.table).select(:id) # rubocop:disable CodeReuse/ActiveRecord + end + end +end diff --git a/app/finders/autocomplete/routes_finder.rb b/app/finders/autocomplete/routes_finder.rb index ecede0c1c1c..ed807d3a295 100644 --- a/app/finders/autocomplete/routes_finder.rb +++ b/app/finders/autocomplete/routes_finder.rb @@ -19,6 +19,7 @@ module Autocomplete .for_routable(routables) .sort_by_path_length .fuzzy_search(@search, [:path]) + .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/421843') .limit(LIMIT) # rubocop: disable CodeReuse/ActiveRecord end @@ -30,9 +31,11 @@ module Autocomplete class NamespacesOnly < self def routables - return Namespace.without_project_namespaces if current_user.can_admin_all_resources? - - current_user.namespaces + if current_user.can_admin_all_resources? + Namespace.without_project_namespaces + else + current_user.namespaces + end.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/420046") end end diff --git a/app/finders/autocomplete/users_finder.rb b/app/finders/autocomplete/users_finder.rb index 7ecf5c98ac0..e7a24cde2bd 100644 --- a/app/finders/autocomplete/users_finder.rb +++ b/app/finders/autocomplete/users_finder.rb @@ -10,21 +10,21 @@ module Autocomplete # ensure good performance. LIMIT = 20 - attr_reader :current_user, :project, :group, :search, :skip_users, + attr_reader :current_user, :project, :group, :search, :author_id, :todo_filter, :todo_state_filter, - :filter_by_current_user, :states + :filter_by_current_user, :states, :push_code def initialize(params:, current_user:, project:, group:) @current_user = current_user @project = project @group = group @search = params[:search] - @skip_users = params[:skip_users] @author_id = params[:author_id] @todo_filter = params[:todo_filter] @todo_state_filter = params[:todo_state_filter] @filter_by_current_user = params[:current_user] @states = params[:states] || ['active'] + @push_code = params[:push_code] end def execute @@ -39,6 +39,8 @@ module Autocomplete end end + items = filter_users_by_push_ability(items) + items.uniq.tap do |unique_items| preload_associations(unique_items) end @@ -65,7 +67,6 @@ module Autocomplete .non_internal .reorder_by_name .optionally_search(search, use_minimum_char_limit: use_minimum_char_limit) - .where_not_in(skip_users) .limit_to_todo_authors( user: current_user, with_todos: todo_filter, @@ -88,7 +89,7 @@ module Autocomplete if project project.authorized_users.union_with_user(author_id) elsif group - group.users_with_parents + ::Autocomplete::GroupUsersFinder.new(group: group).execute # rubocop: disable CodeReuse/Finder elsif current_user User.all else @@ -96,6 +97,12 @@ module Autocomplete end end + def filter_users_by_push_ability(items) + return items unless project && push_code.present? + + items.select { |user| user.can?(:push_code, project) } + end + # rubocop: disable CodeReuse/ActiveRecord def preload_associations(items) ActiveRecord::Associations::Preloader.new(records: items, associations: :status).call @@ -109,5 +116,3 @@ module Autocomplete end end end - -Autocomplete::UsersFinder.prepend_mod_with('Autocomplete::UsersFinder') diff --git a/app/finders/deployments_finder.rb b/app/finders/deployments_finder.rb index 800158dfd0a..9881cb3fc74 100644 --- a/app/finders/deployments_finder.rb +++ b/app/finders/deployments_finder.rb @@ -25,7 +25,7 @@ class DeploymentsFinder # performant with the other filtering/sorting parameters. # The composed query could be significantly slower when the filtering and sorting columns are different. # See https://gitlab.com/gitlab-org/gitlab/-/issues/325627 for example. - ALLOWED_SORT_VALUES = %w[id iid created_at updated_at ref finished_at].freeze + ALLOWED_SORT_VALUES = %w[id iid created_at updated_at finished_at].freeze DEFAULT_SORT_VALUE = 'id' ALLOWED_SORT_DIRECTIONS = %w[asc desc].freeze @@ -128,7 +128,6 @@ class DeploymentsFinder def build_sort_params order_by = ALLOWED_SORT_VALUES.include?(params[:order_by]) ? params[:order_by] : DEFAULT_SORT_VALUE - order_by = DEFAULT_SORT_VALUE if order_by == 'ref' && Feature.enabled?(:remove_deployments_api_ref_sort) order_direction = ALLOWED_SORT_DIRECTIONS.include?(params[:sort]) ? params[:sort] : DEFAULT_SORT_DIRECTION { order_by => order_direction } diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb index 72ab30cf567..3e31c7a2bb2 100644 --- a/app/finders/group_descendants_finder.rb +++ b/app/finders/group_descendants_finder.rb @@ -141,7 +141,7 @@ class GroupDescendantsFinder # rubocop: disable CodeReuse/Finder def direct_child_projects - GroupProjectsFinder.new(group: parent_group, current_user: current_user, params: params, options: { only_owned: true }) + GroupProjectsFinder.new(group: parent_group, current_user: current_user, params: params, options: { exclude_shared: true }) .execute end # rubocop: enable CodeReuse/Finder diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb index 1025e0ebc9b..639db58b00d 100644 --- a/app/finders/group_members_finder.rb +++ b/app/finders/group_members_finder.rb @@ -86,11 +86,6 @@ class GroupMembersFinder < UnionFinder end def members_of_groups(groups, shared_from_groups) - if Feature.disabled?(:members_with_shared_group_access, @group.root_ancestor) - groups << shared_from_groups unless shared_from_groups.nil? - return GroupMember.non_request.of_groups(find_union(groups, Group)) - end - members = GroupMember.non_request.of_groups(find_union(groups, Group)) return members if shared_from_groups.nil? diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb index db8a0f14fbc..21341797910 100644 --- a/app/finders/group_projects_finder.rb +++ b/app/finders/group_projects_finder.rb @@ -9,8 +9,10 @@ # project_ids_relation: int[] - project ids to use # group # options: -# only_owned: boolean +# exclude_shared: boolean +# When true, only projects within the group are included in the result. # only_shared: boolean +# When true, only projects arising from group-project shares are included in the result. # limit: integer # include_subgroups: boolean # include_ancestor_groups: boolean @@ -63,10 +65,10 @@ class GroupProjectsFinder < ProjectsFinder projects = if only_shared? [shared_projects] - elsif only_owned? - [owned_projects] + elsif exclude_shared? + [projects_within_group] else - [owned_projects, shared_projects] + [projects_within_group, shared_projects] end projects.map! do |project_relation| @@ -104,8 +106,8 @@ class GroupProjectsFinder < ProjectsFinder end end - def only_owned? - options.fetch(:only_owned, false) + def exclude_shared? + options.fetch(:exclude_shared, false) end def owned_projects? @@ -126,7 +128,7 @@ class GroupProjectsFinder < ProjectsFinder options.fetch(:include_ancestor_groups, false) end - def owned_projects + def projects_within_group return group.projects unless include_subgroups? || include_ancestor_groups? union_relations = [] diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb index 63f7616884f..074eb9add0f 100644 --- a/app/finders/groups_finder.rb +++ b/app/finders/groups_finder.rb @@ -32,14 +32,8 @@ class GroupsFinder < UnionFinder end def execute - items = all_groups.map do |item| - item = by_parent(item) - item = by_custom_attributes(item) - item = filter_group_ids(item) - item = exclude_group_ids(item) - item = by_search(item) - - item + items = all_groups.map do |groups| + filter_groups(groups) end find_union(items, Group).with_route.order_id_desc @@ -49,6 +43,14 @@ class GroupsFinder < UnionFinder attr_reader :current_user, :params + def filter_groups(groups) + groups = by_parent(groups) + groups = by_custom_attributes(groups) + groups = filter_group_ids(groups) + groups = exclude_group_ids(groups) + by_search(groups) + end + def all_groups return [owned_groups] if params[:owned] return [groups_with_min_access_level] if min_access_level? @@ -147,3 +149,5 @@ class GroupsFinder < UnionFinder groups end end + +GroupsFinder.prepend_mod_with('GroupsFinder') diff --git a/app/finders/issuable_finder/params.rb b/app/finders/issuable_finder/params.rb index e59c2224594..bc136848dd5 100644 --- a/app/finders/issuable_finder/params.rb +++ b/app/finders/issuable_finder/params.rb @@ -133,7 +133,7 @@ class IssuableFinder def projects strong_memoize(:projects) do - next [project] if project? + next Array.wrap(project) if project? projects = if current_user && params[:authorized_only].presence && !current_user_related? diff --git a/app/finders/issuables/assignee_filter.rb b/app/finders/issuables/assignee_filter.rb index c97fdffd32e..5efcd5aa23e 100644 --- a/app/finders/issuables/assignee_filter.rb +++ b/app/finders/issuables/assignee_filter.rb @@ -5,8 +5,6 @@ module Issuables def filter(issuables) filtered = by_assignee(issuables) filtered = by_assignee_union(filtered) - # Cross Joins Fails tests in bin/rspec spec/requests/api/graphql/boards/board_list_issues_query_spec.rb - filtered = filtered.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417462") by_negated_assignee(filtered) end @@ -74,7 +72,7 @@ module Issuables elsif specific_params[:assignee_id].present? Array(specific_params[:assignee_id]) elsif specific_params[:assignee_username].present? - User.by_username(specific_params[:assignee_username]).select(:id) + User.by_username(specific_params[:assignee_username]).pluck_primary_key end end end diff --git a/app/finders/issuables/author_filter.rb b/app/finders/issuables/author_filter.rb index f36daae553d..7707bf51f18 100644 --- a/app/finders/issuables/author_filter.rb +++ b/app/finders/issuables/author_filter.rb @@ -15,6 +15,7 @@ module Issuables issuables.authored(params[:author_id]) elsif params[:author_username].present? issuables.authored(User.by_username(params[:author_username])) + .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/419221") else issuables end @@ -24,6 +25,7 @@ module Issuables return issuables unless or_filters_enabled? && or_params&.fetch(:author_username, false).present? issuables.authored(User.by_username(or_params[:author_username])) + .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/419221") end def by_negated_author(issuables) @@ -33,6 +35,7 @@ module Issuables issuables.not_authored(not_params[:author_id]) elsif not_params[:author_username].present? issuables.not_authored(User.by_username(not_params[:author_username])) + .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/419221") else issuables end diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb index bd81f06f93b..0ba93a76342 100644 --- a/app/finders/issues_finder.rb +++ b/app/finders/issues_finder.rb @@ -72,6 +72,7 @@ class IssuesFinder < IssuableFinder OR EXISTS (:authorizations)))', user_id: current_user.id, authorizations: current_user.authorizations_for_projects(min_access_level: CONFIDENTIAL_ACCESS_LEVEL, related_project_column: "issues.project_id")) + .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/422045') end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb index b1387f2a104..1bf2e3b71e4 100644 --- a/app/finders/labels_finder.rb +++ b/app/finders/labels_finder.rb @@ -24,6 +24,7 @@ class LabelsFinder < UnionFinder items = with_title(items) items = by_subscription(items) items = by_search(items) + items = by_locked_labels(items) items = items.with_preloaded_container if @preload_parent_association sort(items) @@ -94,6 +95,12 @@ class LabelsFinder < UnionFinder labels.optionally_subscribed_by(subscriber_id) end + def by_locked_labels(items) + return items unless params[:locked_labels] + + items.with_lock_on_merge + end + def subscriber_id current_user&.id if subscribed? end diff --git a/app/finders/merge_request_target_project_finder.rb b/app/finders/merge_request_target_project_finder.rb index ea1aa6d2e9e..ee340b79ed0 100644 --- a/app/finders/merge_request_target_project_finder.rb +++ b/app/finders/merge_request_target_project_finder.rb @@ -14,7 +14,8 @@ class MergeRequestTargetProjectFinder def execute(search: nil, include_routes: false) if source_project.fork_network items = include_routes ? projects.inc_routes : projects - by_search(items, search) + by_search(items, search).allow_cross_joins_across_databases( + url: "https://gitlab.com/gitlab-org/gitlab/-/issues/420046") else Project.id_in(source_project.id) end @@ -39,3 +40,5 @@ class MergeRequestTargetProjectFinder end # rubocop: enable CodeReuse/ActiveRecord end + +MergeRequestTargetProjectFinder.prepend_mod_with("MergeRequestTargetProjectFinder") diff --git a/app/finders/metrics/dashboards/annotations_finder.rb b/app/finders/metrics/dashboards/annotations_finder.rb deleted file mode 100644 index e97704738ea..00000000000 --- a/app/finders/metrics/dashboards/annotations_finder.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -module Metrics - module Dashboards - class AnnotationsFinder - def initialize(dashboard:, params:) - @dashboard = dashboard - @params = params - end - - def execute - if dashboard.environment - apply_filters_to(annotations_for_environment) - else - Metrics::Dashboard::Annotation.none - end - end - - private - - attr_reader :dashboard, :params - - def apply_filters_to(annotations) - annotations = annotations.after(params[:from]) if params[:from].present? - annotations = annotations.before(params[:to]) if params[:to].present? && valid_timespan_boundaries? - - by_dashboard(annotations) - end - - def annotations_for_environment - dashboard.environment.metrics_dashboard_annotations - end - - def by_dashboard(annotations) - annotations.for_dashboard(dashboard.path) - end - - def valid_timespan_boundaries? - params[:from].blank? || params[:to] >= params[:from] - end - end - end -end diff --git a/app/finders/metrics/users_starred_dashboards_finder.rb b/app/finders/metrics/users_starred_dashboards_finder.rb deleted file mode 100644 index 2ef706c1b11..00000000000 --- a/app/finders/metrics/users_starred_dashboards_finder.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -module Metrics - class UsersStarredDashboardsFinder - def initialize(user:, project:, params: {}) - @user = user - @project = project - @params = params - end - - def execute - return ::Metrics::UsersStarredDashboard.none unless Ability.allowed?(user, :read_metrics_user_starred_dashboard, project) - - items = starred_dashboards - items = by_project(items) - by_dashboard(items) - end - - private - - attr_reader :user, :project, :params - - def by_project(items) - items.for_project(project) - end - - def by_dashboard(items) - return items unless params[:dashboard_path] - - items.merge(starred_dashboards.for_project_dashboard(project, params[:dashboard_path])) - end - - def starred_dashboards - @starred_dashboards ||= user.metrics_users_starred_dashboards - end - end -end diff --git a/app/finders/packages/nuget/package_finder.rb b/app/finders/packages/nuget/package_finder.rb index 23345f29198..064698d3c37 100644 --- a/app/finders/packages/nuget/package_finder.rb +++ b/app/finders/packages/nuget/package_finder.rb @@ -4,19 +4,43 @@ module Packages module Nuget class PackageFinder < ::Packages::GroupOrProjectPackageFinder MAX_PACKAGES_COUNT = 300 + FORCE_NORMALIZATION_CLIENT_VERSION = '>= 3' def execute + return ::Packages::Package.none unless @params[:package_name].present? + packages.limit_recent(@params[:limit] || MAX_PACKAGES_COUNT) end private def packages - result = base.nuget - .has_version - .with_name_like(@params[:package_name]) - result = result.with_case_insensitive_version(@params[:package_version]) if @params[:package_version].present? + result = find_by_name + find_by_version(result) + end + + def find_by_name + base + .nuget + .has_version + .with_case_insensitive_name(@params[:package_name]) + end + + def find_by_version(result) + return result if @params[:package_version].blank? + result + .with_nuget_version_or_normalized_version( + @params[:package_version], + with_normalized: Feature.enabled?(:nuget_normalized_version, @project_or_group) && + client_forces_normalized_version? + ) + end + + def client_forces_normalized_version? + return true if @params[:client_version].blank? + + VersionSorter.compare(FORCE_NORMALIZATION_CLIENT_VERSION, @params[:client_version]) <= 0 end end end diff --git a/app/finders/packages/pipelines_finder.rb b/app/finders/packages/pipelines_finder.rb new file mode 100644 index 00000000000..c814efbf176 --- /dev/null +++ b/app/finders/packages/pipelines_finder.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Packages + class PipelinesFinder + COLUMNS = %i[id iid project_id sha ref status source created_at updated_at user_id].freeze + + def initialize(pipeline_ids) + @pipeline_ids = pipeline_ids + end + + def execute + ::Ci::Pipeline + .id_in(pipeline_ids) + .select(COLUMNS) + .order_id_desc + end + + private + + attr_reader :pipeline_ids + end +end diff --git a/app/finders/projects/ml/model_finder.rb b/app/finders/projects/ml/model_finder.rb index 9ef5dacb551..99c66f53de7 100644 --- a/app/finders/projects/ml/model_finder.rb +++ b/app/finders/projects/ml/model_finder.rb @@ -8,12 +8,9 @@ module Projects end def execute - @project - .packages - .installable - .ml_model - .order_name_desc_version_desc - .select_only_first_by_name + ::Ml::Model + .by_project(@project) + .including_latest_version .limit(100) # This is a temporary limit before we add pagination end end diff --git a/app/finders/repositories/tree_finder.rb b/app/finders/repositories/tree_finder.rb index 231c1de1513..2a8971d4d86 100644 --- a/app/finders/repositories/tree_finder.rb +++ b/app/finders/repositories/tree_finder.rb @@ -13,7 +13,7 @@ module Repositories def execute(gitaly_pagination: false) raise CommitMissingError unless commit_exists? - request_params = { recursive: recursive } + request_params = { recursive: recursive, rescue_not_found: rescue_not_found } request_params[:pagination_params] = pagination_params if gitaly_pagination repository.tree(commit.id, path, **request_params).sorted_entries @@ -51,6 +51,10 @@ module Repositories params[:recursive] end + def rescue_not_found + params[:rescue_not_found] + end + def pagination_params { limit: params[:per_page] || Kaminari.config.default_per_page, diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb index 9dd7e508c22..cb824aca33f 100644 --- a/app/finders/snippets_finder.rb +++ b/app/finders/snippets_finder.rb @@ -67,17 +67,30 @@ class SnippetsFinder < UnionFinder return Snippet.none if project.nil? && params[:project].present? return Snippet.none if project && !project.feature_available?(:snippets, current_user) - items = init_collection - items = by_ids(items) - items = items.with_optional_visibility(visibility_from_scope) - items = by_created_at(items) - - items.order_by(sort_param) + filter_snippets.order_by(sort_param) end private - def init_collection + def filter_snippets + if return_all_available_and_permited? + snippets = all_snippets_for_admin + else + snippets = all_snippets + snippets = by_ids(snippets) + snippets = snippets.with_optional_visibility(visibility_from_scope) + end + + by_created_at(snippets) + end + + def return_all_available_and_permited? + # Currently limited to access_levels `admin` and `auditor` + # See policies/base_policy.rb files for specifics. + params[:all_available] && current_user&.can_read_all_resources? + end + + def all_snippets if explore? snippets_for_explore elsif only_personal? @@ -121,6 +134,12 @@ class SnippetsFinder < UnionFinder prepared_union(queries) end + def all_snippets_for_admin + return Snippet.only_project_snippets if only_project? + + Snippet.all + end + def snippets_for_a_single_project Snippet.for_project_with_user(project, current_user) end @@ -182,10 +201,10 @@ class SnippetsFinder < UnionFinder end end - def by_ids(items) - return items unless params[:ids].present? + def by_ids(snippets) + return snippets unless params[:ids].present? - items.id_in(params[:ids]) + snippets.id_in(params[:ids]) end def author diff --git a/app/finders/work_items/namespace_work_items_finder.rb b/app/finders/work_items/namespace_work_items_finder.rb new file mode 100644 index 00000000000..aad99d710b6 --- /dev/null +++ b/app/finders/work_items/namespace_work_items_finder.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module WorkItems + class NamespaceWorkItemsFinder < WorkItemsFinder + def initialize(...) + super + + self.parent_param = namespace + end + + def execute + items = init_collection + items = by_namespace(items) + + sort(items) + end + + override :with_confidentiality_access_check + def with_confidentiality_access_check + return model_class.all if params.user_can_see_all_issuables? + + # Only admins can see hidden issues, so for non-admins, we filter out any hidden issues + issues = model_class.without_hidden + + return issues.all if params.user_can_see_all_confidential_issues? + + return issues.public_only if params.user_cannot_see_confidential_issues? + + issues.with_confidentiality_check(current_user) + end + + private + + def by_namespace(items) + if namespace.blank? || !Ability.allowed?(current_user, "read_#{namespace.to_ability_name}".to_sym, namespace) + return klass.none + end + + items.in_namespaces(namespace) + end + + def namespace + return if params[:namespace_id].blank? + + params[:namespace_id].is_a?(Namespace) ? params[:namespace_id] : Namespace.find_by_id(params[:namespace_id]) + end + strong_memoize_attr :namespace + end +end |