diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-19 15:57:54 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-19 15:57:54 +0300 |
commit | 419c53ec62de6e97a517abd5fdd4cbde3a942a34 (patch) | |
tree | 1f43a548b46bca8a5fb8fe0c31cef1883d49c5b6 /app/graphql/resolvers | |
parent | 1da20d9135b3ad9e75e65b028bffc921aaf8deb7 (diff) |
Add latest changes from gitlab-org/gitlab@16-5-stable-eev16.5.0-rc42
Diffstat (limited to 'app/graphql/resolvers')
24 files changed, 164 insertions, 57 deletions
diff --git a/app/graphql/resolvers/achievements/user_achievements_for_user_resolver.rb b/app/graphql/resolvers/achievements/user_achievements_for_user_resolver.rb new file mode 100644 index 00000000000..673babcf14a --- /dev/null +++ b/app/graphql/resolvers/achievements/user_achievements_for_user_resolver.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Resolvers + module Achievements + # rubocop:disable Graphql/ResolverType -- the type is inherited from the parent class + class UserAchievementsForUserResolver < UserAchievementsResolver + def resolve_with_lookahead + super.order_by_priority_asc + end + end + # rubocop:enable Graphql/ResolverType + end +end diff --git a/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb b/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb index b5a19d38b9c..0c9607d9413 100644 --- a/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb +++ b/app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb @@ -7,7 +7,7 @@ module Resolvers class MeasurementsResolver < BaseResolver include Gitlab::Graphql::Authorize::AuthorizeResource - type Types::Admin::Analytics::UsageTrends::MeasurementType, null: true + type Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type, null: true argument :identifier, Types::Admin::Analytics::UsageTrends::MeasurementIdentifierEnum, required: true, diff --git a/app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb b/app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb index 8128023aecb..768265752d5 100644 --- a/app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb +++ b/app/graphql/resolvers/analytics/cycle_analytics/base_issue_resolver.rb @@ -48,3 +48,5 @@ module Resolvers end end end + +Resolvers::Analytics::CycleAnalytics::BaseIssueResolver.prepend_mod diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb index 6f847221f1b..17db91a685f 100644 --- a/app/graphql/resolvers/base_resolver.rb +++ b/app/graphql/resolvers/base_resolver.rb @@ -11,26 +11,25 @@ module Resolvers @requires_argument = true end + def self.requires_argument? + !!@requires_argument + end + def self.calls_gitaly! @calls_gitaly = true end + def self.calls_gitaly? + !!@calls_gitaly + end + # This is a flag to allow us to use `complexity_multiplier` to compute complexity for connection # fields(see BaseField#connection_complexity_multiplier) in resolvers that do external connection pagination, - # thus disabling the default `connection` option(see self.field_options method above). + # thus disabling the default `connection` option. def self.calculate_ext_conn_complexity false end - def self.field_options - extra_options = { - requires_argument: @requires_argument, - calls_gitaly: @calls_gitaly - }.compact - - super.merge(extra_options) - end - def self.singular_type return unless type @@ -63,8 +62,13 @@ module Resolvers type parent.singular_type, null: true def ready?(**args) - ready, early_return = super - [ready, select_result(early_return)] + value = super + + if value.is_a?(Array) + [value[0], select_result(value[1])] + else + value + end end def resolve(**args) diff --git a/app/graphql/resolvers/blobs_resolver.rb b/app/graphql/resolvers/blobs_resolver.rb index 546eeb76ff5..27a15381b43 100644 --- a/app/graphql/resolvers/blobs_resolver.rb +++ b/app/graphql/resolvers/blobs_resolver.rb @@ -36,7 +36,7 @@ module Resolvers ref ||= repository.root_ref validate_ref(ref) - ref = ExtractsRef.qualify_ref(ref, ref_type) + ref = ExtractsRef::RefExtractor.qualify_ref(ref, ref_type) repository.blobs_at(paths.map { |path| [ref, path] }).tap do |blobs| blobs.each do |blob| diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb index ec6ede58cf5..8c85a6aebea 100644 --- a/app/graphql/resolvers/ci/config_resolver.rb +++ b/app/graphql/resolvers/ci/config_resolver.rb @@ -30,11 +30,20 @@ module Resolvers required: false, description: 'Run pipeline creation simulation, or only do static check.' - def resolve(project_path:, content:, sha: nil, dry_run: false) + argument :skip_verify_project_sha, GraphQL::Types::Boolean, + required: false, + alpha: { milestone: '16.5' }, + description: "If the provided `sha` is found in the project's repository but is not " \ + "associated with a Git reference (a detached commit), the verification fails and a " \ + "validation error is returned. Otherwise, verification passes, even if the `sha` is " \ + "invalid. Set to `true` to skip this verification process." + + def resolve(project_path:, content:, sha: nil, dry_run: false, skip_verify_project_sha: false) project = authorized_find!(project_path: project_path) result = ::Gitlab::Ci::Lint - .new(project: project, current_user: context[:current_user], sha: sha) + .new(project: project, current_user: context[:current_user], sha: sha, + verify_project_sha: !skip_verify_project_sha) .validate(content, dry_run: dry_run) response(result) diff --git a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb index 0b9422db2a9..313d71aa345 100644 --- a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb +++ b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb @@ -3,7 +3,7 @@ module Resolvers module Clusters class AgentTokensResolver < BaseResolver - type Types::Clusters::AgentTokenType, null: true + type Types::Clusters::AgentTokenType.connection_type, null: true alias_method :agent, :object diff --git a/app/graphql/resolvers/concerns/caching_array_resolver.rb b/app/graphql/resolvers/concerns/caching_array_resolver.rb index 62649518142..15bf9a90e46 100644 --- a/app/graphql/resolvers/concerns/caching_array_resolver.rb +++ b/app/graphql/resolvers/concerns/caching_array_resolver.rb @@ -22,7 +22,7 @@ # # **important**: If the cardinality of your collection is likely to be greater than 100, # then you will want to pass `max_page_size:` as part of the field definition -# or (ideally) as part of the resolver `field_options`. +# or (ideally) set `max_page_size` in the resolver. # # How to implement: # -------------------- diff --git a/app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb b/app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb index 92fb9ec5cef..71833fbd2b9 100644 --- a/app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb +++ b/app/graphql/resolvers/concerns/work_items/look_ahead_preloads.rb @@ -14,7 +14,8 @@ module WorkItems { work_item_type: :work_item_type, web_url: { namespace: :route, project: [:project_namespace, { namespace: :route }] }, - widgets: { work_item_type: :enabled_widget_definitions } + widgets: { work_item_type: :enabled_widget_definitions }, + archived: :project } end @@ -48,7 +49,8 @@ module WorkItems { project: [:project_feature, :group] }, - :author + :author, + *super ] end end diff --git a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb index 793b73342ab..187cb15ccc5 100644 --- a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb +++ b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb @@ -4,7 +4,6 @@ module Resolvers module ErrorTracking class SentryErrorsResolver < BaseResolver type Types::ErrorTracking::SentryErrorType.connection_type, null: true - extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension argument :search_term, ::GraphQL::Types::String, description: 'Search query for the Sentry error details.', @@ -31,10 +30,6 @@ module Resolvers Gitlab::Graphql::ExternallyPaginatedArray.new(previous_cursor, next_cursor, *issues) end - - def self.field_options - super.merge(connection: false) # we manage the pagination manually, so opt out of the connection field extension - end end end end diff --git a/app/graphql/resolvers/group_issues_resolver.rb b/app/graphql/resolvers/group_issues_resolver.rb index 7bbc662c6c8..5e0fb27bafa 100644 --- a/app/graphql/resolvers/group_issues_resolver.rb +++ b/app/graphql/resolvers/group_issues_resolver.rb @@ -11,7 +11,11 @@ module Resolvers before_connection_authorization do |nodes, _| projects = nodes.map(&:project) - ActiveRecord::Associations::Preloader.new(records: projects, associations: :namespace).call + ActiveRecord::Associations::Preloader.new(records: projects, associations: project_associations).call + end + + def self.project_associations + [:namespace] end def ready?(**args) @@ -24,3 +28,5 @@ module Resolvers end end # rubocop:enable Graphql/ResolverType + +Resolvers::GroupIssuesResolver.prepend_mod diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb index 589366ba26d..34f14eee0e5 100644 --- a/app/graphql/resolvers/issues_resolver.rb +++ b/app/graphql/resolvers/issues_resolver.rb @@ -23,7 +23,11 @@ module Resolvers projects = nodes.map(&:project) ::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute ::Preloaders::GroupPolicyPreloader.new(projects.filter_map(&:group), current_user).execute - ActiveRecord::Associations::Preloader.new(records: projects, associations: :namespace).call + ActiveRecord::Associations::Preloader.new(records: projects, associations: project_associations).call + end + + def self.project_associations + [:namespace] end def ready?(**args) @@ -62,3 +66,5 @@ module Resolvers end end end + +Resolvers::IssuesResolver.prepend_mod diff --git a/app/graphql/resolvers/kas/agent_configurations_resolver.rb b/app/graphql/resolvers/kas/agent_configurations_resolver.rb index 74c5cbe55f1..6e35f64c2ee 100644 --- a/app/graphql/resolvers/kas/agent_configurations_resolver.rb +++ b/app/graphql/resolvers/kas/agent_configurations_resolver.rb @@ -3,7 +3,7 @@ module Resolvers module Kas class AgentConfigurationsResolver < BaseResolver - type Types::Kas::AgentConfigurationType, null: true + type Types::Kas::AgentConfigurationType.connection_type, null: true # Calls Gitaly via KAS calls_gitaly! diff --git a/app/graphql/resolvers/last_commit_resolver.rb b/app/graphql/resolvers/last_commit_resolver.rb index acf7826ab13..ff5701ede8c 100644 --- a/app/graphql/resolvers/last_commit_resolver.rb +++ b/app/graphql/resolvers/last_commit_resolver.rb @@ -12,7 +12,7 @@ module Resolvers # Ensure merge commits can be returned by sending nil to Gitaly instead of '/' path = tree.path == '/' ? nil : tree.path commit = Gitlab::Git::Commit.last_for_path(tree.repository, - ExtractsRef.qualify_ref(tree.sha, tree.ref_type), path, literal_pathspec: true) + ExtractsRef::RefExtractor.qualify_ref(tree.sha, tree.ref_type), path, literal_pathspec: true) ::Commit.new(commit, tree.repository.project) if commit end diff --git a/app/graphql/resolvers/merge_request_pipelines_resolver.rb b/app/graphql/resolvers/merge_request_pipelines_resolver.rb index deb698c63e1..45159e0edd5 100644 --- a/app/graphql/resolvers/merge_request_pipelines_resolver.rb +++ b/app/graphql/resolvers/merge_request_pipelines_resolver.rb @@ -11,9 +11,7 @@ module Resolvers # Return at most 500 pipelines for each MR. # Merge requests generally have many fewer pipelines than this. - def self.field_options - super.merge(max_page_size: 500) - end + max_page_size 500 def resolve(**args) return unless project diff --git a/app/graphql/resolvers/noteable/notes_resolver.rb b/app/graphql/resolvers/noteable/notes_resolver.rb index 0d25c747ffb..b4bd1068723 100644 --- a/app/graphql/resolvers/noteable/notes_resolver.rb +++ b/app/graphql/resolvers/noteable/notes_resolver.rb @@ -7,6 +7,11 @@ module Resolvers type Types::Notes::NoteType.connection_type, null: false + argument :filter, Types::WorkItems::NotesFilterTypeEnum, + required: false, + default_value: ::UserPreference::NOTES_FILTERS[:all_notes], + description: 'Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY.' + before_connection_authorization do |nodes, current_user| next if nodes.blank? @@ -16,8 +21,9 @@ module Resolvers ::Preloaders::Projects::NotesPreloader.new(project, current_user).call(nodes) end - def resolve_with_lookahead(*) - apply_lookahead(object.notes.fresh) + def resolve_with_lookahead(**args) + notes = NotesFinder.new(current_user, build_params(args)).execute + apply_lookahead(notes) end private @@ -31,6 +37,17 @@ module Resolvers award_emoji: [:award_emoji] } end + + def build_params(args) + params = { + project: object.project, + target: object + } + + params[:notes_filter] = args[:filter] if args[:filter].present? + + params + end end end end diff --git a/app/graphql/resolvers/package_pipelines_resolver.rb b/app/graphql/resolvers/package_pipelines_resolver.rb index 7f610915489..40e5456164a 100644 --- a/app/graphql/resolvers/package_pipelines_resolver.rb +++ b/app/graphql/resolvers/package_pipelines_resolver.rb @@ -5,7 +5,7 @@ module Resolvers include Gitlab::Graphql::Authorize::AuthorizeResource type Types::Ci::PipelineType.connection_type, null: true - extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension + extras [:lookahead] authorizes_object! authorize :read_pipeline @@ -41,14 +41,6 @@ module Resolvers end end - # we manage the pagination manually, so opt out of the connection field extension - def self.field_options - super.merge( - connection: false, - extras: [:lookahead] - ) - end - private def lazy_load_pipeline(id) @@ -59,6 +51,7 @@ module Resolvers def default_value_for(first:, last:, after:, before:) Gitlab::Graphql::Pagination::ActiveRecordArrayConnection.new( [], + context: context, first: first, last: last, after: after, diff --git a/app/graphql/resolvers/paginated_tree_resolver.rb b/app/graphql/resolvers/paginated_tree_resolver.rb index de48fbafb04..48c94c144dd 100644 --- a/app/graphql/resolvers/paginated_tree_resolver.rb +++ b/app/graphql/resolvers/paginated_tree_resolver.rb @@ -3,7 +3,6 @@ module Resolvers class PaginatedTreeResolver < BaseResolver type Types::Tree::TreeType.connection_type, null: true - extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension calls_gitaly! @@ -50,9 +49,5 @@ module Resolvers extensions: { code: e.code, gitaly_code: e.status, service: e.service } ) end - - def self.field_options - super.merge(connection: false) # we manage the pagination manually, so opt out of the connection field extension - end end end diff --git a/app/graphql/resolvers/project_packages_protection_rules_resolver.rb b/app/graphql/resolvers/project_packages_protection_rules_resolver.rb new file mode 100644 index 00000000000..5d3d0fbf79d --- /dev/null +++ b/app/graphql/resolvers/project_packages_protection_rules_resolver.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Resolvers + class ProjectPackagesProtectionRulesResolver < BaseResolver + type Types::Packages::Protection::RuleType.connection_type, null: true + + alias_method :project, :object + + def resolve(**_args) + return [] if Feature.disabled?(:packages_protected_packages, project) + + project.package_protection_rules + end + end +end diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb index 08981f2c441..8dd409a8173 100644 --- a/app/graphql/resolvers/projects_resolver.rb +++ b/app/graphql/resolvers/projects_resolver.rb @@ -4,7 +4,7 @@ module Resolvers class ProjectsResolver < BaseResolver include ProjectSearchArguments - type Types::ProjectType, null: true + type Types::ProjectType.connection_type, null: true argument :ids, [GraphQL::Types::ID], required: false, diff --git a/app/graphql/resolvers/user_notes_count_resolver.rb b/app/graphql/resolvers/user_notes_count_resolver.rb index b91815c72f5..ebc54a1c6e8 100644 --- a/app/graphql/resolvers/user_notes_count_resolver.rb +++ b/app/graphql/resolvers/user_notes_count_resolver.rb @@ -20,7 +20,7 @@ module Resolvers def authorized_resource?(object) ability = "read_#{object.class.name.underscore}".to_sym - context[:current_user].present? && Ability.allowed?(context[:current_user], ability, object) + Ability.allowed?(context[:current_user], ability, object) end end end diff --git a/app/graphql/resolvers/work_items/ancestors_resolver.rb b/app/graphql/resolvers/work_items/ancestors_resolver.rb new file mode 100644 index 00000000000..33adbfc9c86 --- /dev/null +++ b/app/graphql/resolvers/work_items/ancestors_resolver.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Resolvers + module WorkItems + class AncestorsResolver < BaseResolver + prepend ::WorkItems::LookAheadPreloads + + type Types::WorkItemType.connection_type, null: true + + def resolve_with_lookahead + ancestors = object.ancestors + return WorkItem.none unless ancestors + + truncate_ancestors(apply_lookahead(ancestors)).reverse! + end + + private + + def truncate_ancestors(ancestors) + # Iterate from closest ancestor until root or first missing ancestor + authorized = authorized_ancestors(ancestors) + + previous_ancestor = object.work_item + authorized.take_while do |ancestor| + is_direct_parent = previous_ancestor.work_item_parent.id == ancestor.id + previous_ancestor = ancestor + + is_direct_parent + end + end + + def authorized_ancestors(ancestors) + preload_resource_parents(ancestors) + + DeclarativePolicy.user_scope do + ancestors.select { |ancestor| Ability.allowed?(current_user, :read_work_item, ancestor) } + end + end + + def preload_resource_parents(work_items) + projects = work_items.filter_map(&:project) + namespaces = work_items.filter_map(&:namespace) + group_namespaces = namespaces.select { |n| n.type == ::Group.sti_name } + + ::Preloaders::GroupPolicyPreloader.new(group_namespaces, current_user).execute if group_namespaces.any? + return unless projects.any? + + ::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute + ::Preloaders::GroupPolicyPreloader.new(projects.filter_map(&:namespace), current_user).execute + ActiveRecord::Associations::Preloader.new(records: projects, associations: [:namespace]).call + end + + def unconditional_includes + [:namespace, :work_item_parent, :work_item_type] + end + end + end +end diff --git a/app/graphql/resolvers/work_items/linked_items_resolver.rb b/app/graphql/resolvers/work_items/linked_items_resolver.rb index 35a6974163a..108d5d41b62 100644 --- a/app/graphql/resolvers/work_items/linked_items_resolver.rb +++ b/app/graphql/resolvers/work_items/linked_items_resolver.rb @@ -28,7 +28,7 @@ module Resolvers private def related_work_items(type) - return [] unless work_item.project.linked_work_items_feature_flag_enabled? + return [] unless work_item.resource_parent.linked_work_items_feature_flag_enabled? work_item.linked_work_items(current_user, preload: { project: [:project_feature, :group] }, link_type: type) end diff --git a/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb b/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb index b40d85e8003..0bbd51a537e 100644 --- a/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb +++ b/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb @@ -4,7 +4,6 @@ module Resolvers module WorkItems class WorkItemDiscussionsResolver < BaseResolver include Gitlab::Graphql::Authorize::AuthorizeResource - extension Gitlab::Graphql::Extensions::ForwardOnlyExternallyPaginatedArrayExtension authorize :read_work_item authorizes_object! @@ -31,11 +30,6 @@ module Resolvers ) end - def self.field_options - # we manage the pagination manually through external array, so opt out of the connection field extension - super.merge(connection: false) - end - def self.calculate_ext_conn_complexity true end |