Cube proxy doesn't work with Cube JS library
Summary
When using the /api/v4/projects/1/product_analytics/request
Cube proxy endpoint in conjunction with Cube JS library, the library tries to use the /api/v4/projects/1/product_analytics/request/load
endpoint even though it doesn't exist and so the proxy returns a 404
. If you update the endpoint:
Index: ee/lib/api/analytics/product_analytics.rb
<+>UTF-8
===================================================================
diff --git a/ee/lib/api/analytics/product_analytics.rb b/ee/lib/api/analytics/product_analytics.rb
--- a/ee/lib/api/analytics/product_analytics.rb (revision Staged)
+++ b/ee/lib/api/analytics/product_analytics.rb (date 1665485601393)
@@ -24,7 +24,7 @@
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Proxy request to cube installation'
- post ':project_id/product_analytics/request' do
+ post ':project_id/product_analytics/request/load' do
not_found! unless ::Feature.enabled?(:cube_api_proxy, project)
unauthorized! unless can?(current_user, :developer_access, project)
The proxy returns a 401
even when logged in because the library doesn't seem to pass on all the authentication information from the parent page when POSTing.
Steps to reproduce
Pull down !98613 (merged) and apply the following patch:
Live data implementation
Index: config/webpack.config.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/webpack.config.js b/config/webpack.config.js
--- a/config/webpack.config.js (revision Staged)
+++ b/config/webpack.config.js (date 1665485350097)
@@ -305,6 +305,11 @@
test: /\.mjs$/,
use: [],
},
+ {
+ test: /(@cubejs-client\/vue).*\.(js)?$/,
+ include: /node_modules/,
+ loader: 'babel-loader',
+ },
WEBPACK_USE_ESBUILD_LOADER && {
test: /\.js$/,
exclude: (modulePath) =>
Index: ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue
<+>UTF-8
===================================================================
diff --git a/ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue b/ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue
--- a/ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue (revision Staged)
+++ b/ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue (date 1665485378835)
@@ -1,15 +1,63 @@
<script>
+import { QueryRenderer } from '@cubejs-client/vue';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { CubejsApi, HttpTransport } from '@cubejs-client/core';
+
+const cubejsApi = new CubejsApi('1', {
+ transport: new HttpTransport({
+ apiUrl: '/api/v4/projects/1/product_analytics/request',
+ method: 'POST',
+ }),
+});
+
export default {
name: 'AudienceWidget',
+ components: {
+ GlLineChart,
+ QueryRenderer,
+ },
props: {
widget: {
type: Object,
required: true,
},
},
+ data() {
+ return { cubejsApi };
+ },
+ methods: {
+ series(resultSet) {
+ if (!resultSet) {
+ return [];
+ }
+
+ const seriesNames = resultSet?.seriesNames();
+ const pivot = resultSet?.chartPivot();
+ const series = [];
+
+ seriesNames.forEach((e) => {
+ const data = pivot.map((p) => [p.x, p[e.key]]);
+ series.push({
+ name: e.title,
+ data,
+ });
+ });
+
+ return series;
+ },
+ },
};
</script>
<template>
- <p>{{ __('Widgets content') }}</p>
+ <query-renderer :cubejs-api="cubejsApi" :query="widget.query">
+ <template #default="{ resultSet }">
+ <gl-line-chart
+ :data="series(resultSet)"
+ :option="widget.options"
+ responsive
+ v-bind="widget.props"
+ />
+ </template>
+ </query-renderer>
</template>
Index: ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue
<+>UTF-8
===================================================================
diff --git a/ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue b/ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue
--- a/ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue (revision Staged)
+++ b/ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue (date 1665485350105)
@@ -2,6 +2,19 @@
import CustomizableDashboard from 'ee/vue_shared/components/customizable_dashboard/customizable_dashboard.vue';
import { __ } from '~/locale';
+const overTimeQueries = {
+ users: {
+ measures: ['Jitsu.count'],
+ timeDimensions: [
+ {
+ granularity: 'day',
+ dimension: 'Jitsu.utcTime',
+ },
+ ],
+ dimensions: ['Jitsu.eventType'],
+ },
+};
+
export default {
name: 'AnalyticsDashboard',
components: {
@@ -12,16 +25,47 @@
widgets: [
{
type: 'ProductAnalyticsAudience',
- gridAttributes: { width: 3, height: 3 },
- props: { title: __('Test A') },
- },
- {
- type: 'ProductAnalyticsAudience',
- gridAttributes: { width: 2, height: 4 },
- props: { title: __('Test B') },
+ gridAttributes: { x: 0, y: 0, height: 4, width: 6, minHeight: 4, minWidth: 6 },
+ props: {
+ title: __('Users / Time'),
+ query: this.withFilters(overTimeQueries.users, 'day'),
+ options: {
+ xAxis: {
+ name: __('Time'),
+ type: 'time',
+ axisLabel: {
+ interval: 0,
+ showMinLabel: false,
+ showMaxLabel: false,
+ align: 'right',
+ },
+ },
+ yAxis: {
+ name: __('Counts'),
+ },
+ legend: { show: false },
+ },
+ },
},
],
};
+ },
+ methods: {
+ withFilters(query, granularity) {
+ const newQuery = {
+ ...query,
+ };
+
+ newQuery.timeDimensions = [
+ {
+ dimension: `Jitsu.utcTime`,
+ dateRange: [new Date(2022, 8), new Date(2022, 10)],
+ granularity: granularity || null,
+ },
+ ];
+
+ return newQuery;
+ },
},
};
</script>
Index: jest.config.base.js
<+>UTF-8
===================================================================
diff --git a/jest.config.base.js b/jest.config.base.js
--- a/jest.config.base.js (revision Staged)
+++ b/jest.config.base.js (date 1665485350107)
@@ -153,6 +153,7 @@
'dateformat',
'lowlight',
'vscode-languageserver-types',
+ '@cubejs-client/vue',
...gfmParserDependencies,
];
Index: package.json
<+>UTF-8
===================================================================
diff --git a/package.json b/package.json
--- a/package.json (revision Staged)
+++ b/package.json (date 1665485350111)
@@ -50,6 +50,8 @@
"@babel/core": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"@codesandbox/sandpack-client": "^1.2.2",
+ "@cubejs-client/core": "^0.31.0",
+ "@cubejs-client/vue": "^0.31.0",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "3.4.0",
@@ -268,4 +270,4 @@
"node": ">=12.22.1",
"yarn": "^1.10.0"
}
-}
\ No newline at end of file
+}
Index: yarn.lock
<+>UTF-8
===================================================================
diff --git a/yarn.lock b/yarn.lock
--- a/yarn.lock (revision Staged)
+++ b/yarn.lock (date 1665485350155)
@@ -992,6 +992,27 @@
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.1.tgz#b6b8d81780b9a9f6459f4bfe9226ac6aefaefe87"
integrity sha512-aG20vknL4/YjQF9BSV7ts4EWm/yrjagAN7OWBNmlbEOUiu0llj4OGrFoOKK3g2vey4/p2omKCoHrWtPxSwV3HA==
+"@cubejs-client/core@^0.31.0":
+ version "0.31.0"
+ resolved "https://registry.yarnpkg.com/@cubejs-client/core/-/core-0.31.0.tgz#ee507a3841962a63b255e19f1575e66fd1c726ee"
+ integrity sha512-72+7dVsLURGEYR0FCImf1XPLnc849zKKYQPDk0O/tHShX+8+k8ARt5VLadCl61mbBHIZZgH3OFzvqSREQm+Stw==
+ dependencies:
+ core-js "^3.6.5"
+ cross-fetch "^3.0.2"
+ dayjs "^1.10.4"
+ ramda "^0.27.0"
+ url-search-params-polyfill "^7.0.0"
+ uuid "^8.3.2"
+
+"@cubejs-client/vue@^0.31.0":
+ version "0.31.0"
+ resolved "https://registry.yarnpkg.com/@cubejs-client/vue/-/vue-0.31.0.tgz#83db7d0ae153d12e2018faaa5b1dec00e02b8a57"
+ integrity sha512-7dm1yKFgQYx50BWnu6DPFr+bBFgnsyAZ0h1skrevtYU+s0kDBiwq1UQ45AZh/Q5w+AageenCh6N7bcn1AvVK8w==
+ dependencies:
+ "@cubejs-client/core" "^0.31.0"
+ core-js "^3.6.5"
+ ramda "^0.27.0"
+
"@discoveryjs/json-ext@^0.5.0":
version "0.5.6"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f"
@@ -3802,7 +3823,7 @@
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^3.25.5:
+core-js@^3.25.5, core-js@^3.6.5:
version "3.25.5"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.5.tgz#e86f651a2ca8a0237a5f064c2fe56cef89646e27"
integrity sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw==
@@ -3882,6 +3903,13 @@
dependencies:
jquery ">= 1.9.1"
+cross-fetch@^3.0.2:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
+ integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
+ dependencies:
+ node-fetch "2.6.7"
+
cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@@ -4580,6 +4608,11 @@
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-5.0.1.tgz#60a27a2deb339f888ba4532f533e25ac73ca3d19"
integrity sha512-DrcKxOW2am3mtqoJwBTK3OlWcF0QSk1p8diEWwpu3Mf//VdURD7XVaeOV738JvcaBiFfm9o2fisoMhiJH0aYxg==
+dayjs@^1.10.4:
+ version "1.11.5"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
+ integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
+
de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
@@ -9163,7 +9196,7 @@
resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
-node-fetch@^2.6.1, node-fetch@^2.6.7:
+node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
@@ -10196,6 +10229,11 @@
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
+ramda@^0.27.0:
+ version "0.27.2"
+ resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1"
+ integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==
+
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -11999,6 +12037,11 @@
mime-types "^2.1.27"
schema-utils "^3.0.0"
+url-search-params-polyfill@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/url-search-params-polyfill/-/url-search-params-polyfill-7.0.1.tgz#b900cd9a0d9d2ff757d500135256f2344879cbff"
+ integrity sha512-bAw7L2E+jn9XHG5P9zrPnHdO0yJub4U+yXJOdpcpkr7OBd9T8oll4lUos0iSGRcDvfZoLUKfx9a6aNmIhJ4+mQ==
+
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
And then visit a dashboard: http://gdk.test:3000/gitlab-org/gitlab-test/-/product_analytics/dashboards
. You should see the 404
.
Apply the API patch in the summary and observe the 401
.
What is the current bug behavior?
The Cube proxy endpoint returns a 404
/401
when being used by the JS library.
What is the expected correct behavior?
The Cube proxy endpoint returns a 201
/200
when being used by the JS library along with the correctly formatted query data.
Possible fixes
Having tested this, I was able to make everything work by changing the Cube proxy endpoint:
- Change to a
GET
- Append the
/load
to the end of the endpoint - Add the
queryType
param to the Cube API query body
A working patch for the frontend
Index: config/webpack.config.js
<+>UTF-8
===================================================================
diff --git a/config/webpack.config.js b/config/webpack.config.js
--- a/config/webpack.config.js (revision HEAD)
+++ b/config/webpack.config.js (revision Staged)
@@ -305,6 +305,11 @@
test: /\.mjs$/,
use: [],
},
+ {
+ test: /(@cubejs-client\/vue).*\.(js)?$/,
+ include: /node_modules/,
+ loader: 'babel-loader',
+ },
WEBPACK_USE_ESBUILD_LOADER && {
test: /\.js$/,
exclude: (modulePath) =>
Index: ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue
<+>UTF-8
===================================================================
diff --git a/ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue b/ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue
--- a/ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue (revision HEAD)
+++ b/ee/app/assets/javascripts/product_analytics/dashboards/components/widgets/audience.vue (revision Staged)
@@ -1,15 +1,60 @@
<script>
+import { QueryRenderer } from '@cubejs-client/vue';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { CubejsApi } from '@cubejs-client/core';
+
+const cubejsApi = new CubejsApi('1', {
+ apiUrl: '/api/v4/projects/1/product_analytics/request',
+});
+
export default {
name: 'AudienceWidget',
+ components: {
+ GlLineChart,
+ QueryRenderer,
+ },
props: {
widget: {
type: Object,
required: true,
},
},
+ data() {
+ return { cubejsApi };
+ },
+ methods: {
+ series(resultSet) {
+ if (!resultSet) {
+ return [];
+ }
+
+ const seriesNames = resultSet?.seriesNames();
+ const pivot = resultSet?.chartPivot();
+ const series = [];
+
+ seriesNames.forEach((e) => {
+ const data = pivot.map((p) => [p.x, p[e.key]]);
+ series.push({
+ name: e.title,
+ data,
+ });
+ });
+
+ return series;
+ },
+ },
};
</script>
<template>
- <p>{{ __('Widgets content') }}</p>
+ <query-renderer :cubejs-api="cubejsApi" :query="widget.query">
+ <template #default="{ resultSet }">
+ <gl-line-chart
+ :data="series(resultSet)"
+ :option="widget.options"
+ responsive
+ v-bind="widget.props"
+ />
+ </template>
+ </query-renderer>
</template>
Index: ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue
<+>UTF-8
===================================================================
diff --git a/ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue b/ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue
--- a/ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue (revision HEAD)
+++ b/ee/app/assets/javascripts/product_analytics/dashboards/components/analytics_dashboard.vue (revision Staged)
@@ -2,6 +2,19 @@
import CustomizableDashboard from 'ee/vue_shared/components/customizable_dashboard/customizable_dashboard.vue';
import { __ } from '~/locale';
+const overTimeQueries = {
+ users: {
+ measures: ['Jitsu.count'],
+ timeDimensions: [
+ {
+ granularity: 'day',
+ dimension: 'Jitsu.utcTime',
+ },
+ ],
+ dimensions: ['Jitsu.eventType'],
+ },
+};
+
export default {
name: 'AnalyticsDashboard',
components: {
@@ -12,16 +25,47 @@
widgets: [
{
type: 'ProductAnalyticsAudience',
- gridAttributes: { width: 3, height: 3 },
- props: { title: __('Test A') },
- },
- {
- type: 'ProductAnalyticsAudience',
- gridAttributes: { width: 2, height: 4 },
- props: { title: __('Test B') },
+ gridAttributes: { x: 0, y: 0, height: 4, width: 6, minHeight: 4, minWidth: 6 },
+ props: {
+ title: __('Users / Time'),
+ query: this.withFilters(overTimeQueries.users, 'day'),
+ options: {
+ xAxis: {
+ name: __('Time'),
+ type: 'time',
+ axisLabel: {
+ interval: 0,
+ showMinLabel: false,
+ showMaxLabel: false,
+ align: 'right',
+ },
+ },
+ yAxis: {
+ name: __('Counts'),
+ },
+ legend: { show: false },
+ },
+ },
},
],
};
+ },
+ methods: {
+ withFilters(query, granularity) {
+ const newQuery = {
+ ...query,
+ };
+
+ newQuery.timeDimensions = [
+ {
+ dimension: `Jitsu.utcTime`,
+ dateRange: [new Date(2022, 8), new Date(2022, 10)],
+ granularity: granularity || null,
+ },
+ ];
+
+ return newQuery;
+ },
},
};
</script>
Index: jest.config.base.js
<+>UTF-8
===================================================================
diff --git a/jest.config.base.js b/jest.config.base.js
--- a/jest.config.base.js (revision HEAD)
+++ b/jest.config.base.js (revision Staged)
@@ -153,6 +153,7 @@
'dateformat',
'lowlight',
'vscode-languageserver-types',
+ '@cubejs-client/vue',
...gfmParserDependencies,
];
Index: package.json
<+>UTF-8
===================================================================
diff --git a/package.json b/package.json
--- a/package.json (revision HEAD)
+++ b/package.json (revision Staged)
@@ -50,6 +50,8 @@
"@babel/core": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"@codesandbox/sandpack-client": "^1.2.2",
+ "@cubejs-client/core": "^0.31.0",
+ "@cubejs-client/vue": "^0.31.0",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "3.4.0",
@@ -268,4 +270,4 @@
"node": ">=12.22.1",
"yarn": "^1.10.0"
}
-}
\ No newline at end of file
+}
Index: yarn.lock
<+>UTF-8
===================================================================
diff --git a/yarn.lock b/yarn.lock
--- a/yarn.lock (revision HEAD)
+++ b/yarn.lock (revision Staged)
@@ -992,6 +992,27 @@
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.1.tgz#b6b8d81780b9a9f6459f4bfe9226ac6aefaefe87"
integrity sha512-aG20vknL4/YjQF9BSV7ts4EWm/yrjagAN7OWBNmlbEOUiu0llj4OGrFoOKK3g2vey4/p2omKCoHrWtPxSwV3HA==
+"@cubejs-client/core@^0.31.0":
+ version "0.31.0"
+ resolved "https://registry.yarnpkg.com/@cubejs-client/core/-/core-0.31.0.tgz#ee507a3841962a63b255e19f1575e66fd1c726ee"
+ integrity sha512-72+7dVsLURGEYR0FCImf1XPLnc849zKKYQPDk0O/tHShX+8+k8ARt5VLadCl61mbBHIZZgH3OFzvqSREQm+Stw==
+ dependencies:
+ core-js "^3.6.5"
+ cross-fetch "^3.0.2"
+ dayjs "^1.10.4"
+ ramda "^0.27.0"
+ url-search-params-polyfill "^7.0.0"
+ uuid "^8.3.2"
+
+"@cubejs-client/vue@^0.31.0":
+ version "0.31.0"
+ resolved "https://registry.yarnpkg.com/@cubejs-client/vue/-/vue-0.31.0.tgz#83db7d0ae153d12e2018faaa5b1dec00e02b8a57"
+ integrity sha512-7dm1yKFgQYx50BWnu6DPFr+bBFgnsyAZ0h1skrevtYU+s0kDBiwq1UQ45AZh/Q5w+AageenCh6N7bcn1AvVK8w==
+ dependencies:
+ "@cubejs-client/core" "^0.31.0"
+ core-js "^3.6.5"
+ ramda "^0.27.0"
+
"@discoveryjs/json-ext@^0.5.0":
version "0.5.6"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f"
@@ -3802,7 +3823,7 @@
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^3.25.5:
+core-js@^3.25.5, core-js@^3.6.5:
version "3.25.5"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.5.tgz#e86f651a2ca8a0237a5f064c2fe56cef89646e27"
integrity sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw==
@@ -3882,6 +3903,13 @@
dependencies:
jquery ">= 1.9.1"
+cross-fetch@^3.0.2:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
+ integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
+ dependencies:
+ node-fetch "2.6.7"
+
cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@@ -4580,6 +4608,11 @@
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-5.0.1.tgz#60a27a2deb339f888ba4532f533e25ac73ca3d19"
integrity sha512-DrcKxOW2am3mtqoJwBTK3OlWcF0QSk1p8diEWwpu3Mf//VdURD7XVaeOV738JvcaBiFfm9o2fisoMhiJH0aYxg==
+dayjs@^1.10.4:
+ version "1.11.5"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
+ integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
+
de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
@@ -9163,7 +9196,7 @@
resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
-node-fetch@^2.6.1, node-fetch@^2.6.7:
+node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
@@ -10196,6 +10229,11 @@
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
+ramda@^0.27.0:
+ version "0.27.2"
+ resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1"
+ integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==
+
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -11999,6 +12037,11 @@
mime-types "^2.1.27"
schema-utils "^3.0.0"
+url-search-params-polyfill@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/url-search-params-polyfill/-/url-search-params-polyfill-7.0.1.tgz#b900cd9a0d9d2ff757d500135256f2344879cbff"
+ integrity sha512-bAw7L2E+jn9XHG5P9zrPnHdO0yJub4U+yXJOdpcpkr7OBd9T8oll4lUos0iSGRcDvfZoLUKfx9a6aNmIhJ4+mQ==
+
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
A working patch for the API endpoint
Index: ee/lib/api/analytics/product_analytics.rb
<+>UTF-8
===================================================================
diff --git a/ee/lib/api/analytics/product_analytics.rb b/ee/lib/api/analytics/product_analytics.rb
--- a/ee/lib/api/analytics/product_analytics.rb (revision HEAD)
+++ b/ee/lib/api/analytics/product_analytics.rb (revision Staged)
@@ -24,7 +24,7 @@
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Proxy request to cube installation'
- post ':project_id/product_analytics/request' do
+ get ':project_id/product_analytics/request/load' do
not_found! unless ::Feature.enabled?(:cube_api_proxy, project)
unauthorized! unless can?(current_user, :developer_access, project)
@@ -42,7 +42,7 @@
"Content-Type": 'application/json',
Authorization: JWT.encode(payload, Gitlab::CurrentSettings.cube_api_key, 'HS256')
},
- body: { "query" => params["query"] }.to_json
+ body: { "query" => params["query"], "queryType": params["queryType"] }.to_json
)
Gitlab::Json.parse(response.body)
Index: ee/spec/requests/api/analytics/product_analytics_spec.rb
<+>UTF-8
===================================================================
diff --git a/ee/spec/requests/api/analytics/product_analytics_spec.rb b/ee/spec/requests/api/analytics/product_analytics_spec.rb
--- a/ee/spec/requests/api/analytics/product_analytics_spec.rb (revision HEAD)
+++ b/ee/spec/requests/api/analytics/product_analytics_spec.rb (revision Staged)
@@ -7,7 +7,7 @@
let(:current_user) { project.owner }
- describe 'POST projects/:id/product_analytics/request' do
+ describe 'GET projects/:id/product_analytics/request/load' do
before do
stub_cube_load
stub_ee_application_setting(cube_api_key: 'testtest')
@@ -20,7 +20,7 @@
end
it 'returns a 404' do
- post api("/projects/#{project.id}/product_analytics/request", current_user)
+ get api("/projects/#{project.id}/product_analytics/request/load", current_user)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -34,7 +34,7 @@
end
it 'returns an unauthorized error' do
- post api("/projects/#{project.id}/product_analytics/request", current_user)
+ get api("/projects/#{project.id}/product_analytics/request/load", current_user)
expect(response).to have_gitlab_http_status(:unauthorized)
end
@@ -47,10 +47,10 @@
project.add_developer(current_user)
end
- it 'returns a 201' do
- post api("/projects/#{project.id}/product_analytics/request", current_user)
+ it 'returns a 200' do
+ get api("/projects/#{project.id}/product_analytics/request/load", current_user)
- expect(response).to have_gitlab_http_status(:created)
+ expect(response).to have_gitlab_http_status(:ok)
end
end
@@ -60,7 +60,7 @@
end
it 'returns a 404' do
- post api("/projects/#{project.id}/product_analytics/request", current_user)
+ get api("/projects/#{project.id}/product_analytics/request/load", current_user)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -72,7 +72,7 @@
end
it 'returns a 404' do
- post api("/projects/#{project.id}/product_analytics/request", current_user)
+ get api("/projects/#{project.id}/product_analytics/request/load", current_user)
expect(response).to have_gitlab_http_status(:not_found)
end