Commit 19efcb2a authored by Alex Kalderimis's avatar Alex Kalderimis

Add resolvers for the user <-> merge-request edges

These resolvers re-use the functionality of the merge_requests_resolver
to find merge requests either authored by or assigned to a user. The
author is the implicit argument of the edge, and they support all the
filtering arguments of the merge_requests_resolver, as well as being
able to restrict the project, either by ID or full-path.
parent 56b2638f
# frozen_string_literal: true
module Resolvers
class AssignedMergeRequestsResolver < UserMergeRequestsResolver
def user_role
:assignee
end
end
end
# frozen_string_literal: true
module Resolvers
class AuthoredMergeRequestsResolver < UserMergeRequestsResolver
def user_role
:author
end
end
end
......@@ -13,10 +13,10 @@ module ResolvesMergeRequests
args[:iids] = Array.wrap(args[:iids]) if args[:iids]
args.compact!
if args.keys == [:iids]
if project && args.keys == [:iids]
batch_load_merge_requests(args[:iids])
else
args[:project_id] = project.id
args[:project_id] ||= project
MergeRequestsFinder.new(current_user, args).execute
end.then(&(single? ? :first : :itself))
......
......@@ -34,7 +34,11 @@ module Resolvers
end
def no_results_possible?(args)
project.nil? || args.values.any? { |v| v.is_a?(Array) && v.empty? }
project.nil? || some_argument_is_empty?(args)
end
def some_argument_is_empty?(args)
args.values.any? { |v| v.is_a?(Array) && v.empty? }
end
end
end
# frozen_string_literal: true
module Resolvers
class UserMergeRequestsResolver < MergeRequestsResolver
include ResolvesProject
argument :project_path, GraphQL::STRING_TYPE,
required: false,
description: 'The full-path of the project the authored merge requests should be in. Incompatible with projectId.'
argument :project_id, GraphQL::ID_TYPE,
required: false,
description: 'The global ID of the project the authored merge requests should be in. Incompatible with projectPath.'
attr_reader :project
alias_method :user, :synchronized_object
def ready?(project_id: nil, project_path: nil, **args)
return early_return unless can_read_profile?
if project_id || project_path
load_project(project_path, project_id)
return early_return unless can_read_project?
elsif args[:iids].present?
raise ::Gitlab::Graphql::Errors::ArgumentError,
'iids requires projectPath or projectId'
end
super(**args)
end
def resolve(**args)
prepare_args(args)
key = :"#{user_role}_id"
super(key => user.id, **args)
end
def user_role
raise NotImplementedError
end
private
def can_read_profile?
Ability.allowed?(current_user, :read_user_profile, user)
end
def can_read_project?
Ability.allowed?(current_user, :read_merge_request, project)
end
def load_project(project_path, project_id)
@project = resolve_project(full_path: project_path, project_id: project_id)
@project = @project.sync if @project.respond_to?(:sync)
end
def no_results_possible?(args)
some_argument_is_empty?(args)
end
# These arguments are handled in load_project, and should not be passed to
# the finder directly.
def prepare_args(args)
args.delete(:project_id)
args.delete(:project_path)
end
end
end
......@@ -4,6 +4,8 @@ module Resolvers
class UserResolver < BaseResolver
description 'Retrieve a single user'
type Types::UserType, null: true
argument :id, GraphQL::ID_TYPE,
required: false,
description: 'ID of the User'
......@@ -12,13 +14,6 @@ module Resolvers
required: false,
description: 'Username of the User'
def resolve(id: nil, username: nil)
id_or_username = GitlabSchema.parse_gid(id, expected_type: ::User).model_id if id
id_or_username ||= username
::UserFinder.new(id_or_username).find_by_id_or_username
end
def ready?(id: nil, username: nil)
unless id.present? ^ username.present?
raise Gitlab::Graphql::Errors::ArgumentError, 'Provide either a single username or id'
......@@ -26,5 +21,23 @@ module Resolvers
super
end
def resolve(id: nil, username: nil)
if id
GitlabSchema.object_from_id(id, expected_type: User)
else
batch_load(username)
end
end
private
def batch_load(username)
BatchLoader::GraphQL.for(username).batch do |usernames, loader|
User.by_username(usernames).each do |user|
loader.call(user.username, user)
end
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment