Commit 363b79d4 authored by Max Woolf's avatar Max Woolf

Add user root query to GraphQL API

Adds a root user query to search
for a user by username or id
parent a8164e36
# frozen_string_literal: true
module Resolvers
class UserResolver < BaseResolver
description 'Retrieve a single user'
argument :id, GraphQL::ID_TYPE,
required: false,
description: 'ID of the User'
argument :username, GraphQL::STRING_TYPE,
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'
end
super
end
end
end
......@@ -47,6 +47,11 @@ module Types
null: false,
description: 'Fields related to design management'
field :user, Types::UserType,
null: true,
description: 'Find a user',
resolver: Resolvers::UserResolver
field :echo, GraphQL::STRING_TYPE, null: false,
description: 'Text to echo back',
resolver: Resolvers::EchoResolver
......
---
title: Add user root query to GraphQL API
merge_request: 33041
author:
type: added
......@@ -57,6 +57,7 @@ The GraphQL API includes the following queries at the root level:
1. `project` : Project information, with many of its associations such as issues and merge requests.
1. `group` : Basic group information and epics **(ULTIMATE)** are currently supported.
1. `user` : Information about a particular user.
1. `namespace` : Within a namespace it is also possible to fetch `projects`.
1. `currentUser`: Information about the currently logged in user.
1. `metaData`: Metadata about GitLab and the GraphQL API.
......
......@@ -9142,6 +9142,21 @@ type Query {
visibility: VisibilityScopesEnum
): SnippetConnection
"""
Find a user
"""
user(
"""
ID of the User
"""
id: ID
"""
Username of the User
"""
username: String
): User
"""
Vulnerabilities reported on projects on the current user's instance security dashboard
"""
......
......@@ -26833,6 +26833,39 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "user",
"description": "Find a user",
"args": [
{
"name": "id",
"description": "ID of the User",
"type": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
},
"defaultValue": null
},
{
"name": "username",
"description": "Username of the User",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "User",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "vulnerabilities",
"description": "Vulnerabilities reported on projects on the current user's instance security dashboard",
# frozen_string_literal: true
require 'spec_helper'
describe Resolvers::UserResolver do
include GraphqlHelpers
describe '#resolve' do
let_it_be(:user) { create(:user) }
context 'when neither an ID or a username is provided' do
it 'raises an ArgumentError' do
expect { resolve_user }
.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
end
it 'raises an ArgumentError when both an ID and username are provided' do
expect { resolve_user(id: user.to_global_id, username: user.username) }
.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
context 'by username' do
it 'returns the correct user' do
expect(
resolve_user(username: user.username)
).to eq(user)
end
end
context 'by ID' do
it 'returns the correct user' do
expect(
resolve_user(id: user.to_global_id)
).to eq(user)
end
end
end
private
def resolve_user(args = {})
resolve(described_class, args: args)
end
end
......@@ -8,9 +8,24 @@ describe GitlabSchema.types['Query'] do
end
it 'has the expected fields' do
expected_fields = %i[project namespace group echo metadata current_user snippets design_management]
expect(described_class).to have_graphql_fields(*expected_fields).at_least
expected_fields = %i[
current_user
design_management
geoNode
group
echo
instanceSecurityDashboard
metadata
namespace
project
projects
snippets
user
vulnerabilities
vulnerabilitiesCountByDayAndSeverity
]
expect(described_class).to have_graphql_fields(*expected_fields)
end
describe 'namespace field' do
......
# frozen_string_literal: true
require 'spec_helper'
describe 'User' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
shared_examples 'a working user query' do
it_behaves_like 'a working graphql query' do
before do
post_graphql(query, current_user: current_user)
end
end
it 'includes the user' do
post_graphql(query, current_user: current_user)
expect(graphql_data['user']).not_to be_nil
end
it 'returns no user when global restricted_visibility_levels includes PUBLIC' do
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
post_graphql(query)
expect(graphql_data['user']).to be_nil
end
end
context 'when id parameter is used' do
let(:query) { graphql_query_for(:user, { id: current_user.to_global_id.to_s }) }
it_behaves_like 'a working user query'
end
context 'when username parameter is used' do
let(:query) { graphql_query_for(:user, { username: current_user.username.to_s }) }
it_behaves_like 'a working user query'
end
context 'when username and id parameter are used' do
let_it_be(:query) { graphql_query_for(:user, { id: current_user.to_global_id.to_s, username: current_user.username }, 'id') }
it 'displays an error' do
post_graphql(query)
expect(graphql_errors).to include(
a_hash_including('message' => a_string_matching(%r{Provide either a single username or id}))
)
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