diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js index 47e91dedd5ae7bd772eb4c2950e595cfe27b22ed..5857f9e22aeaf2935d8e45c98e61ffaf816f64b8 100644 --- a/app/assets/javascripts/lib/graphql.js +++ b/app/assets/javascripts/lib/graphql.js @@ -1,6 +1,8 @@ import { ApolloClient } from 'apollo-client'; import { InMemoryCache } from 'apollo-cache-inmemory'; import { createUploadLink } from 'apollo-upload-client'; +import { ApolloLink } from 'apollo-link'; +import { BatchHttpLink } from 'apollo-link-batch-http'; import csrf from '~/lib/utils/csrf'; export default (resolvers = {}, config = {}) => { @@ -11,13 +13,19 @@ export default (resolvers = {}, config = {}) => { uri = `${config.baseUrl}${uri}`.replace(/\/{3,}/g, '/'); } + const httpOptions = { + uri, + headers: { + [csrf.headerKey]: csrf.token, + }, + }; + return new ApolloClient({ - link: createUploadLink({ - uri, - headers: { - [csrf.headerKey]: csrf.token, - }, - }), + link: ApolloLink.split( + operation => operation.getContext().hasUpload, + createUploadLink(httpOptions), + new BatchHttpLink(httpOptions), + ), cache: new InMemoryCache(config.cacheConfig), resolvers, }); diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index e8f388996474b19fa29ec806900883020725cec8..1ce0afac83bae32f8e42faf30f2885414e05e208 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -53,7 +53,8 @@ class GraphqlController < ApplicationController { query: single_query_info[:query], variables: build_variables(single_query_info[:variables]), - operation_name: single_query_info[:operationName] + operation_name: single_query_info[:operationName], + context: context } end end diff --git a/package.json b/package.json index 7c992f61c001bd5595ed3e922df3af43edbaacae..2b45f25e9c3c1f122136ae0e38667169157917e0 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,8 @@ "@gitlab/ui": "^3.10.1", "apollo-cache-inmemory": "^1.5.1", "apollo-client": "^2.5.1", + "apollo-link": "^1.2.11", + "apollo-link-batch-http": "^1.2.11", "apollo-upload-client": "^10.0.0", "at.js": "^1.5.4", "autosize": "^4.0.0", diff --git a/spec/requests/api/graphql/gitlab_schema_spec.rb b/spec/requests/api/graphql/gitlab_schema_spec.rb index a724c5c3f1cb3ca765fa1d8b9deb5bf081f5c574..9beea2e259404311cc7d89b0b74adb2cf00effc1 100644 --- a/spec/requests/api/graphql/gitlab_schema_spec.rb +++ b/spec/requests/api/graphql/gitlab_schema_spec.rb @@ -52,13 +52,22 @@ describe 'GitlabSchema configurations' do end context 'multiplexed queries' do + let(:current_user) { nil } + subject do queries = [ - { query: graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id name description)) }, - { query: graphql_query_for('echo', { 'text' => "$test" }, []), variables: { "test" => "Hello world" } } + { query: graphql_query_for('project', { 'fullPath' => '$fullPath' }, %w(id name description)) }, + { query: graphql_query_for('echo', { 'text' => "$test" }, []), variables: { "test" => "Hello world" } }, + { query: graphql_query_for('project', { 'fullPath' => project.full_path }, "userPermissions { createIssue }") } ] - post_multiplex(queries) + post_multiplex(queries, current_user: current_user) + end + + it 'does not authenticate all queries' do + subject + + expect(json_response.last['data']['project']).to be_nil end it_behaves_like 'imposing query limits' do @@ -69,18 +78,28 @@ describe 'GitlabSchema configurations' do subject # Expect a response for each query, even though it will be empty - expect(json_response.size).to eq(2) + expect(json_response.size).to eq(3) json_response.each do |single_query_response| expect(single_query_response).not_to have_key('data') end # Expect errors for each query - expect(graphql_errors.size).to eq(2) + expect(graphql_errors.size).to eq(3) graphql_errors.each do |single_query_errors| expect(single_query_errors.first['message']).to include('which exceeds max complexity of 4') end end end + + context 'authentication' do + let(:current_user) { project.owner } + + it 'authenticates all queries' do + subject + + expect(json_response.last['data']['project']['userPermissions']['createIssue']).to be(true) + end + end end context 'when IntrospectionQuery' do diff --git a/yarn.lock b/yarn.lock index 45729eda890145a147b900445e667a0795d59863..421dc7180382f40958e64e52a405cc33b374ec43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1398,6 +1398,24 @@ apollo-client@^2.5.1: tslib "^1.9.3" zen-observable "^0.8.0" +apollo-link-batch-http@^1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/apollo-link-batch-http/-/apollo-link-batch-http-1.2.11.tgz#ae42dbcc02820658e1e267d05bf2aae7ac208088" + integrity sha512-f+KEdbP51I3AeEaBDW2lKS3eaPK/1IXaTM9F2moj02s1hgC/TzeUORRuUeOExW8ggXveW1Jzp6aYMJ2SQkZJyA== + dependencies: + apollo-link "^1.2.11" + apollo-link-batch "^1.1.12" + apollo-link-http-common "^0.2.13" + tslib "^1.9.3" + +apollo-link-batch@^1.1.12: + version "1.1.12" + resolved "https://registry.yarnpkg.com/apollo-link-batch/-/apollo-link-batch-1.1.12.tgz#64eb231082f182b0395ef7ab903600627f6c7fe8" + integrity sha512-6NqLiB9tEGxRiyhtnX/7CPHkmFG0IXfEP7pC5kirhjV+4KxqBaWvJnJGKpGp7Owgdph7KJlV+9+niOKEkcwreg== + dependencies: + apollo-link "^1.2.11" + tslib "^1.9.3" + apollo-link-dedup@^1.0.0: version "1.0.10" resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.10.tgz#7b94589fe7f969777efd18a129043c78430800ae" @@ -1405,7 +1423,7 @@ apollo-link-dedup@^1.0.0: dependencies: apollo-link "^1.2.3" -apollo-link-http-common@^0.2.8: +apollo-link-http-common@^0.2.13, apollo-link-http-common@^0.2.8: version "0.2.13" resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.13.tgz#c688f6baaffdc7b269b2db7ae89dae7c58b5b350" integrity sha512-Uyg1ECQpTTA691Fwx5e6Rc/6CPSu4TB4pQRTGIpwZ4l5JDOQ+812Wvi/e3IInmzOZpwx5YrrOfXrtN8BrsDXoA==