diff options
Diffstat (limited to 'app/graphql/resolvers')
36 files changed, 300 insertions, 55 deletions
diff --git a/app/graphql/resolvers/alert_management/alert_resolver.rb b/app/graphql/resolvers/alert_management/alert_resolver.rb index c3219d9cdc3..b115bd80113 100644 --- a/app/graphql/resolvers/alert_management/alert_resolver.rb +++ b/app/graphql/resolvers/alert_management/alert_resolver.rb @@ -18,6 +18,11 @@ module Resolvers description: 'Sort alerts by this criteria', required: false + argument :domain, Types::AlertManagement::DomainFilterEnum, + description: 'Filter query for given domain', + required: true, + default_value: 'operations' + argument :search, GraphQL::STRING_TYPE, description: 'Search query for title, description, service, or monitoring_tool.', required: false diff --git a/app/graphql/resolvers/assigned_merge_requests_resolver.rb b/app/graphql/resolvers/assigned_merge_requests_resolver.rb index 30415ef5d2d..385f8db51b0 100644 --- a/app/graphql/resolvers/assigned_merge_requests_resolver.rb +++ b/app/graphql/resolvers/assigned_merge_requests_resolver.rb @@ -4,6 +4,7 @@ module Resolvers class AssignedMergeRequestsResolver < UserMergeRequestsResolverBase type ::Types::MergeRequestType.connection_type, null: true accept_author + accept_reviewer def user_role :assignee diff --git a/app/graphql/resolvers/authored_merge_requests_resolver.rb b/app/graphql/resolvers/authored_merge_requests_resolver.rb index 1426ca83c06..4de1046ce0d 100644 --- a/app/graphql/resolvers/authored_merge_requests_resolver.rb +++ b/app/graphql/resolvers/authored_merge_requests_resolver.rb @@ -4,6 +4,7 @@ module Resolvers class AuthoredMergeRequestsResolver < UserMergeRequestsResolverBase type ::Types::MergeRequestType.connection_type, null: true accept_assignee + accept_reviewer def user_role :author diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb index 87a63231b22..539e37db1c2 100644 --- a/app/graphql/resolvers/base_resolver.rb +++ b/app/graphql/resolvers/base_resolver.rb @@ -8,6 +8,14 @@ module Resolvers argument_class ::Types::BaseArgument + def self.requires_argument! + @requires_argument = true + end + + def self.field_options + super.merge(requires_argument: @requires_argument) + end + def self.singular_type return unless type @@ -109,6 +117,10 @@ module Resolvers [args[:iid], args[:iids]].any? ? 0 : 0.01 end + def offset_pagination(relation) + ::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(relation) + end + override :object def object super.tap do |obj| diff --git a/app/graphql/resolvers/board_list_issues_resolver.rb b/app/graphql/resolvers/board_list_issues_resolver.rb index 3421e1024c0..3e4a5a3cb70 100644 --- a/app/graphql/resolvers/board_list_issues_resolver.rb +++ b/app/graphql/resolvers/board_list_issues_resolver.rb @@ -16,7 +16,7 @@ module Resolvers filter_params = issue_filters(args[:filters]).merge(board_id: list.board.id, id: list.id) service = ::Boards::Issues::ListService.new(list.board.resource_parent, context[:current_user], filter_params) - Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(service.execute) + offset_pagination(service.execute) end # https://gitlab.com/gitlab-org/gitlab/-/issues/235681 diff --git a/app/graphql/resolvers/board_lists_resolver.rb b/app/graphql/resolvers/board_lists_resolver.rb index ef12dfa19ff..35d938c50be 100644 --- a/app/graphql/resolvers/board_lists_resolver.rb +++ b/app/graphql/resolvers/board_lists_resolver.rb @@ -3,9 +3,13 @@ module Resolvers class BoardListsResolver < BaseResolver include BoardIssueFilterable + prepend ManualAuthorization include Gitlab::Graphql::Authorize::AuthorizeResource type Types::BoardListType, null: true + extras [:lookahead] + + authorize :read_list argument :id, Types::GlobalIDType[List], required: false, @@ -27,7 +31,7 @@ module Resolvers List.preload_preferences_for_user(lists, context[:current_user]) end - Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(lists) + offset_pagination(lists) end private @@ -42,10 +46,6 @@ module Resolvers service.execute(board, create_default_lists: false) end - def authorized_resource?(board) - Ability.allowed?(context[:current_user], :read_list, board) - end - def load_preferences?(lookahead) lookahead&.selection(:edges)&.selection(:node)&.selects?(:collapsed) end diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb new file mode 100644 index 00000000000..d6e7c206691 --- /dev/null +++ b/app/graphql/resolvers/ci/config_resolver.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module Resolvers + module Ci + class ConfigResolver < BaseResolver + type Types::Ci::Config::ConfigType, null: true + + argument :content, GraphQL::STRING_TYPE, + required: true, + description: 'Contents of .gitlab-ci.yml' + + def resolve(content:) + result = ::Gitlab::Ci::YamlProcessor.new(content).execute + + response = if result.errors.empty? + { + status: :valid, + errors: [], + stages: make_stages(result.jobs) + } + else + { + status: :invalid, + errors: result.errors + } + end + + response.merge(merged_yaml: result.merged_yaml) + end + + private + + def make_jobs(config_jobs) + config_jobs.map do |job_name, job| + { + name: job_name, + stage: job[:stage], + group_name: CommitStatus.new(name: job_name).group_name, + needs: job.dig(:needs, :job) || [] + } + end + end + + def make_groups(job_data) + jobs = make_jobs(job_data) + + jobs_by_group = jobs.group_by { |job| job[:group_name] } + jobs_by_group.map do |name, jobs| + { jobs: jobs, name: name, stage: jobs.first[:stage], size: jobs.size } + end + end + + def make_stages(jobs) + make_groups(jobs) + .group_by { |group| group[:stage] } + .map { |name, groups| { name: name, groups: groups } } + end + end + end +end diff --git a/app/graphql/resolvers/ci/jobs_resolver.rb b/app/graphql/resolvers/ci/jobs_resolver.rb index 8a9ae42b375..2c4911748a5 100644 --- a/app/graphql/resolvers/ci/jobs_resolver.rb +++ b/app/graphql/resolvers/ci/jobs_resolver.rb @@ -5,6 +5,8 @@ module Resolvers class JobsResolver < BaseResolver alias_method :pipeline, :object + type ::Types::Ci::JobType.connection_type, null: true + argument :security_report_types, [Types::Security::ReportTypeEnum], required: false, description: 'Filter jobs by the type of security report they produce' diff --git a/app/graphql/resolvers/ci/pipeline_stages_resolver.rb b/app/graphql/resolvers/ci/pipeline_stages_resolver.rb index f9817d8b97b..98170e0cd2e 100644 --- a/app/graphql/resolvers/ci/pipeline_stages_resolver.rb +++ b/app/graphql/resolvers/ci/pipeline_stages_resolver.rb @@ -5,6 +5,9 @@ module Resolvers class PipelineStagesResolver < BaseResolver include LooksAhead + type Types::Ci::StageType.connection_type, null: true + extras [:lookahead] + alias_method :pipeline, :object def resolve_with_lookahead diff --git a/app/graphql/resolvers/ci/runner_setup_resolver.rb b/app/graphql/resolvers/ci/runner_setup_resolver.rb index 241cd57f74b..f68d71174c3 100644 --- a/app/graphql/resolvers/ci/runner_setup_resolver.rb +++ b/app/graphql/resolvers/ci/runner_setup_resolver.rb @@ -23,7 +23,10 @@ module Resolvers def resolve(platform:, architecture:, **args) instructions = Gitlab::Ci::RunnerInstructions.new( - { current_user: current_user, os: platform, arch: architecture }.merge(target_param(args)) + current_user: current_user, + os: platform, + arch: architecture, + **target_param(args) ) { diff --git a/app/graphql/resolvers/concerns/caching_array_resolver.rb b/app/graphql/resolvers/concerns/caching_array_resolver.rb index 4f2c8b98928..e7555dcf42c 100644 --- a/app/graphql/resolvers/concerns/caching_array_resolver.rb +++ b/app/graphql/resolvers/concerns/caching_array_resolver.rb @@ -43,8 +43,10 @@ # (i.e. `resolve(**args).sync == query_for(query_input(**args)).to_a`). # # Classes may implement: -# - #item_found(A, R) (return value is ignored) # - max_union_size Integer (the maximum number of queries to run in any one union) +# - preload -> Preloads|NilClass (a set of preloads to apply to each query) +# - #item_found(A, R) (return value is ignored) +# - allowed?(R) -> Boolean (if this method returns false, the value is not resolved) module CachingArrayResolver MAX_UNION_SIZE = 50 @@ -62,6 +64,7 @@ module CachingArrayResolver queries.in_groups_of(max_union_size, false).each do |group| by_id = model_class .from_union(tag(group), remove_duplicates: false) + .preload(preload) # rubocop: disable CodeReuse/ActiveRecord .group_by { |r| r[primary_key] } by_id.values.each do |item_group| @@ -75,6 +78,16 @@ module CachingArrayResolver end end + # Override to apply filters on a per-item basis + def allowed?(item) + true + end + + # Override to specify preloads for each query + def preload + nil + end + # Override this to intercept the items once they are found def item_found(query_input, item) end @@ -94,6 +107,8 @@ module CachingArrayResolver end def found(loader, key, value) + return unless allowed?(value) + loader.call(key) do |vs| item_found(key, value) vs << value diff --git a/app/graphql/resolvers/concerns/manual_authorization.rb b/app/graphql/resolvers/concerns/manual_authorization.rb new file mode 100644 index 00000000000..182110b9594 --- /dev/null +++ b/app/graphql/resolvers/concerns/manual_authorization.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +# TODO: remove this entirely when framework authorization is released +# See: https://gitlab.com/gitlab-org/gitlab/-/issues/290216 +module ManualAuthorization + def resolve(**args) + super + rescue ::Gitlab::Graphql::Errors::ResourceNotAvailable + nil + end +end diff --git a/app/graphql/resolvers/design_management/design_resolver.rb b/app/graphql/resolvers/design_management/design_resolver.rb index e0a68bae397..b60c14ca835 100644 --- a/app/graphql/resolvers/design_management/design_resolver.rb +++ b/app/graphql/resolvers/design_management/design_resolver.rb @@ -5,6 +5,8 @@ module Resolvers class DesignResolver < BaseResolver type ::Types::DesignManagement::DesignType, null: true + requires_argument! + argument :id, ::Types::GlobalIDType[::DesignManagement::Design], required: false, description: 'Find a design by its ID' diff --git a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb index 70021057f71..49a4974bfbf 100644 --- a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb +++ b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb @@ -12,6 +12,8 @@ module Resolvers type Types::DesignManagement::DesignAtVersionType, null: true + requires_argument! + authorize :read_design argument :id, DesignAtVersionID, diff --git a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb index ecd7ab3ee45..7d20cfc2c8e 100644 --- a/app/graphql/resolvers/design_management/version_in_collection_resolver.rb +++ b/app/graphql/resolvers/design_management/version_in_collection_resolver.rb @@ -7,6 +7,8 @@ module Resolvers type Types::DesignManagement::VersionType, null: true + requires_argument! + authorize :read_design alias_method :collection, :object diff --git a/app/graphql/resolvers/design_management/versions_resolver.rb b/app/graphql/resolvers/design_management/versions_resolver.rb index 23858c8e991..3c718a631db 100644 --- a/app/graphql/resolvers/design_management/versions_resolver.rb +++ b/app/graphql/resolvers/design_management/versions_resolver.rb @@ -9,6 +9,8 @@ module Resolvers VersionID = ::Types::GlobalIDType[::DesignManagement::Version] + extras [:parent] + argument :earlier_or_equal_to_sha, GraphQL::STRING_TYPE, as: :sha, required: false, diff --git a/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb index 669b487db10..13b5672d750 100644 --- a/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb +++ b/app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb @@ -3,6 +3,8 @@ module Resolvers module ErrorTracking class SentryErrorStackTraceResolver < BaseResolver + type Types::ErrorTracking::SentryErrorStackTraceType, null: true + argument :id, ::Types::GlobalIDType[::Gitlab::ErrorTracking::DetailedError], required: true, description: 'ID of the Sentry issue' diff --git a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb index c5cf924ce7f..e844ffedbeb 100644 --- a/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb +++ b/app/graphql/resolvers/error_tracking/sentry_errors_resolver.rb @@ -4,19 +4,26 @@ module Resolvers module ErrorTracking class SentryErrorsResolver < BaseResolver type Types::ErrorTracking::SentryErrorType.connection_type, null: true + extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension + + argument :search_term, ::GraphQL::STRING_TYPE, + description: 'Search query for the Sentry error details', + required: false + + # TODO: convert to Enum + argument :sort, ::GraphQL::STRING_TYPE, + description: 'Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default', + required: false + + delegate :project, to: :object def resolve(**args) args[:cursor] = args.delete(:after) - project = object.project - result = ::ErrorTracking::ListIssuesService.new( - project, - context[:current_user], - args - ).execute + result = ::ErrorTracking::ListIssuesService.new(project, current_user, args).execute - next_cursor = result[:pagination]&.dig('next', 'cursor') - previous_cursor = result[:pagination]&.dig('previous', 'cursor') + next_cursor = result.dig(:pagination, 'next', 'cursor') + previous_cursor = result.dig(:pagination, 'previous', 'cursor') issues = result[:issues] # ReactiveCache is still fetching data @@ -24,6 +31,10 @@ 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_members_resolver.rb b/app/graphql/resolvers/group_members_resolver.rb index d3aa376c29c..fcdf7c01d8b 100644 --- a/app/graphql/resolvers/group_members_resolver.rb +++ b/app/graphql/resolvers/group_members_resolver.rb @@ -6,6 +6,11 @@ module Resolvers authorize :read_group_member + argument :relations, [Types::GroupMemberRelationEnum], + description: 'Filter members by the given member relations', + required: false, + default_value: GroupMembersFinder::DEFAULT_RELATIONS + private def preloads diff --git a/app/graphql/resolvers/issue_status_counts_resolver.rb b/app/graphql/resolvers/issue_status_counts_resolver.rb index 5d0d5693244..58cff559d0d 100644 --- a/app/graphql/resolvers/issue_status_counts_resolver.rb +++ b/app/graphql/resolvers/issue_status_counts_resolver.rb @@ -6,6 +6,8 @@ module Resolvers type Types::IssueStatusCountsType, null: true + extras [:lookahead] + def continue_issue_resolve(parent, finder, **args) finder.parent_param = parent apply_lookahead(Gitlab::IssuablesCountForState.new(finder, parent)) diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb index dd35219454f..ae27cce9113 100644 --- a/app/graphql/resolvers/issues_resolver.rb +++ b/app/graphql/resolvers/issues_resolver.rb @@ -10,7 +10,7 @@ module Resolvers argument :sort, Types::IssueSortEnum, description: 'Sort issues by this criteria', required: false, - default_value: 'created_desc' + default_value: :created_desc type Types::IssueType.connection_type, null: true @@ -24,7 +24,7 @@ module Resolvers if non_stable_cursor_sort?(args[:sort]) # Certain complex sorts are not supported by the stable cursor pagination yet. # In these cases, we use offset pagination, so we return the correct connection. - Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(issues) + offset_pagination(issues) else issues end diff --git a/app/graphql/resolvers/members_resolver.rb b/app/graphql/resolvers/members_resolver.rb index 523642e912f..cf51fd298bd 100644 --- a/app/graphql/resolvers/members_resolver.rb +++ b/app/graphql/resolvers/members_resolver.rb @@ -14,7 +14,9 @@ module Resolvers def resolve_with_lookahead(**args) authorize!(object) - apply_lookahead(finder_class.new(object, current_user, params: args).execute) + relations = args.delete(:relations) + + apply_lookahead(finder_class.new(object, current_user, params: args).execute(include_relations: relations)) end private diff --git a/app/graphql/resolvers/merge_request_pipelines_resolver.rb b/app/graphql/resolvers/merge_request_pipelines_resolver.rb index 6590dfdc78c..f84eedb4c3b 100644 --- a/app/graphql/resolvers/merge_request_pipelines_resolver.rb +++ b/app/graphql/resolvers/merge_request_pipelines_resolver.rb @@ -5,14 +5,32 @@ module Resolvers class MergeRequestPipelinesResolver < BaseResolver # The GraphQL type here gets defined in this include include ::ResolvesPipelines + include ::CachingArrayResolver alias_method :merge_request, :object + # 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 + def resolve(**args) return unless project - resolve_pipelines(project, args) - .merge(merge_request.all_pipelines) + super + end + + def query_for(args) + resolve_pipelines(project, args).merge(merge_request.all_pipelines) + end + + def model_class + ::Ci::Pipeline + end + + def query_input(**args) + args end def project diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb index cb4a76243ae..98c95565778 100644 --- a/app/graphql/resolvers/merge_requests_resolver.rb +++ b/app/graphql/resolvers/merge_requests_resolver.rb @@ -4,6 +4,8 @@ module Resolvers class MergeRequestsResolver < BaseResolver include ResolvesMergeRequests + type ::Types::MergeRequestType.connection_type, null: true + alias_method :project, :synchronized_object def self.accept_assignee @@ -18,6 +20,12 @@ module Resolvers description: 'Username of the author' end + def self.accept_reviewer + argument :reviewer_username, GraphQL::STRING_TYPE, + required: false, + description: 'Username of the reviewer' + end + argument :iids, [GraphQL::STRING_TYPE], required: false, description: 'Array of IIDs of merge requests, for example `[1, 2]`' @@ -52,7 +60,7 @@ module Resolvers argument :sort, Types::MergeRequestSortEnum, description: 'Sort merge requests by this criteria', required: false, - default_value: 'created_desc' + default_value: :created_desc def self.single ::Resolvers::MergeRequestResolver diff --git a/app/graphql/resolvers/project_members_resolver.rb b/app/graphql/resolvers/project_members_resolver.rb index e64e8b845a5..659b12c2563 100644 --- a/app/graphql/resolvers/project_members_resolver.rb +++ b/app/graphql/resolvers/project_members_resolver.rb @@ -5,6 +5,11 @@ module Resolvers class ProjectMembersResolver < MembersResolver authorize :read_project_member + argument :relations, [Types::ProjectMemberRelationEnum], + description: 'Filter members by the given member relations', + required: false, + default_value: MembersFinder::DEFAULT_RELATIONS + private def finder_class diff --git a/app/graphql/resolvers/project_merge_requests_resolver.rb b/app/graphql/resolvers/project_merge_requests_resolver.rb index bf082c0b182..830649d5e52 100644 --- a/app/graphql/resolvers/project_merge_requests_resolver.rb +++ b/app/graphql/resolvers/project_merge_requests_resolver.rb @@ -5,5 +5,6 @@ module Resolvers type ::Types::MergeRequestType.connection_type, null: true accept_assignee accept_author + accept_reviewer end end diff --git a/app/graphql/resolvers/project_pipeline_resolver.rb b/app/graphql/resolvers/project_pipeline_resolver.rb index 4cf47dbdc60..8bf4e0b08ef 100644 --- a/app/graphql/resolvers/project_pipeline_resolver.rb +++ b/app/graphql/resolvers/project_pipeline_resolver.rb @@ -12,7 +12,9 @@ module Resolvers def resolve(iid:) BatchLoader::GraphQL.for(iid).batch(key: project) do |iids, loader, args| - args[:key].all_pipelines.for_iid(iids).each { |pl| loader.call(pl.iid.to_s, pl) } + finder = ::Ci::PipelinesFinder.new(project, context[:current_user], iids: iids) + + finder.execute.each { |pipeline| loader.call(pipeline.iid.to_s, pipeline) } end end end diff --git a/app/graphql/resolvers/project_pipeline_statistics_resolver.rb b/app/graphql/resolvers/project_pipeline_statistics_resolver.rb new file mode 100644 index 00000000000..29ab9402f5b --- /dev/null +++ b/app/graphql/resolvers/project_pipeline_statistics_resolver.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Resolvers + class ProjectPipelineStatisticsResolver < BaseResolver + type Types::Ci::AnalyticsType, null: true + + def resolve + weekly_stats = Gitlab::Ci::Charts::WeekChart.new(object) + monthly_stats = Gitlab::Ci::Charts::MonthChart.new(object) + yearly_stats = Gitlab::Ci::Charts::YearChart.new(object) + pipeline_times = Gitlab::Ci::Charts::PipelineTime.new(object) + + { + week_pipelines_labels: weekly_stats.labels, + week_pipelines_totals: weekly_stats.total, + week_pipelines_successful: weekly_stats.success, + month_pipelines_labels: monthly_stats.labels, + month_pipelines_totals: monthly_stats.total, + month_pipelines_successful: monthly_stats.success, + year_pipelines_labels: yearly_stats.labels, + year_pipelines_totals: yearly_stats.total, + year_pipelines_successful: yearly_stats.success, + pipeline_times_labels: pipeline_times.labels, + pipeline_times_values: pipeline_times.pipeline_times + } + end + end +end diff --git a/app/graphql/resolvers/projects/jira_imports_resolver.rb b/app/graphql/resolvers/projects/jira_imports_resolver.rb deleted file mode 100644 index efd45c2c465..00000000000 --- a/app/graphql/resolvers/projects/jira_imports_resolver.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Resolvers - module Projects - class JiraImportsResolver < BaseResolver - type Types::JiraImportType.connection_type, null: true - - include Gitlab::Graphql::Authorize::AuthorizeResource - - alias_method :project, :object - - def resolve(**args) - authorize!(project) - - project.jira_imports - end - - def authorized_resource?(project) - context[:current_user].present? && Ability.allowed?(context[:current_user], :read_project, project) - end - end - end -end diff --git a/app/graphql/resolvers/projects/services_resolver.rb b/app/graphql/resolvers/projects/services_resolver.rb index 17d81e21c28..4f5a6cddbb3 100644 --- a/app/graphql/resolvers/projects/services_resolver.rb +++ b/app/graphql/resolvers/projects/services_resolver.rb @@ -3,9 +3,11 @@ module Resolvers module Projects class ServicesResolver < BaseResolver + prepend ManualAuthorization include Gitlab::Graphql::Authorize::AuthorizeResource type Types::Projects::ServiceType.connection_type, null: true + authorize :admin_project argument :active, GraphQL::BOOLEAN_TYPE, @@ -24,10 +26,6 @@ module Resolvers services(args[:active], args[:type]) end - def authorized_resource?(project) - Ability.allowed?(context[:current_user], :admin_project, project) - end - private def services(active, type) diff --git a/app/graphql/resolvers/review_requested_merge_requests_resolver.rb b/app/graphql/resolvers/review_requested_merge_requests_resolver.rb new file mode 100644 index 00000000000..e0ab7b5b600 --- /dev/null +++ b/app/graphql/resolvers/review_requested_merge_requests_resolver.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Resolvers + class ReviewRequestedMergeRequestsResolver < UserMergeRequestsResolverBase + type ::Types::MergeRequestType.connection_type, null: true + accept_author + accept_assignee + + def user_role + :reviewer + end + end +end diff --git a/app/graphql/resolvers/snippets/blobs_resolver.rb b/app/graphql/resolvers/snippets/blobs_resolver.rb index 3a0dcb50faf..cfb1711aed4 100644 --- a/app/graphql/resolvers/snippets/blobs_resolver.rb +++ b/app/graphql/resolvers/snippets/blobs_resolver.rb @@ -3,9 +3,11 @@ module Resolvers module Snippets class BlobsResolver < BaseResolver + prepend ManualAuthorization include Gitlab::Graphql::Authorize::AuthorizeResource type Types::Snippets::BlobType.connection_type, null: true + authorize :read_snippet alias_method :snippet, :object @@ -27,10 +29,6 @@ module Resolvers end end - def authorized_resource?(snippet) - Ability.allowed?(context[:current_user], :read_snippet, snippet) - end - private def transformed_blob_paths(paths) diff --git a/app/graphql/resolvers/user_discussions_count_resolver.rb b/app/graphql/resolvers/user_discussions_count_resolver.rb new file mode 100644 index 00000000000..115997ec666 --- /dev/null +++ b/app/graphql/resolvers/user_discussions_count_resolver.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Resolvers + class UserDiscussionsCountResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource + + type GraphQL::INT_TYPE, null: true + + def resolve + authorize!(object) + + BatchLoader::GraphQL.for(object.id).batch do |ids, loader, args| + counts = Note.count_for_collection(ids, object.class.name, 'COUNT(DISTINCT discussion_id) as count').index_by(&:noteable_id) + + ids.each do |id| + loader.call(id, counts[id]&.count || 0) + end + end + end + + def authorized_resource?(object) + ability = "read_#{object.class.name.underscore}".to_sym + context[:current_user].present? && Ability.allowed?(context[:current_user], ability, object) + end + end +end diff --git a/app/graphql/resolvers/user_notes_count_resolver.rb b/app/graphql/resolvers/user_notes_count_resolver.rb new file mode 100644 index 00000000000..2cb61104c18 --- /dev/null +++ b/app/graphql/resolvers/user_notes_count_resolver.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Resolvers + class UserNotesCountResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource + + type GraphQL::INT_TYPE, null: true + + def resolve + authorize!(object) + + BatchLoader::GraphQL.for(object.id).batch(key: :user_notes_count) do |ids, loader, args| + counts = Note.count_for_collection(ids, object.class.name).index_by(&:noteable_id) + + ids.each do |id| + loader.call(id, counts[id]&.count || 0) + end + end + end + + def authorized_resource?(object) + ability = "read_#{object.class.name.underscore}".to_sym + context[:current_user].present? && Ability.allowed?(context[:current_user], ability, object) + end + end +end diff --git a/app/graphql/resolvers/users/group_count_resolver.rb b/app/graphql/resolvers/users/group_count_resolver.rb index 5033c26554a..ebfe594d31d 100644 --- a/app/graphql/resolvers/users/group_count_resolver.rb +++ b/app/graphql/resolvers/users/group_count_resolver.rb @@ -3,6 +3,8 @@ module Resolvers module Users class GroupCountResolver < BaseResolver + type GraphQL::INT_TYPE, null: true + alias_method :user, :object def resolve(**args) diff --git a/app/graphql/resolvers/users_resolver.rb b/app/graphql/resolvers/users_resolver.rb index f5838642141..a0ed076595d 100644 --- a/app/graphql/resolvers/users_resolver.rb +++ b/app/graphql/resolvers/users_resolver.rb @@ -17,7 +17,7 @@ module Resolvers argument :sort, Types::SortEnum, description: 'Sort users by this criteria', required: false, - default_value: 'created_desc' + default_value: :created_desc argument :search, GraphQL::STRING_TYPE, required: false, |