diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 446129d..a7873b0 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -49,7 +49,7 @@ jobs: SWITCHER_API_LOGGER: false - name: SonarCloud Scan - uses: sonarsource/sonarqube-scan-action@v6.0.0 + uses: sonarsource/sonarqube-scan-action@v7.0.0 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} if: env.SONAR_TOKEN != '' diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index e4a770b..67986f6 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -64,7 +64,7 @@ jobs: SWITCHER_API_LOGGER: false - name: SonarCloud Scan - uses: sonarsource/sonarqube-scan-action@v6.0.0 + uses: sonarsource/sonarqube-scan-action@v7.0.0 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} if: env.SONAR_TOKEN != '' diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 0e84cfc..5a82975 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -23,21 +23,21 @@ "jsonwebtoken": "^9.0.3", "moment": "^2.30.1", "mongodb": "^7.0.0", - "mongoose": "^9.0.0", + "mongoose": "^9.1.1", "pino": "^10.1.0", - "pino-pretty": "^13.1.2", + "pino-pretty": "^13.1.3", "swagger-ui-express": "^5.0.1", "switcher-client": "^4.5.0", - "validator": "^13.15.23" + "validator": "^13.15.26" }, "devDependencies": { "env-cmd": "^11.0.0", - "eslint": "^9.39.1", + "eslint": "^9.39.2", "jest": "^30.2.0", "jest-sonar-reporter": "^2.0.0", "node-notifier": "^10.0.1", "nodemon": "^3.1.11", - "sinon": "^21.0.0", + "sinon": "^21.0.1", "supertest": "^7.1.4" } }, @@ -689,9 +689,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", - "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { @@ -1305,9 +1305,9 @@ } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.2.tgz", - "integrity": "sha512-QgA5AySqB27cGTXBFmnpifAi7HxoGUeezwo6p9dI03MuDB6Pp33zgclqVb6oVK3j6I9Vesg0+oojW2XxB59SGg==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.4.tgz", + "integrity": "sha512-p7X/ytJDIdwUfFL/CLOhKgdfJe1Fa8uw9seJYvdOmnP9JBWGWHW69HkOixXS6Wy9yvGf1MbhcS6lVmrhy4jm2g==", "license": "MIT", "dependencies": { "sparse-bitfield": "^3.0.3" @@ -1387,9 +1387,9 @@ "license": "Apache-2.0" }, "node_modules/@sinclair/typebox": { - "version": "0.34.41", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", - "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "version": "0.34.45", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.45.tgz", + "integrity": "sha512-qJcFVfCa5jxBFSuv7S5WYbA8XdeCPmhnaVVfX/2Y6L8WYg8sk3XY2+6W0zH+3mq1Cz+YC7Ki66HfqX6IHAwnkg==", "dev": true, "license": "MIT" }, @@ -1532,9 +1532,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "version": "25.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", + "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", "dev": true, "license": "MIT", "dependencies": { @@ -2115,9 +2115,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.2.tgz", - "integrity": "sha512-PxSsosKQjI38iXkmb3d0Y32efqyA0uW4s41u4IVBsLlWLhCiYNpH/AfNOVWRqCQBlD8TFJTz6OUWNd4DFJCnmw==", + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", + "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2331,9 +2331,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001759", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", - "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", + "version": "1.0.30001762", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz", + "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==", "dev": true, "funding": [ { @@ -2709,9 +2709,9 @@ } }, "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -2780,9 +2780,9 @@ } }, "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", + "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -2826,9 +2826,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.265", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.265.tgz", - "integrity": "sha512-B7IkLR1/AE+9jR2LtVF/1/6PFhY5TlnEHnlrKmGk7PvkJibg5jr+mLXLLzq3QYl6PA1T/vLDthQPqIPAlS/PPA==", + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", "dev": true, "license": "ISC" }, @@ -2973,9 +2973,9 @@ } }, "node_modules/eslint": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", - "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", "dependencies": { @@ -2985,7 +2985,7 @@ "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.1", + "@eslint/js": "9.39.2", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -3292,9 +3292,9 @@ } }, "node_modules/fast-copy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.0.tgz", - "integrity": "sha512-/oA0gx1xyXE9R2YlV4FXwZJXngFdm9Du0zN8FhY38jnLkhp1u35h6bCyKgRhlsA6C9I+1vfXE4KISdt7xc6M9w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.2.tgz", + "integrity": "sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw==", "license": "MIT" }, "node_modules/fast-deep-equal": { @@ -3880,9 +3880,9 @@ } }, "node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", + "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -5366,9 +5366,9 @@ } }, "node_modules/mongoose": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.0.0.tgz", - "integrity": "sha512-J6wTGC8/hSFpy9K6kPbKDnBNoUcX4iOGCasUrRzlSKdwdVNxdscLA4oHKOQwJlHqh/TxDNg+Uzg6koCyCKP0wA==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.1.1.tgz", + "integrity": "sha512-/CgKSAmjzgIj4o1FyWZIpQ2rmUQlhalwWd4l/Ht3XUVWscHRHev1TIwKz1ADNC5tHHyOQEaUDkEh0jI91c4Ydw==", "license": "MIT", "dependencies": { "kareem": "3.0.0", @@ -6109,9 +6109,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -6289,31 +6289,35 @@ } }, "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "license": "MIT", "dependencies": { - "debug": "^4.3.5", + "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", - "statuses": "^2.0.1" + "statuses": "^2.0.2" }, "engines": { "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", @@ -6323,6 +6327,10 @@ }, "engines": { "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/setprototypeof": { @@ -6479,16 +6487,16 @@ } }, "node_modules/sinon": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-21.0.0.tgz", - "integrity": "sha512-TOgRcwFPbfGtpqvZw+hyqJDvqfapr1qUlOizROIk4bBLjlsjlB00Pg6wMFXNtJRpu+eCZuVOaLatG7M8105kAw==", + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-21.0.1.tgz", + "integrity": "sha512-Z0NVCW45W8Mg5oC/27/+fCqIHFnW8kpkFOq0j9XJIev4Ld0mKmERaZv5DMLAb9fGCevjKwaEeIQz5+MBXfZcDw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.5", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", + "@sinonjs/fake-timers": "^15.1.0", + "@sinonjs/samsam": "^8.0.3", + "diff": "^8.0.2", "supports-color": "^7.2.0" }, "funding": { @@ -6496,6 +6504,16 @@ "url": "https://opencollective.com/sinon" } }, + "node_modules/sinon/node_modules/@sinonjs/fake-timers": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.1.0.tgz", + "integrity": "sha512-cqfapCxwTGsrR80FEgOoPsTonoefMBY7dnUEbQ+GRcved0jvkJLzvX6F4WtN+HBqbPX/SiFsIRUp+IrCW/2I2w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6816,9 +6834,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.30.3", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.30.3.tgz", - "integrity": "sha512-giQl7/ToPxCqnUAx2wpnSnDNGZtGzw1LyUw6ZitIpTmdrvpxKFY/94v1hihm0zYNpgp1/VY0jTDk//R0BBgnRQ==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.31.0.tgz", + "integrity": "sha512-zSUTIck02fSga6rc0RZP3b7J7wgHXwLea8ZjgLA3Vgnb8QeOl3Wou2/j5QkzSGeoz6HusP/coYuJl33aQxQZpg==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" @@ -7076,9 +7094,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -7142,9 +7160,9 @@ } }, "node_modules/validator": { - "version": "13.15.23", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.23.tgz", - "integrity": "sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==", + "version": "13.15.26", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz", + "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==", "license": "MIT", "engines": { "node": ">= 0.10" diff --git a/package.json b/package.json index 72fe4b4..34ac5dc 100644 --- a/package.json +++ b/package.json @@ -50,21 +50,21 @@ "jsonwebtoken": "^9.0.3", "moment": "^2.30.1", "mongodb": "^7.0.0", - "mongoose": "^9.0.0", + "mongoose": "^9.1.1", "pino": "^10.1.0", - "pino-pretty": "^13.1.2", + "pino-pretty": "^13.1.3", "swagger-ui-express": "^5.0.1", "switcher-client": "^4.5.0", - "validator": "^13.15.23" + "validator": "^13.15.26" }, "devDependencies": { "env-cmd": "^11.0.0", - "eslint": "^9.39.1", + "eslint": "^9.39.2", "jest": "^30.2.0", "jest-sonar-reporter": "^2.0.0", "node-notifier": "^10.0.1", "nodemon": "^3.1.11", - "sinon": "^21.0.0", + "sinon": "^21.0.1", "supertest": "^7.1.4" }, "repository": { diff --git a/src/aggregator/criteria-type.js b/src/aggregator/criteria-type.js index 2871d6d..4a2a21a 100644 --- a/src/aggregator/criteria-type.js +++ b/src/aggregator/criteria-type.js @@ -1,7 +1,7 @@ import { GraphQLObjectType, GraphQLString, GraphQLList, GraphQLBoolean, GraphQLNonNull, GraphQLInputObjectType } from 'graphql'; import { domainType, groupConfigType, strategyType } from './configuration-type.js'; import { EnvType } from '../models/environment.js'; -import { resolveCriteria } from './resolvers.js'; +import { evaluateCriteria } from '../services/criteria.js'; export const strategyInputType = new GraphQLInputObjectType({ name: 'StrategyInput', @@ -66,7 +66,7 @@ export const criteriaType = new GraphQLObjectType({ response: { type: responseType, resolve: (source, _params, context) => { - return resolveCriteria(source, context); + return evaluateCriteria(source, context); } } } diff --git a/src/aggregator/resolvers.js b/src/aggregator/resolvers.js index 003c68a..22ca1c4 100644 --- a/src/aggregator/resolvers.js +++ b/src/aggregator/resolvers.js @@ -1,13 +1,8 @@ -import { EnvType } from '../models/environment.js'; import Domain from '../models/domain.js'; import GroupConfig from '../models/group-config.js'; -import { Config, RelayTypes} from '../models/config.js'; -import { addMetrics } from '../models/metric.js'; -import { ConfigStrategy, processOperation } from '../models/config-strategy.js'; -import { resolveNotification, resolveValidation } from '../services/relay.js'; +import { Config} from '../models/config.js'; +import { ConfigStrategy } from '../models/config-strategy.js'; import Component from '../models/component.js'; -import Logger from '../helpers/logger.js'; -import { isRelayVerified, isRelayValid } from '../services/config.js'; export const resolveConfigByKey = async (domain, key) => Config.findOne({ domain, key }, null, { lean: true }); @@ -101,10 +96,6 @@ export async function resolveDomain(activated, context) { return domain; } -export async function findDomain(domainId) { - return Domain.findById(domainId).lean(); -} - /** * Resolve components first is used by SDKs to filter only configurations in which the component * exists resulting in a snapshot size reduction. @@ -129,123 +120,4 @@ async function resolveComponentsFirst(source, context, groups) { return validGroups; } return groups; -} - -async function findGroup(config) { - return GroupConfig.findById(config.group).lean(); -} - -async function findConfigStrategies(configId, domainId, strategyFilter) { - return ConfigStrategy.find({ config: configId, domain: domainId }, strategyFilter).lean(); -} - -async function checkRelay(config, environment, entry, response) { - try { - if (config.relay?.activated[environment]) { - isRelayValid(config.relay); - isRelayVerified(config.relay, environment); - - if (config.relay.type === RelayTypes.NOTIFICATION) { - resolveNotification(config.relay, entry, environment); - } else { - const relayResponse = await resolveValidation(config.relay, entry, environment); - - response.result = relayResponse.result; - response.reason = relayResponse.result ? 'Success' : 'Relay does not agree'; - response.message = relayResponse.message; - response.metadata = relayResponse.metadata; - } - } - } catch (e) { - if (config.relay.type === RelayTypes.VALIDATION) { - response.result = false; - response.reason = `Relay service could not be reached: ${e.message}`; - Logger.error(response.reason, e); - } - } -} - -function isMetricDisabled(config, environment) { - if (config.disable_metrics[environment] === undefined) { - return true; - } - - return config.disable_metrics[environment]; -} - -function checkFlags(config, group, domain, environment) { - if (config.activated[environment] === undefined ? - !config.activated[EnvType.DEFAULT] : !config.activated[environment]) { - throw new Error('Config disabled'); - } else if (group.activated[environment] === undefined ? - !group.activated[EnvType.DEFAULT] : !group.activated[environment]) { - throw new Error('Group disabled'); - } else if (domain.activated[environment] === undefined ? - !domain.activated[EnvType.DEFAULT] : !domain.activated[environment]) { - throw new Error('Domain disabled'); - } -} - -async function checkStrategy(entry, strategies, environment) { - if (strategies) { - for (const strategy of strategies) { - if (!strategy.activated[environment]) { - continue; - } - - await checkStrategyInput(entry, strategy); - } - } -} - -async function checkStrategyInput(entry, { strategy, operation, values }) { - if (entry?.length) { - const strategyEntry = entry.filter(e => e.strategy === strategy); - if (strategyEntry.length == 0 || !(await processOperation(strategy, operation, strategyEntry[0].input, values))) { - throw new Error(`Strategy '${strategy}' does not agree`); - } - } else { - throw new Error(`Strategy '${strategy}' did not receive any input`); - } -} - -export async function resolveCriteria(config, context, strategyFilter) { - context.config_id = config._id; - const environment = context.environment; - let domain, group, strategies; - - await Promise.all([ - findDomain(context.domain), - findGroup(config), - findConfigStrategies(config._id, context.domain, strategyFilter) - ]).then(result => { - domain = result[0]; - group = result[1]; - strategies = result[2]; - }); - - const response = { - domain, - group, - strategies, - result: true, - reason: 'Success' - }; - - try { - checkFlags(config, group, domain, environment); - await checkStrategy(context.entry, strategies, environment); - await checkRelay(config, environment, context.entry, response); - } catch (e) { - response.result = false; - response.reason = e.message; - } finally { - const bypassMetric = context.bypassMetric ? context.bypassMetric === 'true' : false; - if (!bypassMetric && process.env.METRICS_ACTIVATED === 'true' && - !isMetricDisabled(config, environment)) { - addMetrics(context, response); - } - } - - return response; } \ No newline at end of file diff --git a/src/helpers/cache/worker.js b/src/helpers/cache/worker.js index 8788cfc..8db3d60 100644 --- a/src/helpers/cache/worker.js +++ b/src/helpers/cache/worker.js @@ -12,12 +12,10 @@ let getAllDomains = null; /** * Initialize worker and send ready signal */ -(async () => { - await initializeWorker(); - if (dbInitialized) { - parentPort.postMessage({ type: EVENT_TYPE.READY }); - } -})(); +await initializeWorker(); +if (dbInitialized) { + parentPort.postMessage({ type: EVENT_TYPE.READY }); +} /** * Initialize worker by opening database connection and loading services diff --git a/src/routers/client-api.js b/src/routers/client-api.js index e839339..8dc9ac0 100644 --- a/src/routers/client-api.js +++ b/src/routers/client-api.js @@ -3,10 +3,11 @@ import { body, check, query, header } from 'express-validator'; import jwt from 'jsonwebtoken'; import { checkConfig, checkConfigComponent, validate } from '../middleware/validators.js'; import { appAuth, appGenerateCredentials } from '../middleware/auth.js'; -import { resolveCriteria, findDomain } from '../aggregator/resolvers.js'; import { getConfigs } from '../services/config.js'; import { clientLimiter } from '../middleware/limiter.js'; import { StrategiesType } from '../models/config-strategy.js'; +import { evaluateCriteria } from '../services/criteria.js'; +import { getDomainById } from '../services/domain.js'; const router = new express.Router(); @@ -28,7 +29,7 @@ router.post('/criteria', appAuth, clientLimiter, [ const context = { domain, entry, environment, bypassMetric: req.query.bypassMetric, component: req.component }; - const response = await resolveCriteria(req.config, context, 'values description strategy operation activated -_id'); + const response = await evaluateCriteria(req.config, context, 'values description strategy operation activated -_id'); delete response.domain; delete response.group; @@ -51,7 +52,7 @@ router.get('/criteria/snapshot_check/:version', appAuth, clientLimiter, [ check('version', 'Wrong value for domain version').isNumeric() ], validate, async (req, res) => { try { - const domain = await findDomain(req.domain); + const domain = await getDomainById(req.domain); const version = req.params.version; if (domain.lastUpdate > version) { diff --git a/src/services/criteria.js b/src/services/criteria.js new file mode 100644 index 0000000..8be181e --- /dev/null +++ b/src/services/criteria.js @@ -0,0 +1,134 @@ +import Logger from '../helpers/logger.js'; +import { ConfigStrategy, processOperation } from '../models/config-strategy.js'; +import { RelayTypes } from '../models/config.js'; +import Domain from '../models/domain.js'; +import { EnvType } from '../models/environment.js'; +import GroupConfig from '../models/group-config.js'; +import { addMetrics } from '../models/metric.js'; +import { isRelayValid, isRelayVerified } from './config.js'; +import { resolveNotification, resolveValidation } from './relay.js'; + +export async function evaluateCriteria(config, context, strategyFilter) { + context.config_id = config._id; + const environment = context.environment; + let domain, group, strategies; + + // Fetch domain, group and strategies in parallel + await Promise.all([ + findDomain(context.domain), + findGroup(config), + findConfigStrategies(config._id, context.domain, strategyFilter) + ]).then(result => { + domain = result[0]; + group = result[1]; + strategies = result[2]; + }); + + // Prepare response object + const response = { + domain, + group, + strategies, + result: true, + reason: 'Success' + }; + + try { + checkFlags(config, group, domain, environment); + await checkStrategy(context.entry, strategies, environment); + await checkRelay(config, environment, context.entry, response); + } catch (e) { + response.result = false; + response.reason = e.message; + } finally { + const bypassMetric = context.bypassMetric ? context.bypassMetric === 'true' : false; + if (!bypassMetric && process.env.METRICS_ACTIVATED === 'true' && + !isMetricDisabled(config, environment)) { + addMetrics(context, response); + } + } + + return response; +} + +async function findDomain(domainId) { + return Domain.findById(domainId).lean(); +} + +async function findGroup(config) { + return GroupConfig.findById(config.group).lean(); +} + +async function findConfigStrategies(configId, domainId, strategyFilter) { + return ConfigStrategy.find({ config: configId, domain: domainId }, strategyFilter).lean(); +} + +function checkFlags(config, group, domain, environment) { + if (config.activated[environment] === undefined ? + !config.activated[EnvType.DEFAULT] : !config.activated[environment]) { + throw new Error('Config disabled'); + } else if (group.activated[environment] === undefined ? + !group.activated[EnvType.DEFAULT] : !group.activated[environment]) { + throw new Error('Group disabled'); + } else if (domain.activated[environment] === undefined ? + !domain.activated[EnvType.DEFAULT] : !domain.activated[environment]) { + throw new Error('Domain disabled'); + } +} + +async function checkStrategy(entry, strategies, environment) { + if (strategies) { + for (const strategy of strategies) { + if (!strategy.activated[environment]) { + continue; + } + + await checkStrategyInput(entry, strategy); + } + } +} + +async function checkStrategyInput(entry, { strategy, operation, values }) { + if (entry?.length) { + const strategyEntry = entry.filter(e => e.strategy === strategy); + if (strategyEntry.length == 0 || !(await processOperation(strategy, operation, strategyEntry[0].input, values))) { + throw new Error(`Strategy '${strategy}' does not agree`); + } + } else { + throw new Error(`Strategy '${strategy}' did not receive any input`); + } +} + +async function checkRelay(config, environment, entry, response) { + try { + if (config.relay?.activated[environment]) { + isRelayValid(config.relay); + isRelayVerified(config.relay, environment); + + if (config.relay.type === RelayTypes.NOTIFICATION) { + resolveNotification(config.relay, entry, environment); + } else { + const relayResponse = await resolveValidation(config.relay, entry, environment); + + response.result = relayResponse.result; + response.reason = relayResponse.result ? 'Success' : 'Relay does not agree'; + response.message = relayResponse.message; + response.metadata = relayResponse.metadata; + } + } + } catch (e) { + if (config.relay.type === RelayTypes.VALIDATION) { + response.result = false; + response.reason = `Relay service could not be reached: ${e.message}`; + Logger.error(response.reason, e); + } + } +} + +function isMetricDisabled(config, environment) { + if (config.disable_metrics[environment] === undefined) { + return true; + } + + return config.disable_metrics[environment]; +} \ No newline at end of file