diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-20 14:18:08 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-20 14:18:08 +0300 |
commit | 5afcbe03ead9ada87621888a31a62652b10a7e4f (patch) | |
tree | 9918b67a0d0f0bafa6542e839a8be37adf73102d /app/graphql/resolvers | |
parent | c97c0201564848c1f53226fe19d71fdcc472f7d0 (diff) |
Add latest changes from gitlab-org/gitlab@16-4-stable-eev16.4.0-rc42
Diffstat (limited to 'app/graphql/resolvers')
15 files changed, 291 insertions, 54 deletions
diff --git a/app/graphql/resolvers/blame_resolver.rb b/app/graphql/resolvers/blame_resolver.rb new file mode 100644 index 00000000000..f8b985e6582 --- /dev/null +++ b/app/graphql/resolvers/blame_resolver.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +module Resolvers + class BlameResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource + + type Types::Blame::BlameType, null: true + calls_gitaly! + + argument :from_line, GraphQL::Types::Int, + required: false, + default_value: 1, + description: 'Range starting from the line. Cannot be less than 1 or greater than `to_line`.' + argument :to_line, GraphQL::Types::Int, + required: false, + default_value: 1, + description: 'Range ending on the line. Cannot be less than 1 or less than `to_line`.' + + alias_method :blob, :object + + def ready?(**args) + validate_line_params!(args) if feature_enabled? + + super + end + + def resolve(from_line:, to_line:) + return unless feature_enabled? + + authorize! + + Gitlab::Blame.new(blob, blob.repository.commit(blob.commit_id), + range: (from_line..to_line)) + end + + private + + def authorize! + read_code? || raise_resource_not_available_error! + end + + def read_code? + Ability.allowed?(current_user, :read_code, blob.repository.project) + end + + def feature_enabled? + Feature.enabled?(:graphql_git_blame, blob.repository.project) + end + + def validate_line_params!(args) + if args[:from_line] <= 0 || args[:to_line] <= 0 + raise Gitlab::Graphql::Errors::ArgumentError, + '`from_line` and `to_line` must be greater than or equal to 1' + end + + return unless args[:from_line] > args[:to_line] + + raise Gitlab::Graphql::Errors::ArgumentError, + '`to_line` must be greater than or equal to `from_line`' + end + end +end diff --git a/app/graphql/resolvers/ci/all_jobs_resolver.rb b/app/graphql/resolvers/ci/all_jobs_resolver.rb index 5d0193e0e1c..3012a7defa6 100644 --- a/app/graphql/resolvers/ci/all_jobs_resolver.rb +++ b/app/graphql/resolvers/ci/all_jobs_resolver.rb @@ -11,14 +11,24 @@ module Resolvers required: false, description: 'Filter jobs by status.' - def resolve_with_lookahead(statuses: nil) - jobs = ::Ci::JobsFinder.new(current_user: current_user, params: { scope: statuses }).execute + argument :runner_types, [::Types::Ci::RunnerTypeEnum], + required: false, + alpha: { milestone: '16.4' }, + description: 'Filter jobs by runner type if ' \ + 'feature flag `:admin_jobs_filter_runner_type` is enabled.' + + def resolve_with_lookahead(**args) + jobs = ::Ci::JobsFinder.new(current_user: current_user, params: params_data(args)).execute apply_lookahead(jobs) end private + def params_data(args) + { scope: args[:statuses], runner_type: args[:runner_types] } + end + def preloads { previous_stage_jobs_or_needs: [:needs, :pipeline], @@ -32,9 +42,21 @@ module Resolvers browse_artifacts_path: [{ project: { namespace: [:route] } }], play_path: [{ project: { namespace: [:route] } }], web_path: [{ project: { namespace: [:route] } }], - tags: [:tags] + tags: [:tags], + ai_failure_analysis: [{ project: [:project_feature, :namespace] }], + trace: [{ project: [:namespace] }, :job_artifacts_trace] } end + + def nested_preloads + super.merge({ + trace: { + html_summary: [:trace_chunks] + } + }) + end end end end + +Resolvers::Ci::AllJobsResolver.prepend_mod diff --git a/app/graphql/resolvers/ci/pipeline_triggers_resolver.rb b/app/graphql/resolvers/ci/pipeline_triggers_resolver.rb index 3d6e3b3e75d..ecbae1f7b55 100644 --- a/app/graphql/resolvers/ci/pipeline_triggers_resolver.rb +++ b/app/graphql/resolvers/ci/pipeline_triggers_resolver.rb @@ -10,7 +10,8 @@ module Resolvers type Types::Ci::PipelineTriggerType.connection_type, null: false def resolve_with_lookahead - apply_lookahead(object.triggers) + triggers = ::Ci::TriggersFinder.new(current_user, object).execute + apply_lookahead(triggers) end private diff --git a/app/graphql/resolvers/ci/runner_jobs_resolver.rb b/app/graphql/resolvers/ci/runner_jobs_resolver.rb index 9fe25a4d13d..b005702a71d 100644 --- a/app/graphql/resolvers/ci/runner_jobs_resolver.rb +++ b/app/graphql/resolvers/ci/runner_jobs_resolver.rb @@ -18,6 +18,8 @@ module Resolvers alias_method :runner, :object def resolve_with_lookahead(statuses: nil) + context[:job_field_authorization] = :read_build # Instruct JobType to perform field-level authorization + jobs = ::Ci::JobsFinder.new(current_user: current_user, runner: runner, params: { scope: statuses }).execute apply_lookahead(jobs) @@ -30,7 +32,7 @@ module Resolvers previous_stage_jobs_or_needs: [:needs, :pipeline], artifacts: [:job_artifacts], pipeline: [:user], - project: [{ project: [:route, { namespace: [:route] }] }], + project: [{ project: [:route, { namespace: [:route] }, :project_feature] }], detailed_status: [ :metadata, { pipeline: [:merge_request] }, @@ -42,9 +44,19 @@ module Resolvers play_path: [{ project: { namespace: [:route] } }], web_path: [{ project: { namespace: [:route] } }], short_sha: [:pipeline], - tags: [:tags] + tags: [:tags], + ai_failure_analysis: [{ project: [:project_feature, :namespace] }], + trace: [{ project: [:namespace] }, :job_artifacts_trace] } end + + def nested_preloads + super.merge({ + trace: { + html_summary: [:trace_chunks] + } + }) + end end end end diff --git a/app/graphql/resolvers/ci/runners_resolver.rb b/app/graphql/resolvers/ci/runners_resolver.rb index 632655d3681..3289f1d0056 100644 --- a/app/graphql/resolvers/ci/runners_resolver.rb +++ b/app/graphql/resolvers/ci/runners_resolver.rb @@ -46,10 +46,16 @@ module Resolvers ::Ci::RunnersFinder .new(current_user: current_user, params: runners_finder_params(args)) .execute) + rescue Gitlab::Access::AccessDeniedError + handle_access_denied_error! end protected + def handle_access_denied_error! + raise_resource_not_available_error! + end + def runners_finder_params(params) # Give preference to paused argument over the deprecated 'active' argument paused = params.fetch(:paused, params[:active] ? !params[:active] : nil) @@ -85,24 +91,6 @@ module Resolvers tag_list: [:tags] }) end - - def nested_preloads - { - created_by: { - creator: { - full_path: [:route], - web_path: [:route], - web_url: [:route] - } - }, - owner_project: { - owner_project: { - full_path: [:route, { namespace: [:route] }], - web_url: [:route, { namespace: [:route] }] - } - } - } - end end end end diff --git a/app/graphql/resolvers/ci/test_suite_resolver.rb b/app/graphql/resolvers/ci/test_suite_resolver.rb index a2d3af9c664..cccf77452e3 100644 --- a/app/graphql/resolvers/ci/test_suite_resolver.rb +++ b/app/graphql/resolvers/ci/test_suite_resolver.rb @@ -27,7 +27,7 @@ module Resolvers private def load_test_suite_data(builds) - suite = builds.sum do |build| + suite = builds.sum(Gitlab::Ci::Reports::TestSuite.new) do |build| test_report = build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) test_report.get_suite(build.test_suite_name) end diff --git a/app/graphql/resolvers/codequality_reports_comparer_resolver.rb b/app/graphql/resolvers/codequality_reports_comparer_resolver.rb new file mode 100644 index 00000000000..1c034887c0d --- /dev/null +++ b/app/graphql/resolvers/codequality_reports_comparer_resolver.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Resolvers + class CodequalityReportsComparerResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource + + type ::Types::Security::CodequalityReportsComparerType, null: true + + authorize :read_build + + def resolve + return unless Feature.enabled?(:sast_reports_in_inline_diff, object.project) + + authorize!(object.actual_head_pipeline) + + object.compare_codequality_reports + end + end +end diff --git a/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb b/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb index b967460c7ff..946f10a10fa 100644 --- a/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb +++ b/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb @@ -17,8 +17,6 @@ module Resolvers alias_method :dashboard, :object def resolve(**_args) - return if Feature.enabled?(:remove_monitor_metrics) - [] end end diff --git a/app/graphql/resolvers/namespaces/work_item_resolver.rb b/app/graphql/resolvers/namespaces/work_item_resolver.rb new file mode 100644 index 00000000000..d49ef3f53af --- /dev/null +++ b/app/graphql/resolvers/namespaces/work_item_resolver.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Resolvers + module Namespaces + class WorkItemResolver < Resolvers::BaseResolver + type ::Types::WorkItemType, null: true + + argument :iid, GraphQL::Types::String, required: true, description: 'IID of the work item.' + + def ready?(**args) + return false if Feature.disabled?(:namespace_level_work_items, resource_parent) + + super + end + + def resolve(iid:) + ::WorkItem.find_by_namespace_id_and_iid(resource_parent.id, iid) + end + + private + + def resource_parent + # The namespace could have been loaded in batch by `BatchLoader`. + # At this point we need the `id` of the namespace to query for work items, so + # make sure it's loaded and not `nil` before continuing. + object.respond_to?(:sync) ? object.sync : object + end + strong_memoize_attr :resource_parent + end + end +end diff --git a/app/graphql/resolvers/namespaces/work_items_resolver.rb b/app/graphql/resolvers/namespaces/work_items_resolver.rb index 54bb8392071..6985a7a898a 100644 --- a/app/graphql/resolvers/namespaces/work_items_resolver.rb +++ b/app/graphql/resolvers/namespaces/work_items_resolver.rb @@ -2,33 +2,31 @@ module Resolvers module Namespaces - class WorkItemsResolver < BaseResolver - prepend ::WorkItems::LookAheadPreloads + # rubocop:disable Graphql/ResolverType (inherited from Resolvers::WorkItemsResolver) + class WorkItemsResolver < ::Resolvers::WorkItemsResolver + def ready?(**args) + return false if Feature.disabled?(:namespace_level_work_items, resource_parent) - type Types::WorkItemType.connection_type, null: true - - def resolve_with_lookahead(**args) - return unless Feature.enabled?(:namespace_level_work_items, resource_parent) - return WorkItem.none if resource_parent.nil? - - finder = ::WorkItems::NamespaceWorkItemsFinder.new(current_user, args.merge( - namespace_id: resource_parent - )) + super + end - Gitlab::Graphql::Loaders::IssuableLoader.new(resource_parent, finder).batching_find_all do |q| - apply_lookahead(q) - end + override :resolve_with_lookahead + def resolve_with_lookahead(...) + super + rescue ::WorkItems::NamespaceWorkItemsFinder::FilterNotAvailableError => e + raise Gitlab::Graphql::Errors::ArgumentError, e.message end private - def resource_parent - # The project could have been loaded in batch by `BatchLoader`. - # At this point we need the `id` of the project to query for work items, so - # make sure it's loaded and not `nil` before continuing. - object.respond_to?(:sync) ? object.sync : object + override :finder + def finder(args) + ::WorkItems::NamespaceWorkItemsFinder.new( + current_user, + args.merge(namespace_id: resource_parent) + ) end - strong_memoize_attr :resource_parent end + # rubocop:enable Graphql/ResolverType end end diff --git a/app/graphql/resolvers/organizations/groups_resolver.rb b/app/graphql/resolvers/organizations/groups_resolver.rb new file mode 100644 index 00000000000..0f50713b9b4 --- /dev/null +++ b/app/graphql/resolvers/organizations/groups_resolver.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module Resolvers + module Organizations + class GroupsResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource + include ResolvesGroups + + type Types::GroupType.connection_type, null: true + + authorize :read_group + + argument :search, + GraphQL::Types::String, + required: false, + description: 'Search query for group name or full path.', + alpha: { milestone: '16.4' } + + argument :sort, + Types::Organizations::GroupSortEnum, + description: 'Criteria to sort organization groups by.', + required: false, + default_value: { field: 'name', direction: :asc }, + alpha: { milestone: '16.4' } + + private + + def resolve_groups(**args) + return Group.none if Feature.disabled?(:resolve_organization_groups, context[:current_user]) + + ::Organizations::GroupsFinder + .new(organization: object, current_user: context[:current_user], params: args) + .execute + end + end + end +end diff --git a/app/graphql/resolvers/organizations/organization_resolver.rb b/app/graphql/resolvers/organizations/organization_resolver.rb new file mode 100644 index 00000000000..9194d9a32c5 --- /dev/null +++ b/app/graphql/resolvers/organizations/organization_resolver.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Resolvers + module Organizations + class OrganizationResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource + + authorize :read_organization + + type Types::Organizations::OrganizationType, null: true + + argument :id, + Types::GlobalIDType[::Organizations::Organization], + required: true, + description: 'ID of the organization.' + + def resolve(id:) + authorized_find!(id: id) + end + end + end +end diff --git a/app/graphql/resolvers/organizations/organization_users_resolver.rb b/app/graphql/resolvers/organizations/organization_users_resolver.rb new file mode 100644 index 00000000000..b4790da6c0a --- /dev/null +++ b/app/graphql/resolvers/organizations/organization_users_resolver.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Resolvers + module Organizations + class OrganizationUsersResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource + include LooksAhead + + type Types::Organizations::OrganizationUserType.connection_type, null: true + + authorize :read_organization_user + + alias_method :organization, :object + + def resolve_with_lookahead + authorize!(object) + + apply_lookahead(organization_users) + end + + private + + def organization_users + ::Organizations::OrganizationUsersFinder + .new(organization: organization, current_user: context[:current_user]) + .execute + end + + def preloads + { + user: [:user] + } + 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 9c71cd7c0c9..35a6974163a 100644 --- a/app/graphql/resolvers/work_items/linked_items_resolver.rb +++ b/app/graphql/resolvers/work_items/linked_items_resolver.rb @@ -5,10 +5,16 @@ module Resolvers class LinkedItemsResolver < BaseResolver alias_method :linked_items_widget, :object + argument :filter, Types::WorkItems::RelatedLinkTypeEnum, + required: false, + description: "Filter by link type. " \ + "Supported values: #{Types::WorkItems::RelatedLinkTypeEnum.values.keys.to_sentence}. " \ + 'Returns all types if omitted.' + type Types::WorkItems::LinkedItemType.connection_type, null: true - def resolve - related_work_items.map do |related_work_item| + def resolve(filter: nil) + related_work_items(filter).map do |related_work_item| { link_id: related_work_item.issue_link_id, link_type: related_work_item.issue_link_type, @@ -21,10 +27,10 @@ module Resolvers private - def related_work_items + def related_work_items(type) return [] unless work_item.project.linked_work_items_feature_flag_enabled? - work_item.related_issues(current_user, preload: { project: [:project_feature, :group] }) + work_item.linked_work_items(current_user, preload: { project: [:project_feature, :group] }, link_type: type) end def work_item diff --git a/app/graphql/resolvers/work_items_resolver.rb b/app/graphql/resolvers/work_items_resolver.rb index d4f73361e05..995f54f35d8 100644 --- a/app/graphql/resolvers/work_items_resolver.rb +++ b/app/graphql/resolvers/work_items_resolver.rb @@ -21,13 +21,18 @@ module Resolvers def resolve_with_lookahead(**args) return WorkItem.none if resource_parent.nil? - finder = ::WorkItems::WorkItemsFinder.new(current_user, prepare_finder_params(args)) - - Gitlab::Graphql::Loaders::IssuableLoader.new(resource_parent, finder).batching_find_all { |q| apply_lookahead(q) } + Gitlab::Graphql::Loaders::IssuableLoader.new( + resource_parent, + finder(prepare_finder_params(args)) + ).batching_find_all { |q| apply_lookahead(q) } end private + def finder(args) + ::WorkItems::WorkItemsFinder.new(current_user, args) + end + def prepare_finder_params(args) params = super(args) params[:iids] ||= [params.delete(:iid)].compact if params[:iid] |