Add metadata about the GitLab server to GraphQL
This commit is contained in:
parent
42d3117f9c
commit
21779d0018
14 changed files with 171 additions and 5 deletions
11
app/graphql/resolvers/metadata_resolver.rb
Normal file
11
app/graphql/resolvers/metadata_resolver.rb
Normal 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
|
10
app/graphql/types/metadata_type.rb
Normal file
10
app/graphql/types/metadata_type.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
5
changelogs/unreleased/56809-graphql-version-api.yml
Normal file
5
changelogs/unreleased/56809-graphql-version-api.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add metadata about the GitLab server to GraphQL
|
||||
merge_request: 24636
|
||||
author:
|
||||
type: added
|
22
lib/api/helpers/graphql_helpers.rb
Normal file
22
lib/api/helpers/graphql_helpers.rb
Normal 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
|
|
@ -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
|
||||
|
|
11
spec/graphql/resolvers/metadata_resolver_spec.rb
Normal file
11
spec/graphql/resolvers/metadata_resolver_spec.rb
Normal 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
|
5
spec/graphql/types/metadata_type_spec.rb
Normal file
5
spec/graphql/types/metadata_type_spec.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe GitlabSchema.types['Metadata'] do
|
||||
it { expect(described_class.graphql_name).to eq('Metadata') }
|
||||
end
|
|
@ -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
|
||||
|
|
|
@ -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) }
|
||||
|
|
32
spec/requests/api/graphql/metadata_query_spec.rb
Normal file
32
spec/requests/api/graphql/metadata_query_spec.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue