diff --git a/registry/lde/oauth-server.ts b/registry/lde/oauth-server.ts new file mode 100644 index 000000000..1ce7354f7 --- /dev/null +++ b/registry/lde/oauth-server.ts @@ -0,0 +1,19 @@ +import { OAuth2Server } from 'oauth2-mock-server'; + +(async function main() { + try { + const server = new OAuth2Server(); + // Generate a new RSA key and add it to the keystore + await server.issuer.keys.generate('RS256'); + + // Start the server + await server.start(8080, 'localhost'); + console.log('Issuer URL:', server.issuer.url); // -> http://localhost:8080 + + server.service.on('beforeTokenSigning', (token, req) => { + token.payload.unique_name = 'root'; + }); + } catch (error) { + console.error(error); + } +})(); diff --git a/registry/package-lock.json b/registry/package-lock.json index 71561d197..4fe768d3a 100644 --- a/registry/package-lock.json +++ b/registry/package-lock.json @@ -15,12 +15,12 @@ "bcrypt": "^5.1.1", "body-parser": "^1.20.2", "config": "^3.3.9", - "connect-session-knex": "^3.0.1", + "connect-session-knex": "^4.0.0", "deep-equal": "^2.2.2", "dotenv-cli": "^7.3.0", "escape-html": "^1.0.3", "express": "^4.18.2", - "express-session": "^1.17.3", + "express-session": "^1.18.0", "http-shutdown": "^1.2.2", "ilc-plugins-sdk": "^2.1.0", "is-valid-domain": "0.1.6", @@ -31,7 +31,7 @@ "newrelic": "^11.1.0", "node-html-parser": "^6.1.10", "openid-client": "^5.6.0", - "passport": "^0.6.0", + "passport": "^0.7.0", "passport-http-bearer": "^1.0.1", "passport-local": "^1.0.0", "pg": "^8.11.3", @@ -53,29 +53,31 @@ "@types/express-serve-static-core": "4.17.37", "@types/express-session": "^1.17.8", "@types/is-valid-domain": "0.0.2", + "@types/jsonwebtoken": "^9.0.6", "@types/lodash": "^4.14.199", "@types/mocha": "^10.0.2", "@types/newrelic": "^9.14.1", - "@types/node": "^20.8.3", - "@types/passport": "^1.0.13", - "@types/passport-http-bearer": "^1.0.38", - "@types/passport-local": "^1.0.36", + "@types/node": "^20.12.12", + "@types/passport": "^1.0.16", + "@types/passport-http-bearer": "^1.0.41", + "@types/passport-local": "^1.0.38", "@types/sinon": "^10.0.19", "@types/supertest": "^2.0.14", "@types/url-join": "^4.0.1", "@types/uuid": "^9.0.5", "chai": "4.3.10", "cross-env": "7.0.3", + "jsonwebtoken": "^9.0.2", "mocha": "^10.2.0", "nock": "^13.3.3", "nodemon": "^3.0.1", "nyc": "^15.1.0", - "pino-pretty": "^10.2.3", + "oauth2-mock-server": "^7.1.1", + "pino-pretty": "^11.0.0", "rimraf": "^5.0.5", "sinon": "^16.1.0", "supertest": "6.3.3", - "timekeeper": "^2.3.1", - "ts-node": "^10.9.1", + "ts-node": "^10.9.2", "typescript": "^4.9.5" }, "engines": { @@ -95,566 +97,6 @@ "node": ">=6.0.0" } }, - "node_modules/@aws-crypto/crc32": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", - "dependencies": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/crc32/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/ie11-detection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", - "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", - "dependencies": { - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/sha256-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", - "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", - "dependencies": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/sha256-js": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/sha256-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", - "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", - "dependencies": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/supports-web-crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", - "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", - "dependencies": { - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", - "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/util/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-sdk/client-lambda": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.427.0.tgz", - "integrity": "sha512-hTEOZ6wDVg8b1/hmnfZGw95IQgVxFWgdFc6v647ncuiTVoed6WdQvZdJk+trDb1qD3kZ0DxGgGSOBFaCtXdmPg==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.427.0", - "@aws-sdk/credential-provider-node": "3.427.0", - "@aws-sdk/middleware-host-header": "3.425.0", - "@aws-sdk/middleware-logger": "3.425.0", - "@aws-sdk/middleware-recursion-detection": "3.425.0", - "@aws-sdk/middleware-signing": "3.425.0", - "@aws-sdk/middleware-user-agent": "3.427.0", - "@aws-sdk/region-config-resolver": "3.425.0", - "@aws-sdk/types": "3.425.0", - "@aws-sdk/util-endpoints": "3.427.0", - "@aws-sdk/util-user-agent-browser": "3.425.0", - "@aws-sdk/util-user-agent-node": "3.425.0", - "@smithy/config-resolver": "^2.0.11", - "@smithy/eventstream-serde-browser": "^2.0.10", - "@smithy/eventstream-serde-config-resolver": "^2.0.10", - "@smithy/eventstream-serde-node": "^2.0.10", - "@smithy/fetch-http-handler": "^2.2.1", - "@smithy/hash-node": "^2.0.10", - "@smithy/invalid-dependency": "^2.0.10", - "@smithy/middleware-content-length": "^2.0.12", - "@smithy/middleware-endpoint": "^2.0.10", - "@smithy/middleware-retry": "^2.0.13", - "@smithy/middleware-serde": "^2.0.10", - "@smithy/middleware-stack": "^2.0.4", - "@smithy/node-config-provider": "^2.0.13", - "@smithy/node-http-handler": "^2.1.6", - "@smithy/protocol-http": "^3.0.6", - "@smithy/smithy-client": "^2.1.9", - "@smithy/types": "^2.3.4", - "@smithy/url-parser": "^2.0.10", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.13", - "@smithy/util-defaults-mode-node": "^2.0.15", - "@smithy/util-retry": "^2.0.3", - "@smithy/util-stream": "^2.0.14", - "@smithy/util-utf8": "^2.0.0", - "@smithy/util-waiter": "^2.0.10", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.427.0.tgz", - "integrity": "sha512-sFVFEmsQ1rmgYO1SgrOTxE/MTKpeE4hpOkm1WqhLQK7Ij136vXpjCxjH1JYZiHiUzO1wr9t4ex4dlB5J3VS/Xg==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.425.0", - "@aws-sdk/middleware-logger": "3.425.0", - "@aws-sdk/middleware-recursion-detection": "3.425.0", - "@aws-sdk/middleware-user-agent": "3.427.0", - "@aws-sdk/region-config-resolver": "3.425.0", - "@aws-sdk/types": "3.425.0", - "@aws-sdk/util-endpoints": "3.427.0", - "@aws-sdk/util-user-agent-browser": "3.425.0", - "@aws-sdk/util-user-agent-node": "3.425.0", - "@smithy/config-resolver": "^2.0.11", - "@smithy/fetch-http-handler": "^2.2.1", - "@smithy/hash-node": "^2.0.10", - "@smithy/invalid-dependency": "^2.0.10", - "@smithy/middleware-content-length": "^2.0.12", - "@smithy/middleware-endpoint": "^2.0.10", - "@smithy/middleware-retry": "^2.0.13", - "@smithy/middleware-serde": "^2.0.10", - "@smithy/middleware-stack": "^2.0.4", - "@smithy/node-config-provider": "^2.0.13", - "@smithy/node-http-handler": "^2.1.6", - "@smithy/protocol-http": "^3.0.6", - "@smithy/smithy-client": "^2.1.9", - "@smithy/types": "^2.3.4", - "@smithy/url-parser": "^2.0.10", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.13", - "@smithy/util-defaults-mode-node": "^2.0.15", - "@smithy/util-retry": "^2.0.3", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.427.0.tgz", - "integrity": "sha512-le2wLJKILyWuRfPz2HbyaNtu5kEki+ojUkTqCU6FPDRrqUvEkaaCBH9Awo/2AtrCfRkiobop8RuTTj6cAnpiJg==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.427.0", - "@aws-sdk/middleware-host-header": "3.425.0", - "@aws-sdk/middleware-logger": "3.425.0", - "@aws-sdk/middleware-recursion-detection": "3.425.0", - "@aws-sdk/middleware-sdk-sts": "3.425.0", - "@aws-sdk/middleware-signing": "3.425.0", - "@aws-sdk/middleware-user-agent": "3.427.0", - "@aws-sdk/region-config-resolver": "3.425.0", - "@aws-sdk/types": "3.425.0", - "@aws-sdk/util-endpoints": "3.427.0", - "@aws-sdk/util-user-agent-browser": "3.425.0", - "@aws-sdk/util-user-agent-node": "3.425.0", - "@smithy/config-resolver": "^2.0.11", - "@smithy/fetch-http-handler": "^2.2.1", - "@smithy/hash-node": "^2.0.10", - "@smithy/invalid-dependency": "^2.0.10", - "@smithy/middleware-content-length": "^2.0.12", - "@smithy/middleware-endpoint": "^2.0.10", - "@smithy/middleware-retry": "^2.0.13", - "@smithy/middleware-serde": "^2.0.10", - "@smithy/middleware-stack": "^2.0.4", - "@smithy/node-config-provider": "^2.0.13", - "@smithy/node-http-handler": "^2.1.6", - "@smithy/protocol-http": "^3.0.6", - "@smithy/smithy-client": "^2.1.9", - "@smithy/types": "^2.3.4", - "@smithy/url-parser": "^2.0.10", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.13", - "@smithy/util-defaults-mode-node": "^2.0.15", - "@smithy/util-retry": "^2.0.3", - "@smithy/util-utf8": "^2.0.0", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.425.0.tgz", - "integrity": "sha512-J20etnLvMKXRVi5FK4F8yOCNm2RTaQn5psQTGdDEPWJNGxohcSpzzls8U2KcMyUJ+vItlrThr4qwgpHG3i/N0w==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.427.0.tgz", - "integrity": "sha512-NmH1cO/w98CKMltYec3IrJIIco19wRjATFNiw83c+FGXZ+InJwReqBnruxIOmKTx2KDzd6fwU1HOewS7UjaaaQ==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.425.0", - "@aws-sdk/credential-provider-process": "3.425.0", - "@aws-sdk/credential-provider-sso": "3.427.0", - "@aws-sdk/credential-provider-web-identity": "3.425.0", - "@aws-sdk/types": "3.425.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.427.0.tgz", - "integrity": "sha512-wYYbQ57nKL8OfgRbl8k6uXcdnYml+p3LSSfDUAuUEp1HKlQ8lOXFJ3BdLr5qrk7LhpyppSRnWBmh2c3kWa7ANQ==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.425.0", - "@aws-sdk/credential-provider-ini": "3.427.0", - "@aws-sdk/credential-provider-process": "3.425.0", - "@aws-sdk/credential-provider-sso": "3.427.0", - "@aws-sdk/credential-provider-web-identity": "3.425.0", - "@aws-sdk/types": "3.425.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.425.0.tgz", - "integrity": "sha512-YY6tkLdvtb1Fgofp3b1UWO+5vwS14LJ/smGmuGpSba0V7gFJRdcrJ9bcb9vVgAGuMdjzRJ+bUKlLLtqXkaykEw==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.427.0.tgz", - "integrity": "sha512-c+tXyS/i49erHs4bAp6vKNYeYlyQ0VNMBgoco0LCn1rL0REtHbfhWMnqDLF6c2n3yIWDOTrQu0D73Idnpy16eA==", - "dependencies": { - "@aws-sdk/client-sso": "3.427.0", - "@aws-sdk/token-providers": "3.427.0", - "@aws-sdk/types": "3.425.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.425.0.tgz", - "integrity": "sha512-/0R65TgRzL01JU3SzloivWNwdkbIhr06uY/F5pBHf/DynQqaspKNfdHn6AiozgSVDfwRHFjKBTUy6wvf3QFkuA==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.425.0.tgz", - "integrity": "sha512-E5Gt41LObQ+cr8QnLthwsH3MtVSNXy1AKJMowDr85h0vzqA/FHUkgHyOGntgozzjXT5M0MaSRYxS0xwTR5D4Ew==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/protocol-http": "^3.0.6", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.425.0.tgz", - "integrity": "sha512-INE9XWRXx2f4a/r2vOU0tAmgctVp7nEaEasemNtVBYhqbKLZvr9ndLBSgKGgJ8LIcXAoISipaMuFiqIGkFsm7A==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.425.0.tgz", - "integrity": "sha512-77gnzJ5b91bgD75L/ugpOyerx6lR3oyS4080X1YI58EzdyBMkDrHM4FbMcY2RynETi3lwXCFzLRyZjWXY1mRlw==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/protocol-http": "^3.0.6", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.425.0.tgz", - "integrity": "sha512-JFojrg76oKAoBknnr9EL5N2aJ1mRCtBqXoZYST58GSx8uYdFQ89qS65VNQ8JviBXzsrCNAn4vDhZ5Ch5E6TxGQ==", - "dependencies": { - "@aws-sdk/middleware-signing": "3.425.0", - "@aws-sdk/types": "3.425.0", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.425.0.tgz", - "integrity": "sha512-ZpOfgJHk7ovQ0sSwg3tU4NxFOnz53lJlkJRf7S+wxQALHM0P2MJ6LYBrZaFMVsKiJxNIdZBXD6jclgHg72ZW6Q==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.6", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.3.4", - "@smithy/util-middleware": "^2.0.3", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.427.0.tgz", - "integrity": "sha512-y9HxYsNvnA3KqDl8w1jHeCwz4P9CuBEtu/G+KYffLeAMBsMZmh4SIkFFCO9wE/dyYg6+yo07rYcnnIfy7WA0bw==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@aws-sdk/util-endpoints": "3.427.0", - "@smithy/protocol-http": "^3.0.6", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.425.0.tgz", - "integrity": "sha512-u7uv/iUOapIJdRgRkO3wnpYsUgV6ponsZJQgVg/8L+n+Vo5PQL5gAcIuAOwcYSKQPFaeK+KbmByI4SyOK203Vw==", - "dependencies": { - "@smithy/node-config-provider": "^2.0.13", - "@smithy/types": "^2.3.4", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.3", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.427.0.tgz", - "integrity": "sha512-4E5E+4p8lJ69PBY400dJXF06LUHYx5lkKzBEsYqWWhoZcoftrvi24ltIhUDoGVLkrLcTHZIWSdFAWSos4hXqeg==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.425.0", - "@aws-sdk/middleware-logger": "3.425.0", - "@aws-sdk/middleware-recursion-detection": "3.425.0", - "@aws-sdk/middleware-user-agent": "3.427.0", - "@aws-sdk/types": "3.425.0", - "@aws-sdk/util-endpoints": "3.427.0", - "@aws-sdk/util-user-agent-browser": "3.425.0", - "@aws-sdk/util-user-agent-node": "3.425.0", - "@smithy/config-resolver": "^2.0.11", - "@smithy/fetch-http-handler": "^2.2.1", - "@smithy/hash-node": "^2.0.10", - "@smithy/invalid-dependency": "^2.0.10", - "@smithy/middleware-content-length": "^2.0.12", - "@smithy/middleware-endpoint": "^2.0.10", - "@smithy/middleware-retry": "^2.0.13", - "@smithy/middleware-serde": "^2.0.10", - "@smithy/middleware-stack": "^2.0.4", - "@smithy/node-config-provider": "^2.0.13", - "@smithy/node-http-handler": "^2.1.6", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.6", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/smithy-client": "^2.1.9", - "@smithy/types": "^2.3.4", - "@smithy/url-parser": "^2.0.10", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.13", - "@smithy/util-defaults-mode-node": "^2.0.15", - "@smithy/util-retry": "^2.0.3", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.425.0.tgz", - "integrity": "sha512-6lqbmorwerN4v+J5dqbHPAsjynI0mkEF+blf+69QTaKKGaxBBVaXgqoqul9RXYcK5MMrrYRbQIMd0zYOoy90kA==", - "dependencies": { - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.427.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.427.0.tgz", - "integrity": "sha512-rSyiAIFF/EVvity/+LWUqoTMJ0a25RAc9iqx0WZ4tf1UjuEXRRXxZEb+jEZg1bk+pY84gdLdx9z5E+MSJCZxNQ==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/node-config-provider": "^2.0.13", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", - "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.425.0.tgz", - "integrity": "sha512-22Y9iMtjGcFjGILR6/xdp1qRezlHVLyXtnpEsbuPTiernRCPk6zfAnK/ATH77r02MUjU057tdxVkd5umUBTn9Q==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/types": "^2.3.4", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.425.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.425.0.tgz", - "integrity": "sha512-SIR4F5uQeeVAi8lv4OgRirtdtNi5zeyogTuQgGi9su8F/WP1N6JqxofcwpUY5f8/oJ2UlXr/tx1f09UHfJJzvA==", - "dependencies": { - "@aws-sdk/types": "3.425.0", - "@smithy/node-config-provider": "^2.0.13", - "@smithy/types": "^2.3.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "dependencies": { - "tslib": "^2.3.1" - } - }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -1156,9 +598,9 @@ } }, "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", "engines": { "node": ">=0.1.90" } @@ -1206,21 +648,21 @@ "optional": true }, "node_modules/@grpc/grpc-js": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.5.tgz", - "integrity": "sha512-iouYNlPxRAwZ2XboDT+OfRKHuaKHiqjB5VFYZ0NFrHkbEF+AV3muIUY9olQsp8uxU4VvRCMiRk9ftzFDGb61aw==", + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.6.tgz", + "integrity": "sha512-xP58G7wDQ4TCmN/cMUHh00DS7SRDv/+lC+xFLrTkMIN8h55X5NhZMLYbvy7dSELP15qlI6hPhNCRWVMtZMwqLA==", "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.10", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=12.10.0" } }, "node_modules/@grpc/proto-loader": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", - "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "version": "0.7.12", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.12.tgz", + "integrity": "sha512-DCVwMxqYzpUCiDMl7hQ384FqP4T3DbNpXU8pt681l3UWCip1WUiD5JrkImUwCB9a7f2cq4CUTmi5r/xIMRPY1Q==", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", @@ -1543,6 +985,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", @@ -1582,25 +1033,19 @@ "integrity": "sha512-EQh8nDsV9LPTpa18DARIbIuIDf4d+MybGtDhixTld/5us7smcbGEpHvs8FxxP6bygQhntewDprSK52s4eQxVww==" }, "node_modules/@newrelic/aws-sdk": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@newrelic/aws-sdk/-/aws-sdk-7.0.1.tgz", - "integrity": "sha512-lZF/WT6Qj3BuvU7DGQHgMArROsY8KGjV3nwxaFbtvl3xFlGeg9D/M2quVR6KUIstfBqK7KyUPiBvHOlOqwJ7qw==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@newrelic/aws-sdk/-/aws-sdk-7.4.1.tgz", + "integrity": "sha512-WiNkAtjptvK9E+9ZNRoYLtsEf6bvpK9XuN0LeaBfm38/G93ubcGIyzFV+NiRCVCtCePYna4jXs2/tGSq6Y+NdQ==", "engines": { "node": ">=16.0.0" - }, - "peerDependencies": { - "newrelic": ">=10.0.0" } }, "node_modules/@newrelic/koa": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@newrelic/koa/-/koa-8.0.0.tgz", - "integrity": "sha512-aaqEVLnRk12DzChCGbWthVQR4PxomqeNVVxnBF3txfHCMhDL2rkOjjcu8VYVoLkhVXrNtY0M226sYN/uqzQ+bQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@newrelic/koa/-/koa-9.1.0.tgz", + "integrity": "sha512-huLV/11IZ1CByVlNzU79bUV1p/SHpglFNPT1DJV5NfcfW+czZ0VIWH9gJd8PK1azaZ1Gy2+HV+nZ1mFuoIANnA==", "engines": { "node": ">=16.0.0" - }, - "peerDependencies": { - "newrelic": ">=6.11.0" } }, "node_modules/@newrelic/native-metrics": { @@ -1618,14 +1063,47 @@ "npm": ">=6" } }, + "node_modules/@newrelic/ritm": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@newrelic/ritm/-/ritm-7.2.0.tgz", + "integrity": "sha512-I4iVhm+wlTEDJXQT8EydF/U5vlR9bBHrtBGyvd/D9WCucoMtrPrCNyILQh9bZ+46E8QRE7zh6QEGyQcnc3qNMg==", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@newrelic/ritm/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@newrelic/ritm/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/@newrelic/security-agent": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@newrelic/security-agent/-/security-agent-0.2.1.tgz", - "integrity": "sha512-oFPnBO+BlJap/qC3r80NuiHmedXdjpWnVnzAlNjsSZoAT7qJM/29tip6ZX/Qmp17mZAIiOVJ2MkyQ5OXHXPdLw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@newrelic/security-agent/-/security-agent-1.2.0.tgz", + "integrity": "sha512-Snk++TQmqHKuxPYOH5bEU4GCr5xKYurUZWx3oiuoQUV73pw61qeEMrb/8iuGgAghwpCEC/8n+308efqCIZkiiQ==", "dependencies": { - "@aws-sdk/client-lambda": "^3.363.0", - "axios": "0.21.4", - "check-disk-space": "3.3.1", + "axios": "^1.6.8", + "check-disk-space": "^3.4.0", "content-type": "^1.0.5", "fast-safe-stringify": "^2.1.1", "find-package-json": "^1.2.0", @@ -1642,791 +1120,232 @@ "semver": "^7.5.4", "sync-request": "^6.1.0", "unescape": "^1.0.1", - "unescape-js": "^1.1.4", - "uuid": "^9.0.0", - "ws": "^7.5.9" - } - }, - "node_modules/@newrelic/security-agent/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/@newrelic/superagent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@newrelic/superagent/-/superagent-7.0.0.tgz", - "integrity": "sha512-fNB4NC+pJYYrFZRLcXaTb4Z7XFEfHi7fVQ3O9Qh10m/9CBM2W+Qc/6yyK9M1liRfgUGo5NOILRdjA23SS7720A==", - "engines": { - "node": ">=16.0" - }, - "peerDependencies": { - "newrelic": ">=6.11.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "optional": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "optional": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "optional": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@prisma/prisma-fmt-wasm": { - "version": "4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085", - "resolved": "https://registry.npmjs.org/@prisma/prisma-fmt-wasm/-/prisma-fmt-wasm-4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085.tgz", - "integrity": "sha512-zYz3rFwPB82mVlHGknAPdnSY/a308dhPOblxQLcZgZTDRtDXOE1MgxoRAys+jekwR4/bm3+rZDPs1xsFMsPZig==", - "optional": true - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true - }, - "node_modules/@smithy/abort-controller": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.11.tgz", - "integrity": "sha512-MSzE1qR2JNyb7ot3blIOT3O3H0Jn06iNDEgHRaqZUwBgx5EG+VIx24Y21tlKofzYryIOcWpIohLrIIyocD6LMA==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.14.tgz", - "integrity": "sha512-K1K+FuWQoy8j/G7lAmK85o03O89s2Vvh6kMFmzEmiHUoQCRH1rzbDtMnGNiaMHeSeYJ6y79IyTusdRG+LuWwtg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.1", - "@smithy/types": "^2.3.5", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.16.tgz", - "integrity": "sha512-tKa2xF+69TvGxJT+lnJpGrKxUuAZDLYXFhqnPEgnHz+psTpkpcB4QRjHj63+uj83KaeFJdTfW201eLZeRn6FfA==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.1", - "@smithy/property-provider": "^2.0.12", - "@smithy/types": "^2.3.5", - "@smithy/url-parser": "^2.0.11", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.11.tgz", - "integrity": "sha512-BQCTjxhCYRZIfXapa2LmZSaH8QUBGwMZw7XRN83hrdixbLjIcj+o549zjkedFS07Ve2TlvWUI6BTzP+nv7snBA==", - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.3.5", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.11.tgz", - "integrity": "sha512-p9IK4uvwT6B3pT1VGlODvcVBfPVikjBFHAcKpvvNF+7lAEI+YiC6d0SROPkpjnvCgVBYyGXa3ciqrWnFze6mwQ==", - "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.11", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.11.tgz", - "integrity": "sha512-vN32E8yExo0Z8L7kXhlU9KRURrhqOpPdLxQMp3MwfMThrjiqbr1Sk5srUXc1ed2Ygl/l0TEN9vwNG0bQHg6AjQ==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.11.tgz", - "integrity": "sha512-Gjqbpg7UmD+YzkpgNShNcDNZcUpBWIkvX2XCGptz5PoxJU/UQbuF9eSc93ZlIb7j4aGjtFfqk23HUMW8Hopg2Q==", - "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.11", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-universal": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.11.tgz", - "integrity": "sha512-F8FsxLTbFN4+Esgpo+nNKcEajrgRZJ+pG9c8+MhLM4Odp5ejLHw2GMCXd81cGsgmfcbnzdDEXazPPVzOwj89MQ==", - "dependencies": { - "@smithy/eventstream-codec": "^2.0.11", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.2.tgz", - "integrity": "sha512-K7aRtRuaBjzlk+jWWeyfDTLAmRRvmA4fU8eHUXtjsuEDgi3f356ZE32VD2ssxIH13RCLVZbXMt5h7wHzYiSuVA==", - "dependencies": { - "@smithy/protocol-http": "^3.0.7", - "@smithy/querystring-builder": "^2.0.11", - "@smithy/types": "^2.3.5", - "@smithy/util-base64": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.11.tgz", - "integrity": "sha512-PbleVugN2tbhl1ZoNWVrZ1oTFFas/Hq+s6zGO8B9bv4w/StTriTKA9W+xZJACOj9X7zwfoTLbscM+avCB1KqOQ==", - "dependencies": { - "@smithy/types": "^2.3.5", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.11.tgz", - "integrity": "sha512-zazq99ujxYv/NOf9zh7xXbNgzoVLsqE0wle8P/1zU/XdhPi/0zohTPKWUzIxjGdqb5hkkwfBkNkl5H+LE0mvgw==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", - "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.13.tgz", - "integrity": "sha512-Md2kxWpaec3bXp1oERFPQPBhOXCkGSAF7uc1E+4rkwjgw3/tqAXRtbjbggu67HJdwaif76As8AV6XxbD1HzqTQ==", - "dependencies": { - "@smithy/protocol-http": "^3.0.7", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.11.tgz", - "integrity": "sha512-mCugsvB15up6fqpzUEpMT4CuJmFkEI+KcozA7QMzYguXCaIilyMKsyxgamwmr+o7lo3QdjN0//XLQ9bWFL129g==", - "dependencies": { - "@smithy/middleware-serde": "^2.0.11", - "@smithy/types": "^2.3.5", - "@smithy/url-parser": "^2.0.11", - "@smithy/util-middleware": "^2.0.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.16.tgz", - "integrity": "sha512-Br5+0yoiMS0ugiOAfJxregzMMGIRCbX4PYo1kDHtLgvkA/d++aHbnHB819m5zOIAMPvPE7AThZgcsoK+WOsUTA==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.1", - "@smithy/protocol-http": "^3.0.7", - "@smithy/service-error-classification": "^2.0.4", - "@smithy/types": "^2.3.5", - "@smithy/util-middleware": "^2.0.4", - "@smithy/util-retry": "^2.0.4", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-retry/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.11.tgz", - "integrity": "sha512-NuxnjMyf4zQqhwwdh0OTj5RqpnuT6HcH5Xg5GrPijPcKzc2REXVEVK4Yyk8ckj8ez1XSj/bCmJ+oNjmqB02GWA==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.5.tgz", - "integrity": "sha512-bVQU/rZzBY7CbSxIrDTGZYnBWKtIw+PL/cRc9B7etZk1IKSOe0NvKMJyWllfhfhrTeMF6eleCzOihIQympAvPw==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.1.tgz", - "integrity": "sha512-1lF6s1YWBi1LBu2O30tD3jyTgMtuvk/Z1twzXM4GPYe4dmZix4nNREPJIPOcfFikNU2o0eTYP80+izx5F2jIJA==", - "dependencies": { - "@smithy/property-provider": "^2.0.12", - "@smithy/shared-ini-file-loader": "^2.2.0", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.7.tgz", - "integrity": "sha512-PQIKZXlp3awCDn/xNlCSTFE7aYG/5Tx33M05NfQmWYeB5yV1GZZOSz4dXpwiNJYTXb9jPqjl+ueXXkwtEluFFA==", - "dependencies": { - "@smithy/abort-controller": "^2.0.11", - "@smithy/protocol-http": "^3.0.7", - "@smithy/querystring-builder": "^2.0.11", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.12.tgz", - "integrity": "sha512-Un/OvvuQ1Kg8WYtoMCicfsFFuHb/TKL3pCA6ZIo/WvNTJTR94RtoRnL7mY4XkkUAoFMyf6KjcQJ76y1FX7S5rw==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.7.tgz", - "integrity": "sha512-HnZW8y+r66ntYueCDbLqKwWcMNWW8o3eVpSrHNluwtBJ/EUWfQHRKSiu6vZZtc6PGfPQWgVfucoCE/C3QufMAA==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.11.tgz", - "integrity": "sha512-b4kEbVMxpmfv2VWUITn2otckTi7GlMteZQxi+jlwedoATOGEyrCJPfRcYQJjbCi3fZ2QTfh3PcORvB27+j38Yg==", - "dependencies": { - "@smithy/types": "^2.3.5", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.11.tgz", - "integrity": "sha512-YXe7jhi7s3dQ0Fu9dLoY/gLu6NCyy8tBWJL/v2c9i7/RLpHgKT+uT96/OqZkHizCJ4kr0ZD46tzMjql/o60KLg==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.4.tgz", - "integrity": "sha512-77506l12I5gxTZqBkx3Wb0RqMG81bMYLaVQ+EqIWFwQDJRs5UFeXogKxSKojCmz1wLUziHZQXm03MBzPQiumQw==", - "dependencies": { - "@smithy/types": "^2.3.5" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.0.tgz", - "integrity": "sha512-xFXqs4vAb5BdkzHSRrTapFoaqS4/3m/CGZzdw46fBjYZ0paYuLAoMY60ICCn1FfGirG+PiJ3eWcqJNe4/SkfyA==", - "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.11.tgz", - "integrity": "sha512-EFVU1dT+2s8xi227l1A9O27edT/GNKvyAK6lZnIZ0zhIHq/jSLznvkk15aonGAM1kmhmZBVGpI7Tt0odueZK9A==", - "dependencies": { - "@smithy/eventstream-codec": "^2.0.11", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.3.5", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.4", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.10.tgz", - "integrity": "sha512-2OEmZDiW1Z196QHuQZ5M6cBE8FCSG0H2HADP1G+DY8P3agsvb0YJyfhyKuJbxIQy15tr3eDAK6FOrlbxgKOOew==", - "dependencies": { - "@smithy/middleware-stack": "^2.0.5", - "@smithy/types": "^2.3.5", - "@smithy/util-stream": "^2.0.15", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.3.5.tgz", - "integrity": "sha512-ehyDt8M9hehyxrLQGoA1BGPou8Js1Ocoh5M0ngDhJMqbFmNK5N6Xhr9/ZExWkyIW8XcGkiMPq3ZUEE0ScrhbuQ==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.11.tgz", - "integrity": "sha512-h89yXMCCF+S5k9XIoKltMIWTYj+FcEkU/IIFZ6RtE222fskOTL4Iak6ZRG+ehSvZDt8yKEcxqheTDq7JvvtK3g==", - "dependencies": { - "@smithy/querystring-parser": "^2.0.11", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/util-base64": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", - "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "unescape-js": "^1.1.4", + "uuid": "^9.0.1", + "ws": "^8.14.2" } }, - "node_modules/@smithy/util-body-length-browser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", - "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "node_modules/@newrelic/security-agent/node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dependencies": { - "tslib": "^2.5.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/@smithy/util-body-length-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", - "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", - "dependencies": { - "tslib": "^2.5.0" - }, + "node_modules/@newrelic/superagent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@newrelic/superagent/-/superagent-7.0.1.tgz", + "integrity": "sha512-QZlW0VxHSVOXcMAtlkg+Mth0Nz3vFku8rfzTEmoI/pXcckHXGEYuiVUhhboCTD3xTKVgnZRUp9BWF6SOggGUSw==", "engines": { - "node": ">=14.0.0" + "node": ">=16.0" } }, - "node_modules/@smithy/util-buffer-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", - "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=14.0.0" + "node": ">= 8" } }, - "node_modules/@smithy/util-config-provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", - "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", - "dependencies": { - "tslib": "^2.5.0" - }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "engines": { - "node": ">=14.0.0" + "node": ">= 8" } }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.14.tgz", - "integrity": "sha512-NupG7SWUucm3vJrvlpt9jG1XeoPJphjcivgcUUXhDJbUPy4F04LhlTiAhWSzwlCNcF8OJsMvZ/DWbpYD3pselw==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dependencies": { - "@smithy/property-provider": "^2.0.12", - "@smithy/smithy-client": "^2.1.10", - "@smithy/types": "^2.3.5", - "bowser": "^2.11.0", - "tslib": "^2.5.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">= 10.0.0" + "node": ">= 8" } }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.18.tgz", - "integrity": "sha512-+3jMom/b/Cdp21tDnY4vKu249Al+G/P0HbRbct7/aSZDlROzv1tksaYukon6UUv7uoHn+/McqnsvqZHLlqvQ0g==", + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, "dependencies": { - "@smithy/config-resolver": "^2.0.14", - "@smithy/credential-provider-imds": "^2.0.16", - "@smithy/node-config-provider": "^2.1.1", - "@smithy/property-provider": "^2.0.12", - "@smithy/smithy-client": "^2.1.10", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" } }, - "node_modules/@smithy/util-hex-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", - "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "optional": true, "dependencies": { - "tslib": "^2.5.0" + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=10" } }, - "node_modules/@smithy/util-middleware": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.4.tgz", - "integrity": "sha512-Pbu6P4MBwRcjrLgdTR1O4Y3c0sTZn2JdOiJNcgL7EcIStcQodj+6ZTXtbyU/WTEU3MV2NMA10LxFc3AWHZ3+4A==", + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, "dependencies": { - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, "engines": { - "node": ">=14.0.0" + "node": ">=14" } }, - "node_modules/@smithy/util-retry": { + "node_modules/@prisma/prisma-fmt-wasm": { + "version": "4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085", + "resolved": "https://registry.npmjs.org/@prisma/prisma-fmt-wasm/-/prisma-fmt-wasm-4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085.tgz", + "integrity": "sha512-zYz3rFwPB82mVlHGknAPdnSY/a308dhPOblxQLcZgZTDRtDXOE1MgxoRAys+jekwR4/bm3+rZDPs1xsFMsPZig==", + "optional": true + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.4.tgz", - "integrity": "sha512-b+n1jBBKc77C1E/zfBe1Zo7S9OXGBiGn55N0apfhZHxPUP/fMH5AhFUUcWaJh7NAnah284M5lGkBKuhnr3yK5w==", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "dependencies": { - "@smithy/service-error-classification": "^2.0.4", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 14.0.0" + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" } }, - "node_modules/@smithy/util-stream": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.15.tgz", - "integrity": "sha512-A/hkYJPH2N5MCWYvky4tTpQihpYAEzqnUfxDyG3L/yMndy/2sLvxnyQal9Opuj1e9FiKSTeMyjnU9xxZGs0mRw==", + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", "dependencies": { - "@smithy/fetch-http-handler": "^2.2.2", - "@smithy/node-http-handler": "^2.1.7", - "@smithy/types": "^2.3.5", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@hapi/hoek": "^9.0.0" } }, - "node_modules/@smithy/util-uri-escape": { + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", - "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "type-detect": "4.0.8" } }, - "node_modules/@smithy/util-utf8": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", - "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@smithy/util-waiter": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.11.tgz", - "integrity": "sha512-8SJWUl9O1YhjC77EccgltI3q4XZQp3vp9DGEW6o0OdkUcwqm/H4qOLnMkA2n+NDojuM5Iia2jWoCdbluIiG7TA==", + "node_modules/@sinonjs/samsam": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "dev": true, "dependencies": { - "@smithy/abort-controller": "^2.0.11", - "@smithy/types": "^2.3.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@sinonjs/commons": "^2.0.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" } }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -2612,6 +1531,15 @@ "integrity": "sha512-18CgqfDjh0m+GFfekGz1q3g32XESx7vutfBFnPkIdpDtuvgvOac8lrghRiw3SLI19vNa/XdPKIhL6CQpFMIDug==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", + "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/keygrip": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.3.tgz", @@ -2668,23 +1596,26 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.3.tgz", - "integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==" + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/passport": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.13.tgz", - "integrity": "sha512-XXURryL+EZAWtbQFOHX1eNB+RJwz5XMPPz1xrGpEKr2xUZCXM4NCPkHMtZQ3B2tTSG/1IRaAcTHjczRA4sSFCw==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", + "integrity": "sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/passport-http-bearer": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@types/passport-http-bearer/-/passport-http-bearer-1.0.38.tgz", - "integrity": "sha512-KTtVZIXll6MlDqkke0S0AznKKwxxvCfqrmy9ujLxxkXa7ywjO+BA7VxF0xvgrwH8C2oPsWmIl9dkFO+Y+fYyaA==", + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/@types/passport-http-bearer/-/passport-http-bearer-1.0.41.tgz", + "integrity": "sha512-ecW+9e8C+0id5iz3YZ+uIarsk/vaRPkKSajt1i1Am66t0mC9gDfQDKXZz9fnPOW2xKUufbmCSou4005VM94Feg==", "dev": true, "dependencies": { "@types/express": "*", @@ -2693,9 +1624,9 @@ } }, "node_modules/@types/passport-local": { - "version": "1.0.36", - "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.36.tgz", - "integrity": "sha512-NoL8ynRuzZHw/xUkLOTCscykNYlu6EasXKrGizF0ibMB+vq//big56+jgS2jtd9DZwL7q5fSJZDrZusex72Fjg==", + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", + "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", "dev": true, "dependencies": { "@types/express": "*", @@ -2786,9 +1717,9 @@ } }, "node_modules/@types/triple-beam": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.3.tgz", - "integrity": "sha512-6tOUG+nVHn0cJbVp25JFayS5UE6+xlbcNF9Lo9mU7U0zk3zeUShZied4YEQZjy1JBF043FSkdXw8YkUJuVtB5g==" + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" }, "node_modules/@types/url-join": { "version": "4.0.1", @@ -3110,6 +2041,24 @@ } ] }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "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==", + "dev": true + }, "node_modules/bcrypt": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", @@ -3173,11 +2122,6 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, - "node_modules/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3259,6 +2203,12 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3465,11 +2415,11 @@ } }, "node_modules/check-disk-space": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-3.3.1.tgz", - "integrity": "sha512-iOrT8yCZjSnyNZ43476FE2rnssvgw5hnuwOM0hm8Nj1qa0v4ieUUEbCyxxsEliaoDUb/75yCOL71zkDiDBLbMQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-3.4.0.tgz", + "integrity": "sha512-drVkSqfwA+TvuEhFipiR1OC9boEGZL5RrWvVsOthdcvQNXyCCuKkEiTOTXZ7qxSf/GLwq4GvzfrQD/Wz325hgw==", "engines": { - "node": ">=12" + "node": ">=16" } }, "node_modules/check-error": { @@ -3637,99 +2587,28 @@ } }, "node_modules/config": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/config/-/config-3.3.9.tgz", - "integrity": "sha512-G17nfe+cY7kR0wVpc49NCYvNtelm/pPy8czHoFkAgtV1lkmcp7DHtWCdDu+C9Z7gb2WVqa9Tm3uF9aKaPbCfhg==", - "dependencies": { - "json5": "^2.2.3" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/connect-session-knex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/connect-session-knex/-/connect-session-knex-3.0.1.tgz", - "integrity": "sha512-w+sNn/mdEmAGCfw90hyXlC0QixGvkfzTs9hZpDWLnzdyI3BQqnWUxZshWJlYNeZza45OrTxT+yqe3epNMPbs2Q==", - "dependencies": { - "bluebird": "^3.7.2", - "knex": "^2.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/connect-session-knex/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.9.tgz", + "integrity": "sha512-G17nfe+cY7kR0wVpc49NCYvNtelm/pPy8czHoFkAgtV1lkmcp7DHtWCdDu+C9Z7gb2WVqa9Tm3uF9aKaPbCfhg==", "dependencies": { - "ms": "2.1.2" + "json5": "^2.2.3" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 10.0.0" } }, - "node_modules/connect-session-knex/node_modules/knex": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/knex/-/knex-2.5.1.tgz", - "integrity": "sha512-z78DgGKUr4SE/6cm7ku+jHvFT0X97aERh/f0MUKAKgFnwCYBEW4TFBqtHWFYiJFid7fMrtpZ/gxJthvz5mEByA==", + "node_modules/connect-session-knex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/connect-session-knex/-/connect-session-knex-4.0.0.tgz", + "integrity": "sha512-syZf6ao03b+x42k5iwr76IBnHC6l+0Kr9d88lCTmGWimbW45ns6UYGEKv/ug60DkMrh3Wt8mO3hjhdaZLH1Rbg==", "dependencies": { - "colorette": "2.0.19", - "commander": "^10.0.0", - "debug": "4.3.4", - "escalade": "^3.1.1", - "esm": "^3.2.25", - "get-package-type": "^0.1.0", - "getopts": "2.3.0", - "interpret": "^2.2.0", - "lodash": "^4.17.21", - "pg-connection-string": "2.6.1", - "rechoir": "^0.8.0", - "resolve-from": "^5.0.0", - "tarn": "^3.0.2", - "tildify": "2.0.0" - }, - "bin": { - "knex": "bin/cli.js" + "bluebird": "^3.7.2", + "knex": "3" }, "engines": { - "node": ">=12" - }, - "peerDependenciesMeta": { - "better-sqlite3": { - "optional": true - }, - "mysql": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-native": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } + "node": ">=8" } }, - "node_modules/connect-session-knex/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -3784,6 +2663,19 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -4120,6 +3012,15 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4337,12 +3238,12 @@ } }, "node_modules/express-session": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", - "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", "dependencies": { - "cookie": "0.4.2", - "cookie-signature": "1.0.6", + "cookie": "0.6.0", + "cookie-signature": "1.0.7", "debug": "2.6.9", "depd": "~2.0.0", "on-headers": "~1.0.2", @@ -4355,13 +3256,18 @@ } }, "node_modules/express-session/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, "node_modules/express/node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -4444,27 +3350,6 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, - "node_modules/fast-xml-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", - "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", - "funding": [ - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - }, - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -4562,14 +3447,14 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -4610,7 +3495,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -4984,68 +3868,10 @@ } }, "node_modules/help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "dev": true, - "dependencies": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/help-me/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/help-me/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/help-me/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/help-me/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true }, "node_modules/hexoid": { "version": "1.0.0", @@ -5057,9 +3883,9 @@ } }, "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", "funding": [ { "type": "github", @@ -5300,9 +4126,9 @@ } }, "node_modules/import-in-the-middle": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz", - "integrity": "sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.3.tgz", + "integrity": "sha512-R2I11NRi0lI3jD2+qjqyVlVEahsejw7LDnYEbGb47QEFjczE3bZYsmWheCTQA+LFs2DzOQxR7Pms7naHW1V4bQ==", "dependencies": { "acorn": "^8.8.2", "acorn-import-assertions": "^1.9.0", @@ -5573,6 +4399,15 @@ "node": ">=8" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -5934,9 +4769,9 @@ } }, "node_modules/jose": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.2.tgz", - "integrity": "sha512-IY73F228OXRl9ar3jJagh7Vnuhj/GzBunPiZP13K0lOl7Am9SoWW3kEzq3MCllJMTtZqHTiDXQvoRd4U95aU6A==", + "version": "4.15.5", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz", + "integrity": "sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -6019,12 +4854,61 @@ "node": "*" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dev": true, + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, "node_modules/just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/knex": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/knex/-/knex-3.0.1.tgz", @@ -6133,6 +5017,48 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -6186,16 +5112,19 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/logform": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", - "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", "dependencies": { - "@colors/colors": "1.5.0", + "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" } }, "node_modules/logform/node_modules/ms": { @@ -6637,24 +5566,25 @@ } }, "node_modules/newrelic": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/newrelic/-/newrelic-11.1.0.tgz", - "integrity": "sha512-TMpUUuVOTjVQs9cp6DsSocf9pQYyQ2QHp3cFYOUZyxfJewjvb4J9TG6uZZP9xN+0olDt2oef/d6eZNTAFM3tsw==", + "version": "11.15.0", + "resolved": "https://registry.npmjs.org/newrelic/-/newrelic-11.15.0.tgz", + "integrity": "sha512-sP5zLP/JgaTivDiLfS/kcYpQK7lZQTk6Qqw/9hdAOgtzx/uZdKzxLmNzXk3uS0eVnwQVgKvVr3pGILJUGhGtPA==", "dependencies": { - "@grpc/grpc-js": "^1.8.10", + "@grpc/grpc-js": "^1.9.4", "@grpc/proto-loader": "^0.7.5", - "@newrelic/aws-sdk": "^7.0.0", - "@newrelic/koa": "^8.0.0", - "@newrelic/security-agent": "0.2.1", - "@newrelic/superagent": "^7.0.0", + "@newrelic/aws-sdk": "^7.3.0", + "@newrelic/koa": "^9.1.0", + "@newrelic/ritm": "^7.2.0", + "@newrelic/security-agent": "^1.1.1", + "@newrelic/superagent": "^7.0.1", "@tyriar/fibonacci-heap": "^2.0.7", "concat-stream": "^2.0.0", "https-proxy-agent": "^7.0.1", - "import-in-the-middle": "^1.4.2", + "import-in-the-middle": "^1.6.0", "json-bigint": "^1.0.0", "json-stringify-safe": "^5.0.0", + "module-details-from-path": "^1.0.3", "readable-stream": "^3.6.1", - "require-in-the-middle": "^7.2.0", "semver": "^7.5.2", "winston-transport": "^4.5.0" }, @@ -6672,9 +5602,9 @@ } }, "node_modules/newrelic/node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { "debug": "^4.3.4" }, @@ -6699,9 +5629,9 @@ } }, "node_modules/newrelic/node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -6857,9 +5787,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", - "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", "optional": true, "bin": { "node-gyp-build": "bin.js", @@ -7265,6 +6195,26 @@ "node": ">=6" } }, + "node_modules/oauth2-mock-server": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/oauth2-mock-server/-/oauth2-mock-server-7.1.1.tgz", + "integrity": "sha512-4/PdPZLySsC68IoiO79BKpr5Rv2j2+WgFZskox7bzSlsXqoX8Nm9OWm3IXB0HQ7xJCbzcR4vvvcDe6UnA/UIiw==", + "dev": true, + "dependencies": { + "basic-auth": "^2.0.1", + "cors": "^2.8.5", + "express": "^4.18.2", + "is-plain-object": "^5.0.0", + "jose": "^4.15.4" + }, + "bin": { + "oauth2-mock-server": "dist/oauth2-mock-server.js" + }, + "engines": { + "node": "^18.12 || ^20", + "yarn": "^1.15.2" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7487,9 +6437,9 @@ } }, "node_modules/passport": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", - "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", "dependencies": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -7775,16 +6725,16 @@ } }, "node_modules/pino-pretty": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.2.3.tgz", - "integrity": "sha512-4jfIUc8TC1GPUfDyMSlW1STeORqkoxec71yhxIpLDQapUu8WOuoz2TTCoidrIssyz78LZC69whBMPIKCMbi3cw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.0.0.tgz", + "integrity": "sha512-YFJZqw59mHIY72wBnBs7XhLGG6qpJMa4pEQTRgEPEbjIYbng2LXEZZF1DoyDg9CfejEy8uZCyzpcBXXG0oOCwQ==", "dev": true, "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^3.0.0", "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", + "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", @@ -7800,9 +6750,9 @@ } }, "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, "dependencies": { "abort-controller": "^3.0.0", @@ -8006,9 +6956,9 @@ } }, "node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -8040,6 +6990,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -8254,40 +7209,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/require-in-the-middle/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/require-in-the-middle/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -8337,9 +7258,9 @@ } }, "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" }, "node_modules/rimraf": { "version": "5.0.5", @@ -9038,11 +7959,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" - }, "node_modules/superagent": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", @@ -9291,12 +8207,6 @@ "node": ">=8" } }, - "node_modules/timekeeper": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.3.1.tgz", - "integrity": "sha512-LeQRS7/4JcC0PgdSFnfUiStQEdiuySlCj/5SJ18D+T1n9BoY7PxKFfCwLulpHXoLUFr67HxBddQdEX47lDGx1g==", - "dev": true - }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -9366,9 +8276,9 @@ } }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -9417,11 +8327,6 @@ "node": ">=0.3.1" } }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -9496,6 +8401,11 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unescape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz", @@ -9718,16 +8628,16 @@ } }, "node_modules/winston-transport": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", - "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", "dependencies": { "logform": "^2.3.2", "readable-stream": "^3.6.0", "triple-beam": "^1.3.0" }, "engines": { - "node": ">= 6.4.0" + "node": ">= 12.0.0" } }, "node_modules/winston-transport/node_modules/readable-stream": { @@ -9801,15 +8711,15 @@ } }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/registry/package.json b/registry/package.json index b0e769767..4860b9a1a 100644 --- a/registry/package.json +++ b/registry/package.json @@ -6,7 +6,7 @@ "scripts": { "tsc": "tsc", "compile": "tsc --incremental", - "dev": "nodemon -e ts,json5 --exec \"npx tsc --incremental && dotenv -- npm run start\" ", + "dev": "nodemon -e ts,json5 --exec \"npx tsc --incremental || exit 1 && npm run start | pino-pretty\" ", "build": "npm run compile && cd ./client && npm run build", "start": "dotenv -- node -r source-map-support/register ./build/server/index.js", "start-docker": "npm run migrate && npm start", @@ -38,29 +38,31 @@ "@types/express-serve-static-core": "4.17.37", "@types/express-session": "^1.17.8", "@types/is-valid-domain": "0.0.2", + "@types/jsonwebtoken": "^9.0.6", "@types/lodash": "^4.14.199", "@types/mocha": "^10.0.2", "@types/newrelic": "^9.14.1", - "@types/node": "^20.8.3", - "@types/passport": "^1.0.13", - "@types/passport-http-bearer": "^1.0.38", - "@types/passport-local": "^1.0.36", + "@types/node": "^20.12.12", + "@types/passport": "^1.0.16", + "@types/passport-http-bearer": "^1.0.41", + "@types/passport-local": "^1.0.38", "@types/sinon": "^10.0.19", "@types/supertest": "^2.0.14", "@types/url-join": "^4.0.1", "@types/uuid": "^9.0.5", "chai": "4.3.10", "cross-env": "7.0.3", + "jsonwebtoken": "^9.0.2", "mocha": "^10.2.0", "nock": "^13.3.3", "nodemon": "^3.0.1", "nyc": "^15.1.0", - "pino-pretty": "^10.2.3", + "oauth2-mock-server": "^7.1.1", + "pino-pretty": "^11.0.0", "rimraf": "^5.0.5", "sinon": "^16.1.0", "supertest": "6.3.3", - "timekeeper": "^2.3.1", - "ts-node": "^10.9.1", + "ts-node": "^10.9.2", "typescript": "^4.9.5" }, "dependencies": { @@ -70,12 +72,12 @@ "bcrypt": "^5.1.1", "body-parser": "^1.20.2", "config": "^3.3.9", - "connect-session-knex": "^3.0.1", + "connect-session-knex": "^4.0.0", "deep-equal": "^2.2.2", "dotenv-cli": "^7.3.0", "escape-html": "^1.0.3", "express": "^4.18.2", - "express-session": "^1.17.3", + "express-session": "^1.18.0", "http-shutdown": "^1.2.2", "ilc-plugins-sdk": "^2.1.0", "is-valid-domain": "0.1.6", @@ -86,7 +88,7 @@ "newrelic": "^11.1.0", "node-html-parser": "^6.1.10", "openid-client": "^5.6.0", - "passport": "^0.6.0", + "passport": "^0.7.0", "passport-http-bearer": "^1.0.1", "passport-local": "^1.0.0", "pg": "^8.11.3", diff --git a/registry/server/app.ts b/registry/server/app.ts index ef4bf1c1b..68e1bd90f 100644 --- a/registry/server/app.ts +++ b/registry/server/app.ts @@ -5,7 +5,7 @@ import config from 'config'; import express, { Application, RequestHandler } from 'express'; import serveStatic from 'serve-static'; -import auth from './auth'; +import { useAuth } from './auth'; import errorHandler from './errorHandler'; import { loadPlugins } from './util/pluginManager'; import * as routes from './routes/routes'; @@ -13,6 +13,8 @@ import settingsService from './settings/services/SettingsService'; import pong from './util/ping'; import { contextMiddleware } from './middleware/context'; import { logConnectionString } from './util/db'; +import { getLogger } from './util/logger'; +import { OpenIdService } from './auth/services/OpenIdService'; export default async (withAuth: boolean = true): Promise => { loadPlugins(); @@ -38,9 +40,15 @@ export default async (withAuth: boolean = true): Promise => { let authMw: RequestHandler[] = [(req, res, next) => next()]; if (withAuth) { - authMw = await auth(app, settingsService, { - session: { secret: config.get('auth.sessionSecret') }, - }); + const openIdService = new OpenIdService(settingsService); + authMw = await useAuth( + app, + openIdService, + { + session: { secret: config.get('auth.sessionSecret') }, + }, + getLogger(), + ); } app.use('/api/v1/config', routes.config); diff --git a/registry/server/auth.ts b/registry/server/auth.ts deleted file mode 100644 index 3ae6af952..000000000 --- a/registry/server/auth.ts +++ /dev/null @@ -1,347 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import config from 'config'; -import { Express, RequestHandler } from 'express'; -import session from 'express-session'; -import { Issuer as OIDCIssuer, Strategy as OIDCStrategy, TokenSet } from 'openid-client'; -import passport from 'passport'; -import { Strategy as BearerStrategy } from 'passport-http-bearer'; -import { Strategy as LocalStrategy } from 'passport-local'; -import urljoin from 'url-join'; - -import { AuthRoles } from './authEntities/interfaces'; -import db from './db'; -import { SettingKeys } from './settings/interfaces'; -import { SettingsService } from './settings/services/SettingsService'; -import { getLogger } from './util/logger'; -import { storage } from './middleware/context'; -import { userContextMiddleware } from './middleware/userContext'; - -// https://github.com/gx0r/connect-session-knex/issues/91 -const sessionKnex = require('connect-session-knex'); - -export interface User { - authEntityId: number; - identifier: string; - role: string; -} - -async function registerOpenIdStrategy(settingsService: SettingsService, callerId: string) { - const authDiscoveryUrl = await settingsService.get(SettingKeys.AuthOpenIdDiscoveryUrl, callerId); - if (typeof authDiscoveryUrl === 'undefined') { - getLogger().info( - `Skipping registering oauth strategy due to missing setting ${SettingKeys.AuthOpenIdDiscoveryUrl}`, - ); - return; - } - - const issuer = await OIDCIssuer.discover(authDiscoveryUrl); // => Promise - - const redirectUri = config.get('infra.settings.baseUrl') - ? urljoin(config.get('infra.settings.baseUrl'), '/auth/openid/return') - : urljoin(await settingsService.get(SettingKeys.BaseUrl, callerId), '/auth/openid/return'); - - //console.log('Discovered issuer %s %O', issuer.issuer, issuer.metadata); - const client = new issuer.Client({ - client_id: await settingsService.get(SettingKeys.AuthOpenIdClientId, callerId), - client_secret: await settingsService.get(SettingKeys.AuthOpenIdClientSecret, callerId), - redirect_uris: [redirectUri], - response_types: ['code'], - }); - - passport.use( - 'openid', - new OIDCStrategy( - { - client, - params: { - scope: await settingsService.get(SettingKeys.AuthOpenIdRequestedScopes, callerId), - response_mode: await settingsService.get(SettingKeys.AuthOpenIdResponseMode, callerId), - }, - }, - async function (tokenSet: TokenSet /*, userinfo: UserinfoResponse*/, done: any) { - try { - if (tokenSet.expired()) { - return done(null, false, { - message: 'Expired OpenID token', - }); - } - - const claims = tokenSet.claims(); - const idClaimName = await settingsService.get(SettingKeys.AuthOpenIdIdentifierClaimName, callerId); - const uidClaimName = await settingsService.get( - SettingKeys.AuthOpenIdUniqueIdentifierClaimName, - callerId, - ); - - let identifiers: string[] = claims[idClaimName] as any; - if (!identifiers) { - return done(null, false, { - message: "Can't find user identifier using IdentityClaimName", - }); - } else if (!Array.isArray(identifiers)) { - identifiers = [identifiers]; - } - - let user: User | null = null; - for (let id of identifiers) { - const entity = await getEntityWithCreds('openid', id, null); - if (!entity) { - continue; - } - - user = entity; - - // we may have case when user exists for a few identifiers, so we try find the most permissive role - if (entity.role === AuthRoles.admin) { - break; - } - } - - if (!user) { - return done(null, false, { - message: `Can\'t find presented identifiers "${identifiers.toString()}" in auth entities list`, - }); - } - if (uidClaimName && claims[uidClaimName]) { - user.identifier = claims[uidClaimName] as string; - } - - return done(null, user); - } catch (e) { - return done(e); - } - }, - ), - ); -} - -export default async (app: Express, settingsService: SettingsService, config: any): Promise => { - const SessionKnex = sessionKnex(session); - const sessionConfig = Object.assign( - { - resave: false, - saveUninitialized: false, - cookie: { httpOnly: true, secure: false }, - store: new SessionKnex({ - knex: db, - createTable: false, - tablename: 'sessions', - }), - }, - config.session, - ); - - if (app.get('env') === 'production') { - app.set('trust proxy', 1); // trust first proxy - //sessionConfig.cookie.secure = true; // serve secure cookies - } - - app.use(session(sessionConfig)); - - passport.use( - new LocalStrategy(async function (username, password, done) { - try { - const user = await getEntityWithCreds('local', username, password); - if (!user) { - return done(null, false); - } - - return done(null, user); - } catch (e) { - return done(e); - } - }), - ); - passport.use( - new BearerStrategy(async function (token, done) { - try { - const tokenParts = token.split(':'); - if (tokenParts.length !== 2) { - return done(null, false); - } - - const id = Buffer.from(tokenParts[0], 'base64').toString('utf8'); - const secret = Buffer.from(tokenParts[1], 'base64').toString('utf8'); - - const user = await getEntityWithCreds('bearer', id, secret); - if (!user) { - return done(null, false); - } - - return done(null, user); - } catch (e) { - return done(e); - } - }), - ); - - // This can be used to keep a smaller payload - passport.serializeUser(function (user: Express.User, done) { - done(null, user); - }); - - passport.deserializeUser(function (user: Express.User, done) { - done(null, user); - }); - - // ... - app.use(passport.initialize()); - app.use(passport.session()); - app.use(userContextMiddleware); - - await registerOpenIdStrategy(settingsService, 'auth'); - - // Accept the OpenID identifier and redirect the user to their OpenID - // provider for authentication. When complete, the provider will redirect - // the user back to the application at: - // /auth/openid/return - app.get( - '/auth/openid', - async (req, res, next) => { - if ((await settingsService.get(SettingKeys.AuthOpenIdEnabled)) === false) { - return res.sendStatus(404); - } - if (req.user) { - return res.redirect('/'); - } - - const callerId = 'auth'; - const keysToWatch = [ - SettingKeys.AuthOpenIdClientId, - SettingKeys.AuthOpenIdClientSecret, - SettingKeys.BaseUrl, - SettingKeys.AuthOpenIdResponseMode, - SettingKeys.AuthOpenIdIdentifierClaimName, - SettingKeys.AuthOpenIdUniqueIdentifierClaimName, - SettingKeys.AuthOpenIdRequestedScopes, - ]; - if (await settingsService.hasChanged(callerId, keysToWatch)) { - getLogger().info('Change of the OpenID authentication config detected. Reinitializing auth backend...'); - - await registerOpenIdStrategy(settingsService, callerId); - } - - next(); - }, - passport.authenticate('openid'), - ); - - const openidReturnHandlers: RequestHandler[] = [ - async (req, res, next) => { - if ((await settingsService.get(SettingKeys.AuthOpenIdEnabled)) === true) { - return next(); - } - - res.sendStatus(404); - }, - (req, res, next) => { - passport.authenticate('openid', function (err: any, user: Express.User | false | null, info: any) { - if (err) { - return next(err); - } - if (!user) { - res.status(401); - res.header('Content-type', 'text/html'); - return res.end(`
${info.message}

Go to main page`); - } - - getLogger().info(`User ${user.identifier} authenticated via OpenID`); - req.logIn(user, function (err) { - if (err) { - return next(err); - } - - res.cookie('ilc:userInfo', JSON.stringify(user)); - return res.redirect('/'); - }); - })(req, res, next); - }, - ]; - // The OpenID provider has redirected the user back to the application. - // Finish the authentication process by verifying the assertion. If valid, - // the user will be logged in. Otherwise, authentication has failed. - app.get('/auth/openid/return', openidReturnHandlers); //Regular flow - app.post('/auth/openid/return', openidReturnHandlers); //response_mode: 'form_post' flow - - // Accept passed username/password pair & perform an attempt to authenticate against local DB - app.post('/auth/local', passport.authenticate(['local']), (req, res) => { - res.cookie('ilc:userInfo', JSON.stringify(req.user)); - res.send('ok'); - }); - - app.get('/auth/logout', (req, res, next) => { - req.logout((err) => { - if (err) return next(err); - res.clearCookie('ilc:userInfo'); - - if (req.session) { - req.session.regenerate((err) => { - if (err) { - next(err); - } - res.redirect('/'); - }); - } else { - res.redirect('/'); - } - }); - }); - - app.get('/auth/available-methods', async (req, res) => { - const availableMethods = ['local']; - - if ((await settingsService.get(SettingKeys.AuthOpenIdEnabled)) === true) { - availableMethods.push('openid'); - } - - res.json(availableMethods); - }); - - const rolesMiddleware = (req: any, res: any, next: any) => { - if (req.user.role === AuthRoles.readonly && req.method !== 'GET') { - return res.status(403).send({ - message: `Access denied. "${req.user.identifier}" has "readonly" access.`, - }); - } - - return next(); - }; - - return [ - (req: any, res: any, next: any) => { - if (!req.user) { - return passport.authenticate('bearer', { session: false })(req, res, next); - } - - return next(); - }, - rolesMiddleware, - ]; -}; - -async function getEntityWithCreds(provider: string, identifier: string, secret: string | null): Promise { - const user = await db - .select() - .from('auth_entities') - .first('identifier', 'id', 'role', 'secret') - .where({ - provider, - }) - .andWhereRaw('LOWER(identifier) = LOWER(?)', [identifier]); - if (!user) { - return null; - } - - if (secret !== null && user.secret !== null) { - //Support of the password less auth methods, like OpenID Connect - if (!(await bcrypt.compare(secret, user.secret))) { - return null; - } - } - - return { - authEntityId: user.id, - identifier: user.identifier, - role: user.role, - }; -} diff --git a/registry/server/auth/handlers/availableMethodsHandler.ts b/registry/server/auth/handlers/availableMethodsHandler.ts new file mode 100644 index 000000000..00cb51dbc --- /dev/null +++ b/registry/server/auth/handlers/availableMethodsHandler.ts @@ -0,0 +1,14 @@ +import { type RequestHandler } from 'express'; +import { type OpenIdService } from '../services/OpenIdService'; + +export function availableMethodsHandlerFactory(openIdService: OpenIdService): RequestHandler { + return async function availableMethodsHandler(req, res) { + const availableMethods = ['local']; + + if (await openIdService.isEnabled()) { + availableMethods.push('openid'); + } + + res.json(availableMethods); + }; +} diff --git a/registry/server/auth/handlers/localLoginHandler.ts b/registry/server/auth/handlers/localLoginHandler.ts new file mode 100644 index 000000000..95bddd23e --- /dev/null +++ b/registry/server/auth/handlers/localLoginHandler.ts @@ -0,0 +1,8 @@ +import { RequestHandler } from 'express'; + +export function localLoginHandlerFactory(): RequestHandler { + return function (req, res) { + res.cookie('ilc:userInfo', JSON.stringify(req.user)); + res.sendStatus(200); + }; +} diff --git a/registry/server/auth/handlers/logoutHandler.ts b/registry/server/auth/handlers/logoutHandler.ts new file mode 100644 index 000000000..2575e83ee --- /dev/null +++ b/registry/server/auth/handlers/logoutHandler.ts @@ -0,0 +1,21 @@ +import { type RequestHandler } from 'express'; + +export function logoutHandlerFactory(): RequestHandler { + return function logoutHandler(req, res, next) { + req.logout((err) => { + if (err) return next(err); + res.clearCookie('ilc:userInfo'); + + if (req.session) { + req.session.regenerate((err) => { + if (err) { + next(err); + } + res.redirect('/'); + }); + } else { + res.redirect('/'); + } + }); + }; +} diff --git a/registry/server/auth/handlers/openIdAuthCallbackHandler.ts b/registry/server/auth/handlers/openIdAuthCallbackHandler.ts new file mode 100644 index 000000000..97400edc3 --- /dev/null +++ b/registry/server/auth/handlers/openIdAuthCallbackHandler.ts @@ -0,0 +1,33 @@ +import { type RequestHandler } from 'express'; +import { type Logger } from 'ilc-plugins-sdk'; +import passport from 'passport'; +import { AuthProviders } from '../../authEntities/interfaces'; + +export function openIdAuthCallbackHandlerFactory(logger: Logger): RequestHandler { + return function openIdAuthCallbackHandler(req, res, next) { + passport.authenticate( + AuthProviders.OpenID, + (err: unknown, user: Express.User | false | null, info: { message: string }) => { + if (err) { + return next(err); + } + if (!user) { + logger.warn({ info }, 'Failed to login'); + res.status(401); + res.header('Content-type', 'text/html'); + return res.end(`
${info.message}

Go to main page`); + } + + logger.info(`User ${user.identifier} authenticated via OpenID`); + req.logIn(user, (err) => { + if (err) { + return next(err); + } + + res.cookie('ilc:userInfo', JSON.stringify(user)); + return res.redirect('/'); + }); + }, + )(req, res, next); + }; +} diff --git a/registry/server/auth/index.ts b/registry/server/auth/index.ts new file mode 100644 index 000000000..f1316cbdc --- /dev/null +++ b/registry/server/auth/index.ts @@ -0,0 +1,99 @@ +import sessionKnex from 'connect-session-knex'; +import { Express, RequestHandler } from 'express'; +import session from 'express-session'; +import { Logger } from 'ilc-plugins-sdk'; +import passport from 'passport'; + +import { AuthProviders } from '../authEntities/interfaces'; +import db from '../db'; +import { userContextMiddleware } from '../middleware/userContext'; +import { availableMethodsHandlerFactory } from './handlers/availableMethodsHandler'; +import { localLoginHandlerFactory } from './handlers/localLoginHandler'; +import { logoutHandlerFactory } from './handlers/logoutHandler'; +import { openIdAuthCallbackHandlerFactory } from './handlers/openIdAuthCallbackHandler'; +import { bearerAuthenticationMiddlewareFactory } from './middleware/bearerAuthenticationMiddleware'; +import { initializeOpenIdMiddlewareFactory } from './middleware/initializeOpenIdMiddleware'; +import { rolesMiddlewareFactory } from './middleware/rolesMiddleware'; +import { validateSessionMiddlewareFactory } from './middleware/validateSessionMiddleware'; +import { authService } from './services/AuthService'; +import { OpenIdService } from './services/OpenIdService'; +import { bearerStrategyFactory } from './strategies/bearer'; +import { localStrategyFactory } from './strategies/local'; + +type SetupAuthOptions = { + session?: session.SessionOptions; +}; + +export async function useAuth( + app: Express, + openIdService: OpenIdService, + config: SetupAuthOptions, + logger: Logger, +): Promise { + const SessionKnex = sessionKnex(session); + const sessionConfig = Object.assign( + { + resave: false, + saveUninitialized: false, + cookie: { httpOnly: true, secure: false }, + store: new SessionKnex({ + knex: db, + createtable: false, + tablename: 'sessions', + }), + }, + config.session, + ); + + if (app.get('env') === 'production') { + app.set('trust proxy', 1); // trust first proxy + //sessionConfig.cookie.secure = true; // serve secure cookies + } + + app.use(session(sessionConfig)); + + passport.use(await localStrategyFactory(authService)); + passport.use(await bearerStrategyFactory(authService)); + + // This can be used to keep a smaller payload + passport.serializeUser(function (user, done) { + done(null, user); + }); + + passport.deserializeUser(function (user: Express.User, done) { + done(null, user); + }); + + // ... + app.use(passport.initialize()); + app.use(passport.session()); + app.use(userContextMiddleware); + + // Accept the OpenID identifier and redirect the user to their OpenID + // provider for authentication. When complete, the provider will redirect + // the user back to the application at: + // /auth/openid/return + const initializeOpenIdMiddleware = initializeOpenIdMiddlewareFactory(logger, openIdService, authService); + + app.get('/auth/openid', initializeOpenIdMiddleware, passport.authenticate(AuthProviders.OpenID)); + + const openidReturnHandlers: RequestHandler[] = [ + initializeOpenIdMiddleware, + validateSessionMiddlewareFactory(), + openIdAuthCallbackHandlerFactory(logger), + ]; + // The OpenID provider has redirected the user back to the application. + // Finish the authentication process by verifying the assertion. If valid, + // the user will be logged in. Otherwise, authentication has failed. + app.get('/auth/openid/return', openidReturnHandlers); //Regular flow + app.post('/auth/openid/return', openidReturnHandlers); //response_mode: 'form_post' flow + + // Accept passed username/password pair & perform an attempt to authenticate against local DB + app.post('/auth/local', passport.authenticate(AuthProviders.Local), localLoginHandlerFactory()); + + app.get('/auth/logout', logoutHandlerFactory()); + + app.get('/auth/available-methods', availableMethodsHandlerFactory(openIdService)); + + return [bearerAuthenticationMiddlewareFactory(), rolesMiddlewareFactory()]; +} diff --git a/registry/server/auth/middleware/bearerAuthenticationMiddleware.ts b/registry/server/auth/middleware/bearerAuthenticationMiddleware.ts new file mode 100644 index 000000000..1ad842e6e --- /dev/null +++ b/registry/server/auth/middleware/bearerAuthenticationMiddleware.ts @@ -0,0 +1,12 @@ +import { RequestHandler } from 'express'; +import passport from 'passport'; + +export function bearerAuthenticationMiddlewareFactory(): RequestHandler { + return function bearerAuthenticationMiddleware(req, res, next) { + if (!req.user) { + return passport.authenticate('bearer', { session: false })(req, res, next); + } + + return next(); + }; +} diff --git a/registry/server/auth/middleware/initializeOpenIdMiddleware.ts b/registry/server/auth/middleware/initializeOpenIdMiddleware.ts new file mode 100644 index 000000000..d127918bf --- /dev/null +++ b/registry/server/auth/middleware/initializeOpenIdMiddleware.ts @@ -0,0 +1,32 @@ +import { type RequestHandler } from 'express'; +import { Logger } from 'ilc-plugins-sdk'; +import passport from 'passport'; +import { AuthProviders } from '../../authEntities/interfaces'; +import { SettingsService } from '../../settings/services/SettingsService'; +import { AuthService } from '../services/AuthService'; +import { OpenIdService } from '../services/OpenIdService'; +import { oidcStrategyFactory } from '../strategies/oidc'; + +export function initializeOpenIdMiddlewareFactory( + logger: Logger, + openIdService: OpenIdService, + authService: AuthService, +): RequestHandler { + return async function initializeOpenIdMiddleware(req, res, next) { + if (!(await openIdService.isEnabled())) { + return res.sendStatus(404); + } + + if (req.user) { + return res.redirect('/'); + } + + if (await openIdService.hasConfigurationChanged()) { + logger.info('Change of the OpenID authentication config detected. Reinitializing auth backend...'); + passport.unuse(AuthProviders.OpenID); + passport.use(AuthProviders.OpenID, await oidcStrategyFactory(openIdService, authService, logger)); + } + + next(); + }; +} diff --git a/registry/server/auth/middleware/openIdAuthMiddleware.ts b/registry/server/auth/middleware/openIdAuthMiddleware.ts new file mode 100644 index 000000000..e69de29bb diff --git a/registry/server/auth/middleware/rolesMiddleware.ts b/registry/server/auth/middleware/rolesMiddleware.ts new file mode 100644 index 000000000..25ef0f843 --- /dev/null +++ b/registry/server/auth/middleware/rolesMiddleware.ts @@ -0,0 +1,14 @@ +import { type RequestHandler } from 'express'; +import { AuthRoles } from '../../authEntities/interfaces'; + +export function rolesMiddlewareFactory(): RequestHandler { + return function rolesMiddlewre(req, res, next) { + if (req.user?.role === AuthRoles.readonly && req.method !== 'GET') { + return res.status(403).send({ + message: `Access denied. "${req.user.identifier}" has "readonly" access.`, + }); + } + + return next(); + }; +} diff --git a/registry/server/auth/middleware/validateSessionMiddleware.ts b/registry/server/auth/middleware/validateSessionMiddleware.ts new file mode 100644 index 000000000..70ce15434 --- /dev/null +++ b/registry/server/auth/middleware/validateSessionMiddleware.ts @@ -0,0 +1,10 @@ +import { type RequestHandler } from 'express'; + +export function validateSessionMiddlewareFactory(): RequestHandler { + return function validateSessionMiddleware(req, res, next) { + if (!req.session.oidc) { + return res.sendStatus(401); + } + next(); + }; +} diff --git a/registry/server/auth/services/AuthService.ts b/registry/server/auth/services/AuthService.ts new file mode 100644 index 000000000..61f8b05eb --- /dev/null +++ b/registry/server/auth/services/AuthService.ts @@ -0,0 +1,46 @@ +import * as bcrypt from 'bcrypt'; +import { User } from '../../../typings/User'; +import { AuthProviders } from '../../authEntities/interfaces'; +import db, { type VersionedKnex } from '../../db'; + +export class AuthService { + constructor(private readonly db: VersionedKnex) {} + + public async getAuthEntity( + provider: AuthProviders, + identifier: string, + secret: string | null, + ): Promise { + const user = await this.db + .select() + .from('auth_entities') + .first('identifier', 'id', 'role', 'secret') + .where({ + provider, + }) + .andWhereRaw('LOWER(identifier) = LOWER(?)', [identifier]); + + if (!user) { + return null; + } + + if (user.secret === null && secret !== null) { + return null; + } + + if (user.secret !== null && secret !== null) { + //Support of the password less auth methods, like OpenID Connect + if (!(await bcrypt.compare(secret, user.secret))) { + return null; + } + } + + return { + authEntityId: user.id, + identifier: user.identifier, + role: user.role, + }; + } +} + +export const authService = new AuthService(db); diff --git a/registry/server/auth/services/OpenIdService.ts b/registry/server/auth/services/OpenIdService.ts new file mode 100644 index 000000000..95a334bd4 --- /dev/null +++ b/registry/server/auth/services/OpenIdService.ts @@ -0,0 +1,29 @@ +import { SettingKeys } from '../../settings/interfaces'; +import settingsService, { SettingsService } from '../../settings/services/SettingsService'; + +export class OpenIdService { + private readonly callerId = OpenIdService.name; + + constructor(private readonly settings: SettingsService) {} + + public async isEnabled(): Promise { + return await this.settings.get(SettingKeys.AuthOpenIdEnabled, this.callerId); + } + + public async hasConfigurationChanged(): Promise { + const keysToWatch = [ + SettingKeys.AuthOpenIdClientId, + SettingKeys.AuthOpenIdClientSecret, + SettingKeys.BaseUrl, + SettingKeys.AuthOpenIdResponseMode, + SettingKeys.AuthOpenIdIdentifierClaimName, + SettingKeys.AuthOpenIdUniqueIdentifierClaimName, + SettingKeys.AuthOpenIdRequestedScopes, + ]; + return await this.settings.hasChanged(this.callerId, keysToWatch); + } + + public async getConfigValue(key: SettingKeys): Promise { + return await this.settings.get(key, this.callerId); + } +} diff --git a/registry/server/auth/strategies/bearer.ts b/registry/server/auth/strategies/bearer.ts new file mode 100644 index 000000000..8a8b13ff5 --- /dev/null +++ b/registry/server/auth/strategies/bearer.ts @@ -0,0 +1,27 @@ +import { type Strategy } from 'passport'; +import { Strategy as BearerStrategy } from 'passport-http-bearer'; +import { AuthProviders } from '../../authEntities/interfaces'; +import { type AuthService } from '../services/AuthService'; + +export async function bearerStrategyFactory(authService: AuthService): Promise { + return new BearerStrategy(async function (token, done) { + try { + const tokenParts = token.split(':'); + if (tokenParts.length !== 2) { + return done(null, false); + } + + const id = Buffer.from(tokenParts[0], 'base64').toString('utf8'); + const secret = Buffer.from(tokenParts[1], 'base64').toString('utf8'); + + const user = await authService.getAuthEntity(AuthProviders.Bearer, id, secret); + if (!user) { + return done(null, false); + } + + return done(null, user); + } catch (e) { + return done(e); + } + }); +} diff --git a/registry/server/auth/strategies/local.ts b/registry/server/auth/strategies/local.ts new file mode 100644 index 000000000..bc56eb2b6 --- /dev/null +++ b/registry/server/auth/strategies/local.ts @@ -0,0 +1,19 @@ +import { type Strategy } from 'passport'; +import { Strategy as LocalStrategy } from 'passport-local'; +import { AuthProviders } from '../../authEntities/interfaces'; +import { type AuthService } from '../services/AuthService'; + +export async function localStrategyFactory(authService: AuthService): Promise { + return new LocalStrategy(async function (username, password, done) { + try { + const user = await authService.getAuthEntity(AuthProviders.Local, username, password); + if (!user) { + return done(null, false); + } + + return done(null, user); + } catch (e) { + return done(e); + } + }); +} diff --git a/registry/server/auth/strategies/oidc.ts b/registry/server/auth/strategies/oidc.ts new file mode 100644 index 000000000..1415ffa70 --- /dev/null +++ b/registry/server/auth/strategies/oidc.ts @@ -0,0 +1,123 @@ +import config from 'config'; +import { Logger } from 'ilc-plugins-sdk'; +import { Issuer as OIDCIssuer, Strategy as OIDCStrategy, type TokenSet } from 'openid-client'; +import { type Strategy } from 'passport'; +import urljoin from 'url-join'; +import { User } from '../../../typings/User'; +import { AuthProviders, AuthRoles } from '../../authEntities/interfaces'; +import { SettingKeys } from '../../settings/interfaces'; +import { AuthService } from '../services/AuthService'; +import { OpenIdService } from '../services/OpenIdService'; + +function extractClaims(value: unknown): string[] | null { + if (typeof value === 'string') { + return [value]; + } else if (Array.isArray(value)) { + return value.filter((x) => typeof x === 'string'); + } else { + return null; + } +} + +export async function oidcStrategyFactory( + openIdService: OpenIdService, + authService: AuthService, + logger: Logger, +): Promise { + async function findMostPermissiveUser(identifiers: string[]): Promise { + const userEntities = await Promise.all( + identifiers.map(async (identifier) => { + const entity = await authService.getAuthEntity(AuthProviders.OpenID, identifier, null); + return entity; + }), + ); + + const filteredEntities = userEntities.filter((x): x is User => x !== null); + + const mostPermissiveUser = filteredEntities.reduce((prevUser: User | null, currentUser: User) => { + if (!prevUser) { + return currentUser; + } + if (currentUser.role === AuthRoles.admin) { + return currentUser; + } + return prevUser; + }, null); + + return mostPermissiveUser; + } + + const authDiscoveryUrl = await openIdService.getConfigValue(SettingKeys.AuthOpenIdDiscoveryUrl); + let issuer: OIDCIssuer; + try { + issuer = await OIDCIssuer.discover(authDiscoveryUrl); + } catch (error) { + throw error; + } + + const redirectUri = config.get('infra.settings.baseUrl') + ? urljoin(config.get('infra.settings.baseUrl'), '/auth/openid/return') + : urljoin(await openIdService.getConfigValue(SettingKeys.BaseUrl), '/auth/openid/return'); + + const client = new issuer.Client({ + client_id: await openIdService.getConfigValue(SettingKeys.AuthOpenIdClientId), + client_secret: await openIdService.getConfigValue(SettingKeys.AuthOpenIdClientSecret), + redirect_uris: [redirectUri], + response_types: ['code'], + }); + + return new OIDCStrategy( + { + client, + params: { + scope: await openIdService.getConfigValue(SettingKeys.AuthOpenIdRequestedScopes), + response_mode: await openIdService.getConfigValue(SettingKeys.AuthOpenIdResponseMode), + }, + sessionKey: 'oidc', + }, + async ( + tokenSet: TokenSet, + done: (err: unknown, user?: User | false, options?: { message: string }) => void, + ) => { + try { + if (tokenSet.expired()) { + return done(null, false, { + message: 'Expired OpenID token', + }); + } + + const claims = tokenSet.claims(); + const idClaimName = await openIdService.getConfigValue(SettingKeys.AuthOpenIdIdentifierClaimName); + const uidClaimName = await openIdService.getConfigValue( + SettingKeys.AuthOpenIdUniqueIdentifierClaimName, + ); + + const identifiers = extractClaims(claims[idClaimName]); + if (!identifiers) { + const message = "Can't find user identifier using IdentityClaimName"; + logger.warn({ claims: claims[idClaimName] }, message); + return done(null, false, { message }); + } + + const user = await findMostPermissiveUser(identifiers); + + if (!user) { + return done(null, false, { + message: `Can\'t find presented identifiers "${identifiers.toString()}" in auth entities list`, + }); + } + + if (uidClaimName) { + const claim = claims[uidClaimName]; + if (typeof claim === 'string') { + user.identifier = claim; + } + } + + return done(null, user); + } catch (e) { + return done(e); + } + }, + ); +} diff --git a/registry/server/authEntities/interfaces.ts b/registry/server/authEntities/interfaces.ts index 369e7eab9..cc4b42d68 100644 --- a/registry/server/authEntities/interfaces.ts +++ b/registry/server/authEntities/interfaces.ts @@ -13,7 +13,7 @@ export enum AuthRoles { } const AuthRolesVals = Object.values(AuthRoles); -export default interface AuthEntity { +export interface AuthEntity { id: number | null; identifier: string; secret?: string | null; @@ -21,6 +21,8 @@ export default interface AuthEntity { role: AuthRoles; } +export default AuthEntity; // TODO remove + const commonSchema = { identifier: Joi.string().min(1).max(255), secret: Joi.string(), diff --git a/registry/server/middleware/context.ts b/registry/server/middleware/context.ts index 8fa969211..e45ebdd77 100644 --- a/registry/server/middleware/context.ts +++ b/registry/server/middleware/context.ts @@ -2,7 +2,7 @@ import { Request, RequestHandler } from 'express'; import { AsyncLocalStorage } from 'node:async_hooks'; import { v4 } from 'uuid'; -import { User } from '../auth'; +import { User } from '../../typings/User'; import { getPluginManagerInstance } from '../util/pluginManager'; import { TypedMap } from '../util/TypedMap'; diff --git a/registry/server/migrations/20200409190157_auth_entitites_default.ts b/registry/server/migrations/20200409190157_auth_entitites_default.ts index 9f9d4366c..dcfc986e1 100644 --- a/registry/server/migrations/20200409190157_auth_entitites_default.ts +++ b/registry/server/migrations/20200409190157_auth_entitites_default.ts @@ -9,6 +9,11 @@ export async function up(knex: Knex): Promise { provider: 'local', role: 'admin', }, + { + identifier: 'root', + provider: 'openid', + role: 'admin', + }, { identifier: 'root_api_token', secret: await bcrypt.hash('token_secret', await bcrypt.genSalt()), diff --git a/registry/server/migrations/20201013140633_settings_default.ts b/registry/server/migrations/20201013140633_settings_default.ts index 67ffd6728..84a1765c0 100644 --- a/registry/server/migrations/20201013140633_settings_default.ts +++ b/registry/server/migrations/20201013140633_settings_default.ts @@ -50,7 +50,7 @@ export async function up(knex: Knex): Promise { }, { key: SettingKeys.AuthOpenIdDiscoveryUrl, - value: '', + value: 'http://localhost:8080', default: '', scope: Scope.Registry, secret: false, @@ -60,7 +60,7 @@ export async function up(knex: Knex): Promise { }, { key: SettingKeys.AuthOpenIdClientId, - value: '', + value: 'ilc_registry', default: '', scope: Scope.Registry, secret: false, diff --git a/registry/server/settings/routes/updateSetting.ts b/registry/server/settings/routes/updateSetting.ts index 64b4658ef..dc2b8997a 100644 --- a/registry/server/settings/routes/updateSetting.ts +++ b/registry/server/settings/routes/updateSetting.ts @@ -6,7 +6,7 @@ import db from '../../db'; import preProcessResponse from '../services/preProcessResponse'; import validateRequestFactory from '../../common/services/validateRequest'; import settingService from '../services/SettingsService'; -import { User } from '../../auth'; +import { User } from '../../../typings/User'; type RequestParams = { key: SettingKeys; diff --git a/registry/server/settings/services/SettingsService.ts b/registry/server/settings/services/SettingsService.ts index 6af1e3b29..9404c360d 100644 --- a/registry/server/settings/services/SettingsService.ts +++ b/registry/server/settings/services/SettingsService.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import db from '../../db'; import { SettingKeys, SettingTypes } from '../interfaces'; -import { User } from '../../auth'; +import { User } from '../../../typings/User'; import { AllowedSettingKeysForDomains } from '../interfaces'; import { SettingRaw, SettingParsed, Setting, Scope } from '../interfaces'; import { safeParseJSON, JSONValue, isNumeric } from '../../common/services/json'; @@ -20,7 +20,7 @@ export class SettingsService { constructor() {} - async get(key: SettingKeys, callerId: string | null = null): Promise { + async get(key: SettingKeys, callerId: string | null = null): Promise { const value = await this.getVal(key); if (callerId) { diff --git a/registry/server/versioning/services/Versioning.ts b/registry/server/versioning/services/Versioning.ts index 7bb2f2d4e..c16415e98 100644 --- a/registry/server/versioning/services/Versioning.ts +++ b/registry/server/versioning/services/Versioning.ts @@ -1,6 +1,6 @@ import versioningConfig from '../config'; import { Knex } from 'knex'; -import { User } from '../../auth'; +import { User } from '../../../typings/User'; import _ from 'lodash'; import * as errors from '../errors'; diff --git a/registry/tests/auth.spec.ts b/registry/tests/auth.spec.ts index d7f5d9087..ad5c1aa0e 100644 --- a/registry/tests/auth.spec.ts +++ b/registry/tests/auth.spec.ts @@ -1,22 +1,22 @@ -import fs from 'fs'; import assert from 'assert'; -import querystring from 'querystring'; -import tk from 'timekeeper'; -import express, { NextFunction, Request, Response } from 'express'; +import * as bcrypt from 'bcrypt'; import bodyParser from 'body-parser'; +import express, { NextFunction, Request, Response, type Express } from 'express'; +import fs from 'fs'; +import nock from 'nock'; +import querystring from 'querystring'; import sinon from 'sinon'; import supertest, { agent as supertestAgent, SuperTest } from 'supertest'; -import settingsService from '../server/settings/services/SettingsService'; - +import { useAuth } from '../server/auth'; +import { OpenIdService } from '../server/auth/services/OpenIdService'; import db from '../server/db'; -import auth from '../server/auth'; import { SettingKeys } from '../server/settings/interfaces'; -import nock from 'nock'; -import * as bcrypt from 'bcrypt'; -import { muteConsole, unmuteConsole } from './utils/console'; +import settingsService from '../server/settings/services/SettingsService'; +import { getLogger } from '../server/util/logger'; import { loadPlugins } from '../server/util/pluginManager'; -import { isSqlite } from '../server/util/db'; -import knex from 'knex'; +import keys from './data/auth/keys'; +import token, { generateIdToken } from './data/auth/token-response'; +import { muteConsole, unmuteConsole } from './utils/console'; const generateResp403 = (username: string) => ({ message: `Access denied. "${username}" has "readonly" access.`, @@ -29,9 +29,14 @@ const getApp = async () => { app.use(bodyParser.json()); app.use( - await auth(app, settingsService, { - session: { secret: 'testSecret' }, - }), + await useAuth( + app, + new OpenIdService(settingsService), + { + session: { secret: 'testSecret' }, + }, + getLogger(), + ), ); app.use('/protected', (req, res) => res.send('ok')); @@ -44,11 +49,6 @@ const getApp = async () => { }; describe('Authentication / Authorization', () => { - // 1 minute before test JWT token expiration - // necessary for JWT signature validation - before(() => tk.travel(new Date(1596125628000))); - after(() => tk.reset()); - afterEach(() => { sinon.restore(); nock.cleanAll(); @@ -222,23 +222,24 @@ describe('Authentication / Authorization', () => { }); describe('OpenID Connect', () => { + let app: Express; let agent: supertest.SuperTest; + let oidcServer: nock.Scope; + let tokenEndpoint: nock.Scope; beforeEach(async () => { - agent = supertestAgent(await getApp()); + app = await getApp(); + agent = supertestAgent(app); }); beforeEach(() => { - const oidcServer = nock('https://ad.example.doesnotmatter.com/'); - //oidcServer.log(console.log); + oidcServer = nock('https://ad.example.doesnotmatter.com/').persist(); oidcServer .get('/adfs/.well-known/openid-configuration') .reply(200, fs.readFileSync(__dirname + '/data/auth/openid-configuration.json')); - oidcServer - .post('/adfs/oauth2/token/') - .reply(200, fs.readFileSync(__dirname + '/data/auth/token-response.json')); - oidcServer.get('/adfs/discovery/keys').reply(200, fs.readFileSync(__dirname + '/data/auth/keys.json')); + tokenEndpoint = oidcServer.post('/adfs/oauth2/token/').reply(200, JSON.stringify(token)); + oidcServer.get('/adfs/discovery/keys').reply(200, JSON.stringify(keys)); }); it('should be possible to turn it off/on in settings', async () => { @@ -286,7 +287,7 @@ describe('Authentication / Authorization', () => { getStub .withArgs(SettingKeys.AuthOpenIdClientId) .returns(Promise.resolve('ba05c345-e144-4688-b0be-3e1097ddd32d')); - getStub.withArgs(SettingKeys.AuthOpenIdClientSecret).returns(Promise.resolve('test')); + getStub.withArgs(SettingKeys.AuthOpenIdClientSecret).returns(Promise.resolve('secret')); getStub.withArgs(SettingKeys.AuthOpenIdIdentifierClaimName).returns(Promise.resolve('email')); }); @@ -315,20 +316,70 @@ describe('Authentication / Authorization', () => { await agent.get('/protected').expect(401); }); + it('should fail if missing claim in response', async () => { + getStub.withArgs(SettingKeys.AuthOpenIdIdentifierClaimName).returns(Promise.resolve('some')); + + const res = await agent + .get('/auth/openid') + .expect(302) + .expect( + 'Location', + new RegExp( + 'https://ad\\.example\\.doesnotmatter\\.com/adfs/oauth2/authorize/\\?client_id=ba05c345-e144-4688-b0be-3e1097ddd32d&scope=openid&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A4000%2Fauth%2Fopenid%2Freturn&state=.+?$', + ), + ); + + await agent + .get(`/auth/openid/return?${getQueryOfCodeAndSessionState(res.header['location'])}`) + .expect(401) + .expect( + `
Can't find user identifier using IdentityClaimName

Go to main page`, + ); + + await agent.get('/protected').expect(401); + }); + + it('should fail if call reply without session', async () => { + const res = await agent + .get('/auth/openid') + .expect(302) + .expect( + 'Location', + new RegExp( + 'https://ad\\.example\\.doesnotmatter\\.com/adfs/oauth2/authorize/\\?client_id=ba05c345-e144-4688-b0be-3e1097ddd32d&scope=openid&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A4000%2Fauth%2Fopenid%2Freturn&state=.+?$', + ), + ); + + agent = supertestAgent(app); + + await agent + .get(`/auth/openid/return?${getQueryOfCodeAndSessionState(res.header['location'])}`) + .expect(401) + .expect('Unauthorized'); + + await agent.get('/protected').expect(401); + }); + describe('Create test user & perform authentication', () => { const userIdentifier = 'main-user@namecheap.com'; // Same as in test token + const readonlyIdentifier = 'readonly-user@namecheap.com'; beforeEach(async () => { - await db('auth_entities').where('identifier', userIdentifier).delete(); + await db('auth_entities').whereIn('identifier', [userIdentifier, readonlyIdentifier]).delete(); await db('auth_entities').insert({ identifier: userIdentifier, provider: 'openid', role: 'admin', }); + await db('auth_entities').insert({ + identifier: readonlyIdentifier, + provider: 'openid', + role: 'readonly', + }); }); afterEach(async () => { - await db('auth_entities').where('identifier', userIdentifier).delete(); + await db('auth_entities').whereIn('identifier', [userIdentifier, readonlyIdentifier]).delete(); }); it('should authenticate against OpenID server', async () => { @@ -366,12 +417,20 @@ describe('Authentication / Authorization', () => { await agent.get('/protected').expect(401); }); it('should authenticate against OpenID server (case-insensitive identifier)', async () => { - await db('auth_entities').where('identifier', userIdentifier.toUpperCase()).delete(); - await db('auth_entities').insert({ - identifier: userIdentifier.toUpperCase(), - provider: 'openid', - role: 'admin', - }); + nock.cleanAll(); + oidcServer = nock('https://ad.example.doesnotmatter.com/').persist(); + + oidcServer + .get('/adfs/.well-known/openid-configuration') + .reply(200, fs.readFileSync(__dirname + '/data/auth/openid-configuration.json')); + tokenEndpoint = oidcServer + .post('/adfs/oauth2/token/') + .reply( + 200, + JSON.stringify({ ...token, id_token: generateIdToken(userIdentifier.toUpperCase()) }), + ); + oidcServer.get('/adfs/discovery/keys').reply(200, JSON.stringify(keys)); + const res = await agent .get('/auth/openid') .expect(302) @@ -394,7 +453,7 @@ describe('Authentication / Authorization', () => { const parts: any = querystring.parse(setCookie[0].replace(/\s?;\s?/, '&')); const userInfo = JSON.parse(parts['ilc:userInfo']); - assert.strictEqual(userInfo.identifier, userIdentifier.toUpperCase()); + assert.strictEqual(userInfo.identifier, userIdentifier); assert.strictEqual(userInfo.role, 'admin'); }); @@ -404,7 +463,6 @@ describe('Authentication / Authorization', () => { // correctly logout await agent.get('/auth/logout').expect(302); await agent.get('/protected').expect(401); - await db('auth_entities').where('identifier', userIdentifier.toUpperCase()).delete(); }); it('should authenticate against OpenID server & perform impersonation', async () => { @@ -474,6 +532,31 @@ describe('Authentication / Authorization', () => { await agent.delete('/protected').expect(403, generateResp403(userIdentifier)); }); + + it('in case multiple auth entities provide one with highest privileges', async () => { + nock.cleanAll(); + oidcServer = nock('https://ad.example.doesnotmatter.com/').persist(); + + oidcServer + .get('/adfs/.well-known/openid-configuration') + .reply(200, fs.readFileSync(__dirname + '/data/auth/openid-configuration.json')); + tokenEndpoint = oidcServer.post('/adfs/oauth2/token/').reply( + 200, + JSON.stringify({ + ...token, + id_token: generateIdToken([readonlyIdentifier, userIdentifier, readonlyIdentifier]), + }), + ); + oidcServer.get('/adfs/discovery/keys').reply(200, JSON.stringify(keys)); + + const res = await agent.get('/auth/openid'); + await agent.get(`/auth/openid/return?${getQueryOfCodeAndSessionState(res.header['location'])}`); + + await agent.get('/protected').expect(200, 'ok'); + await agent.post('/protected').expect(200, 'ok'); + await agent.put('/protected').expect(200, 'ok'); + await agent.delete('/protected').expect(200, 'ok'); + }); }); }); }); diff --git a/registry/tests/authEntities.spec.ts b/registry/tests/authEntities.spec.ts index 539c9d8f4..da62a7af4 100644 --- a/registry/tests/authEntities.spec.ts +++ b/registry/tests/authEntities.spec.ts @@ -110,7 +110,7 @@ describe(`Tests ${example.url}`, () => { const expectedRes = _.omit(Object.assign({ id: authEntityId }, example.correct), ['secret']); expect(response.body).to.be.an('array').that.is.not.empty; - expect(response.body).to.have.lengthOf(4); + expect(response.body).to.have.lengthOf(5); expect(response.body[0].versionId).to.match(/^\d+\.[-_0-9a-zA-Z]{32}$/); response.body.forEach((item: any) => { diff --git a/registry/tests/authService.spec.ts b/registry/tests/authService.spec.ts new file mode 100644 index 000000000..8cf6628ff --- /dev/null +++ b/registry/tests/authService.spec.ts @@ -0,0 +1,80 @@ +import bcrypt from 'bcrypt'; +import { expect } from 'chai'; +import { AuthService } from '../server/auth/services/AuthService'; +import { AuthProviders } from '../server/authEntities/interfaces'; +import db from '../server/db'; +import { EntityTypes } from '../server/versioning/interfaces'; + +describe('AuthService', () => { + let authService: AuthService; + + const provider = 'testProvider' as AuthProviders; + + before(() => { + authService = new AuthService(db); + }); + + after(async () => { + await db(EntityTypes.auth_entities).delete().where('provider', provider); + }); + + describe('getAuthEntity', () => { + it('should return null when user not found', async () => { + const user = await authService.getAuthEntity(provider, 'nonexistent', 'secret'); + expect(user).to.be.null; + }); + + it('should return user when found and secret matches', async () => { + const testUser = { + provider: 'testProvider', + identifier: 'existing_user@example.com', + secret: await bcrypt.hash('password', 10), // Hash the password for comparison + }; + const [dbUser] = await db(EntityTypes.auth_entities).insert(testUser).returning('*'); + + const user = await authService.getAuthEntity(provider, 'existing_user@example.com', 'password'); + expect(user).to.deep.equal({ + authEntityId: dbUser.id, + identifier: dbUser.identifier, + role: dbUser.role, + }); + }); + + it('should return null when secret does not match', async () => { + const testUser = { + provider: 'testProvider', + identifier: 'user_with_wrong_secret@example.com', + secret: await bcrypt.hash('password', 10), // Hash the password for comparison + }; + await db(EntityTypes.auth_entities).insert(testUser); + + const user = await authService.getAuthEntity( + provider, + 'user_with_wrong_secret@example.com', + 'wrong_password', + ); + expect(user).to.be.null; + }); + + it('should return user when secret is null in database', async () => { + const testUser = { + provider: 'testProvider', + identifier: 'user_with_null_secret@example.com', + secret: null, + }; + const [dbUser] = await db(EntityTypes.auth_entities).insert(testUser).returning('*'); + + const user = await authService.getAuthEntity(provider, 'user_with_null_secret@example.com', null); + expect(user).to.deep.equal({ + authEntityId: dbUser.id, + identifier: dbUser.identifier, + role: dbUser.role, + }); + }); + + it('should return null when secret is null in database and input secret is not null', async () => { + const user = await authService.getAuthEntity(provider, 'user_with_null_secret@example.com', 'password'); + expect(user).to.be.null; + }); + }); +}); diff --git a/registry/tests/data/auth/keys.json b/registry/tests/data/auth/keys.json deleted file mode 100644 index 0fa91fd1a..000000000 --- a/registry/tests/data/auth/keys.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "keys": [ - { - "kty": "RSA", - "use": "sig", - "alg": "RS256", - "x5t": "zp_FmfS0MCDz20JvaqMwJwA84hmgmXkcL76e01I7wgw", - "kid": "zp_FmfS0MCDz20JvaqMwJwA84hmgmXkcL76e01I7wgw", - "n": "t9hftJAXobhLet9XVc8onIFfoyc5uyxCFIkamTkLTR-1JWnkQGwAEVrlcU092EFncZUHaI9mpMEs50MIVBC69JG5MG6Hs9JqkiPhuBJE1GebuXafDH08SgTEUoBF6Cc2nQogwplpIuMTTgDA08_sP13UMcBkofNDiRYTvsu7whzhOM42hfRlRfTQDinnaEpREKqsUyEyPrudFKkbOm3iwNfLfGaMbsk9ylj8lVCDkd7kmPlv2hBZjEBeap7MNAHs7yhMoT-G6tKH7HL8YVoNtDyo0Q2kuyqgKNRjhsAJUTQQmdTIuCR9cbAxi0acDoMeExYD3ADNjX4CGDv_jwvZwQ", - "e": "AQAB" - } - ] -} diff --git a/registry/tests/data/auth/keys.ts b/registry/tests/data/auth/keys.ts new file mode 100644 index 000000000..f2ffc6a11 --- /dev/null +++ b/registry/tests/data/auth/keys.ts @@ -0,0 +1,13 @@ +import { publicKey } from './rsa'; + +export default { + keys: [ + { + kty: 'RSA', + use: 'sig', + alg: 'RS256', + kid: 'test', + ...publicKey, + }, + ], +}; diff --git a/registry/tests/data/auth/rsa.ts b/registry/tests/data/auth/rsa.ts new file mode 100644 index 000000000..77e3c9029 --- /dev/null +++ b/registry/tests/data/auth/rsa.ts @@ -0,0 +1,17 @@ +import { generateKeyPairSync, createPublicKey } from 'node:crypto'; + +const { privateKey, publicKey: pemPublicKey } = generateKeyPairSync('rsa', { + modulusLength: 2048, + publicKeyEncoding: { + type: 'spki', + format: 'pem', + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'pem', + }, +}); + +const publicKey = createPublicKey(pemPublicKey).export({ format: 'jwk' }); + +export { privateKey, publicKey }; diff --git a/registry/tests/data/auth/token-response.json b/registry/tests/data/auth/token-response.json deleted file mode 100644 index 78ee90b4a..000000000 --- a/registry/tests/data/auth/token-response.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "access_token": "SlAV32hkKG", - "token_type": "Bearer", - "refresh_token": "8xLOxBtZp8", - "expires_in": 3600, - "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6InpwX0ZtZlMwTUNEejIwSnZhcU13SndBODRobWdtWGtjTDc2ZTAxSTd3Z3ciLCJraWQiOiJ6cF9GbWZTME1DRHoyMEp2YXFNd0p3QTg0aG1nbVhrY0w3NmUwMUk3d2d3In0.eyJhdWQiOiJiYTA1YzM0NS1lMTQ0LTQ2ODgtYjBiZS0zZTEwOTdkZGQzMmQiLCJpc3MiOiJodHRwczovL2FkLmV4YW1wbGUuZG9lc25vdG1hdHRlci5jb20vYWRmcyIsImlhdCI6MTU5NjEyMjA4OCwibmJmIjoxNTk2MTIyMDg4LCJleHAiOjE1OTYxMjU2ODgsImF1dGhfdGltZSI6MTU5NjEwNDI4OSwic3ViIjoiZk1QTEdiRGZKYXpzRkI1YkFoMy9JdUdaS2JSUFVwdGFxWHRPMHoxZkJIUT0iLCJ1cG4iOiJtYWluLXVzZXJAbmFtZWNoZWFwLmNvbSIsInB3ZF91cmwiOiJodHRwczovL2FkLmV4YW1wbGUuZG9lc25vdG1hdHRlci5jb20vYWRmcy9wb3J0YWwvdXBkYXRlcGFzc3dvcmQvIiwicHdkX2V4cCI6IjI4Mjg3ODgiLCJzaWQiOiJTLTEtNS0yMS01NTM5NjU0OTEtMjI4ODQ3ODU5Mi0yODg5MzY1NTItMjI3OSIsInVuaXF1ZV9uYW1lIjoiSm9uaCBEb2UiLCJlbWFpbCI6Im1haW4tdXNlckBuYW1lY2hlYXAuY29tIiwicm9sZSI6WyJzb21lIiwidGVzdCJdLCJhcHB0eXBlIjoiQ29uZmlkZW50aWFsIiwiYXBwaWQiOiJiYTA1YzM0NS1lMTQ0LTQ2ODgtYjBiZS0zZTEwOTdkZGQzMmQiLCJhdXRobWV0aG9kIjoidXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmRQcm90ZWN0ZWRUcmFuc3BvcnQiLCJ2ZXIiOiIxLjAiLCJzY3AiOiJhbGxhdGNsYWltcyBlbWFpbCBvcGVuaWQifQ.ZkUp475eBWsPrnyvgbsn8r9nM8oiKwV39UOBboXnxd1Zqu2fwpCVe-DbAsNlKyDvwV6aUEmxyZqZQZR-c6iXDzaAIpkysnbN-gfJ4Jn0cPefdd9d3OAxQfP8RNzk226uHDZUsAUR69BXacxVRbXSUD9pRntGmWbXl1jOim5MVEua9hSfDddAz7z_QGU-WNXhfl1jRnkxIYnvG9gYAm7QZ-Srb7aqiL1S6PzEuvtGjHMVcnre842eaA-nCmdx8cYPHWLcjbHpjXAg8MKDS73kEVLGzxTkEfRhYarcBS8UAa3XbcZjJVlaroj4wvCimGmn7AK4PSgE571UbALQBakvIQ" -} diff --git a/registry/tests/data/auth/token-response.ts b/registry/tests/data/auth/token-response.ts new file mode 100644 index 000000000..3041c0ebf --- /dev/null +++ b/registry/tests/data/auth/token-response.ts @@ -0,0 +1,46 @@ +import { sign } from 'jsonwebtoken'; +import { privateKey } from './rsa'; + +const accessTokenPayload = { + aud: 'microsoft:identityserver:test', + iss: 'https://ad.example.doesnotmatter.com/adfs/services/trust', + apptype: 'Confidential', + appid: 'ilc_registry', + authmethod: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', + auth_time: '2024-05-15T12:47:33.196Z', + ver: '1.0', + scp: 'email openid', +}; + +const idTokenPayload = { + aud: 'ba05c345-e144-4688-b0be-3e1097ddd32d', + iss: 'https://ad.example.doesnotmatter.com/adfs', + auth_time: 1715777253, + sub: 'main-user@namecheap.com', + upn: 'main-user@namecheap.com', + email: 'main-user@namecheap.com', + apptype: 'Confidential', + appid: 'ba05c345-e144-4688-b0be-3e1097ddd32d', + authmethod: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', + ver: '1.0', + scp: 'email openid', +}; + +export function generateJwtToken(payload: object): string { + return sign(payload, privateKey, { algorithm: 'RS256', expiresIn: 3600 }); +} + +export function generateIdToken(email: string | string[]): string { + return generateJwtToken({ ...idTokenPayload, email }); +} + +export default { + access_token: generateJwtToken(accessTokenPayload), + token_type: 'bearer', + expires_in: 3600, + resource: 'ba05c345-e144-4688-b0be-3e1097ddd32d', + refresh_token: '8xLOxBtZp8', + refresh_token_expires_in: 27920, + scope: 'email openid', + id_token: generateJwtToken(idTokenPayload), +}; diff --git a/registry/tests/settings.spec.ts b/registry/tests/settings.spec.ts index 12e984b6c..568f0d0a5 100644 --- a/registry/tests/settings.spec.ts +++ b/registry/tests/settings.spec.ts @@ -119,6 +119,7 @@ describe(url, () => { chai.expect(response.body).to.deep.include({ key: SettingKeys.AuthOpenIdDiscoveryUrl, + value: 'http://localhost:8080', scope: Scope.Registry, secret: false, meta: { @@ -127,6 +128,7 @@ describe(url, () => { }); chai.expect(response.body).to.deep.include({ key: SettingKeys.AuthOpenIdClientId, + value: 'ilc_registry', scope: Scope.Registry, secret: false, meta: { diff --git a/registry/tests/versioning.unit.spec.ts b/registry/tests/versioning.unit.spec.ts index e21019222..d9d543195 100644 --- a/registry/tests/versioning.unit.spec.ts +++ b/registry/tests/versioning.unit.spec.ts @@ -5,7 +5,7 @@ import { expect, dbFactory } from './common'; import { VersionedKnex } from '../server/db'; import { Versioning } from '../server/versioning/services/Versioning'; import versioningConfig from '../server/versioning/config'; -import { User } from '../server/auth'; +import { User } from '../typings/User'; const testUser: User = Object.freeze({ identifier: 'testUser', diff --git a/registry/typings/User.ts b/registry/typings/User.ts new file mode 100644 index 000000000..226b982a9 --- /dev/null +++ b/registry/typings/User.ts @@ -0,0 +1,5 @@ +export interface User { + authEntityId: number; + identifier: string; + role: string; +} diff --git a/registry/typings/index.d.ts b/registry/typings/index.d.ts index c683a4535..8e850921d 100644 --- a/registry/typings/index.d.ts +++ b/registry/typings/index.d.ts @@ -1,4 +1,4 @@ -import type { User as RegistryUser } from '../server/auth'; +import { User as RegistryUser } from './User'; declare global { namespace Express { @@ -6,4 +6,10 @@ declare global { } } +declare module 'express-session' { + interface SessionData { + oidc: object; + } +} + export {}; diff --git a/start_all.js b/start_all.js index e1f96c77e..88195dcf9 100644 --- a/start_all.js +++ b/start_all.js @@ -22,6 +22,11 @@ const commands = [ command: `npm run migrate && npm run seed && npm run ${noWatch ? 'start' : 'dev'}`, name: 'registry', }, + { + cwd: 'registry', + command: 'npx ts-node lde/oauth-server.ts', + name: 'oauth-server', + }, ]; if (!noWatch) { @@ -39,7 +44,7 @@ concurrently(commands, { prefix: 'name', killOthers: ['failure', 'success'], killSignal: 'SIGKILL', - prefixColors: ['auto'] + prefixColors: ['auto'], }).result.then( () => { console.log('concurrently was finished successfully');