From 05f0ebba3a2c8ddf39e436f412dc2ab5bf1353b2 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 18 Jan 2023 19:00:14 +0000 Subject: Add latest changes from gitlab-org/gitlab@15-8-stable-ee --- app/graphql/resolvers/ci/jobs_resolver.rb | 7 ++++- app/graphql/resolvers/ci/runner_groups_resolver.rb | 2 +- .../resolvers/concerns/board_item_filterable.rb | 1 + .../resolvers/concerns/caching_array_resolver.rb | 1 + .../concerns/issues/look_ahead_preloads.rb | 5 ++- .../resolvers/concerns/resolves_merge_requests.rb | 2 +- app/graphql/resolvers/concerns/search_arguments.rb | 23 ++++++++++++++ app/graphql/resolvers/issues/base_resolver.rb | 21 +++++-------- app/graphql/resolvers/issues_resolver.rb | 16 ++++++++++ .../resolvers/projects/branch_rules_resolver.rb | 10 +++++- app/graphql/resolvers/timelog_resolver.rb | 36 ++++++++++++++++------ app/graphql/resolvers/work_items_resolver.rb | 2 +- 12 files changed, 98 insertions(+), 28 deletions(-) (limited to 'app/graphql/resolvers') diff --git a/app/graphql/resolvers/ci/jobs_resolver.rb b/app/graphql/resolvers/ci/jobs_resolver.rb index 91f29948ad0..31cc350f331 100644 --- a/app/graphql/resolvers/ci/jobs_resolver.rb +++ b/app/graphql/resolvers/ci/jobs_resolver.rb @@ -19,10 +19,15 @@ module Resolvers required: false, description: 'Filter jobs by retry-status.' - def resolve(statuses: nil, security_report_types: [], retried: nil) + argument :when_executed, [::GraphQL::Types::String], + required: false, + description: 'Filter jobs by when they are executed.' + + def resolve(statuses: nil, security_report_types: [], retried: nil, when_executed: nil) jobs = init_collection(security_report_types) jobs = jobs.with_status(statuses) if statuses.present? jobs = jobs.retried if retried + jobs = jobs.with_when_executed(when_executed) if when_executed.present? jobs = jobs.latest if retried == false jobs diff --git a/app/graphql/resolvers/ci/runner_groups_resolver.rb b/app/graphql/resolvers/ci/runner_groups_resolver.rb index 3360e820bd2..c1d9bcbb9bb 100644 --- a/app/graphql/resolvers/ci/runner_groups_resolver.rb +++ b/app/graphql/resolvers/ci/runner_groups_resolver.rb @@ -6,7 +6,7 @@ module Resolvers include Gitlab::Graphql::Authorize::AuthorizeResource include ResolvesGroups - type Types::GroupConnection, null: true + type 'Types::GroupConnection', null: true authorize :read_runner authorizes_object! diff --git a/app/graphql/resolvers/concerns/board_item_filterable.rb b/app/graphql/resolvers/concerns/board_item_filterable.rb index 9c0ada4f72c..035cdbbd282 100644 --- a/app/graphql/resolvers/concerns/board_item_filterable.rb +++ b/app/graphql/resolvers/concerns/board_item_filterable.rb @@ -22,6 +22,7 @@ module BoardItemFilterable rewrite_param_name(filters[:or], :author_usernames, :author_username) rewrite_param_name(filters[:or], :assignee_usernames, :assignee_username) + rewrite_param_name(filters[:or], :label_names, :label_name) end filters diff --git a/app/graphql/resolvers/concerns/caching_array_resolver.rb b/app/graphql/resolvers/concerns/caching_array_resolver.rb index e7555dcf42c..62649518142 100644 --- a/app/graphql/resolvers/concerns/caching_array_resolver.rb +++ b/app/graphql/resolvers/concerns/caching_array_resolver.rb @@ -63,6 +63,7 @@ module CachingArrayResolver queries.in_groups_of(max_union_size, false).each do |group| by_id = model_class + .select(all_fields, :union_member_idx) .from_union(tag(group), remove_duplicates: false) .preload(preload) # rubocop: disable CodeReuse/ActiveRecord .group_by { |r| r[primary_key] } diff --git a/app/graphql/resolvers/concerns/issues/look_ahead_preloads.rb b/app/graphql/resolvers/concerns/issues/look_ahead_preloads.rb index c6e32be245d..2ea7a02bf15 100644 --- a/app/graphql/resolvers/concerns/issues/look_ahead_preloads.rb +++ b/app/graphql/resolvers/concerns/issues/look_ahead_preloads.rb @@ -20,7 +20,7 @@ module Issues end def preloads - { + preload_hash = { alert_management_alert: [:alert_management_alert], assignees: [:assignees], participants: Issue.participant_includes, @@ -28,6 +28,9 @@ module Issues customer_relations_contacts: { customer_relations_contacts: [:group] }, escalation_status: [:incident_management_issuable_escalation_status] } + preload_hash[:type] = :work_item_type if Feature.enabled?(:issue_type_uses_work_item_types_table) + + preload_hash end end end diff --git a/app/graphql/resolvers/concerns/resolves_merge_requests.rb b/app/graphql/resolvers/concerns/resolves_merge_requests.rb index d56951bc821..c68e120ee24 100644 --- a/app/graphql/resolvers/concerns/resolves_merge_requests.rb +++ b/app/graphql/resolvers/concerns/resolves_merge_requests.rb @@ -34,7 +34,7 @@ module ResolvesMergeRequests end def unconditional_includes - [:target_project] + [:target_project, :author] end def preloads diff --git a/app/graphql/resolvers/concerns/search_arguments.rb b/app/graphql/resolvers/concerns/search_arguments.rb index ccc012f2bf9..cc1a13fdf29 100644 --- a/app/graphql/resolvers/concerns/search_arguments.rb +++ b/app/graphql/resolvers/concerns/search_arguments.rb @@ -18,6 +18,7 @@ module SearchArguments def ready?(**args) validate_search_in_params!(args) validate_anonymous_search_access!(args) + validate_search_rate_limit!(args) super end @@ -39,6 +40,28 @@ module SearchArguments '`search` should be present when including the `in` argument' end + def validate_search_rate_limit!(args) + return if args[:search].blank? || context[:request].nil? || Feature.disabled?(:rate_limit_issuable_searches) + + if current_user.present? + rate_limiter_key = :search_rate_limit + rate_limiter_scope = [current_user] + else + rate_limiter_key = :search_rate_limit_unauthenticated + rate_limiter_scope = [context[:request].ip] + end + + if ::Gitlab::ApplicationRateLimiter.throttled_request?( + context[:request], + current_user, + rate_limiter_key, + scope: rate_limiter_scope + ) + raise Gitlab::Graphql::Errors::ResourceNotAvailable, + 'This endpoint has been requested with the search argument too many times. Try again later.' + end + end + def prepare_finder_params(args) prepare_search_params(args) end diff --git a/app/graphql/resolvers/issues/base_resolver.rb b/app/graphql/resolvers/issues/base_resolver.rb index 9a2c4572abb..fefd17d5e20 100644 --- a/app/graphql/resolvers/issues/base_resolver.rb +++ b/app/graphql/resolvers/issues/base_resolver.rb @@ -129,7 +129,8 @@ module Resolvers params[:or] = params[:or].to_h if params[:or] params[:iids] ||= [params.delete(:iid)].compact if params[:iid] - prepare_author_username_params(params) + rewrite_param_name(params[:or], :author_usernames, :author_username) + rewrite_param_name(params[:or], :label_names, :label_name) prepare_assignee_username_params(params) prepare_release_tag_params(params) @@ -143,20 +144,14 @@ module Resolvers args[:release_tag] ||= release_tag_wildcard end - def prepare_author_username_params(args) - args[:or][:author_username] = args[:or].delete(:author_usernames) if args.dig(:or, :author_usernames).present? - end - def prepare_assignee_username_params(args) - args[:assignee_username] = args.delete(:assignee_usernames) if args[:assignee_usernames].present? - - if args.dig(:or, :assignee_usernames).present? - args[:or][:assignee_username] = args[:or].delete(:assignee_usernames) - end - - return unless args.dig(:not, :assignee_usernames).present? + rewrite_param_name(args, :assignee_usernames, :assignee_username) + rewrite_param_name(args[:or], :assignee_usernames, :assignee_username) + rewrite_param_name(args[:not], :assignee_usernames, :assignee_username) + end - args[:not][:assignee_username] = args[:not].delete(:assignee_usernames) + def rewrite_param_name(params, old_name, new_name) + params[new_name] = params.delete(old_name) if params && params[old_name].present? end def mutually_exclusive_release_tag_args diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb index 3e61ba755d8..24009bf7e18 100644 --- a/app/graphql/resolvers/issues_resolver.rb +++ b/app/graphql/resolvers/issues_resolver.rb @@ -5,6 +5,8 @@ module Resolvers prepend ::Issues::LookAheadPreloads include ::Issues::SortArguments + NON_FILTER_ARGUMENTS = %i[sort lookahead].freeze + argument :state, Types::IssuableStateEnum, required: false, description: 'Current state of this issue.' @@ -17,6 +19,14 @@ module Resolvers ::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute end + def ready?(**args) + unless filter_provided?(args) + raise Gitlab::Graphql::Errors::ArgumentError, _('You must provide at least one filter argument for this query') + end + + super + end + def resolve_with_lookahead(**args) return unless Feature.enabled?(:root_level_issues_query) @@ -32,5 +42,11 @@ module Resolvers issues end end + + private + + def filter_provided?(args) + args.except(*NON_FILTER_ARGUMENTS).values.any?(&:present?) + end end end diff --git a/app/graphql/resolvers/projects/branch_rules_resolver.rb b/app/graphql/resolvers/projects/branch_rules_resolver.rb index e99d7ae4d5f..d1b39df602f 100644 --- a/app/graphql/resolvers/projects/branch_rules_resolver.rb +++ b/app/graphql/resolvers/projects/branch_rules_resolver.rb @@ -10,7 +10,15 @@ module Resolvers alias_method :project, :object def resolve_with_lookahead(**args) - apply_lookahead(project.protected_branches) + protected_branches.map do |protected_branch| + ::Projects::BranchRule.new(project, protected_branch) + end + end + + private + + def protected_branches + apply_lookahead(project.protected_branches.sorted_by_name) end end end diff --git a/app/graphql/resolvers/timelog_resolver.rb b/app/graphql/resolvers/timelog_resolver.rb index 52c4508003a..dc42a5f38c9 100644 --- a/app/graphql/resolvers/timelog_resolver.rb +++ b/app/graphql/resolvers/timelog_resolver.rb @@ -34,19 +34,23 @@ module Resolvers required: false, description: 'List timelogs for a user.' + argument :sort, Types::TimeTracking::TimelogSortEnum, + description: 'List timelogs in a particular order.', + required: false, + default_value: { field: 'spent_at', direction: :asc } + def resolve_with_lookahead(**args) validate_args!(object, args) - timelogs = object&.timelogs || Timelog.limit(GitlabSchema.default_max_page_size) + timelogs = object&.timelogs || Timelog.all - if args.any? - args = parse_datetime_args(args) + args = parse_datetime_args(args) - timelogs = apply_user_filter(timelogs, args) - timelogs = apply_project_filter(timelogs, args) - timelogs = apply_time_filter(timelogs, args) - timelogs = apply_group_filter(timelogs, args) - end + timelogs = apply_user_filter(timelogs, args) + timelogs = apply_project_filter(timelogs, args) + timelogs = apply_time_filter(timelogs, args) + timelogs = apply_group_filter(timelogs, args) + timelogs = apply_sorting(timelogs, args) apply_lookahead(timelogs) end @@ -60,7 +64,12 @@ module Resolvers end def validate_args!(object, args) - if args.empty? && object.nil? + # sort is always provided because of its default value so we + # should check the remaining args to make sure at least one filter + # argument was provided + cleaned_args = args.except(:sort) + + if cleaned_args.empty? && object.nil? raise_argument_error('Provide at least one argument') elsif args[:start_time] && args[:start_date] raise_argument_error('Provide either a start date or time, but not both') @@ -132,6 +141,15 @@ module Resolvers timelogs end + def apply_sorting(timelogs, args) + return timelogs unless args[:sort] + + field = args[:sort][:field] + direction = args[:sort][:direction] + + timelogs.sort_by_field(field, direction) + end + def raise_argument_error(message) raise Gitlab::Graphql::Errors::ArgumentError, message end diff --git a/app/graphql/resolvers/work_items_resolver.rb b/app/graphql/resolvers/work_items_resolver.rb index a3de875c196..83ed8c37250 100644 --- a/app/graphql/resolvers/work_items_resolver.rb +++ b/app/graphql/resolvers/work_items_resolver.rb @@ -55,7 +55,7 @@ module Resolvers last_edited_by: :last_edited_by, assignees: :assignees, parent: :work_item_parent, - children: { work_item_children: [:author, { project: :project_feature }] }, + children: { work_item_children_by_created_at: [:author, { project: :project_feature }] }, labels: :labels, milestone: :milestone } -- cgit v1.2.1