2019-03-03 12:53:03 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
describe 'GraphQL' do
|
|
|
|
include GraphqlHelpers
|
|
|
|
|
|
|
|
let(:query) { graphql_query_for('echo', 'text' => 'Hello world' ) }
|
|
|
|
|
2019-05-02 00:16:49 +00:00
|
|
|
context 'logging' do
|
2019-05-23 21:29:19 +00:00
|
|
|
shared_examples 'logging a graphql query' do
|
|
|
|
let(:expected_params) do
|
2019-05-23 22:43:47 +00:00
|
|
|
{ query_string: query, variables: variables.to_s, duration: anything, depth: 1, complexity: 1 }
|
2019-05-23 21:29:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'logs a query with the expected params' do
|
2019-05-23 22:43:47 +00:00
|
|
|
expect(Gitlab::GraphqlLogger).to receive(:info).with(expected_params).once
|
|
|
|
|
2019-05-23 21:29:19 +00:00
|
|
|
post_graphql(query, variables: variables)
|
|
|
|
end
|
|
|
|
|
2019-05-23 22:43:47 +00:00
|
|
|
it 'does not instantiate any query analyzers' do # they are static and re-used
|
|
|
|
expect(GraphQL::Analysis::QueryComplexity).not_to receive(:new)
|
|
|
|
expect(GraphQL::Analysis::QueryDepth).not_to receive(:new)
|
|
|
|
|
|
|
|
2.times { post_graphql(query, variables: variables) }
|
|
|
|
end
|
2019-05-02 07:09:10 +00:00
|
|
|
end
|
2019-05-02 00:16:49 +00:00
|
|
|
|
2019-05-02 07:09:10 +00:00
|
|
|
context 'with no variables' do
|
2019-05-23 21:29:19 +00:00
|
|
|
let(:variables) { {} }
|
2019-05-02 07:09:10 +00:00
|
|
|
|
2019-05-23 21:29:19 +00:00
|
|
|
it_behaves_like 'logging a graphql query'
|
2019-05-02 00:16:49 +00:00
|
|
|
end
|
|
|
|
|
2019-05-02 07:09:10 +00:00
|
|
|
context 'with variables' do
|
2019-05-23 21:29:19 +00:00
|
|
|
let(:variables) do
|
2019-05-22 05:13:06 +00:00
|
|
|
{ "foo" => "bar" }
|
2019-05-02 07:09:10 +00:00
|
|
|
end
|
|
|
|
|
2019-05-23 21:29:19 +00:00
|
|
|
it_behaves_like 'logging a graphql query'
|
2019-05-02 07:09:10 +00:00
|
|
|
end
|
2019-05-23 22:43:47 +00:00
|
|
|
|
|
|
|
context 'when there is an error in the logger' do
|
|
|
|
before do
|
|
|
|
allow_any_instance_of(Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer).to receive(:process_variables).and_raise(StandardError.new("oh noes!"))
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'logs the exception in Sentry and continues with the request' do
|
|
|
|
expect(Gitlab::Sentry).to receive(:track_exception).at_least(1).times
|
|
|
|
expect(Gitlab::GraphqlLogger).to receive(:info)
|
|
|
|
|
|
|
|
post_graphql(query, variables: {})
|
|
|
|
end
|
|
|
|
end
|
2019-05-02 00:16:49 +00:00
|
|
|
end
|
|
|
|
|
2019-03-03 12:53:03 +00:00
|
|
|
context 'invalid variables' do
|
|
|
|
it 'returns an error' do
|
|
|
|
post_graphql(query, variables: "This is not JSON")
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(422)
|
|
|
|
expect(json_response['errors'].first['message']).not_to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'authentication', :allow_forgery_protection do
|
|
|
|
let(:user) { create(:user) }
|
|
|
|
|
|
|
|
it 'allows access to public data without authentication' do
|
|
|
|
post_graphql(query)
|
|
|
|
|
|
|
|
expect(graphql_data['echo']).to eq('nil says: Hello world')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not authenticate a user with an invalid CSRF' do
|
|
|
|
login_as(user)
|
|
|
|
|
|
|
|
post_graphql(query, headers: { 'X-CSRF-Token' => 'invalid' })
|
|
|
|
|
|
|
|
expect(graphql_data['echo']).to eq('nil says: Hello world')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'authenticates a user with a valid session token' do
|
|
|
|
# Create a session to get a CSRF token from
|
|
|
|
login_as(user)
|
|
|
|
get('/')
|
|
|
|
|
|
|
|
post '/api/graphql', params: { query: query }, headers: { 'X-CSRF-Token' => response.session['_csrf_token'] }
|
|
|
|
|
|
|
|
expect(graphql_data['echo']).to eq("\"#{user.username}\" says: Hello world")
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'token authentication' do
|
|
|
|
let(:token) { create(:personal_access_token) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
stub_authentication_activity_metrics(debug: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'Authenticates users with a PAT' do
|
|
|
|
expect(authentication_metrics)
|
|
|
|
.to increment(:user_authenticated_counter)
|
|
|
|
.and increment(:user_session_override_counter)
|
|
|
|
.and increment(:user_sessionless_authentication_counter)
|
|
|
|
|
|
|
|
post_graphql(query, headers: { 'PRIVATE-TOKEN' => token.token })
|
|
|
|
|
|
|
|
expect(graphql_data['echo']).to eq("\"#{token.user.username}\" says: Hello world")
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the personal access token has no api scope' do
|
|
|
|
it 'does not log the user in' do
|
|
|
|
token.update(scopes: [:read_user])
|
|
|
|
|
|
|
|
post_graphql(query, headers: { 'PRIVATE-TOKEN' => token.token })
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(200)
|
|
|
|
|
|
|
|
expect(graphql_data['echo']).to eq('nil says: Hello world')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-06-21 14:20:00 +00:00
|
|
|
|
|
|
|
describe 'testing for Gitaly calls' do
|
|
|
|
let(:project) { create(:project, :repository) }
|
|
|
|
let(:user) { create(:user) }
|
|
|
|
|
|
|
|
let(:query) do
|
2019-06-28 01:24:47 +00:00
|
|
|
graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id))
|
2019-06-21 14:20:00 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
project.add_developer(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'a working graphql query' do
|
|
|
|
before do
|
|
|
|
post_graphql(query, current_user: user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when Gitaly is called' do
|
|
|
|
before do
|
|
|
|
allow(Gitlab::GitalyClient).to receive(:get_request_count).and_return(1, 2)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "logs a warning that the 'calls_gitaly' field declaration is missing" do
|
|
|
|
expect(Gitlab::Sentry).to receive(:track_exception).once
|
|
|
|
|
|
|
|
post_graphql(query, current_user: user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-03-03 12:53:03 +00:00
|
|
|
end
|