From 25a42bc7580033aed371ee6a40294d4697506135 Mon Sep 17 00:00:00 2001 From: Jessica McInchak Date: Mon, 18 Dec 2023 12:58:38 +0000 Subject: [PATCH 1/9] chore: bump planx-core (#2574) --- api.planx.uk/package.json | 2 +- api.planx.uk/pnpm-lock.yaml | 47 ++++++++++------------- e2e/tests/api-driven/package.json | 2 +- e2e/tests/api-driven/pnpm-lock.yaml | 41 +++++++++----------- e2e/tests/ui-driven/package.json | 2 +- e2e/tests/ui-driven/pnpm-lock.yaml | 41 +++++++++----------- editor.planx.uk/package.json | 2 +- editor.planx.uk/pnpm-lock.yaml | 58 ++++++++++------------------- 8 files changed, 78 insertions(+), 117 deletions(-) diff --git a/api.planx.uk/package.json b/api.planx.uk/package.json index be443e7358..3519c7a668 100644 --- a/api.planx.uk/package.json +++ b/api.planx.uk/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@airbrake/node": "^2.1.8", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#8f2f850", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#95b54b3", "@types/isomorphic-fetch": "^0.0.36", "adm-zip": "^0.5.10", "aws-sdk": "^2.1467.0", diff --git a/api.planx.uk/pnpm-lock.yaml b/api.planx.uk/pnpm-lock.yaml index ea50ec0432..484f729ac4 100644 --- a/api.planx.uk/pnpm-lock.yaml +++ b/api.planx.uk/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^2.1.8 version: 2.1.8 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#8f2f850 - version: github.com/theopensystemslab/planx-core/8f2f850 + specifier: git+https://github.com/theopensystemslab/planx-core#95b54b3 + version: github.com/theopensystemslab/planx-core/95b54b3 '@types/isomorphic-fetch': specifier: ^0.0.36 version: 0.0.36 @@ -349,6 +349,7 @@ packages: dependencies: '@babel/highlight': 7.22.20 chalk: 2.4.2 + dev: true /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} @@ -356,7 +357,6 @@ packages: dependencies: '@babel/highlight': 7.23.4 chalk: 2.4.2 - dev: true /@babel/compat-data@7.22.9: resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} @@ -584,6 +584,7 @@ packages: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 + dev: true /@babel/highlight@7.23.4: resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} @@ -592,7 +593,6 @@ packages: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 - dev: true /@babel/parser@7.23.0: resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} @@ -797,13 +797,6 @@ packages: regenerator-runtime: 0.13.11 dev: false - /@babel/runtime@7.23.2: - resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.0 - dev: false - /@babel/runtime@7.23.6: resolution: {integrity: sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==} engines: {node: '>=6.9.0'} @@ -889,7 +882,7 @@ packages: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: '@babel/helper-module-imports': 7.22.15 - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.2 @@ -936,7 +929,7 @@ packages: react: optional: true dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 @@ -973,7 +966,7 @@ packages: react: optional: true dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 '@emotion/react': 11.11.1(react@18.2.0) @@ -1214,13 +1207,13 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.55.0 + eslint: 8.56.0 eslint-visitor-keys: 3.4.3 dev: false @@ -1272,8 +1265,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@eslint/js@8.55.0: - resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} + /@eslint/js@8.56.0: + resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false @@ -2783,7 +2776,7 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 cosmiconfig: 7.1.0 resolve: 1.22.2 dev: false @@ -3959,15 +3952,15 @@ packages: - supports-color dev: true - /eslint@8.55.0: - resolution: {integrity: sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==} + /eslint@8.56.0: + resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@eslint-community/regexpp': 4.6.2 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.55.0 + '@eslint/js': 8.56.0 '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -6727,7 +6720,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.22.13 + '@babel/code-frame': 7.23.5 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -8594,8 +8587,8 @@ packages: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false - github.com/theopensystemslab/planx-core/8f2f850: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/8f2f850} + github.com/theopensystemslab/planx-core/95b54b3: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/95b54b3} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true @@ -8610,7 +8603,7 @@ packages: cheerio: 1.0.0-rc.12 copyfiles: 2.4.1 docx: 8.2.4 - eslint: 8.55.0 + eslint: 8.56.0 fast-xml-parser: 4.3.2 graphql: 16.8.1 graphql-request: 6.1.0(graphql@16.8.1) diff --git a/e2e/tests/api-driven/package.json b/e2e/tests/api-driven/package.json index b091ead296..6fedc20130 100644 --- a/e2e/tests/api-driven/package.json +++ b/e2e/tests/api-driven/package.json @@ -6,7 +6,7 @@ }, "dependencies": { "@cucumber/cucumber": "^9.3.0", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#8f2f850", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#95b54b3", "axios": "^1.6.0", "dotenv": "^16.3.1", "dotenv-expand": "^10.0.0", diff --git a/e2e/tests/api-driven/pnpm-lock.yaml b/e2e/tests/api-driven/pnpm-lock.yaml index 3380429c3a..9e5b84862d 100644 --- a/e2e/tests/api-driven/pnpm-lock.yaml +++ b/e2e/tests/api-driven/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^9.3.0 version: 9.3.0 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#8f2f850 - version: github.com/theopensystemslab/planx-core/8f2f850 + specifier: git+https://github.com/theopensystemslab/planx-core#95b54b3 + version: github.com/theopensystemslab/planx-core/95b54b3 axios: specifier: ^1.6.0 version: 1.6.0 @@ -94,13 +94,6 @@ packages: regenerator-runtime: 0.13.11 dev: false - /@babel/runtime@7.23.2: - resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.0 - dev: false - /@babel/runtime@7.23.6: resolution: {integrity: sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==} engines: {node: '>=6.9.0'} @@ -278,7 +271,7 @@ packages: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: '@babel/helper-module-imports': 7.22.5 - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.2 @@ -323,7 +316,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 @@ -358,7 +351,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 '@emotion/react': 11.11.1(react@18.2.0) @@ -388,13 +381,13 @@ packages: resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} dev: false - /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.55.0 + eslint: 8.56.0 eslint-visitor-keys: 3.4.3 dev: false @@ -420,8 +413,8 @@ packages: - supports-color dev: false - /@eslint/js@8.55.0: - resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} + /@eslint/js@8.56.0: + resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false @@ -892,7 +885,7 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 cosmiconfig: 7.1.0 resolve: 1.22.2 dev: false @@ -1322,15 +1315,15 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false - /eslint@8.55.0: - resolution: {integrity: sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==} + /eslint@8.56.0: + resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@eslint-community/regexpp': 4.6.2 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.55.0 + '@eslint/js': 8.56.0 '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -2828,8 +2821,8 @@ packages: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false - github.com/theopensystemslab/planx-core/8f2f850: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/8f2f850} + github.com/theopensystemslab/planx-core/95b54b3: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/95b54b3} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true @@ -2844,7 +2837,7 @@ packages: cheerio: 1.0.0-rc.12 copyfiles: 2.4.1 docx: 8.2.4 - eslint: 8.55.0 + eslint: 8.56.0 fast-xml-parser: 4.3.2 graphql: 16.8.1 graphql-request: 6.1.0(graphql@16.8.1) diff --git a/e2e/tests/ui-driven/package.json b/e2e/tests/ui-driven/package.json index 5548757f15..dd9aff78a7 100644 --- a/e2e/tests/ui-driven/package.json +++ b/e2e/tests/ui-driven/package.json @@ -8,7 +8,7 @@ "postinstall": "./install-dependencies.sh" }, "dependencies": { - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#8f2f850", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#95b54b3", "axios": "^1.6.0", "dotenv": "^16.3.1", "eslint": "^8.44.0", diff --git a/e2e/tests/ui-driven/pnpm-lock.yaml b/e2e/tests/ui-driven/pnpm-lock.yaml index 4ac40058a1..316b576a2d 100644 --- a/e2e/tests/ui-driven/pnpm-lock.yaml +++ b/e2e/tests/ui-driven/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#8f2f850 - version: github.com/theopensystemslab/planx-core/8f2f850 + specifier: git+https://github.com/theopensystemslab/planx-core#95b54b3 + version: github.com/theopensystemslab/planx-core/95b54b3 axios: specifier: ^1.6.0 version: 1.6.0 @@ -87,13 +87,6 @@ packages: js-tokens: 4.0.0 dev: false - /@babel/runtime@7.23.2: - resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.0 - dev: false - /@babel/runtime@7.23.6: resolution: {integrity: sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==} engines: {node: '>=6.9.0'} @@ -124,7 +117,7 @@ packages: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: '@babel/helper-module-imports': 7.22.5 - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.2 @@ -169,7 +162,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 @@ -204,7 +197,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 '@emotion/react': 11.11.1(react@18.2.0) @@ -243,13 +236,13 @@ packages: eslint: 8.47.0 eslint-visitor-keys: 3.4.3 - /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.55.0 + eslint: 8.56.0 eslint-visitor-keys: 3.4.3 dev: false @@ -294,8 +287,8 @@ packages: resolution: {integrity: sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@eslint/js@8.55.0: - resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} + /@eslint/js@8.56.0: + resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false @@ -746,7 +739,7 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 cosmiconfig: 7.1.0 resolve: 1.22.4 dev: false @@ -1256,15 +1249,15 @@ packages: transitivePeerDependencies: - supports-color - /eslint@8.55.0: - resolution: {integrity: sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==} + /eslint@8.56.0: + resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@eslint-community/regexpp': 4.6.2 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.55.0 + '@eslint/js': 8.56.0 '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -2632,8 +2625,8 @@ packages: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false - github.com/theopensystemslab/planx-core/8f2f850: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/8f2f850} + github.com/theopensystemslab/planx-core/95b54b3: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/95b54b3} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true @@ -2648,7 +2641,7 @@ packages: cheerio: 1.0.0-rc.12 copyfiles: 2.4.1 docx: 8.2.4 - eslint: 8.55.0 + eslint: 8.56.0 fast-xml-parser: 4.3.2 graphql: 16.8.1 graphql-request: 6.1.0(graphql@16.8.1) diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index 22f9a9ba20..5f950c3c8c 100644 --- a/editor.planx.uk/package.json +++ b/editor.planx.uk/package.json @@ -14,7 +14,7 @@ "@mui/styles": "^5.14.5", "@mui/utils": "^5.14.5", "@opensystemslab/map": "^0.7.5", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#8f2f850", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#95b54b3", "@tiptap/core": "^2.0.3", "@tiptap/extension-bold": "^2.0.3", "@tiptap/extension-bubble-menu": "^2.1.6", diff --git a/editor.planx.uk/pnpm-lock.yaml b/editor.planx.uk/pnpm-lock.yaml index e7b1d22b02..292ddbdefb 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -45,8 +45,8 @@ dependencies: specifier: ^0.7.5 version: 0.7.5 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#8f2f850 - version: github.com/theopensystemslab/planx-core/8f2f850(@types/react@18.2.20) + specifier: git+https://github.com/theopensystemslab/planx-core#95b54b3 + version: github.com/theopensystemslab/planx-core/95b54b3(@types/react@18.2.20) '@tiptap/core': specifier: ^2.0.3 version: 2.0.3(@tiptap/pm@2.0.3) @@ -3965,13 +3965,13 @@ packages: eslint: 8.44.0 eslint-visitor-keys: 3.4.3 - /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.55.0 + eslint: 8.56.0 eslint-visitor-keys: 3.4.3 dev: false @@ -4016,8 +4016,8 @@ packages: resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@eslint/js@8.55.0: - resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} + /@eslint/js@8.56.0: + resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false @@ -4664,8 +4664,8 @@ packages: dependencies: '@babel/runtime': 7.23.5 '@emotion/is-prop-valid': 1.2.1 - '@mui/types': 7.2.10(@types/react@18.2.20) - '@mui/utils': 5.14.5(react@18.2.0) + '@mui/types': 7.2.11(@types/react@18.2.20) + '@mui/utils': 5.15.0(@types/react@18.2.20)(react@18.2.0) '@popperjs/core': 2.11.8 '@types/react': 18.2.20 clsx: 2.0.0 @@ -4806,7 +4806,7 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.5 - '@mui/utils': 5.14.19(@types/react@18.2.20)(react@18.2.0) + '@mui/utils': 5.15.0(@types/react@18.2.20)(react@18.2.0) '@types/react': 18.2.20 prop-types: 15.8.1 react: 18.2.0 @@ -4925,8 +4925,8 @@ packages: '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.20)(react@18.2.0) '@mui/private-theming': 5.14.19(@types/react@18.2.20)(react@18.2.0) '@mui/styled-engine': 5.14.19(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) - '@mui/types': 7.2.10(@types/react@18.2.20) - '@mui/utils': 5.14.19(@types/react@18.2.20)(react@18.2.0) + '@mui/types': 7.2.11(@types/react@18.2.20) + '@mui/utils': 5.15.0(@types/react@18.2.20)(react@18.2.0) '@types/react': 18.2.20 clsx: 2.0.0 csstype: 3.1.2 @@ -4986,24 +4986,6 @@ packages: '@types/react': 18.2.20 dev: false - /@mui/utils@5.14.19(@types/react@18.2.20)(react@18.2.0): - resolution: {integrity: sha512-qAHvTXzk7basbyqPvhgWqN6JbmI2wLB/mf97GkSlz5c76MiKYV6Ffjvw9BjKZQ1YRb8rDX9kgdjRezOcoB91oQ==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.23.5 - '@types/prop-types': 15.7.11 - '@types/react': 18.2.20 - prop-types: 15.8.1 - react: 18.2.0 - react-is: 18.2.0 - dev: false - /@mui/utils@5.14.5(react@18.2.0): resolution: {integrity: sha512-6Hzw63VR9C5xYv+CbjndoRLU6Gntal8rJ5W+GUzkyHrGWIyYPWZPa6AevnyGioySNETATe1H9oXS8f/7qgIHJA==} engines: {node: '>=12.0.0'} @@ -9761,7 +9743,7 @@ packages: dev: false /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} /concat-stream@1.6.2: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} @@ -11566,15 +11548,15 @@ packages: transitivePeerDependencies: - supports-color - /eslint@8.55.0: - resolution: {integrity: sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==} + /eslint@8.56.0: + resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@eslint-community/regexpp': 4.10.0 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.55.0 + '@eslint/js': 8.56.0 '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -20906,9 +20888,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - github.com/theopensystemslab/planx-core/8f2f850(@types/react@18.2.20): - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/8f2f850} - id: github.com/theopensystemslab/planx-core/8f2f850 + github.com/theopensystemslab/planx-core/95b54b3(@types/react@18.2.20): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/95b54b3} + id: github.com/theopensystemslab/planx-core/95b54b3 name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true @@ -20923,7 +20905,7 @@ packages: cheerio: 1.0.0-rc.12 copyfiles: 2.4.1 docx: 8.2.4 - eslint: 8.55.0 + eslint: 8.56.0 fast-xml-parser: 4.3.2 graphql: 16.8.1 graphql-request: 6.1.0(graphql@16.8.1) From fc08523db6b8467a4a396a4fc06026694d816e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dafydd=20Ll=C5=B7r=20Pearson?= Date: Mon, 18 Dec 2023 13:24:22 +0000 Subject: [PATCH 2/9] feat: Hasura input validation for tables storing user-submitted HTML (#2551) --- api.planx.uk/modules/webhooks/controller.ts | 24 ++ api.planx.uk/modules/webhooks/docs.yaml | 63 +++++ api.planx.uk/modules/webhooks/routes.ts | 8 + .../webhooks/service/validateInput/schema.ts | 50 ++++ .../service/validateInput/utils.test.ts | 114 +++++++++ .../webhooks/service/validateInput/utils.ts | 45 ++++ .../validateInput/validateInput.test.ts | 221 ++++++++++++++++++ api.planx.uk/shared/middleware/validate.ts | 11 +- editor.planx.uk/src/lib/graphql.ts | 93 +++++--- hasura.planx.uk/metadata/tables.yaml | 72 ++++++ 10 files changed, 666 insertions(+), 35 deletions(-) create mode 100644 api.planx.uk/modules/webhooks/service/validateInput/schema.ts create mode 100644 api.planx.uk/modules/webhooks/service/validateInput/utils.test.ts create mode 100644 api.planx.uk/modules/webhooks/service/validateInput/utils.ts create mode 100644 api.planx.uk/modules/webhooks/service/validateInput/validateInput.test.ts diff --git a/api.planx.uk/modules/webhooks/controller.ts b/api.planx.uk/modules/webhooks/controller.ts index edb43ac4eb..451af35473 100644 --- a/api.planx.uk/modules/webhooks/controller.ts +++ b/api.planx.uk/modules/webhooks/controller.ts @@ -14,6 +14,7 @@ import { } from "./service/paymentRequestEvents"; import { SanitiseApplicationData } from "./service/sanitiseApplicationData/types"; import { sanitiseApplicationData } from "./service/sanitiseApplicationData"; +import { IsCleanJSONBController } from "./service/validateInput/schema"; export const sendSlackNotificationController: SendSlackNotification = async ( _req, @@ -144,3 +145,26 @@ export const sanitiseApplicationDataController: SanitiseApplicationData = ); } }; + +export const isCleanJSONBController: IsCleanJSONBController = async ( + _req, + res, + next, +) => { + try { + const { isClean } = res.locals.parsedReq.body; + + return isClean + ? res.status(200).send() + : res.status(400).json({ + message: "Invalid HTML content", + }); + } catch (error) { + return next( + new ServerError({ + message: "Failed to validate application data", + cause: error, + }), + ); + } +}; diff --git a/api.planx.uk/modules/webhooks/docs.yaml b/api.planx.uk/modules/webhooks/docs.yaml index 309976e562..320afb9f27 100644 --- a/api.planx.uk/modules/webhooks/docs.yaml +++ b/api.planx.uk/modules/webhooks/docs.yaml @@ -126,6 +126,32 @@ components: email: type: string format: email + requests: + ValidateInputRequest: + description: | + Request generated by Hasura input validation + + Docs: [https://hasura.io/docs/latest/schema/postgres/input-validations/#request](https://hasura.io/docs/latest/schema/postgres/input-validations/#request) + type: object + required: + - body + properties: + body: + type: object + required: + - data + properties: + data: + type: object + required: + - input + properties: + input: + type: array + items: + type: object + additionalProperties: + type: string responses: SlackNotificationSuccessMessage: content: @@ -190,6 +216,20 @@ components: errorMessage: type: string required: false + InputValidationSuccess: + description: Successful response with no content + InputValidationFailure: + description: Input validation failed. Message will be returned to client. + content: + application/json: + example: + message: Invalid HTML content + schema: + type: object + properties: + message: + type: string + description: A message returned to the client paths: /webhooks/hasura/sendSlackNotification: post: @@ -311,3 +351,26 @@ paths: $ref: "#/components/responses/OperationResultSuccess" "500": $ref: "#/components/responses/OperationResultFailure" + /webhooks/hasura/validate-input/jsonb/clean-html: + post: + tags: ["webhooks"] + security: + - hasuraAuth: [] + summary: Validate if user-submitted JSONB contains safe HTML + description: | + Endpoint called by Hasura on INSERT or UPDATE to a table which containts user-submitted HTML content. + + Hasura runs a [Postgres Input Validation](https://hasura.io/docs/latest/schema/postgres/input-validations/) call against this endpoint which checks incoming content is clean and valid HTML. + + This endpoint does not sanitise and respond with clean data, it simply accepts or rejects the user-submitted changes. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/requests/ValidateInputRequest" + responses: + "200": + $ref: "#/components/responses/InputValidationSuccess" + "500": + $ref: "#/components/responses/InputValidationFailure" diff --git a/api.planx.uk/modules/webhooks/routes.ts b/api.planx.uk/modules/webhooks/routes.ts index 0be7edb4be..cde31db050 100644 --- a/api.planx.uk/modules/webhooks/routes.ts +++ b/api.planx.uk/modules/webhooks/routes.ts @@ -3,6 +3,7 @@ import { useHasuraAuth } from "../auth/middleware"; import { createPaymentSendEvents } from "../pay/service/inviteToPay/createPaymentSendEvents"; import { validate } from "../../shared/middleware/validate"; import { + isCleanJSONBController, createPaymentExpiryEventsController, createPaymentInvitationEventsController, createPaymentReminderEventsController, @@ -14,6 +15,7 @@ import { import { sendSlackNotificationSchema } from "./service/sendNotification/schema"; import { createPaymentEventSchema } from "./service/paymentRequestEvents/schema"; import { createSessionEventSchema } from "./service/lowcalSessionEvents/schema"; +import { isCleanJSONBSchema } from "./service/validateInput/schema"; const router = Router(); @@ -53,6 +55,12 @@ router.post( sanitiseApplicationDataController, ); +router.post( + "/webhooks/hasura/validate-input/jsonb/clean-html", + validate(isCleanJSONBSchema), + isCleanJSONBController, +); + // TODO: Convert to the new API module structure router.post( "/webhooks/hasura/create-payment-send-events", diff --git a/api.planx.uk/modules/webhooks/service/validateInput/schema.ts b/api.planx.uk/modules/webhooks/service/validateInput/schema.ts new file mode 100644 index 0000000000..f25250eb75 --- /dev/null +++ b/api.planx.uk/modules/webhooks/service/validateInput/schema.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; +import { ValidatedRequestHandler } from "../../../../shared/middleware/validate"; +import { isCleanHTML, isObjectValid } from "./utils"; + +// Definition: https://hasura.io/docs/latest/schema/postgres/input-validations/#response +type HasuraValidateInputResponse = undefined | { message: string }; + +// Definition: https://hasura.io/docs/latest/schema/postgres/input-validations/#request +// Abstract base type that can be merged with specific schemas for data validation +const hasuraValidateInputRequestSchema = z.object({ + body: z.object({ + data: z.object({ + input: z.array(z.record(z.string(), z.unknown())), + }), + }), +}); + +type HasuraValidateInputRequest = z.infer< + typeof hasuraValidateInputRequestSchema +>; + +interface IsCleanJSONBRequest { + body: { + isClean: boolean; + }; +} + +type isCleanJSONBSchema = z.ZodType< + IsCleanJSONBRequest, + z.ZodTypeDef, + HasuraValidateInputRequest +>; + +/** + * Schema which iterates over values of a JSONB column + * Checks using DOMPurify to ensure that user-submitted HTML is clean + * Fails fast - will reject on first instance of unclean HTML + */ +export const isCleanJSONBSchema: isCleanJSONBSchema = + hasuraValidateInputRequestSchema.transform((original) => { + const isClean = original.body.data.input.every((input) => + isObjectValid(input, isCleanHTML), + ); + return { body: { isClean } }; + }); + +export type IsCleanJSONBController = ValidatedRequestHandler< + typeof isCleanJSONBSchema, + HasuraValidateInputResponse +>; diff --git a/api.planx.uk/modules/webhooks/service/validateInput/utils.test.ts b/api.planx.uk/modules/webhooks/service/validateInput/utils.test.ts new file mode 100644 index 0000000000..c3d58232ec --- /dev/null +++ b/api.planx.uk/modules/webhooks/service/validateInput/utils.test.ts @@ -0,0 +1,114 @@ +import { isCleanHTML, isObjectValid } from "./utils"; + +describe("isObjectValid", () => { + it("calls the callback for each child if validator returns true", () => { + const mockValidator = jest.fn().mockReturnValue(true); + + const testObject = { + a: 1, + b: { + c: 2, + d: [3, 4], + e: { + f: 5, + }, + }, + }; + + isObjectValid(testObject, mockValidator); + + expect(mockValidator).toHaveBeenCalledTimes(5); + }); + + it("fails fast if any validator encounters any false values", () => { + const mockValidator = jest + .fn() + .mockReturnValueOnce(true) + .mockReturnValueOnce(false); + + const testObject = { + a: 1, + b: { + c: 2, + d: [3, 4], + e: { + f: 5, + }, + }, + }; + + isObjectValid(testObject, mockValidator); + + expect(mockValidator).toHaveBeenCalledTimes(2); + }); + + it("handles arrays correctly", () => { + const mockValidator = jest.fn().mockReturnValue(true); + + const testArray = [1, [2, 3], { a: 4 }]; + + isObjectValid(testArray, mockValidator); + + expect(mockValidator).toHaveBeenCalledTimes(4); + }); + + it("handles an object containing an array of objects", () => { + const mockValidator = jest.fn().mockReturnValue(true); + + const objectWithArrayOfObjects = { + a: 1, + b: { + c: [{ d: 2, e: { f: 3 } }, { g: 4 }, { h: [5, 6] }], + }, + }; + + isObjectValid(objectWithArrayOfObjects, mockValidator); + + expect(mockValidator).toHaveBeenCalledTimes(6); + }); + + it("handles empty objects and arrays", () => { + const mockValidator = jest.fn().mockReturnValue(true); + + const emptyObject = {}; + const emptyArray: unknown[] = []; + + isObjectValid(emptyObject, mockValidator); + isObjectValid(emptyArray, mockValidator); + + expect(mockValidator).not.toHaveBeenCalled(); + }); +}); + +describe("isCleanHTML() helper function", () => { + const dirtyHTML = [ + "", + "", + "

abc