Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/graphql/resolvers')
-rw-r--r--app/graphql/resolvers/base_issues_resolver.rb7
-rw-r--r--app/graphql/resolvers/ci/runner_owner_project_resolver.rb65
-rw-r--r--app/graphql/resolvers/clusters/agent_tokens_resolver.rb2
-rw-r--r--app/graphql/resolvers/clusters/agents_resolver.rb2
-rw-r--r--app/graphql/resolvers/concerns/issue_resolver_arguments.rb5
-rw-r--r--app/graphql/resolvers/concerns/resolves_groups.rb2
-rw-r--r--app/graphql/resolvers/concerns/resolves_merge_requests.rb1
-rw-r--r--app/graphql/resolvers/crm/contacts_resolver.rb36
-rw-r--r--app/graphql/resolvers/crm/organizations_resolver.rb36
-rw-r--r--app/graphql/resolvers/design_management/versions_resolver.rb2
-rw-r--r--app/graphql/resolvers/merge_request_pipelines_resolver.rb7
-rw-r--r--app/graphql/resolvers/milestones_resolver.rb23
-rw-r--r--app/graphql/resolvers/paginated_tree_resolver.rb2
-rw-r--r--app/graphql/resolvers/tree_resolver.rb2
-rw-r--r--app/graphql/resolvers/user_resolver.rb8
-rw-r--r--app/graphql/resolvers/users_resolver.rb5
-rw-r--r--app/graphql/resolvers/work_items_resolver.rb60
17 files changed, 231 insertions, 34 deletions
diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb
index a1fda976876..ec47a8996eb 100644
--- a/app/graphql/resolvers/base_issues_resolver.rb
+++ b/app/graphql/resolvers/base_issues_resolver.rb
@@ -33,13 +33,6 @@ module Resolvers
end
end
- def prepare_params(args, parent)
- return unless [:escalation_status_asc, :escalation_status_desc].include?(args[:sort])
- return if Feature.enabled?(:incident_escalations, parent)
-
- args[:sort] = :created_desc # default for sort argument
- end
-
private
def unconditional_includes
diff --git a/app/graphql/resolvers/ci/runner_owner_project_resolver.rb b/app/graphql/resolvers/ci/runner_owner_project_resolver.rb
new file mode 100644
index 00000000000..14b5f8f90eb
--- /dev/null
+++ b/app/graphql/resolvers/ci/runner_owner_project_resolver.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class RunnerOwnerProjectResolver < BaseResolver
+ include LooksAhead
+
+ type Types::ProjectType, null: true
+
+ alias_method :runner, :object
+
+ def resolve_with_lookahead(**args)
+ resolve_owner
+ end
+
+ def preloads
+ {
+ full_path: [:route]
+ }
+ end
+
+ def filtered_preloads
+ selection = lookahead
+
+ preloads.each.flat_map do |name, requirements|
+ selection&.selects?(name) ? requirements : []
+ end
+ end
+
+ private
+
+ def resolve_owner
+ return unless runner.project_type?
+
+ BatchLoader::GraphQL.for(runner.id).batch(key: :runner_owner_projects) do |runner_ids, loader|
+ # rubocop: disable CodeReuse/ActiveRecord
+ runner_and_projects_with_row_number =
+ ::Ci::RunnerProject
+ .where(runner_id: runner_ids)
+ .select('id, runner_id, project_id, ROW_NUMBER() OVER (PARTITION BY runner_id ORDER BY id ASC)')
+ runner_and_owner_projects =
+ ::Ci::RunnerProject
+ .select(:id, :runner_id, :project_id)
+ .from("(#{runner_and_projects_with_row_number.to_sql}) temp WHERE row_number = 1")
+ owner_project_id_by_runner_id =
+ runner_and_owner_projects
+ .group_by(&:runner_id)
+ .transform_values { |runner_projects| runner_projects.first.project_id }
+ project_ids = owner_project_id_by_runner_id.values.uniq
+
+ all_preloads = unconditional_includes + filtered_preloads
+ owner_relation = Project.all
+ owner_relation = owner_relation.preload(*all_preloads) if all_preloads.any?
+ projects = owner_relation.where(id: project_ids).index_by(&:id)
+
+ runner_ids.each do |runner_id|
+ owner_project_id = owner_project_id_by_runner_id[runner_id]
+ loader.call(runner_id, projects[owner_project_id])
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
index 722fbab3bb7..9740bc6bb6a 100644
--- a/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
+++ b/app/graphql/resolvers/clusters/agent_tokens_resolver.rb
@@ -16,7 +16,7 @@ module Resolvers
def resolve(**args)
return ::Clusters::AgentToken.none unless can_read_agent_tokens?
- tokens = agent.last_used_agent_tokens
+ tokens = agent.agent_tokens
tokens = tokens.with_status(args[:status]) if args[:status].present?
tokens
diff --git a/app/graphql/resolvers/clusters/agents_resolver.rb b/app/graphql/resolvers/clusters/agents_resolver.rb
index 5ad66ed7cdd..28618bef807 100644
--- a/app/graphql/resolvers/clusters/agents_resolver.rb
+++ b/app/graphql/resolvers/clusters/agents_resolver.rb
@@ -30,7 +30,7 @@ module Resolvers
def preloads
{
activity_events: { activity_events: [:user, agent_token: :agent] },
- tokens: :last_used_agent_tokens
+ tokens: :agent_tokens
}
end
end
diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
index de44dbb26d7..fe213936f55 100644
--- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
+++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
@@ -66,7 +66,6 @@ module IssueResolverArguments
description: 'Filter for confidential issues. If "false", excludes confidential issues. If "true", returns only confidential issues.'
argument :not, Types::Issues::NegatedIssueFilterInputType,
description: 'Negated arguments.',
- prepare: ->(negated_args, ctx) { negated_args.to_h },
required: false
argument :crm_contact_id, GraphQL::Types::String,
required: false,
@@ -85,12 +84,12 @@ module IssueResolverArguments
# Will need to be made group & namespace aware with
# https://gitlab.com/gitlab-org/gitlab-foss/issues/54520
+ args[:not] = args[:not].to_h if args[:not].present?
args[:iids] ||= [args.delete(:iid)].compact if args[:iid]
args[:attempt_project_search_optimizations] = true if args[:search].present?
prepare_assignee_username_params(args)
prepare_release_tag_params(args)
- prepare_params(args, parent) if defined?(prepare_params)
finder = IssuesFinder.new(current_user, args)
@@ -98,6 +97,8 @@ module IssueResolverArguments
end
def ready?(**args)
+ args[:not] = args[:not].to_h if args[:not].present?
+
params_not_mutually_exclusive(args, mutually_exclusive_assignee_username_args)
params_not_mutually_exclusive(args, mutually_exclusive_milestone_args)
params_not_mutually_exclusive(args.fetch(:not, {}), mutually_exclusive_milestone_args)
diff --git a/app/graphql/resolvers/concerns/resolves_groups.rb b/app/graphql/resolvers/concerns/resolves_groups.rb
index c451d4e7936..2a3dce80057 100644
--- a/app/graphql/resolvers/concerns/resolves_groups.rb
+++ b/app/graphql/resolvers/concerns/resolves_groups.rb
@@ -18,11 +18,9 @@ module ResolvesGroups
def preloads
{
- contacts: [:contacts],
container_repositories_count: [:container_repositories],
custom_emoji: [:custom_emoji],
full_path: [:route],
- organizations: [:organizations],
path: [:route],
dependency_proxy_blob_count: [:dependency_proxy_blobs],
dependency_proxy_blobs: [:dependency_proxy_blobs],
diff --git a/app/graphql/resolvers/concerns/resolves_merge_requests.rb b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
index a72b9a09118..697cc6f5b03 100644
--- a/app/graphql/resolvers/concerns/resolves_merge_requests.rb
+++ b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
@@ -52,6 +52,7 @@ module ResolvesMergeRequests
security_auto_fix: [:author],
head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }],
timelogs: [:timelogs],
+ pipelines: [:merge_request_diffs], # used by `recent_diff_head_shas` to load pipelines
committers: [merge_request_diff: [:merge_request_diff_commits]]
}
end
diff --git a/app/graphql/resolvers/crm/contacts_resolver.rb b/app/graphql/resolvers/crm/contacts_resolver.rb
new file mode 100644
index 00000000000..58d0e2ce13d
--- /dev/null
+++ b/app/graphql/resolvers/crm/contacts_resolver.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Crm
+ class ContactsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include ResolvesIds
+
+ authorize :read_crm_contact
+
+ type Types::CustomerRelations::ContactType, null: true
+
+ argument :search, GraphQL::Types::String,
+ required: false,
+ description: 'Search term to find contacts with.'
+
+ argument :state, Types::CustomerRelations::ContactStateEnum,
+ required: false,
+ description: 'State of the contacts to search for.'
+
+ argument :ids, [::Types::GlobalIDType[CustomerRelations::Contact]],
+ required: false,
+ description: 'Filter contacts by IDs.'
+
+ def resolve(**args)
+ args[:ids] = resolve_ids(args.delete(:ids))
+
+ ::Crm::ContactsFinder.new(current_user, { group: group }.merge(args)).execute
+ end
+
+ def group
+ object.respond_to?(:sync) ? object.sync : object
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/crm/organizations_resolver.rb b/app/graphql/resolvers/crm/organizations_resolver.rb
new file mode 100644
index 00000000000..ca0a908ee22
--- /dev/null
+++ b/app/graphql/resolvers/crm/organizations_resolver.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Crm
+ class OrganizationsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include ResolvesIds
+
+ authorize :read_crm_organization
+
+ type Types::CustomerRelations::OrganizationType, null: true
+
+ argument :search, GraphQL::Types::String,
+ required: false,
+ description: 'Search term used to find organizations with.'
+
+ argument :state, Types::CustomerRelations::OrganizationStateEnum,
+ required: false,
+ description: 'State of the organization to search for.'
+
+ argument :ids, [Types::GlobalIDType[CustomerRelations::Organization]],
+ required: false,
+ description: 'Filter organizations by IDs.'
+
+ def resolve(**args)
+ args[:ids] = resolve_ids(args.delete(:ids))
+
+ ::Crm::OrganizationsFinder.new(current_user, { group: group }.merge(args)).execute
+ end
+
+ def group
+ object.respond_to?(:sync) ? object.sync : object
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/design_management/versions_resolver.rb b/app/graphql/resolvers/design_management/versions_resolver.rb
index de636655087..bd9b82283c3 100644
--- a/app/graphql/resolvers/design_management/versions_resolver.rb
+++ b/app/graphql/resolvers/design_management/versions_resolver.rb
@@ -42,8 +42,6 @@ module Resolvers
def cutoff(id, sha)
if sha.present? || id.present?
specific_version(id, sha)
- elsif at_version = context[:at_version_argument]
- by_id(at_version) # See: DesignsResolver
else
:unconstrained
end
diff --git a/app/graphql/resolvers/merge_request_pipelines_resolver.rb b/app/graphql/resolvers/merge_request_pipelines_resolver.rb
index f84eedb4c3b..deb698c63e1 100644
--- a/app/graphql/resolvers/merge_request_pipelines_resolver.rb
+++ b/app/graphql/resolvers/merge_request_pipelines_resolver.rb
@@ -21,8 +21,9 @@ module Resolvers
super
end
- def query_for(args)
- resolve_pipelines(project, args).merge(merge_request.all_pipelines)
+ def query_for(input)
+ mr, args = input
+ resolve_pipelines(mr.source_project, args).merge(mr.all_pipelines)
end
def model_class
@@ -30,7 +31,7 @@ module Resolvers
end
def query_input(**args)
- args
+ [merge_request, args]
end
def project
diff --git a/app/graphql/resolvers/milestones_resolver.rb b/app/graphql/resolvers/milestones_resolver.rb
index dc6d781f584..25ff783b408 100644
--- a/app/graphql/resolvers/milestones_resolver.rb
+++ b/app/graphql/resolvers/milestones_resolver.rb
@@ -4,6 +4,11 @@ module Resolvers
class MilestonesResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
include TimeFrameArguments
+ include LooksAhead
+
+ # authorize before resolution
+ authorize :read_milestone
+ authorizes_object!
argument :ids, [GraphQL::Types::ID],
required: false,
@@ -34,12 +39,10 @@ module Resolvers
NON_STABLE_CURSOR_SORTS = %i[expired_last_due_date_asc expired_last_due_date_desc].freeze
- def resolve(**args)
+ def resolve_with_lookahead(**args)
validate_timeframe_params!(args)
- authorize!
-
- milestones = MilestonesFinder.new(milestones_finder_params(args)).execute
+ milestones = apply_lookahead(MilestonesFinder.new(milestones_finder_params(args)).execute)
if non_stable_cursor_sort?(args[:sort])
offset_pagination(milestones)
@@ -50,6 +53,12 @@ module Resolvers
private
+ def preloads
+ {
+ releases: :releases
+ }
+ end
+
def milestones_finder_params(args)
{
ids: parse_gids(args[:ids]),
@@ -69,12 +78,6 @@ module Resolvers
raise NotImplementedError
end
- # MilestonesFinder does not check for current_user permissions,
- # so for now we need to keep it here.
- def authorize!
- Ability.allowed?(context[:current_user], :read_milestone, parent) || raise_resource_not_available_error!
- end
-
def parse_gids(gids)
gids&.map { |gid| GitlabSchema.parse_gid(gid, expected_type: Milestone).model_id }
end
diff --git a/app/graphql/resolvers/paginated_tree_resolver.rb b/app/graphql/resolvers/paginated_tree_resolver.rb
index d29d87ca204..1b4211366e0 100644
--- a/app/graphql/resolvers/paginated_tree_resolver.rb
+++ b/app/graphql/resolvers/paginated_tree_resolver.rb
@@ -17,7 +17,6 @@ module Resolvers
description: 'Used to get a recursive tree. Default is false.'
argument :ref, GraphQL::Types::String,
required: false,
- default_value: :head,
description: 'Commit ref to get the tree for. Default value is HEAD.'
alias_method :repository, :object
@@ -26,6 +25,7 @@ module Resolvers
return unless repository.exists?
cursor = args.delete(:after)
+ args[:ref] ||= :head
pagination_params = {
limit: @field.max_page_size || 100,
diff --git a/app/graphql/resolvers/tree_resolver.rb b/app/graphql/resolvers/tree_resolver.rb
index f02eb226810..553f9aa6cd9 100644
--- a/app/graphql/resolvers/tree_resolver.rb
+++ b/app/graphql/resolvers/tree_resolver.rb
@@ -16,7 +16,6 @@ module Resolvers
description: 'Used to get a recursive tree. Default is false.'
argument :ref, GraphQL::Types::String,
required: false,
- default_value: :head,
description: 'Commit ref to get the tree for. Default value is HEAD.'
alias_method :repository, :object
@@ -24,6 +23,7 @@ module Resolvers
def resolve(**args)
return unless repository.exists?
+ args[:ref] ||= :head
repository.tree(args[:ref], args[:path], recursive: args[:recursive])
end
end
diff --git a/app/graphql/resolvers/user_resolver.rb b/app/graphql/resolvers/user_resolver.rb
index 99fd0d4927d..f0fd60e9cbb 100644
--- a/app/graphql/resolvers/user_resolver.rb
+++ b/app/graphql/resolvers/user_resolver.rb
@@ -2,6 +2,8 @@
module Resolvers
class UserResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
description 'Retrieve a single user'
type Types::UserType, null: true
@@ -23,6 +25,8 @@ module Resolvers
end
def resolve(id: nil, username: nil)
+ authorize!
+
if id
GitlabSchema.object_from_id(id, expected_type: User)
else
@@ -39,5 +43,9 @@ module Resolvers
end
end
end
+
+ def authorize!
+ raise_resource_not_available_error! unless context[:current_user].present?
+ end
end
end
diff --git a/app/graphql/resolvers/users_resolver.rb b/app/graphql/resolvers/users_resolver.rb
index 1424c14083d..b0d704d09fc 100644
--- a/app/graphql/resolvers/users_resolver.rb
+++ b/app/graphql/resolvers/users_resolver.rb
@@ -47,10 +47,7 @@ module Resolvers
end
def authorize!(usernames)
- authorized = Ability.allowed?(context[:current_user], :read_users_list)
- authorized &&= usernames.present? if context[:current_user].blank?
-
- raise_resource_not_available_error! unless authorized
+ raise_resource_not_available_error! unless context[:current_user].present?
end
private
diff --git a/app/graphql/resolvers/work_items_resolver.rb b/app/graphql/resolvers/work_items_resolver.rb
new file mode 100644
index 00000000000..1bc74131b9e
--- /dev/null
+++ b/app/graphql/resolvers/work_items_resolver.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class WorkItemsResolver < BaseResolver
+ include SearchArguments
+ include LooksAhead
+
+ type Types::WorkItemType.connection_type, null: true
+
+ argument :iid, GraphQL::Types::String,
+ required: false,
+ description: 'IID of the issue. For example, "1".'
+ argument :iids, [GraphQL::Types::String],
+ required: false,
+ description: 'List of IIDs of work items. For example, `["1", "2"]`.'
+ argument :sort, Types::WorkItemSortEnum,
+ description: 'Sort work items by this criteria.',
+ required: false,
+ default_value: :created_desc
+ argument :state, Types::IssuableStateEnum,
+ required: false,
+ description: 'Current state of this work item.'
+ argument :types, [Types::IssueTypeEnum],
+ as: :issue_types,
+ description: 'Filter work items by the given work item types.',
+ required: false
+
+ def resolve_with_lookahead(**args)
+ # The project could have been loaded in batch by `BatchLoader`.
+ # At this point we need the `id` of the project to query for issues, so
+ # make sure it's loaded and not `nil` before continuing.
+ parent = object.respond_to?(:sync) ? object.sync : object
+ return WorkItem.none if parent.nil? || !parent.work_items_feature_flag_enabled?
+
+ args[:iids] ||= [args.delete(:iid)].compact if args[:iid]
+ args[:attempt_project_search_optimizations] = true if args[:search].present?
+
+ finder = ::WorkItems::WorkItemsFinder.new(current_user, args)
+
+ Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) }
+ end
+
+ def ready?(**args)
+ validate_anonymous_search_access! if args[:search].present?
+
+ super
+ end
+
+ private
+
+ def unconditional_includes
+ [
+ {
+ project: [:project_feature, :group]
+ },
+ :author
+ ]
+ end
+ end
+end