From f27573f394df4bbf9858a37b671fb4d3114993ef Mon Sep 17 00:00:00 2001 From: Mingfei Shao <2475897+mfshao@users.noreply.github.com> Date: Mon, 18 Dec 2023 14:03:23 -0600 Subject: [PATCH] PPS-588 Fix/csrf (#251) * add csrf * add more csrf * remove unneeded pkg * fix: missing args * fix missing * ask when token ready * add missing pass over * remove unneeded logic * update version * fix according to suggestions --- devHelper/scripts/commands.sh | 1 + package-lock.json | 200 +---------------------- package.json | 3 +- src/components/ConnectedFilter/index.jsx | 7 +- src/components/ConnectedFilter/utils.js | 3 +- src/components/GuppyWrapper/index.jsx | 12 ++ src/components/Utils/queries.js | 54 +++--- 7 files changed, 50 insertions(+), 230 deletions(-) diff --git a/devHelper/scripts/commands.sh b/devHelper/scripts/commands.sh index 609eeec5..1ba6122c 100755 --- a/devHelper/scripts/commands.sh +++ b/devHelper/scripts/commands.sh @@ -99,6 +99,7 @@ curl -iv -X PUT "${ESHOST}/${indexName}" \ "some_string_inside_nested": { "type": "keyword", "fields": { "analyzed": {"type": "text", "analyzer": "ngram_analyzer", "search_analyzer": "search_analyzer", "term_vector": "with_positions_offsets"} } } } }, + "consortium_id": { "type": "integer" }, "some_integer_field": { "type": "integer" }, "some_long_field": { "type": "long" }, "sensitive": { "type": "keyword" } diff --git a/package-lock.json b/package-lock.json index 54fb0eb9..cb82a253 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@gen3/guppy", - "version": "0.17.1", + "version": "0.18.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@gen3/guppy", - "version": "0.17.1", + "version": "0.18.0", "license": "ISC", "dependencies": { "@apollo/server": "^4.9.4", @@ -16,7 +16,6 @@ "array.prototype.flatmap": "^1.3.2", "body-parser": "^1.20.2", "cors": "^2.8.5", - "csurf": "^1.11.0", "dd-trace": "^4.5.0", "express": "^4.18.2", "file-saver": "^2.0.5", @@ -11728,14 +11727,6 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -11845,19 +11836,6 @@ "resolved": "https://registry.npmjs.org/crypto-randomuuid/-/crypto-randomuuid-1.0.0.tgz", "integrity": "sha512-/RC5F4l1SCqD/jazwUF6+t34Cd8zTSAGZ7rvvZu1whZUhD2a5MOGKjSGowoGcpj/cbVZk1ZODIooJEQQq3nNAA==" }, - "node_modules/csrf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", - "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", - "dependencies": { - "rndm": "1.2.0", - "tsscmp": "1.0.6", - "uid-safe": "2.1.5" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/css-animation": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.6.1.tgz", @@ -11997,65 +11975,6 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "peer": true }, - "node_modules/csurf": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz", - "integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==", - "deprecated": "Please use another csrf package", - "dependencies": { - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "csrf": "3.1.0", - "http-errors": "~1.7.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/csurf/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/csurf/node_modules/http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/csurf/node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "node_modules/csurf/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/csurf/node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", @@ -20205,14 +20124,6 @@ "url": "https://opencollective.com/ramda" } }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -21655,11 +21566,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==" - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -23134,14 +23040,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" }, - "node_modules/tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", - "engines": { - "node": ">=0.6.x" - } - }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", @@ -23302,17 +23200,6 @@ "node": ">=0.8.0" } }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -32249,11 +32136,6 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -32337,16 +32219,6 @@ "resolved": "https://registry.npmjs.org/crypto-randomuuid/-/crypto-randomuuid-1.0.0.tgz", "integrity": "sha512-/RC5F4l1SCqD/jazwUF6+t34Cd8zTSAGZ7rvvZu1whZUhD2a5MOGKjSGowoGcpj/cbVZk1ZODIooJEQQq3nNAA==" }, - "csrf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", - "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", - "requires": { - "rndm": "1.2.0", - "tsscmp": "1.0.6", - "uid-safe": "2.1.5" - } - }, "css-animation": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.6.1.tgz", @@ -32448,51 +32320,6 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "peer": true }, - "csurf": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz", - "integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==", - "requires": { - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "csrf": "3.1.0", - "http-errors": "~1.7.3" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - } - } - }, "d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", @@ -38522,11 +38349,6 @@ "integrity": "sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==", "dev": true }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -39634,11 +39456,6 @@ "glob": "^7.1.3" } }, - "rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==" - }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -40783,11 +40600,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" }, - "tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" - }, "tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", @@ -40898,14 +40710,6 @@ "dev": true, "optional": true }, - "uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "requires": { - "random-bytes": "~1.0.0" - } - }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", diff --git a/package.json b/package.json index ab7a8bc3..b3c7fa8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gen3/guppy", - "version": "0.17.1", + "version": "0.18.0", "description": "Server that support GraphQL queries on data from elasticsearch", "main": "src/server/server.js", "directories": { @@ -34,7 +34,6 @@ "array.prototype.flatmap": "^1.3.2", "body-parser": "^1.20.2", "cors": "^2.8.5", - "csurf": "^1.11.0", "dd-trace": "^4.5.0", "express": "^4.18.2", "file-saver": "^2.0.5", diff --git a/src/components/ConnectedFilter/index.jsx b/src/components/ConnectedFilter/index.jsx index 39ce33a5..06472148 100644 --- a/src/components/ConnectedFilter/index.jsx +++ b/src/components/ConnectedFilter/index.jsx @@ -78,6 +78,7 @@ class ConnectedFilter extends React.Component { this.state.allAsTextAggFields, this.state.filter, this.state.accessibility, + this.props.csrfToken, ) .then((res) => { if (!res.data) { @@ -112,7 +113,7 @@ class ConnectedFilter extends React.Component { } /** - * Handler function that is called everytime filter changes + * Handler function that is called every time filter changes * What this function does: * 1. Ask guppy for aggregation data using (processed) filter * 2. After get aggregation response, call `handleReceiveNewAggsData` handler @@ -137,6 +138,7 @@ class ConnectedFilter extends React.Component { this.state.allAsTextAggFields, mergedFilterResults, this.state.accessibility, + this.props.csrfToken, ) .then((res) => { this.handleReceiveNewAggsData( @@ -285,6 +287,7 @@ class ConnectedFilter extends React.Component { this.props.guppyConfig, this.arrayFields, this.props.filterValuesToHide, + this.props.csrfToken, ); const filterStatus = this.state.filterStatusArray ? this.state.filterStatusArray[index] : null; @@ -371,6 +374,7 @@ ConnectedFilter.propTypes = { userFilterFromURL: PropTypes.object, hideEmptyFilterSection: PropTypes.bool, filterValuesToHide: PropTypes.arrayOf(PropTypes.string), + csrfToken: PropTypes.string, }; ConnectedFilter.defaultProps = { @@ -391,6 +395,7 @@ ConnectedFilter.defaultProps = { userFilterFromURL: {}, hideEmptyFilterSection: false, filterValuesToHide: [], + csrfToken: '', }; export default ConnectedFilter; diff --git a/src/components/ConnectedFilter/utils.js b/src/components/ConnectedFilter/utils.js index 2d7f3f00..20d3ba15 100644 --- a/src/components/ConnectedFilter/utils.js +++ b/src/components/ConnectedFilter/utils.js @@ -111,6 +111,7 @@ export const getFilterSections = ( guppyConfig, arrayFields, filterValuesToHide, + csrfToken, ) => { let searchFieldSections = []; @@ -144,7 +145,7 @@ export const getFilterSections = ( title: label, options: selectedOptions, isSearchFilter: true, - onSearchFilterLoadOptions: createSearchFilterLoadOptionsFn(field, guppyConfig), + onSearchFilterLoadOptions: createSearchFilterLoadOptionsFn(field, guppyConfig, csrfToken), }; }); } diff --git a/src/components/GuppyWrapper/index.jsx b/src/components/GuppyWrapper/index.jsx index 2303fd07..9b37a105 100644 --- a/src/components/GuppyWrapper/index.jsx +++ b/src/components/GuppyWrapper/index.jsx @@ -79,6 +79,7 @@ class GuppyWrapper extends React.Component { getAllFieldsFromGuppy( this.props.guppyConfig.path, this.props.guppyConfig.type, + this.props.csrfToken, ).then((fields) => { const rawDataFields = (this.props.rawDataFields && this.props.rawDataFields.length > 0) ? this.props.rawDataFields : fields; @@ -94,6 +95,7 @@ class GuppyWrapper extends React.Component { this.props.guppyConfig.path, this.props.guppyConfig.type, this.props.accessibleFieldCheckList, + this.props.csrfToken, ).then(({ accessibleFieldObject, unaccessibleFieldObject }) => { this.setState({ accessibleFieldObject, @@ -166,6 +168,7 @@ class GuppyWrapper extends React.Component { accessibility: this.state.accessibility, format, }, + this.props.csrfToken, ); } @@ -189,6 +192,7 @@ class GuppyWrapper extends React.Component { filter: this.state.filter, accessibility: this.state.accessibility, }, + this.props.csrfToken, ); } @@ -203,6 +207,7 @@ class GuppyWrapper extends React.Component { type, filter, this.state.accessibility, + this.props.csrfToken, ); } @@ -218,6 +223,7 @@ class GuppyWrapper extends React.Component { type, filter, this.state.accessibility, + this.props.csrfToken, ) .then((count) => downloadDataFromGuppy( this.props.guppyConfig.path, @@ -227,6 +233,7 @@ class GuppyWrapper extends React.Component { fields, filter, }, + this.props.csrfToken, )); } @@ -262,6 +269,7 @@ class GuppyWrapper extends React.Component { [], this.filter, this.state.accessibility, + this.props.csrfToken, ).then((res) => { if (!res || !res.data) { throw new Error(`Error getting raw ${this.props.guppyConfig.type} data from Guppy server ${this.props.guppyConfig.path}.`); @@ -292,6 +300,7 @@ class GuppyWrapper extends React.Component { offset, size, this.state.accessibility, + this.props.csrfToken, ).then((res) => { if (!res || !res.data) { throw new Error(`Error getting raw ${this.props.guppyConfig.type} data from Guppy server ${this.props.guppyConfig.path}.`); @@ -343,6 +352,7 @@ class GuppyWrapper extends React.Component { onUpdateAccessLevel: this.handleAccessLevelUpdate.bind(this), adminAppliedPreFilters: this.props.adminAppliedPreFilters, accessibleFieldCheckList: this.props.accessibleFieldCheckList, + csrfToken: this.props.csrfToken, })) } @@ -375,6 +385,7 @@ GuppyWrapper.propTypes = { accessibleFieldCheckList: PropTypes.arrayOf(PropTypes.string), adminAppliedPreFilters: PropTypes.object, initialFilterFromURL: PropTypes.object, + csrfToken: PropTypes.string, }; GuppyWrapper.defaultProps = { @@ -384,6 +395,7 @@ GuppyWrapper.defaultProps = { accessibleFieldCheckList: undefined, adminAppliedPreFilters: {}, initialFilterFromURL: {}, + csrfToken: '', }; export default GuppyWrapper; diff --git a/src/components/Utils/queries.js b/src/components/Utils/queries.js index 48edb520..7c9c9b4b 100644 --- a/src/components/Utils/queries.js +++ b/src/components/Utils/queries.js @@ -4,6 +4,9 @@ import { jsonToFormat } from './conversion'; const graphqlEndpoint = '/graphql'; const downloadEndpoint = '/download'; const statusEndpoint = '/_status'; +const headers = { + 'Content-Type': 'application/json', +}; const histogramQueryStrForEachField = (field, isAsTextAgg = false) => { const splittedFieldArray = field.split('.'); @@ -23,7 +26,7 @@ const histogramQueryStrForEachField = (field, isAsTextAgg = false) => { }`); }; -const queryGuppyForAggs = (path, type, regularAggFields, asTextAggFields, gqlFilter, acc) => { +const queryGuppyForAggs = (path, type, regularAggFields, asTextAggFields, gqlFilter, acc, csrfToken = '') => { let accessibility = acc; if (accessibility !== 'all' && accessibility !== 'accessible' && accessibility !== 'unaccessible') { accessibility = 'all'; @@ -54,18 +57,14 @@ const queryGuppyForAggs = (path, type, regularAggFields, asTextAggFields, gqlFil return fetch(`${path}${graphqlEndpoint}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: csrfToken ? { ...headers, 'x-csrf-token': csrfToken } : headers, body: JSON.stringify(queryBody), }).then((response) => response.json()); }; const queryGuppyForStatus = (path) => fetch(`${path}${statusEndpoint}`, { method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, + headers, }).then((response) => response.json()); const nestedHistogramQueryStrForEachField = (mainField, numericAggAsText) => (` @@ -97,6 +96,7 @@ const queryGuppyForSubAgg = ( gqlFilter, acc, numericAggAsText = false, + csrfToken = '', ) => { let accessibility = acc; if (accessibility !== 'all' && accessibility !== 'accessible' && accessibility !== 'unaccessible') { @@ -133,9 +133,7 @@ const queryGuppyForSubAgg = ( } return fetch(`${path}${graphqlEndpoint}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: csrfToken ? { ...headers, 'x-csrf-token': csrfToken } : headers, body: JSON.stringify(queryBody), }).then((response) => response.json()) .catch((err) => { @@ -167,6 +165,7 @@ export const queryGuppyForRawDataAndTotalCounts = ( offset = 0, size = 20, accessibility = 'all', + csrfToken = '', ) => { let queryLine = 'query {'; if (gqlFilter || sort || format) { @@ -198,9 +197,7 @@ export const queryGuppyForRawDataAndTotalCounts = ( if (sort) queryBody.variables.sort = sort; return fetch(`${path}${graphqlEndpoint}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: csrfToken ? { ...headers, 'x-csrf-token': csrfToken } : headers, body: JSON.stringify(queryBody), }).then((response) => response.json()) .catch((err) => { @@ -279,9 +276,10 @@ export const askGuppyForAggregationData = ( asTextAggFields, filter, accessibility, + csrfToken = '', ) => { const gqlFilter = getGQLFilter(filter); - return queryGuppyForAggs(path, type, regularAggFields, asTextAggFields, gqlFilter, accessibility); + return queryGuppyForAggs(path, type, regularAggFields, asTextAggFields, gqlFilter, accessibility, csrfToken); }; export const askGuppyForSubAggregationData = ( @@ -293,6 +291,7 @@ export const askGuppyForSubAggregationData = ( missedNestedFields, filter, accessibility, + csrfToken, ) => { const gqlFilter = getGQLFilter(filter); return queryGuppyForSubAgg( @@ -304,6 +303,7 @@ export const askGuppyForSubAggregationData = ( gqlFilter, accessibility, numericAggAsText, + csrfToken, ); }; @@ -317,6 +317,7 @@ export const askGuppyForRawData = ( offset = 0, size = 20, accessibility = 'all', + csrfToken = '', ) => { const gqlFilter = getGQLFilter(filter); return queryGuppyForRawDataAndTotalCounts( @@ -329,13 +330,14 @@ export const askGuppyForRawData = ( offset, size, accessibility, + csrfToken, ); }; export const getAllFieldsFromFilterConfigs = (filterTabConfigs) => filterTabConfigs.reduce((acc, cur) => { Object.keys(cur) .filter((key) => key === 'fields' || key === 'asTextAggFields') - .forEach((key) => acc[key] = acc[key].concat(cur[key], [])); + .forEach((key) => { acc[key] = acc[key].concat(cur[key], []); }); return acc; }, { fields: [], asTextAggFields: [] }); @@ -355,6 +357,7 @@ export const downloadDataFromGuppy = ( accessibility, format, }, + csrfToken = '', ) => { const SCROLL_SIZE = 10000; const JSON_FORMAT = (format === 'json' || format === undefined); @@ -366,15 +369,13 @@ export const downloadDataFromGuppy = ( if (typeof accessibility !== 'undefined') queryBody.accessibility = accessibility; return fetch(`${path}${downloadEndpoint}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: csrfToken ? { ...headers, 'x-csrf-token': csrfToken } : headers, body: JSON.stringify(queryBody), }) .then((r) => r.json()) .then((res) => (JSON_FORMAT ? res : jsonToFormat(res, format))); } - return askGuppyForRawData(path, type, fields, filter, sort, format, 0, totalCount, accessibility) + return askGuppyForRawData(path, type, fields, filter, sort, format, 0, totalCount, accessibility, csrfToken) .then((res) => { if (res && res.data && res.data[type]) { return JSON_FORMAT ? res.data[type] : jsonToFormat(res.data[type], format); @@ -388,6 +389,7 @@ export const askGuppyForTotalCounts = ( type, filter, accessibility = 'all', + csrfToken = '', ) => { const gqlFilter = getGQLFilter(filter); const queryLine = `query ${gqlFilter ? '($filter: JSON)' : ''}{`; @@ -405,9 +407,7 @@ export const askGuppyForTotalCounts = ( return fetch(`${path}${graphqlEndpoint}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: csrfToken ? { ...headers, 'x-csrf-token': csrfToken } : headers, body: JSON.stringify(queryBody), }).then((response) => response.json()) .then((response) => { @@ -424,6 +424,7 @@ export const askGuppyForTotalCounts = ( export const getAllFieldsFromGuppy = ( path, type, + csrfToken = '', ) => { const query = `{ _mapping { @@ -433,9 +434,7 @@ export const getAllFieldsFromGuppy = ( const queryBody = { query }; return fetch(`${path}${graphqlEndpoint}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: csrfToken ? { ...headers, 'x-csrf-token': csrfToken } : headers, body: JSON.stringify(queryBody), }).then((response) => response.json()) .then((response) => response.data._mapping[type]) @@ -448,6 +447,7 @@ export const getAccessibleResources = async ( path, type, accessibleFieldCheckList, + csrfToken = '', ) => { const accessiblePromiseList = []; const unaccessiblePromiseList = []; @@ -469,9 +469,7 @@ export const getAccessibleResources = async ( return fetch(`${path}${graphqlEndpoint}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: csrfToken ? { ...headers, 'x-csrf-token': csrfToken } : headers, body: JSON.stringify(queryBody), }) .then((response) => response.json())