Add metadata about the GitLab server to GraphQL

This commit is contained in:
Nick Thomas 2019-01-24 16:23:57 +00:00
parent 42d3117f9c
commit 21779d0018
No known key found for this signature in database
GPG key ID: 2A313A47AFADACE9
14 changed files with 171 additions and 5 deletions

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
module Resolvers
class MetadataResolver < BaseResolver
type Types::MetadataType, null: false
def resolve(**args)
{ version: Gitlab::VERSION, revision: Gitlab.revision }
end
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Types
class MetadataType < ::Types::BaseObject
graphql_name 'Metadata'
field :version, GraphQL::STRING_TYPE, null: false
field :revision, GraphQL::STRING_TYPE, null: false
end
end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
module Types
class QueryType < BaseObject
class QueryType < ::Types::BaseObject
graphql_name 'Query'
field :project, Types::ProjectType,
@ -10,6 +10,14 @@ module Types
description: "Find a project",
authorize: :read_project
field :metadata, Types::MetadataType,
null: true,
resolver: Resolvers::MetadataResolver,
description: 'Metadata about GitLab' do |*args|
authorize :read_instance_metadata
end
field :echo, GraphQL::STRING_TYPE, null: false, function: Functions::Echo.new
end
end

View file

@ -68,6 +68,10 @@ class GlobalPolicy < BasePolicy
enable :read_users_list
end
rule { ~anonymous }.policy do
enable :read_instance_metadata
end
rule { admin }.policy do
enable :read_custom_attribute
enable :update_custom_attribute

View file

@ -0,0 +1,5 @@
---
title: Add metadata about the GitLab server to GraphQL
merge_request: 24636
author:
type: added

View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
module API
module Helpers
# GraphqlHelpers is used by the REST API when it is acting like a client
# against the graphql API. Helper code for the graphql server implementation
# should be in app/graphql/ or lib/gitlab/graphql/
module GraphqlHelpers
def conditionally_graphql!(fallback:, query:, context: {}, transform: nil)
return fallback.call unless Feature.enabled?(:graphql)
result = GitlabSchema.execute(query, context: context)
if transform
transform.call(result)
else
result
end
end
end
end
end

View file

@ -2,13 +2,29 @@
module API
class Version < Grape::API
helpers ::API::Helpers::GraphqlHelpers
before { authenticate! }
METADATA_QUERY = <<~EOF
{
metadata {
version
revision
}
}
EOF
desc 'Get the version information of the GitLab instance.' do
detail 'This feature was introduced in GitLab 8.13.'
end
get '/version' do
{ version: Gitlab::VERSION, revision: Gitlab.revision }
conditionally_graphql!(
query: METADATA_QUERY,
context: { current_user: current_user },
transform: ->(result) { result.dig('data', 'metadata') },
fallback: -> { { version: Gitlab::VERSION, revision: Gitlab.revision } }
)
end
end
end

View file

@ -0,0 +1,11 @@
require 'spec_helper'
describe Resolvers::MetadataResolver do
include GraphqlHelpers
describe '#resolve' do
it 'returns version and revision' do
expect(resolve(described_class)).to eq(version: Gitlab::VERSION, revision: Gitlab.revision)
end
end
end

View file

@ -0,0 +1,5 @@
require 'spec_helper'
describe GitlabSchema.types['Metadata'] do
it { expect(described_class.graphql_name).to eq('Metadata') }
end

View file

@ -5,7 +5,7 @@ describe GitlabSchema.types['Query'] do
expect(described_class.graphql_name).to eq('Query')
end
it { is_expected.to have_graphql_fields(:project, :echo) }
it { is_expected.to have_graphql_fields(:project, :echo, :metadata) }
describe 'project field' do
subject { described_class.fields['project'] }
@ -20,4 +20,17 @@ describe GitlabSchema.types['Query'] do
is_expected.to require_graphql_authorizations(:read_project)
end
end
describe 'metadata field' do
subject { described_class.fields['metadata'] }
it 'returns metadata' do
is_expected.to have_graphql_type(Types::MetadataType)
is_expected.to have_graphql_resolver(Resolvers::MetadataResolver)
end
it 'authorizes with log_in' do
is_expected.to require_graphql_authorizations(:read_instance_metadata)
end
end
end

View file

@ -181,6 +181,18 @@ describe GlobalPolicy do
end
end
describe 'read instance metadata' do
context 'regular user' do
it { is_expected.to be_allowed(:read_instance_metadata) }
end
context 'anonymous' do
let(:current_user) { nil }
it { is_expected.not_to be_allowed(:read_instance_metadata) }
end
end
describe 'read instance statistics' do
context 'regular user' do
it { is_expected.to be_allowed(:read_instance_statistics) }

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
require 'spec_helper'
describe 'getting project information' do
include GraphqlHelpers
let(:query) { graphql_query_for('metadata', {}, all_graphql_fields_for('Metadata')) }
context 'logged in' do
it 'returns version and revision' do
post_graphql(query, current_user: create(:user))
expect(graphql_errors).to be_nil
expect(graphql_data).to eq(
'metadata' => {
'version' => Gitlab::VERSION,
'revision' => Gitlab.revision
}
)
end
end
context 'anonymous user' do
it 'returns nothing' do
post_graphql(query, current_user: nil)
expect(graphql_errors).to be_nil
expect(graphql_data).to eq('metadata' => nil)
end
end
end

View file

@ -1,7 +1,7 @@
require 'spec_helper'
describe API::Version do
describe 'GET /version' do
shared_examples_for 'GET /version' do
context 'when unauthenticated' do
it 'returns authentication error' do
get api('/version')
@ -22,4 +22,20 @@ describe API::Version do
end
end
end
context 'with graphql enabled' do
before do
stub_feature_flags(graphql: true)
end
include_examples 'GET /version'
end
context 'with graphql disabled' do
before do
stub_feature_flags(graphql: false)
end
include_examples 'GET /version'
end
end

View file

@ -77,8 +77,9 @@ module GraphqlHelpers
def query_graphql_field(name, attributes = {}, fields = nil)
fields ||= all_graphql_fields_for(name.classify)
attributes = attributes_to_graphql(attributes)
attributes = "(#{attributes})" if attributes.present?
<<~QUERY
#{name}(#{attributes}) {
#{name}#{attributes} {
#{fields}
}
QUERY