From 992c9ce1d81eab0011b229fa614a2e8d7f3e9d38 Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Sat, 29 Nov 2025 15:03:12 -0800 Subject: [PATCH] Bump mongoose@9.0.0, express-validator@7.3.1, validator@13.15.23 --- .github/workflows/master.yml | 8 +- .github/workflows/re-release.yml | 6 +- .github/workflows/release.yml | 6 +- .github/workflows/sonar.yml | 4 +- npm-shrinkwrap.json | 332 ++++++++++++------------------- package.json | 8 +- src/models/admin.js | 15 +- src/models/component.js | 11 +- src/models/config-strategy.js | 23 +-- src/models/config.js | 7 +- src/models/domain.js | 15 +- src/models/environment.js | 7 +- src/models/group-config.js | 6 +- src/models/slack.js | 3 +- src/models/team.js | 11 +- src/services/admin.js | 40 +++- src/services/domain.js | 31 ++- tests/admin.test.js | 28 +-- 18 files changed, 236 insertions(+), 325 deletions(-) diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index f3ef728d..60359869 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Git checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -24,7 +24,7 @@ jobs: node-version: 24.x - name: Start MongoDB - uses: supercharge/mongodb-github-action@1.12.0 + uses: supercharge/mongodb-github-action@1.12.1 with: mongodb-version: 8.0 @@ -102,12 +102,12 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: 'master' - name: Checkout Kustomize - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: token: ${{ secrets.ARGOCD_PAT }} repository: switcherapi/switcher-deployment diff --git a/.github/workflows/re-release.yml b/.github/workflows/re-release.yml index 0acd045c..63dcd191 100644 --- a/.github/workflows/re-release.yml +++ b/.github/workflows/re-release.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Git checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 ref: ${{ github.event.inputs.tag }} @@ -26,7 +26,7 @@ jobs: node-version: 24.x - name: Start MongoDB - uses: supercharge/mongodb-github-action@1.12.0 + uses: supercharge/mongodb-github-action@1.12.1 with: mongodb-version: 8.0 @@ -68,7 +68,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 ref: ${{ github.event.inputs.tag }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 694db840..0b156f3f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Git checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -21,7 +21,7 @@ jobs: node-version: 24.x - name: Start MongoDB - uses: supercharge/mongodb-github-action@1.12.0 + uses: supercharge/mongodb-github-action@1.12.1 with: mongodb-version: 8.0 @@ -63,7 +63,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Docker meta id: meta diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index a2a8312f..04599957 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -28,7 +28,7 @@ jobs: core.setOutput('base_ref', pr.data.base.ref); core.setOutput('head_sha', pr.data.head.sha); - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: ref: ${{ steps.pr.outputs.head_sha }} fetch-depth: 0 @@ -39,7 +39,7 @@ jobs: node-version: 24.x - name: Start MongoDB - uses: supercharge/mongodb-github-action@1.12.0 + uses: supercharge/mongodb-github-action@1.12.1 with: mongodb-version: 8.0 diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 96164433..d4c28a1a 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -17,7 +17,7 @@ "express-basic-auth": "^1.2.1", "express-rate-limit": "^8.2.1", "express-session": "^1.18.2", - "express-validator": "^7.3.0", + "express-validator": "^7.3.1", "graphql": "^16.12.0", "graphql-http": "^1.22.4", "graphql-tag": "^2.12.6", @@ -25,13 +25,13 @@ "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", "mongodb": "^7.0.0", - "mongoose": "^8.19.3", + "mongoose": "^9.0.0", "passport": "^0.7.0", "pino": "^10.1.0", "pino-pretty": "^13.1.2", "swagger-ui-express": "^5.0.1", "switcher-client": "^4.5.0", - "validator": "^13.15.20" + "validator": "^13.15.23" }, "devDependencies": { "env-cmd": "^11.0.0", @@ -39,7 +39,7 @@ "jest": "^30.2.0", "jest-sonar-reporter": "^2.0.0", "node-notifier": "^10.0.1", - "nodemon": "^3.1.10", + "nodemon": "^3.1.11", "sinon": "^21.0.0", "supertest": "^7.1.4" } @@ -551,9 +551,9 @@ } }, "node_modules/@emnapi/core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz", - "integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", "dev": true, "license": "MIT", "optional": true, @@ -563,9 +563,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", - "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", "dev": true, "license": "MIT", "optional": true, @@ -840,9 +840,9 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -1645,9 +1645,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz", - "integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -1755,9 +1755,9 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.34", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.34.tgz", - "integrity": "sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==", + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", "dev": true, "license": "MIT", "dependencies": { @@ -2324,9 +2324,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.25", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz", - "integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==", + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", + "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2345,12 +2345,6 @@ "node": ">= 0.8" } }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, "node_modules/bcryptjs": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz", @@ -2418,9 +2412,9 @@ } }, "node_modules/browserslist": { - "version": "4.27.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", - "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", + "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", "dev": true, "funding": [ { @@ -2438,10 +2432,10 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.19", - "caniuse-lite": "^1.0.30001751", - "electron-to-chromium": "^1.5.238", - "node-releases": "^2.0.26", + "baseline-browser-mapping": "^2.8.25", + "caniuse-lite": "^1.0.30001754", + "electron-to-chromium": "^1.5.249", + "node-releases": "^2.0.27", "update-browserslist-db": "^1.1.4" }, "bin": { @@ -2542,9 +2536,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001754", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", - "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "version": "1.0.30001756", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", + "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", "dev": true, "funding": [ { @@ -2812,15 +2806,16 @@ "license": "MIT" }, "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/content-type": { @@ -3036,9 +3031,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.249", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.249.tgz", - "integrity": "sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==", + "version": "1.5.259", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.259.tgz", + "integrity": "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==", "dev": true, "license": "ISC" }, @@ -3527,14 +3522,34 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/express-session/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/express-validator": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.3.0.tgz", - "integrity": "sha512-ujK2BX5JUun5NR4JuBo83YSXoDDIpoGz3QxgHTzQcHFevkKnwV1in4K7YNuuXQ1W3a2ObXB/P4OTnTZpUyGWiw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.3.1.tgz", + "integrity": "sha512-IGenaSf+DnWc69lKuqlRE9/i/2t5/16VpH5bXoqdxWz1aCpRvEdrBuu1y95i/iL5QP8ZYVATiwLFhwk3EDl5vg==", "license": "MIT", "dependencies": { "lodash": "^4.17.21", - "validator": "~13.15.15" + "validator": "~13.15.23" }, "engines": { "node": ">= 8.0.0" @@ -3702,9 +3717,9 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -3886,9 +3901,9 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -4095,28 +4110,23 @@ "license": "MIT" }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/human-signals": { @@ -5105,9 +5115,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -5227,12 +5237,12 @@ } }, "node_modules/kareem": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", - "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-3.0.0.tgz", + "integrity": "sha512-RKhaOBSPN8L7y4yAgNhDT2602G5FD6QbOIISbjN9D6mjHPeqeg7K+EB5IGSU5o81/X2Gzm3ICnAvQW3x3OP8HA==", "license": "Apache-2.0", "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/keyv": { @@ -5486,15 +5496,19 @@ } }, "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/mimic-fn": { @@ -5608,101 +5622,26 @@ } }, "node_modules/mongoose": { - "version": "8.19.3", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.19.3.tgz", - "integrity": "sha512-fTAGaIohkk8wCggMuBuqTVD4YrM1/J8cBr1ekqzFqtz65qkLjtX2dcy3NH1e+2rk2365dyrrsPAnt4YTxBhEiQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.0.0.tgz", + "integrity": "sha512-J6wTGC8/hSFpy9K6kPbKDnBNoUcX4iOGCasUrRzlSKdwdVNxdscLA4oHKOQwJlHqh/TxDNg+Uzg6koCyCKP0wA==", "license": "MIT", "dependencies": { - "bson": "^6.10.4", - "kareem": "2.6.3", - "mongodb": "~6.20.0", + "kareem": "3.0.0", + "mongodb": "~7.0", "mpath": "0.9.0", - "mquery": "5.0.0", + "mquery": "6.0.0", "ms": "2.1.3", "sift": "17.1.3" }, "engines": { - "node": ">=16.20.1" + "node": ">=20.19.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mongoose" } }, - "node_modules/mongoose/node_modules/@types/whatwg-url": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", - "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" - } - }, - "node_modules/mongoose/node_modules/bson": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", - "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", - "license": "Apache-2.0", - "engines": { - "node": ">=16.20.1" - } - }, - "node_modules/mongoose/node_modules/mongodb": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.20.0.tgz", - "integrity": "sha512-Tl6MEIU3K4Rq3TSHd+sZQqRBoGlFsOgNrH5ltAcFBV62Re3Fd+FcaVf8uSEQFOJ51SDowDVttBTONMfoYWrWlQ==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/saslprep": "^1.3.0", - "bson": "^6.10.4", - "mongodb-connection-string-url": "^3.0.2" - }, - "engines": { - "node": ">=16.20.1" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.3.2", - "socks": "^2.7.1" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, - "node_modules/mongoose/node_modules/mongodb-connection-string-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", - "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^14.1.0 || ^13.0.0" - } - }, "node_modules/mpath": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", @@ -5713,15 +5652,12 @@ } }, "node_modules/mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-6.0.0.tgz", + "integrity": "sha512-b2KQNsmgtkscfeDgkYMcWGn9vZI9YoXh802VDEwE6qc50zxBFQ0Oo8ROkawbPAsXCY1/Z1yp0MagqsZStPWJjw==", "license": "MIT", - "dependencies": { - "debug": "4.x" - }, "engines": { - "node": ">=14.0.0" + "node": ">=20.19.0" } }, "node_modules/ms": { @@ -5805,9 +5741,9 @@ "license": "MIT" }, "node_modules/nodemon": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", - "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.11.tgz", + "integrity": "sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==", "dev": true, "license": "MIT", "dependencies": { @@ -6499,15 +6435,15 @@ } }, "node_modules/raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.10" @@ -6618,23 +6554,9 @@ } }, "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, "node_modules/safe-stable-stringify": { @@ -7558,9 +7480,9 @@ } }, "node_modules/validator": { - "version": "13.15.20", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.20.tgz", - "integrity": "sha512-KxPOq3V2LmfQPP4eqf3Mq/zrT0Dqp2Vmx2Bn285LwVahLc+CsxOM0crBHczm8ijlcjZ0Q5Xd6LW3z3odTPnlrw==", + "version": "13.15.23", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.23.tgz", + "integrity": "sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==", "license": "MIT", "engines": { "node": ">= 0.10" diff --git a/package.json b/package.json index 4373c53c..f6fb3f51 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "express-basic-auth": "^1.2.1", "express-rate-limit": "^8.2.1", "express-session": "^1.18.2", - "express-validator": "^7.3.0", + "express-validator": "^7.3.1", "graphql": "^16.12.0", "graphql-http": "^1.22.4", "graphql-tag": "^2.12.6", @@ -52,14 +52,14 @@ "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", "mongodb": "^7.0.0", - "mongoose": "^8.19.3", + "mongoose": "^9.0.0", "passport": "^0.7.0", "@node-saml/passport-saml": "^5.1.0", "pino": "^10.1.0", "pino-pretty": "^13.1.2", "swagger-ui-express": "^5.0.1", "switcher-client": "^4.5.0", - "validator": "^13.15.20" + "validator": "^13.15.23" }, "devDependencies": { "env-cmd": "^11.0.0", @@ -67,7 +67,7 @@ "jest": "^30.2.0", "jest-sonar-reporter": "^2.0.0", "node-notifier": "^10.0.1", - "nodemon": "^3.1.10", + "nodemon": "^3.1.11", "sinon": "^21.0.0", "supertest": "^7.1.4" }, diff --git a/src/models/admin.js b/src/models/admin.js index c9826898..92c85bf1 100644 --- a/src/models/admin.js +++ b/src/models/admin.js @@ -218,24 +218,14 @@ adminSchema.statics.extractTokenPart = (token) => { return token.substring(token.length - 8, token.length); }; -adminSchema.pre('save', async function (next) { +adminSchema.pre('save', async function () { if (this.isModified('password')) { this.password = await bcryptjs.hash(this.password, EncryptionSalts.ADMIN); notifyAcCreation(this._id); } - - next(); -}); - -adminSchema.post('save', function(error, _doc, next) { - if (error.name === 'MongoServerError' && error.code === 11000) { - return next(new Error('Account is already registered.')); - } - - next(error); }); -adminSchema.pre('deleteOne', { document: true, query: false }, async function (next) { +adminSchema.pre('deleteOne', { document: true, query: false }, async function () { const teams = await Team.find({ members: this._id }).exec(); for (const team of teams) { let indexMmeber = team.members.indexOf(this._id); @@ -244,7 +234,6 @@ adminSchema.pre('deleteOne', { document: true, query: false }, async function (n } notifyAcDeletion(this._id); - next(); }); const Admin = mongoose.model('Admin', adminSchema); diff --git a/src/models/component.js b/src/models/component.js index 71d276bf..9a9d7aca 100644 --- a/src/models/component.js +++ b/src/models/component.js @@ -68,25 +68,20 @@ const existComponent = async ({ domain, name, __v }) => { return false; }; -componentSchema.pre('validate', async function (next) { +componentSchema.pre('validate', async function () { // Verify if component already exists if (await existComponent(this)) { - const err = new Error(`Unable to complete the operation. Component '${this.name}' already exists for this Domain`); - next(err); + throw new Error(`Unable to complete the operation. Component '${this.name}' already exists for this Domain`); } - - next(); }); -componentSchema.pre('deleteOne', { document: true, query: false }, async function (next) { +componentSchema.pre('deleteOne', { document: true, query: false }, async function () { const configsToRemoveFrom = await Config.find({ components: { $in: [this._id] } }).exec(); for (const config of configsToRemoveFrom) { const indexValue = config.components.indexOf(this._id); config.components.splice(indexValue, 1); config.save(); } - - next(); }); const Component = mongoose.model('Component', componentSchema); diff --git a/src/models/config-strategy.js b/src/models/config-strategy.js index 6ebe623c..da018bba 100644 --- a/src/models/config-strategy.js +++ b/src/models/config-strategy.js @@ -237,28 +237,25 @@ configStrategySchema.options.toJSON = { } }; -configStrategySchema.pre('deleteOne', { document: true, query: false }, async function (next) { +configStrategySchema.pre('deleteOne', { document: true, query: false }, async function () { await History.deleteMany({ domainId: this.domain, elementId: this._id }).exec(); - - next(); }); -configStrategySchema.pre('save', async function (next) { +configStrategySchema.pre('save', async function () { const strategy = this.strategy; const operationStrategy = this.operation; const { min, max } = OperationValuesValidation.find(element => element.operation === operationStrategy); // Verify if strategy already exists if (await existStrategy(this)) { - const err = new Error(`Unable to complete the operation. Strategy '${strategy}' already exists for this configuration and environment`); - return next(err); + throw new Error(`Unable to complete the operation. Strategy '${strategy}' already exists for this configuration and environment`); } // Verify strategy value quantity if (!this.values || this.values.length < min || this.values.length > max) { const err = new Error(`Unable to complete the operation. The number of values for the operation '${operationStrategy}', are min: ${min} and max: ${max} values`); - return next(err); + throw err; } const operations = StrategyRequirementDefinition.find(element => element.strategy === strategy).operations; @@ -267,21 +264,15 @@ configStrategySchema.pre('save', async function (next) { // Verify strategy operation requirements if (!foundOperation) { const err = new Error(`Unable to complete the operation. The strategy '${strategy}' needs ${operations} as operation`); - return next(err); + throw err; } // Verify strategy values format - try { - for (const value of this.values) { - validateStrategyValue(strategy, value); - } - } catch (err) { - return next(err); + for (const value of this.values) { + validateStrategyValue(strategy, value); } await recordStrategyHistory(this, this.modifiedPaths()); - - next(); }); Object.assign(configStrategySchema.statics, { StrategiesType, OperationsType }); diff --git a/src/models/config.js b/src/models/config.js index 854ea2f4..2c045786 100644 --- a/src/models/config.js +++ b/src/models/config.js @@ -180,7 +180,7 @@ configSchema.virtual('configStrategy', { foreignField: 'config' }); -configSchema.pre('deleteOne', { document: true, query: false }, async function (next) { +configSchema.pre('deleteOne', { document: true, query: false }, async function () { const strategies = await ConfigStrategy.find({ config: this._id }).exec(); if (strategies) { for (const strategy of strategies) { @@ -189,17 +189,14 @@ configSchema.pre('deleteOne', { document: true, query: false }, async function ( } await History.deleteMany({ domainId: this.domain, elementId: this._id }).exec(); - next(); }); -configSchema.pre('save', async function (next) { +configSchema.pre('save', async function () { await this.populate({ path: 'component_list' }); await this.populate({ path: 'component_list' }); await recordConfigHistory(this.toJSON(), this.modifiedPaths()); await checkMetrics(this); hasRelayEndpointUpdates(this, this.modifiedPaths()); - - next(); }); export const Config = mongoose.model('Config', configSchema); diff --git a/src/models/domain.js b/src/models/domain.js index 8c2bf59f..e6cd7f71 100644 --- a/src/models/domain.js +++ b/src/models/domain.js @@ -108,7 +108,7 @@ domainSchema.options.toJSON = { } }; -domainSchema.pre('deleteOne', { document: true, query: false }, async function (next) { +domainSchema.pre('deleteOne', { document: true, query: false }, async function () { const groups = await GroupConfig.find({ domain: this._id }).exec(); if (groups) { @@ -130,8 +130,6 @@ domainSchema.pre('deleteOne', { document: true, query: false }, async function ( History.deleteMany({ domainId: this._id }), Metric.deleteMany({ domain: this._id }) ]); - - next(); }); async function recordDomainHistory(domain, modifiedField) { @@ -141,17 +139,8 @@ async function recordDomainHistory(domain, modifiedField) { } } -domainSchema.pre('save', async function (next) { +domainSchema.pre('save', async function () { await recordDomainHistory(this, this.modifiedPaths()); - next(); -}); - -domainSchema.post('save', function(error, _doc, next) { - if (error.name === 'MongoServerError' && error.code === 11000) { - return next(new Error('The domain name is already in use.')); - } - - next(error); }); const Domain = mongoose.model('Domain', domainSchema); diff --git a/src/models/environment.js b/src/models/environment.js index 97257b60..cf7819c9 100644 --- a/src/models/environment.js +++ b/src/models/environment.js @@ -41,16 +41,13 @@ environmentSchema.options.toJSON = { } }; -environmentSchema.pre('validate', async function (next) { +environmentSchema.pre('validate', async function () { const { name, domain } = this; const existEnv = await Environment.findOne({ name, domain }).exec(); if (existEnv) { - const err = new Error(`Unable to complete the operation. Environment '${name}' already exists for this Domain`); - next(err); + throw new Error(`Unable to complete the operation. Environment '${name}' already exists for this Domain`); } - - next(); }); export const Environment = mongoose.model('Environment', environmentSchema); \ No newline at end of file diff --git a/src/models/group-config.js b/src/models/group-config.js index 4c4e7841..14cf85c8 100644 --- a/src/models/group-config.js +++ b/src/models/group-config.js @@ -74,7 +74,7 @@ groupConfigSchema.virtual('config', { foreignField: 'group' }); -groupConfigSchema.pre('deleteOne', { document: true, query: false }, async function (next) { +groupConfigSchema.pre('deleteOne', { document: true, query: false }, async function () { const configs = await Config.find({ group: this._id }).exec(); if (configs) { @@ -84,12 +84,10 @@ groupConfigSchema.pre('deleteOne', { document: true, query: false }, async funct } await History.deleteMany({ domainId: this.domain, elementId: this._id }).exec(); - next(); }); -groupConfigSchema.pre('save', async function (next) { +groupConfigSchema.pre('save', async function () { await recordGroupHistory(this, this.modifiedPaths()); - next(); }); const GroupConfig = mongoose.model('GroupConfig', groupConfigSchema); diff --git a/src/models/slack.js b/src/models/slack.js index 9c952936..e95e4c43 100644 --- a/src/models/slack.js +++ b/src/models/slack.js @@ -58,9 +58,8 @@ slackSchema.options.toJSON = { } }; -slackSchema.pre('deleteOne', { document: true, query: false }, async function (next) { +slackSchema.pre('deleteOne', { document: true, query: false }, async function () { await SlackTicket.deleteMany({ slack: this._id }).exec(); - next(); }); const Slack = mongoose.model('Slack', slackSchema); diff --git a/src/models/team.js b/src/models/team.js index 7256a5ad..1d7bb16f 100644 --- a/src/models/team.js +++ b/src/models/team.js @@ -66,17 +66,14 @@ const existTeam = async (team) => { return false; }; -teamSchema.pre('validate', async function (next) { +teamSchema.pre('validate', async function () { // Verify if team already exists if (await existTeam(this)) { - const err = new Error(`Unable to complete the operation. Team '${this.name}' already exists for this Domain`); - next(err); + throw new Error(`Unable to complete the operation. Team '${this.name}' already exists for this Domain`); } - - next(); }); -teamSchema.pre('deleteOne', { document: true, query: false }, async function (next) { +teamSchema.pre('deleteOne', { document: true, query: false }, async function () { await Permission.deleteMany({ _id: { $in: this.permissions } }).exec(); const membersToRemve = await Admin.find({ teams: this._id }).exec(); @@ -85,8 +82,6 @@ teamSchema.pre('deleteOne', { document: true, query: false }, async function (ne member.teams.splice(indexValue, 1); member.save(); } - - next(); }); export const Team = mongoose.model('Team', teamSchema); \ No newline at end of file diff --git a/src/services/admin.js b/src/services/admin.js index 3b5843bb..6aacc4c5 100644 --- a/src/services/admin.js +++ b/src/services/admin.js @@ -3,6 +3,7 @@ import { validate_token } from '../external/google-recaptcha.js'; import { getBitBucketToken, getBitBucketUserInfo } from '../external/oauth-bitbucket.js'; import { getGitToken, getGitUserInfo } from '../external/oauth-git.js'; import { checkAdmin } from '../external/switcher-api-facade.js'; +import Logger from '../helpers/logger.js'; import Admin from '../models/admin.js'; import Domain from '../models/domain.js'; import { response } from './common.js'; @@ -28,7 +29,7 @@ export async function signUp(args, remoteAddress) { await validate_token(args.token, remoteAddress); const admin = new Admin(args); - return admin.save(); + return saveAdmin(admin); } export async function signUpGitHub(code) { @@ -36,7 +37,7 @@ export async function signUpGitHub(code) { const userInfo = await getGitUserInfo(token); let admin = await Admin.findUserByGitId(userInfo.id); - admin = await Admin.createThirdPartyAccount( + admin = await createThirdPartyAccount( admin, userInfo, 'github', '_gitid', checkAdmin); const jwt = await admin.generateAuthToken(); @@ -48,7 +49,7 @@ export async function signUpBitbucket(code) { const userInfo = await getBitBucketUserInfo(token); let admin = await Admin.findUserByBitBucketId(userInfo.id); - admin = await Admin.createThirdPartyAccount( + admin = await createThirdPartyAccount( admin, userInfo, 'bitbucket', '_bitbucketid', checkAdmin); const jwt = await admin.generateAuthToken(); @@ -57,7 +58,7 @@ export async function signUpBitbucket(code) { export async function signUpSaml(userInfo) { let admin = await Admin.findUserBySamlId(userInfo.id); - admin = await Admin.createThirdPartyAccount( + admin = await createThirdPartyAccount( admin, userInfo, 'saml', '_samlid', checkAdmin); const jwt = await admin.generateAuthToken(); @@ -74,7 +75,7 @@ export async function loginRequestRecovery(email) { const admin = await getAdmin({ email }); if (admin) { await admin.generateAuthCode(); - admin.save(); + await saveAdmin(admin); } } @@ -94,13 +95,13 @@ export async function loginRecovery(args, remoteAddress) { export async function logout(admin) { admin.token = null; - await admin.save(); + await saveAdmin(admin); } export async function updateAccount(args, admin) { const updates = Object.keys(args); updates.forEach((update) => admin[update] = args[update]); - return admin.save(); + return saveAdmin(admin); } export async function leaveDomain(domainid, admin) { @@ -117,7 +118,7 @@ export async function leaveDomain(domainid, admin) { let indexTeam = admin.teams.indexOf(admin_team._id); admin.teams.splice(indexTeam, 1); - await admin.save(); + await saveAdmin(admin); } return admin; @@ -131,4 +132,27 @@ export async function deleteAccount(admin) { } return admin.deleteOne(); +} + +async function saveAdmin(admin) { + try { + return await admin.save(); + } catch (e) { + Logger.error('saveAdmin', e); + if (e.name === 'MongoServerError' && e.code === 11000) { + throw new BadRequestError('Account is already registered.'); + } + + throw e; + } +} + +async function createThirdPartyAccount(admin, userInfo, platform, attributeIdName, checkAdmin) { + try { + return await Admin.createThirdPartyAccount( + admin, userInfo, platform, attributeIdName, checkAdmin); + } catch (e) { + Logger.error(`createThirdPartyAccount - ${platform}`, e); + throw new Error('Unable to create account - account may already be registered.'); + } } \ No newline at end of file diff --git a/src/services/domain.js b/src/services/domain.js index 7aa073e8..73ddd869 100644 --- a/src/services/domain.js +++ b/src/services/domain.js @@ -11,12 +11,14 @@ import { ActionTypes, RouterTypes } from '../models/permission.js'; import { formatInput, verifyOwnership, checkEnvironmentStatusRemoval } from '../helpers/index.js'; import { permissionCache } from '../helpers/cache.js'; import { response } from './common.js'; +import Logger from '../helpers/logger.js'; +import { BadRequestError } from '../exceptions/index.js'; export async function removeDomainStatus(domain, environmentName) { try { await checkEnvironmentStatusRemoval(domain._id, environmentName); domain.activated.delete(environmentName); - return await domain.save(); + return await saveDomain(domain); } catch (e) { throw new Error(e.message); } @@ -60,7 +62,7 @@ export async function createDomain(args, admin) { }); environment.save(); - return domain.save(); + return saveDomain(domain); } export async function deleteDomainHistory(id, admin) { @@ -84,7 +86,7 @@ export async function transferDomain(args, admin) { domain.updatedBy = admin.email; domain.transfer = domain.transfer ? null : true; - return domain.save(); + return saveDomain(domain); } export async function transferDomainAccept(args, admin) { @@ -98,7 +100,7 @@ export async function transferDomainAccept(args, admin) { ConfigStrategy.updateMany({ domain: domain._id }, { owner: admin._id }), Component.updateMany({ domain: domain._id }, { owner: admin._id }), Environment.updateMany({ domain: domain._id }, { owner: admin._id }), - domain.save() + saveDomain(domain) ]); return domain; @@ -113,7 +115,7 @@ export async function updateDomain(id, args, admin) { const updates = Object.keys(args); updates.forEach((update) => domain[update] = args[update]); - return domain.save(); + return saveDomain(domain); } export async function updateDomainStatus(id, args, admin) { @@ -127,7 +129,7 @@ export async function updateDomainStatus(id, args, admin) { const updates = await checkEnvironmentStatusChange(args, id); updates.forEach((update) => domain.activated.set(update, args[update])); - return domain.save(); + return saveDomain(domain); } export async function removeDomainStatusEnv(id, env, admin) { @@ -144,7 +146,7 @@ export async function removeDomainStatusEnv(id, env, admin) { export async function updateDomainVersion(domainId) { const domain = await getDomainById(domainId); domain.lastUpdate = Date.now(); - return domain.save(); + return saveDomain(domain); } export async function getRelayVerificationCode(id, admin) { @@ -155,8 +157,21 @@ export async function getRelayVerificationCode(id, admin) { if (!domain.integrations.relay.verification_code) { domain.integrations.relay.verification_code = randomUUID(); - await domain.save(); + await saveDomain(domain); } return domain.integrations.relay.verification_code; +} + +async function saveDomain(domain) { + try { + return await domain.save(); + } catch (e) { + Logger.error('saveDomain', e); + if (e.name === 'MongoServerError' && e.code === 11000) { + throw new BadRequestError('The domain name is already in use.'); + } + + throw e; + } } \ No newline at end of file diff --git a/tests/admin.test.js b/tests/admin.test.js index 41ca4d4e..55c6819e 100644 --- a/tests/admin.test.js +++ b/tests/admin.test.js @@ -941,12 +941,12 @@ describe('Testing Admin collaboration endpoint - Reading permissions', () => { expect(response.body.length > 0).toEqual(true); - const read = response.body.filter(permission => permission.action === 'READ'); - expect(read[0].result).toEqual('ok'); - const update = response.body.filter(permission => permission.action === 'UPDATE'); - expect(update[0].result).toEqual('nok'); - const create = response.body.filter(permission => permission.action === 'CREATE'); - expect(create[0].result).toEqual('nok'); + const read = response.body.find(permission => permission.action === 'READ'); + expect(read.result).toEqual('ok'); + const update = response.body.find(permission => permission.action === 'UPDATE'); + expect(update.result).toEqual('nok'); + const create = response.body.find(permission => permission.action === 'CREATE'); + expect(create.result).toEqual('nok'); }); test('ADMIN_SUITE - Should read permissions given request - Group - From Cache', async () => { @@ -980,12 +980,12 @@ describe('Testing Admin collaboration endpoint - Reading permissions', () => { expect(response.body.length > 0).toEqual(true); expect(cacheSpy.callCount).toBe(1); - const read = response.body.filter(permission => permission.action === 'READ'); - expect(read[0].result).toEqual('ok'); - const update = response.body.filter(permission => permission.action === 'UPDATE'); - expect(update[0].result).toEqual('nok'); - const create = response.body.filter(permission => permission.action === 'CREATE'); - expect(create[0].result).toEqual('nok'); + const read = response.body.find(permission => permission.action === 'READ'); + expect(read.result).toEqual('ok'); + const update = response.body.find(permission => permission.action === 'UPDATE'); + expect(update.result).toEqual('nok'); + const create = response.body.find(permission => permission.action === 'CREATE'); + expect(create.result).toEqual('nok'); }); test('ADMIN_SUITE - Should read permissions given request - Access forbidden for staging', async () => { @@ -1002,8 +1002,8 @@ describe('Testing Admin collaboration endpoint - Reading permissions', () => { expect(response.body.length > 0).toEqual(true); - const read = response.body.filter(permission => permission.action === 'READ'); - expect(read[0].result).toEqual('nok'); + const read = response.body.find(permission => permission.action === 'READ'); + expect(read.result).toEqual('nok'); }); });