Commit 0da8fa97 authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Heinrich Lee Yu

Add ability to query projects in GraphQL API

This change adds ability to search projects by search criteria and user
membership to Projects GraphQL API.
parent 6fe061f1
# frozen_string_literal: true
module Resolvers
class ProjectsResolver < BaseResolver
type Types::ProjectType, null: true
argument :membership, GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Limit projects that the current user is a member of'
argument :search, GraphQL::STRING_TYPE,
required: false,
description: 'Search criteria'
def resolve(**args)
ProjectsFinder
.new(current_user: current_user, params: project_finder_params(args))
.execute
end
private
def project_finder_params(params)
{
without_deleted: true,
non_public: params[:membership],
search: params[:search]
}.compact
end
end
end
...@@ -9,6 +9,11 @@ module Types ...@@ -9,6 +9,11 @@ module Types
resolver: Resolvers::ProjectResolver, resolver: Resolvers::ProjectResolver,
description: "Find a project" description: "Find a project"
field :projects, Types::ProjectType.connection_type,
null: true,
resolver: Resolvers::ProjectsResolver,
description: "Find projects visible to the current user"
field :group, Types::GroupType, field :group, Types::GroupType,
null: true, null: true,
resolver: Resolvers::GroupResolver, resolver: Resolvers::GroupResolver,
......
---
title: Add ability to query Projects using GraphQL API
merge_request: 30146
author:
type: added
...@@ -8088,6 +8088,41 @@ type Query { ...@@ -8088,6 +8088,41 @@ type Query {
fullPath: ID! fullPath: ID!
): Project ): Project
"""
Find projects visible to the current user
"""
projects(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
"""
Limit projects that the current user is a member of
"""
membership: Boolean
"""
Search criteria
"""
search: String
): ProjectConnection
""" """
Find Snippets visible to the current user Find Snippets visible to the current user
""" """
......
...@@ -23887,6 +23887,79 @@ ...@@ -23887,6 +23887,79 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "projects",
"description": "Find projects visible to the current user",
"args": [
{
"name": "membership",
"description": "Limit projects that the current user is a member of",
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"defaultValue": null
},
{
"name": "search",
"description": "Search criteria",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "ProjectConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "snippets", "name": "snippets",
"description": "Find Snippets visible to the current user", "description": "Find Snippets visible to the current user",
......
# frozen_string_literal: true
require 'spec_helper'
describe Resolvers::ProjectsResolver do
include GraphqlHelpers
describe '#resolve' do
subject { resolve(described_class, obj: nil, args: filters, ctx: { current_user: current_user }) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:other_project) { create(:project, :public) }
let_it_be(:private_project) { create(:project, :private) }
let_it_be(:other_private_project) { create(:project, :private) }
let_it_be(:user) { create(:user) }
let(:filters) { {} }
before_all do
project.add_developer(user)
private_project.add_developer(user)
end
context 'when user is not logged in' do
let(:current_user) { nil }
context 'when no filters are applied' do
it 'returns all public projects' do
is_expected.to contain_exactly(project, other_project)
end
context 'when search filter is provided' do
let(:filters) { { search: project.name } }
it 'returns matching project' do
is_expected.to contain_exactly(project)
end
end
context 'when membership filter is provided' do
let(:filters) { { membership: true } }
it 'returns empty list' do
is_expected.to be_empty
end
end
end
end
context 'when user is logged in' do
let(:current_user) { user }
context 'when no filters are applied' do
it 'returns all visible projects for the user' do
is_expected.to contain_exactly(project, other_project, private_project)
end
context 'when search filter is provided' do
let(:filters) { { search: project.name } }
it 'returns matching project' do
is_expected.to contain_exactly(project)
end
end
context 'when membership filter is provided' do
let(:filters) { { membership: true } }
it 'returns projects that user is member of' do
is_expected.to contain_exactly(project, private_project)
end
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