diff --git a/backend-mongo/.dockerignore b/backend-mongo/.dockerignore deleted file mode 100644 index b484ea02a..000000000 --- a/backend-mongo/.dockerignore +++ /dev/null @@ -1,11 +0,0 @@ -node_modules -.env -.env.* -.git -.gitignore -Dockerfile -.dockerignore -docker-compose.* -.DS_Store -*.swp -*~ diff --git a/backend-mongo/.eslintignore b/backend-mongo/.eslintignore deleted file mode 100644 index 76d195ba3..000000000 --- a/backend-mongo/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -built \ No newline at end of file diff --git a/backend-mongo/.eslintrc b/backend-mongo/.eslintrc deleted file mode 100644 index 31bcc259b..000000000 --- a/backend-mongo/.eslintrc +++ /dev/null @@ -1,41 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "plugins": [ - "@typescript-eslint", - "unused-imports" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended" - ], - "rules": { - "no-empty-function": "off", - "@typescript-eslint/no-empty-function": "off", - "no-console": 2, - "quotes": [ - "error", - "double", - { - "avoidEscape": true - } - ], - "comma-dangle": [ - "error", - "only-multiline" - ], - "@typescript-eslint/no-unused-vars": "off", - "unused-imports/no-unused-imports": "error", - "@typescript-eslint/no-extra-semi": "off", // added to be able to push - "unused-imports/no-unused-vars": [ - "warn", - { - "vars": "all", - "varsIgnorePattern": "^_", - "args": "after-used", - "argsIgnorePattern": "^_" - } - ], - "sort-imports": 1 - } -} \ No newline at end of file diff --git a/backend-mongo/.prettierrc b/backend-mongo/.prettierrc deleted file mode 100644 index 0b8ef54d2..000000000 --- a/backend-mongo/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "singleQuote": false, - "printWidth": 100, - "trailingComma": "none", - "tabWidth": 2, - "semi": true -} diff --git a/backend-mongo/Dockerfile b/backend-mongo/Dockerfile deleted file mode 100644 index 06448ad91..000000000 --- a/backend-mongo/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -# Build stage -FROM node:16-alpine AS build - -WORKDIR /app - -COPY package*.json ./ -RUN npm ci --only-production - -COPY . . -RUN npm run build - -# Production stage -FROM node:16-alpine - -WORKDIR /app - -ENV npm_config_cache /home/node/.npm - -COPY package*.json ./ -RUN npm ci --only-production && npm cache clean --force - -COPY --from=build /app . - -RUN apk add --no-cache bash curl && curl -1sLf \ - 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \ - && apk add infisical=0.8.1 && apk add --no-cache git - -HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \ - CMD node healthcheck.js - -EXPOSE 4000 - -CMD ["node", "build/index.js"] diff --git a/backend-mongo/environment.d.ts b/backend-mongo/environment.d.ts deleted file mode 100644 index 25f56dcc6..000000000 --- a/backend-mongo/environment.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -export {}; - -declare global { - namespace NodeJS { - interface ProcessEnv { - PORT: string; - ENCRYPTION_KEY: string; - SALT_ROUNDS: string; - JWT_AUTH_LIFETIME: string; - JWT_AUTH_SECRET: string; - JWT_REFRESH_LIFETIME: string; - JWT_REFRESH_SECRET: string; - JWT_SERVICE_SECRET: string; - JWT_SIGNUP_LIFETIME: string; - JWT_SIGNUP_SECRET: string; - MONGO_URL: string; - NODE_ENV: "development" | "staging" | "testing" | "production"; - VERBOSE_ERROR_OUTPUT: string; - LOKI_HOST: string; - CLIENT_ID_HEROKU: string; - CLIENT_ID_VERCEL: string; - CLIENT_ID_NETLIFY: string; - CLIENT_ID_GITHUB: string; - CLIENT_ID_GITLAB: string; - CLIENT_SECRET_HEROKU: string; - CLIENT_SECRET_VERCEL: string; - CLIENT_SECRET_NETLIFY: string; - CLIENT_SECRET_GITHUB: string; - CLIENT_SECRET_GITLAB: string; - CLIENT_SLUG_VERCEL: string; - POSTHOG_HOST: string; - POSTHOG_PROJECT_API_KEY: string; - SENTRY_DSN: string; - SITE_URL: string; - SMTP_HOST: string; - SMTP_SECURE: string; - SMTP_PORT: string; - SMTP_USERNAME: string; - SMTP_PASSWORD: string; - SMTP_FROM_ADDRESS: string; - SMTP_FROM_NAME: string; - TELEMETRY_ENABLED: string; - LICENSE_KEY: string; - } - } -} diff --git a/backend-mongo/healthcheck.js b/backend-mongo/healthcheck.js deleted file mode 100644 index 8cb3dfcaa..000000000 --- a/backend-mongo/healthcheck.js +++ /dev/null @@ -1,24 +0,0 @@ -const http = require('http'); -const PORT = process.env.PORT || 4000; -const options = { - host: 'localhost', - port: PORT, - timeout: 2000, - path: '/healthcheck' -}; - -const healthCheck = http.request(options, (res) => { - console.log(`HEALTHCHECK STATUS: ${res.statusCode}`); - if (res.statusCode == 200) { - process.exit(0); - } else { - process.exit(1); - } -}); - -healthCheck.on('error', function (err) { - console.error(`HEALTH CHECK ERROR: ${err}`); - process.exit(1); -}); - -healthCheck.end(); diff --git a/backend-mongo/img/dashboard.png b/backend-mongo/img/dashboard.png deleted file mode 100644 index 75791f4e9..000000000 Binary files a/backend-mongo/img/dashboard.png and /dev/null differ diff --git a/backend-mongo/jest.config.ts b/backend-mongo/jest.config.ts deleted file mode 100644 index 7c657505b..000000000 --- a/backend-mongo/jest.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -export default { - preset: "ts-jest", - testEnvironment: "node", - collectCoverageFrom: ["src/*.{js,ts}", "!**/node_modules/**"], - modulePaths: ["/src"], - testMatch: ["/tests/**/*.test.ts"], - setupFiles: ["/test-resources/env-vars.js"], - setupFilesAfterEnv: ["/tests/setupTests.ts"], -}; diff --git a/backend-mongo/nodemon.json b/backend-mongo/nodemon.json deleted file mode 100644 index 7ea1ca760..000000000 --- a/backend-mongo/nodemon.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "watch": ["src"], - "ext": ".ts,.js", - "ignore": [], - "exec": "ts-node ./src/index.ts" -} \ No newline at end of file diff --git a/backend-mongo/package-lock.json b/backend-mongo/package-lock.json deleted file mode 100644 index 91bc26205..000000000 --- a/backend-mongo/package-lock.json +++ /dev/null @@ -1,32861 +0,0 @@ -{ - "name": "infisical-api", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "infisical-api", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.319.0", - "@casl/ability": "^6.5.0", - "@casl/mongoose": "^7.2.1", - "@godaddy/terminus": "^4.12.0", - "@node-saml/passport-saml": "^4.0.4", - "@octokit/rest": "^19.0.5", - "@sentry/node": "^7.77.0", - "@sentry/tracing": "^7.48.0", - "@serdnam/pino-cloudwatch-transport": "^1.0.4", - "@types/crypto-js": "^4.1.1", - "@types/libsodium-wrappers": "^0.7.10", - "@ucast/mongo2js": "^1.3.4", - "ajv": "^8.12.0", - "argon2": "^0.30.3", - "aws-sdk": "^2.1364.0", - "axios": "^1.6.0", - "axios-retry": "^3.4.0", - "bcrypt": "^5.1.0", - "bigint-conversion": "^2.4.0", - "cookie-parser": "^1.4.6", - "cors": "^2.8.5", - "crypto-js": "^4.2.0", - "dotenv": "^16.0.1", - "express": "^4.18.1", - "express-async-errors": "^3.1.1", - "express-rate-limit": "^6.7.0", - "express-validator": "^6.14.2", - "handlebars": "^4.7.7", - "helmet": "^5.1.1", - "infisical-node": "^1.2.1", - "ioredis": "^5.3.2", - "jmespath": "^0.16.0", - "js-yaml": "^4.1.0", - "jsonwebtoken": "^9.0.0", - "jsrp": "^0.2.4", - "libsodium-wrappers": "^0.7.10", - "lodash": "^4.17.21", - "mongoose": "^7.4.1", - "mysql2": "^3.6.2", - "nanoid": "^3.3.6", - "node-cache": "^5.1.2", - "nodemailer": "^6.8.0", - "ora": "^5.4.1", - "passport": "^0.6.0", - "passport-github": "^1.1.0", - "passport-gitlab2": "^5.0.0", - "passport-google-oauth20": "^2.0.0", - "pg": "^8.11.3", - "pino": "^8.16.1", - "pino-http": "^8.5.1", - "posthog-node": "^2.6.0", - "probot": "^12.3.3", - "query-string": "^7.1.3", - "rate-limit-mongo": "^2.3.2", - "rimraf": "^3.0.2", - "swagger-ui-express": "^4.6.2", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1", - "typescript": "^4.9.3", - "utility-types": "^3.10.0", - "zod": "^3.22.3" - }, - "devDependencies": { - "@jest/globals": "^29.3.1", - "@posthog/plugin-scaffold": "^1.3.4", - "@swc/core": "^1.3.99", - "@swc/helpers": "^0.5.3", - "@types/bcrypt": "^5.0.0", - "@types/bcryptjs": "^2.4.2", - "@types/bull": "^4.10.0", - "@types/cookie-parser": "^1.4.3", - "@types/cors": "^2.8.12", - "@types/express": "^4.17.14", - "@types/jest": "^29.5.0", - "@types/jmespath": "^0.15.1", - "@types/jsonwebtoken": "^8.5.9", - "@types/lodash": "^4.14.191", - "@types/node": "^18.11.3", - "@types/nodemailer": "^6.4.6", - "@types/passport": "^1.0.12", - "@types/pg": "^8.10.7", - "@types/picomatch": "^2.3.0", - "@types/pino": "^7.0.5", - "@types/supertest": "^2.0.12", - "@types/swagger-jsdoc": "^6.0.1", - "@types/swagger-ui-express": "^4.1.3", - "@typescript-eslint/eslint-plugin": "^5.54.0", - "@typescript-eslint/parser": "^5.40.1", - "cross-env": "^7.0.3", - "eslint": "^8.26.0", - "eslint-plugin-unused-imports": "^2.0.0", - "install": "^0.13.0", - "jest": "^29.3.1", - "jest-junit": "^15.0.0", - "nodemon": "^2.0.19", - "npm": "^8.19.3", - "pino-pretty": "^10.2.3", - "regenerator-runtime": "^0.14.0", - "smee-client": "^1.2.3", - "supertest": "^6.3.3", - "swagger-autogen": "^2.23.5", - "ts-jest": "^29.0.3", - "ts-node": "^10.9.1" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "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-cloudwatch-logs": { - "version": "3.454.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.454.0.tgz", - "integrity": "sha512-anXMEIZvDvqsFAURYmNHaJU8SH85Rqkahkk0TsDiTLc6/J4Qh8xvcem358qTiXzRpPJmZe4m20XKqL0fXsJgIw==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.454.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/credential-provider-node": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/client-sso": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.451.0.tgz", - "integrity": "sha512-KkYSke3Pdv3MfVH/5fT528+MKjMyPKlcLcd4zQb0x6/7Bl7EHrPh1JZYjzPLHelb+UY5X0qN8+cb8iSu1eiwIQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/client-sts": { - "version": "3.454.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.454.0.tgz", - "integrity": "sha512-0fDvr8WeB6IYO8BUCzcivWmahgGl/zDbaYfakzGnt4mrl5ztYaXE875WI6b7+oFcKMRvN+KLvwu5TtyFuNY+GQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/credential-provider-node": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-sdk-sts": "3.451.0", - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-utf8": "^2.0.2", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-env": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.451.0.tgz", - "integrity": "sha512-9dAav7DcRgaF7xCJEQR5ER9ErXxnu/tdnVJ+UPmb1NPeIZdESv1A3lxFDEq1Fs8c4/lzAj9BpshGyJVIZwZDKg==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.451.0.tgz", - "integrity": "sha512-TySt64Ci5/ZbqFw1F9Z0FIGvYx5JSC9e6gqDnizIYd8eMnn8wFRUscRrD7pIHKfrhvVKN5h0GdYovmMO/FMCBw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.451.0", - "@aws-sdk/credential-provider-process": "3.451.0", - "@aws-sdk/credential-provider-sso": "3.451.0", - "@aws-sdk/credential-provider-web-identity": "3.451.0", - "@aws-sdk/types": "3.451.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.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.451.0.tgz", - "integrity": "sha512-AEwM1WPyxUdKrKyUsKyFqqRFGU70e4qlDyrtBxJnSU9NRLZI8tfEZ67bN7fHSxBUBODgDXpMSlSvJiBLh5/3pw==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.451.0", - "@aws-sdk/credential-provider-ini": "3.451.0", - "@aws-sdk/credential-provider-process": "3.451.0", - "@aws-sdk/credential-provider-sso": "3.451.0", - "@aws-sdk/credential-provider-web-identity": "3.451.0", - "@aws-sdk/types": "3.451.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.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-process": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.451.0.tgz", - "integrity": "sha512-HQywSdKeD5PErcLLnZfSyCJO+6T+ZyzF+Lm/QgscSC+CbSUSIPi//s15qhBRVely/3KBV6AywxwNH+5eYgt4lQ==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.451.0.tgz", - "integrity": "sha512-Usm/N51+unOt8ID4HnQzxIjUJDrkAQ1vyTOC0gSEEJ7h64NSSPGD5yhN7il5WcErtRd3EEtT1a8/GTC5TdBctg==", - "dependencies": { - "@aws-sdk/client-sso": "3.451.0", - "@aws-sdk/token-providers": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.451.0.tgz", - "integrity": "sha512-Xtg3Qw65EfDjWNG7o2xD6sEmumPfsy3WDGjk2phEzVg8s7hcZGxf5wYwe6UY7RJvlEKrU0rFA+AMn6Hfj5oOzg==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.451.0.tgz", - "integrity": "sha512-j8a5jAfhWmsK99i2k8oR8zzQgXrsJtgrLxc3js6U+525mcZytoiDndkWTmD5fjJ1byU1U2E5TaPq+QJeDip05Q==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-logger": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.451.0.tgz", - "integrity": "sha512-0kHrYEyVeB2QBfP6TfbI240aRtatLZtcErJbhpiNUb+CQPgEL3crIjgVE8yYiJumZ7f0jyjo8HLPkwD1/2APaw==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.451.0.tgz", - "integrity": "sha512-J6jL6gJ7orjHGM70KDRcCP7so/J2SnkN4vZ9YRLTeeZY6zvBuHDjX8GCIgSqPn/nXFXckZO8XSnA7u6+3TAT0w==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.451.0.tgz", - "integrity": "sha512-UJ6UfVUEgp0KIztxpAeelPXI5MLj9wUtUCqYeIMP7C1ZhoEMNm3G39VLkGN43dNhBf1LqjsV9jkKMZbVfYXuwg==", - "dependencies": { - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-signing": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.451.0.tgz", - "integrity": "sha512-s5ZlcIoLNg1Huj4Qp06iKniE8nJt/Pj1B/fjhWc6cCPCM7XJYUCejCnRh6C5ZJoBEYodjuwZBejPc1Wh3j+znA==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.451.0.tgz", - "integrity": "sha512-8NM/0JiKLNvT9wtAQVl1DFW0cEO7OvZyLSUBLNLTHqyvOZxKaZ8YFk7d8PL6l76LeUKRxq4NMxfZQlUIRe0eSA==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/token-providers": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.451.0.tgz", - "integrity": "sha512-ij1L5iUbn6CwxVOT1PG4NFjsrsKN9c4N1YEM0lkl6DwmaNOscjLKGSNyj9M118vSWsOs1ZDbTwtj++h0O/BWrQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/types": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.451.0.tgz", - "integrity": "sha512-rhK+qeYwCIs+laJfWCcrYEjay2FR/9VABZJ2NRM89jV/fKqGVQR52E5DQqrI+oEIL5JHMhhnr4N4fyECMS35lw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/util-endpoints": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.451.0.tgz", - "integrity": "sha512-giqLGBTnRIcKkDqwU7+GQhKbtJ5Ku35cjGQIfMyOga6pwTBUbaK0xW1Sdd8sBQ1GhApscnChzI9o/R9x0368vw==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/util-endpoints": "^1.0.4", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.451.0.tgz", - "integrity": "sha512-Ws5mG3J0TQifH7OTcMrCTexo7HeSAc3cBgjfhS/ofzPUzVCtsyg0G7I6T7wl7vJJETix2Kst2cpOsxygPgPD9w==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.451.0.tgz", - "integrity": "sha512-TBzm6P+ql4mkGFAjPlO1CI+w3yUT+NulaiALjl/jNX/nnUp6HsJsVxJf4nVFQTG5KRV0iqMypcs7I3KIhH+LmA==", - "dependencies": { - "@aws-sdk/types": "3.451.0", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/abort-controller": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", - "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/config-resolver": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.18.tgz", - "integrity": "sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/credential-provider-imds": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.1.tgz", - "integrity": "sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/property-provider": "^2.0.14", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/eventstream-codec": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.13.tgz", - "integrity": "sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==", - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/fetch-http-handler": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.6.tgz", - "integrity": "sha512-PStY3XO1Ksjwn3wMKye5U6m6zxXpXrXZYqLy/IeCbh3nM9QB3Jgw/B0PUSLUWKdXg4U8qgEu300e3ZoBvZLsDg==", - "dependencies": { - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", - "@smithy/util-base64": "^2.0.1", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/hash-node": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.15.tgz", - "integrity": "sha512-t/qjEJZu/G46A22PAk1k/IiJZT4ncRkG5GOCNWN9HPPy5rCcSZUbh7gwp7CGKgJJ7ATMMg+0Td7i9o1lQTwOfQ==", - "dependencies": { - "@smithy/types": "^2.5.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/invalid-dependency": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.13.tgz", - "integrity": "sha512-XsGYhVhvEikX1Yz0kyIoLssJf2Rs6E0U2w2YuKdT4jSra5A/g8V2oLROC1s56NldbgnpesTYB2z55KCHHbKyjw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/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/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/middleware-content-length": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.15.tgz", - "integrity": "sha512-xH4kRBw01gJgWiU+/mNTrnyFXeozpZHw39gLb3JKGsFDVmSrJZ8/tRqu27tU/ki1gKkxr2wApu+dEYjI3QwV1Q==", - "dependencies": { - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/middleware-endpoint": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.2.0.tgz", - "integrity": "sha512-tddRmaig5URk2106PVMiNX6mc5BnKIKajHHDxb7K0J5MLdcuQluHMGnjkv18iY9s9O0tF+gAcPd/pDXA5L9DZw==", - "dependencies": { - "@smithy/middleware-serde": "^2.0.13", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/middleware-retry": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.20.tgz", - "integrity": "sha512-X2yrF/SHDk2WDd8LflRNS955rlzQ9daz9UWSp15wW8KtzoTXg3bhHM78HbK1cjr48/FWERSJKh9AvRUUGlIawg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/protocol-http": "^3.0.9", - "@smithy/service-error-classification": "^2.0.6", - "@smithy/types": "^2.5.0", - "@smithy/util-middleware": "^2.0.6", - "@smithy/util-retry": "^2.0.6", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/middleware-serde": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.13.tgz", - "integrity": "sha512-tBGbeXw+XsE6pPr4UaXOh+UIcXARZeiA8bKJWxk2IjJcD1icVLhBSUQH9myCIZLNNzJIH36SDjUX8Wqk4xJCJg==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/middleware-stack": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.7.tgz", - "integrity": "sha512-L1KLAAWkXbGx1t2jjCI/mDJ2dDNq+rp4/ifr/HcC6FHngxho5O7A5bQLpKHGlkfATH6fUnOEx0VICEVFA4sUzw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/node-config-provider": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.5.tgz", - "integrity": "sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==", - "dependencies": { - "@smithy/property-provider": "^2.0.14", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/node-http-handler": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.9.tgz", - "integrity": "sha512-+K0q3SlNcocmo9OZj+fz67gY4lwhOCvIJxVbo/xH+hfWObvaxrMTx7JEzzXcluK0thnnLz++K3Qe7Z/8MDUreA==", - "dependencies": { - "@smithy/abort-controller": "^2.0.13", - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/property-provider": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.14.tgz", - "integrity": "sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/protocol-http": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.9.tgz", - "integrity": "sha512-U1wl+FhYu4/BC+rjwh1lg2gcJChQhytiNQSggREgQ9G2FzmoK9sACBZvx7thyWMvRyHQTE22mO2d5UM8gMKDBg==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/querystring-builder": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.13.tgz", - "integrity": "sha512-JhXKwp3JtsFUe96XLHy/nUPEbaXqn6r7xE4sNaH8bxEyytE5q1fwt0ew/Ke6+vIC7gP87HCHgQpJHg1X1jN2Fw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/querystring-parser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.13.tgz", - "integrity": "sha512-TEiT6o8CPZVxJ44Rly/rrsATTQsE+b/nyBVzsYn2sa75xAaZcurNxsFd8z1haoUysONiyex24JMHoJY6iCfLdA==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/service-error-classification": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.6.tgz", - "integrity": "sha512-fCQ36frtYra2fqY2/DV8+3/z2d0VB/1D1hXbjRcM5wkxTToxq6xHbIY/NGGY6v4carskMyG8FHACxgxturJ9Pg==", - "dependencies": { - "@smithy/types": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/shared-ini-file-loader": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.4.tgz", - "integrity": "sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/signature-v4": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.15.tgz", - "integrity": "sha512-SRTEJSEhQYVlBKIIdZ9SZpqW+KFqxqcNnEcBX+8xkDdWx+DItme9VcCDkdN32yTIrICC+irUufnUdV7mmHPjoA==", - "dependencies": { - "@smithy/eventstream-codec": "^2.0.13", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/smithy-client": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.15.tgz", - "integrity": "sha512-rngZcQu7Jvs9UbHihK1EI67RMPuzkc3CJmu4MBgB7D7yBnMGuFR86tq5rqHfL2gAkNnMelBN/8kzQVvZjNKefQ==", - "dependencies": { - "@smithy/middleware-stack": "^2.0.7", - "@smithy/types": "^2.5.0", - "@smithy/util-stream": "^2.0.20", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/url-parser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.13.tgz", - "integrity": "sha512-okWx2P/d9jcTsZWTVNnRMpFOE7fMkzloSFyM53fA7nLKJQObxM2T4JlZ5KitKKuXq7pxon9J6SF2kCwtdflIrA==", - "dependencies": { - "@smithy/querystring-parser": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-base64": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.1.tgz", - "integrity": "sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==", - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/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==", - "dependencies": { - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/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" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/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==", - "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/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" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.19.tgz", - "integrity": "sha512-VHP8xdFR7/orpiABJwgoTB0t8Zhhwpf93gXhNfUBiwAE9O0rvsv7LwpQYjgvbOUDDO8JfIYQB2GYJNkqqGWsXw==", - "dependencies": { - "@smithy/property-provider": "^2.0.14", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.25", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.25.tgz", - "integrity": "sha512-jkmep6/JyWmn2ADw9VULDeGbugR4N/FJCKOt+gYyVswmN1BJOfzF2umaYxQ1HhQDvna3kzm1Dbo1qIfBW4iuHA==", - "dependencies": { - "@smithy/config-resolver": "^2.0.18", - "@smithy/credential-provider-imds": "^2.1.1", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/property-provider": "^2.0.14", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/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==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.6.tgz", - "integrity": "sha512-7W4uuwBvSLgKoLC1x4LfeArCVcbuHdtVaC4g30kKsD1erfICyQ45+tFhhs/dZNeQg+w392fhunCm/+oCcb6BSA==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-retry": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.6.tgz", - "integrity": "sha512-PSO41FofOBmyhPQJwBQJ6mVlaD7Sp9Uff9aBbnfBJ9eqXOE/obrqQjn0PNdkfdvViiPXl49BINfnGcFtSP4kYw==", - "dependencies": { - "@smithy/service-error-classification": "^2.0.6", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-stream": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.20.tgz", - "integrity": "sha512-tT8VASuD8jJu0yjHEMTCPt1o5E3FVzgdsxK6FQLAjXKqVv5V8InCnc0EOsYrijgspbfDqdAJg7r0o2sySfcHVg==", - "dependencies": { - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/types": "^2.5.0", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-uri-escape": { - "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==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-utf8": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.2.tgz", - "integrity": "sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==", - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.388.0.tgz", - "integrity": "sha512-5sCogMJ1utRlwLQiameyOrrcyhueknbsC2YK1G9Y7pgmgUl2zzUo7htQS2luW71SeBHiwkTQa3OZjbmGsotJvg==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.388.0", - "@aws-sdk/credential-provider-node": "3.388.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/client-sso": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.387.0.tgz", - "integrity": "sha512-E7uKSvbA0XMKSN5KLInf52hmMpe9/OKo6N9OPffGXdn3fNEQlvyQq3meUkqG7Is0ldgsQMz5EUBNtNybXzr3tQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/client-sts": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.388.0.tgz", - "integrity": "sha512-y9FAcAYHT8O6T/jqhgsIQUb4gLiSTKD3xtzudDvjmFi8gl0oRIY1npbeckSiK6k07VQugm2s64I0nDnDxtWsBg==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.388.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-sdk-sts": "3.387.0", - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@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/client-cognito-identity/node_modules/@aws-sdk/credential-provider-env": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.387.0.tgz", - "integrity": "sha512-PVqNk7XPIYe5CMYNvELkcALtkl/pIM8/uPtqEtTg+mgnZBeL4fAmgXZiZMahQo1DxP5t/JaK384f6JG+A0qDjA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.388.0.tgz", - "integrity": "sha512-3dg3A8AiZ5vXkSAYyyI3V/AW3Eo6KQJyE/glA+Nr2M0oAjT4z3vHhS3pf2B+hfKGZBTuKKgxusrrhrQABd/Diw==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.388.0.tgz", - "integrity": "sha512-BqWAkIG08gj/wevpesaZhAjALjfUNVjseHQRk+DNUoHIfyibW7Ahf3q/GIPs11dA2o8ECwR9/fo68Sq+sK799A==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-ini": "3.388.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-process": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.387.0.tgz", - "integrity": "sha512-tQScLHmDlqkQN+mqw4s3cxepEUeHYDhFl5eH+J8puvPqWjXMYpCEdY79SAtWs6SZd4CWiZ0VLeYU6xQBZengbQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.388.0.tgz", - "integrity": "sha512-RH02+rntaO0UhnSBr42n+7q8HOztc+Dets/hh6cWovf3Yi9s9ghLgYLN9FXpSosfot3XkmT/HOCa+CphAmGN9A==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/client-sso": "3.387.0", - "@aws-sdk/token-providers": "3.388.0", - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.387.0.tgz", - "integrity": "sha512-6ueMPl+J3KWv6ZaAWF4Z138QCuBVFZRVAgwbtP3BNqWrrs4Q6TPksOQJ79lRDMpv0EUoyVl04B6lldNlhN8RdA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.387.0.tgz", - "integrity": "sha512-EWm9PXSr8dSp7hnRth1U7OfelXQp9dLf1yS1kUL+UhppYDJpjhdP7ql3NI4xJKw8e76sP2FuJYEuzWnJHuWoyQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/middleware-logger": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.387.0.tgz", - "integrity": "sha512-FjAvJr1XyaInT81RxUwgifnbXoFJrRBFc64XeFJgFanGIQCWLYxRrK2HV9eBpao/AycbmuoHgLd/f0sa4hZFoQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.387.0.tgz", - "integrity": "sha512-ZF45T785ru8OwvYZw6awD9Z76OwSMM1eZzj2eY+FDz1cHfkpLjxEiti2iIH1FxbyK7n9ZqDUx29lVlCv238YyQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.387.0.tgz", - "integrity": "sha512-7ZzRKOJ4V/JDQmKz9z+FjZqw59mrMATEMLR6ff0H0JHMX0Uk5IX8TQB058ss+ar14qeJ4UcteYzCqHNI0O1BHw==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/middleware-signing": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.387.0.tgz", - "integrity": "sha512-oJXlE0MES8gxNLo137PPNNiOICQGOaETTvq3kBSJgb/gtEAxQajMIlaNT7s1wsjOAruFHt4975nCXuY4lpx7GQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.387.0.tgz", - "integrity": "sha512-hTfFTwDtp86xS98BKa+RFuLfcvGftxwzrbZeisZV8hdb4ZhvNXjSxnvM3vetW0GUEnY9xHPSGyp2ERRTinPKFQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/token-providers": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.388.0.tgz", - "integrity": "sha512-2lo1gFJl624kfjo/YdU6zW+k6dEwhoqjNkDNbOZEFgS1KDofHe9GX8W4/ReKb0Ggho5/EcjzZ53/1CjkzUq4tA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/types": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.387.0.tgz", - "integrity": "sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/util-endpoints": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.387.0.tgz", - "integrity": "sha512-g7kvuCXehGXHHBw9PkSQdwVyDFmNUZLmfrRmqMyrMDG9QLQrxr4pyWcSaYgTE16yUzhQQOR+QSey+BL6W9/N6g==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.387.0.tgz", - "integrity": "sha512-lpgSVvDqx+JjHZCTYs/yQSS7J71dPlJeAlvxc7bmx5m+vfwKe07HAnIs+929DngS0QbAp/VaXbTiMFsInLkO4Q==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.387.0.tgz", - "integrity": "sha512-r9OVkcWpRYatjLhJacuHFgvO2T5s/Nu5DDbScMrkUD8b4aGIIqsrdZji0vZy9FCjsUFQMM92t9nt4SejrGjChA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/abort-controller": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.2.tgz", - "integrity": "sha512-ln5Cob0mksym62sLr7NiPOSqJ0jKao4qjfcNLDdgINM1lQI12hXrZBlKdPHbXJqpKhKiECDgonMoqCM8bigq4g==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/config-resolver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.2.tgz", - "integrity": "sha512-0kdsqBL6BdmSbdU6YaDkodVBMua5MuQQluC3nocJ7OJ6PnOuM7i2FEQHE46LBadLqT+CimlDSM+6j91uHNL1ng==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/credential-provider-imds": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.2.tgz", - "integrity": "sha512-mbWFYEZ00LBRDk3WvcXViwpdpkJQcfrM3seuKzFxZnF6wIBLMwrcWcsj+OUC/1L+86m8aQY9imXMAaQsAoGxow==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/node-config-provider": "^2.0.2", - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/eventstream-codec": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.2.tgz", - "integrity": "sha512-PQZiKx7fMnNwx4zxcUCm82VjnqK6wV4MEHSmMy3taj5dKfXV782IjRGyaDT+8TsmNqVdZIkve5zLRAzh+7kOhA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/fetch-http-handler": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.2.tgz", - "integrity": "sha512-Wo2m1RaiXNSLF4J3D62LpdSoj/YYb+6tn0H8is1tSrzr7eXAdiYVBc0wIa23N0wT4zmN0iG/yNY6gTCDQ6799A==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/querystring-builder": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/util-base64": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/hash-node": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.2.tgz", - "integrity": "sha512-JKDzZ1YVR7JzOBaJoWy3ToJCE86OQE6D4kOBvvVsu93a3lcF9kv6KYTKBYEWAjwOn/CpK4NH7mKB01OQ8H+aiA==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/invalid-dependency": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.2.tgz", - "integrity": "sha512-inQZQ5gCO3WRWuXpsc1YJ4KBjsvj2qsoU32yTIKznBWTCQe/D5Dp+sSaysqBqxe0VTZ+8nFEHdUMWUX2BxQThw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/middleware-content-length": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.2.tgz", - "integrity": "sha512-FmHlNfuvYgDZE3fIx0G3rD/wLXfAmBYE4mVc/w6d7RllA7TygPzq2pfHL1iCMzWkWTdoAVnt3h4aavAZnhaxEQ==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/middleware-endpoint": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.2.tgz", - "integrity": "sha512-ropE7/c+g22QeluZ+By/B/WvVep0UFreX+IeRMGIO7EbOUPgqtJRXpbJFdG6JKB1uC+CdaJLn4MnZnVBpcyjuA==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/middleware-serde": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/middleware-retry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.2.tgz", - "integrity": "sha512-wtBUXqtZVriiXppYaFkUrybAPhFVX7vebnW/yVPliLMWMcguOMS58qhOYPZe3t9Wki2+mASfyu+kO3An8lAg2A==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/service-error-classification": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-retry": "^2.0.0", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/middleware-serde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.2.tgz", - "integrity": "sha512-Kw9xLdlueIaivUWslKB67WZ/cCUg3QnzYVIA3t5KfgsseEEuU4UxXw8NSTvIt71gqQloY+Um8ugS+idgxrWWnw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/middleware-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", - "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/node-config-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.2.tgz", - "integrity": "sha512-9wVJccASfuCctNWrzR0zrDkf0ox3HCHGEhFlWL2LBoghUYuK28pVRBbG69wvnkhlHnB8dDZHagxH+Nq9dm7eWw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/property-provider": "^2.0.2", - "@smithy/shared-ini-file-loader": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/node-http-handler": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.0.2.tgz", - "integrity": "sha512-lpZjmtmyZqSAtMPsbrLhb7XoAQ2kAHeuLY/csW6I2k+QyFvOk7cZeQsqEngWmZ9SJaeYiDCBINxAIM61i5WGLw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/abort-controller": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/querystring-builder": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/property-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.2.tgz", - "integrity": "sha512-DfaZ8cO+d/mgnMzIllcXcU4OYP+omiOl2LYdn/fTGpw/EAQSVzscYV2muV3sDDnuPYQ/r014hUqIxnF+pzh+SQ==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/protocol-http": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-2.0.2.tgz", - "integrity": "sha512-qWu8g1FUy+m36KpO1sREJSF7BaLmjw9AqOuwxLVVSdYz+nUQjc9tFAZ9LB6jJXKdsZFSjfkjHJBbhD78QdE7Rw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/querystring-builder": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.2.tgz", - "integrity": "sha512-H99LOMWEssfwqkOoTs4Y12UiZ7CTGQSX5Nrx5UkYgRbUEpC1GnnaprHiYrqclC58/xr4K76aNchdPyioxewMzA==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/querystring-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.2.tgz", - "integrity": "sha512-L4VtKQ8O4/aWPQJbiFymbhAmxdfLnEaROh/Vs0OstJ7jtOZeBl2QJmuWY2V7hjt64W7V+tEn2sv6vVvnxkm/xQ==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/service-error-classification": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", - "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", - "optional": true, - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/shared-ini-file-loader": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.2.tgz", - "integrity": "sha512-2VkNOM/82u4vatVdK5nfusgGIlvR48Fkq6me17Oc+V1iyxfR/1x0pG6LzW0br1qlGtzBYFZKmDyviBRcPVFTVw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/signature-v4": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.2.tgz", - "integrity": "sha512-YMooDEw/UmGxcXY4qWnSXkbPFsRloluSvyXVT678YPDN/K2AS1GzKfRsvSU7fbccOB4WF8MHZf2UqcRGEltE3Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/eventstream-codec": "^2.0.2", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/smithy-client": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.0.2.tgz", - "integrity": "sha512-mDfokI8WwLU5C0gcQ4ww/zJI/WLGSh2+vdIA42JRnjfYUjJNH/rKfX9YOnn2eBOxl3loATERVUqkHmKe+P8s2Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/middleware-stack": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-stream": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.1.0.tgz", - "integrity": "sha512-KLsCsqxX0j2l99iP8s0f7LBlcsp7a7ceXGn0LPYPyVOsqmIKvSaPQajq0YevlL4T9Bm+DtcyXfBTbtBcLX1I7A==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/url-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.2.tgz", - "integrity": "sha512-X1mHCzrSVDlhVy7d3S7Vq+dTfYzwh4n7xGHhyJumu77nJqIss0lazVug85Pwo0DKIoO314wAOvMnBxNYDa+7wA==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/querystring-parser": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/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==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-body-length-node": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.0.0.tgz", - "integrity": "sha512-ZV7Z/WHTMxHJe/xL/56qZwSUcl63/5aaPAGjkfynJm4poILjdD4GmFI+V+YWabh2WJIjwTKZ5PNsuvPQKt93Mg==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/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==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.2.tgz", - "integrity": "sha512-c2tMMjb624XLuzmlRoZpnFOkejVxcgw3WQKdmgdGZYZapcLzXyC0H9JhnXMjQCt30GqLTlsILRNVBYwFRbw/4Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.2.tgz", - "integrity": "sha512-gt7m5LLqUtEKldJLyc14DE4kb85vxwomvt9AfEMEvWM4VwfWS1kGJqiStZFb5KNqnQPXw8vvpgLTi8NrWAOXqg==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/config-resolver": "^2.0.2", - "@smithy/credential-provider-imds": "^2.0.2", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-middleware": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", - "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-retry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", - "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/service-error-classification": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-stream": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.2.tgz", - "integrity": "sha512-Mg9IJcKIu4YKlbzvpp1KLvh4JZLdcPgpxk+LICuDwzZCfxe47R9enVK8dNEiuyiIGK2ExbfvzCVT8IBru62vZw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/types": "^2.1.0", - "@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" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-uri-escape": { - "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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity/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==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.370.0.tgz", - "integrity": "sha512-1o1mpWbI1RyzCQ4cVpHQJnm6PziAJ+ptLt4p+wlN74Z330/nnE0JkK3t9l3CxhPqCIW8VjGbTCno5IzwAXnjPw==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.370.0", - "@aws-sdk/credential-provider-node": "3.370.0", - "@aws-sdk/middleware-host-header": "3.370.0", - "@aws-sdk/middleware-logger": "3.370.0", - "@aws-sdk/middleware-recursion-detection": "3.370.0", - "@aws-sdk/middleware-signing": "3.370.0", - "@aws-sdk/middleware-user-agent": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@aws-sdk/util-user-agent-browser": "3.370.0", - "@aws-sdk/util-user-agent-node": "3.370.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.2", - "@smithy/middleware-retry": "^1.0.3", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.370.0.tgz", - "integrity": "sha512-0Ty1iHuzNxMQtN7nahgkZr4Wcu1XvqGfrQniiGdKKif9jG/4elxsQPiydRuQpFqN6b+bg7wPP7crFP1uTxx2KQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.370.0", - "@aws-sdk/middleware-logger": "3.370.0", - "@aws-sdk/middleware-recursion-detection": "3.370.0", - "@aws-sdk/middleware-user-agent": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@aws-sdk/util-user-agent-browser": "3.370.0", - "@aws-sdk/util-user-agent-node": "3.370.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.2", - "@smithy/middleware-retry": "^1.0.3", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.370.0.tgz", - "integrity": "sha512-jAYOO74lmVXylQylqkPrjLzxvUnMKw476JCUTvCO6Q8nv3LzCWd76Ihgv/m9Q4M2Tbqi1iP2roVK5bstsXzEjA==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.370.0", - "@aws-sdk/middleware-logger": "3.370.0", - "@aws-sdk/middleware-recursion-detection": "3.370.0", - "@aws-sdk/middleware-user-agent": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@aws-sdk/util-user-agent-browser": "3.370.0", - "@aws-sdk/util-user-agent-node": "3.370.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.2", - "@smithy/middleware-retry": "^1.0.3", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.370.0.tgz", - "integrity": "sha512-utFxOPWIzbN+3kc415Je2o4J72hOLNhgR2Gt5EnRSggC3yOnkC4GzauxG8n7n5gZGBX45eyubHyPOXLOIyoqQA==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.370.0", - "@aws-sdk/middleware-host-header": "3.370.0", - "@aws-sdk/middleware-logger": "3.370.0", - "@aws-sdk/middleware-recursion-detection": "3.370.0", - "@aws-sdk/middleware-sdk-sts": "3.370.0", - "@aws-sdk/middleware-signing": "3.370.0", - "@aws-sdk/middleware-user-agent": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@aws-sdk/util-user-agent-browser": "3.370.0", - "@aws-sdk/util-user-agent-node": "3.370.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.2", - "@smithy/middleware-retry": "^1.0.3", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "@smithy/util-utf8": "^1.0.1", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.451.0.tgz", - "integrity": "sha512-SamWW2zHEf1ZKe3j1w0Piauryl8BQIlej0TBS18A4ACzhjhWXhCs13bO1S88LvPR5mBFXok3XOT6zPOnKDFktw==", - "dependencies": { - "@smithy/smithy-client": "^2.1.15", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/abort-controller": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", - "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/fetch-http-handler": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.6.tgz", - "integrity": "sha512-PStY3XO1Ksjwn3wMKye5U6m6zxXpXrXZYqLy/IeCbh3nM9QB3Jgw/B0PUSLUWKdXg4U8qgEu300e3ZoBvZLsDg==", - "dependencies": { - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", - "@smithy/util-base64": "^2.0.1", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/core/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/@aws-sdk/core/node_modules/@smithy/middleware-stack": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.7.tgz", - "integrity": "sha512-L1KLAAWkXbGx1t2jjCI/mDJ2dDNq+rp4/ifr/HcC6FHngxho5O7A5bQLpKHGlkfATH6fUnOEx0VICEVFA4sUzw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/node-http-handler": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.9.tgz", - "integrity": "sha512-+K0q3SlNcocmo9OZj+fz67gY4lwhOCvIJxVbo/xH+hfWObvaxrMTx7JEzzXcluK0thnnLz++K3Qe7Z/8MDUreA==", - "dependencies": { - "@smithy/abort-controller": "^2.0.13", - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/protocol-http": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.9.tgz", - "integrity": "sha512-U1wl+FhYu4/BC+rjwh1lg2gcJChQhytiNQSggREgQ9G2FzmoK9sACBZvx7thyWMvRyHQTE22mO2d5UM8gMKDBg==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/querystring-builder": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.13.tgz", - "integrity": "sha512-JhXKwp3JtsFUe96XLHy/nUPEbaXqn6r7xE4sNaH8bxEyytE5q1fwt0ew/Ke6+vIC7gP87HCHgQpJHg1X1jN2Fw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/smithy-client": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.15.tgz", - "integrity": "sha512-rngZcQu7Jvs9UbHihK1EI67RMPuzkc3CJmu4MBgB7D7yBnMGuFR86tq5rqHfL2gAkNnMelBN/8kzQVvZjNKefQ==", - "dependencies": { - "@smithy/middleware-stack": "^2.0.7", - "@smithy/types": "^2.5.0", - "@smithy/util-stream": "^2.0.20", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/util-base64": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.1.tgz", - "integrity": "sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==", - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/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==", - "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/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==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/util-stream": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.20.tgz", - "integrity": "sha512-tT8VASuD8jJu0yjHEMTCPt1o5E3FVzgdsxK6FQLAjXKqVv5V8InCnc0EOsYrijgspbfDqdAJg7r0o2sySfcHVg==", - "dependencies": { - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/types": "^2.5.0", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/util-uri-escape": { - "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==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@smithy/util-utf8": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.2.tgz", - "integrity": "sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==", - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.388.0.tgz", - "integrity": "sha512-j1oyBc0/O76YouOC2wMZuQUfHOjfrKWgBibIwrwqEqacYWMx/IBxZkk9j2fFerIVaKhhMNkZHAGb+qBx0urR/Q==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.388.0", - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity/node_modules/@aws-sdk/types": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.387.0.tgz", - "integrity": "sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity/node_modules/@smithy/property-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.2.tgz", - "integrity": "sha512-DfaZ8cO+d/mgnMzIllcXcU4OYP+omiOl2LYdn/fTGpw/EAQSVzscYV2muV3sDDnuPYQ/r014hUqIxnF+pzh+SQ==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity/node_modules/@smithy/types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.1.0.tgz", - "integrity": "sha512-KLsCsqxX0j2l99iP8s0f7LBlcsp7a7ceXGn0LPYPyVOsqmIKvSaPQajq0YevlL4T9Bm+DtcyXfBTbtBcLX1I7A==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.370.0.tgz", - "integrity": "sha512-raR3yP/4GGbKFRPP5hUBNkEmTnzxI9mEc2vJAJrcv4G4J4i/UP6ELiLInQ5eO2/VcV/CeKGZA3t7d1tsJ+jhCg==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.370.0.tgz", - "integrity": "sha512-eJyapFKa4NrC9RfTgxlXnXfS9InG/QMEUPPVL+VhG7YS6nKqetC1digOYgivnEeu+XSKE0DJ7uZuXujN2Y7VAQ==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.370.0", - "@aws-sdk/credential-provider-process": "3.370.0", - "@aws-sdk/credential-provider-sso": "3.370.0", - "@aws-sdk/credential-provider-web-identity": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.370.0.tgz", - "integrity": "sha512-gkFiotBFKE4Fcn8CzQnMeab9TAR06FEAD02T4ZRYW1xGrBJOowmje9dKqdwQFHSPgnWAP+8HoTA8iwbhTLvjNA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.370.0", - "@aws-sdk/credential-provider-ini": "3.370.0", - "@aws-sdk/credential-provider-process": "3.370.0", - "@aws-sdk/credential-provider-sso": "3.370.0", - "@aws-sdk/credential-provider-web-identity": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.370.0.tgz", - "integrity": "sha512-0BKFFZmUO779Xdw3u7wWnoWhYA4zygxJbgGVSyjkOGBvdkbPSTTcdwT1KFkaQy2kOXYeZPl+usVVRXs+ph4ejg==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.370.0.tgz", - "integrity": "sha512-PFroYm5hcPSfC/jkZnCI34QFL3I7WVKveVk6/F3fud/cnP8hp6YjA9NiTNbqdFSzsyoiN/+e5fZgNKih8vVPTA==", - "dependencies": { - "@aws-sdk/client-sso": "3.370.0", - "@aws-sdk/token-providers": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.370.0.tgz", - "integrity": "sha512-CFaBMLRudwhjv1sDzybNV93IaT85IwS+L8Wq6VRMa0mro1q9rrWsIZO811eF+k0NEPfgU1dLH+8Vc2qhw4SARQ==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.388.0.tgz", - "integrity": "sha512-5opHLYjj6rHrw2OaxE+IcLhC9JfiopPH7hRknzKjFnSrJ+HjzcHCML5xghwHLJOLGcoWU40CCSlwJVPLlJluMw==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.388.0", - "@aws-sdk/client-sso": "3.387.0", - "@aws-sdk/client-sts": "3.388.0", - "@aws-sdk/credential-provider-cognito-identity": "3.388.0", - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-ini": "3.388.0", - "@aws-sdk/credential-provider-node": "3.388.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/client-sso": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.387.0.tgz", - "integrity": "sha512-E7uKSvbA0XMKSN5KLInf52hmMpe9/OKo6N9OPffGXdn3fNEQlvyQq3meUkqG7Is0ldgsQMz5EUBNtNybXzr3tQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/client-sts": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.388.0.tgz", - "integrity": "sha512-y9FAcAYHT8O6T/jqhgsIQUb4gLiSTKD3xtzudDvjmFi8gl0oRIY1npbeckSiK6k07VQugm2s64I0nDnDxtWsBg==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.388.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-sdk-sts": "3.387.0", - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@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-providers/node_modules/@aws-sdk/credential-provider-env": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.387.0.tgz", - "integrity": "sha512-PVqNk7XPIYe5CMYNvELkcALtkl/pIM8/uPtqEtTg+mgnZBeL4fAmgXZiZMahQo1DxP5t/JaK384f6JG+A0qDjA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.388.0.tgz", - "integrity": "sha512-3dg3A8AiZ5vXkSAYyyI3V/AW3Eo6KQJyE/glA+Nr2M0oAjT4z3vHhS3pf2B+hfKGZBTuKKgxusrrhrQABd/Diw==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.388.0.tgz", - "integrity": "sha512-BqWAkIG08gj/wevpesaZhAjALjfUNVjseHQRk+DNUoHIfyibW7Ahf3q/GIPs11dA2o8ECwR9/fo68Sq+sK799A==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-ini": "3.388.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-process": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.387.0.tgz", - "integrity": "sha512-tQScLHmDlqkQN+mqw4s3cxepEUeHYDhFl5eH+J8puvPqWjXMYpCEdY79SAtWs6SZd4CWiZ0VLeYU6xQBZengbQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.388.0.tgz", - "integrity": "sha512-RH02+rntaO0UhnSBr42n+7q8HOztc+Dets/hh6cWovf3Yi9s9ghLgYLN9FXpSosfot3XkmT/HOCa+CphAmGN9A==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/client-sso": "3.387.0", - "@aws-sdk/token-providers": "3.388.0", - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.387.0.tgz", - "integrity": "sha512-6ueMPl+J3KWv6ZaAWF4Z138QCuBVFZRVAgwbtP3BNqWrrs4Q6TPksOQJ79lRDMpv0EUoyVl04B6lldNlhN8RdA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.387.0.tgz", - "integrity": "sha512-EWm9PXSr8dSp7hnRth1U7OfelXQp9dLf1yS1kUL+UhppYDJpjhdP7ql3NI4xJKw8e76sP2FuJYEuzWnJHuWoyQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/middleware-logger": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.387.0.tgz", - "integrity": "sha512-FjAvJr1XyaInT81RxUwgifnbXoFJrRBFc64XeFJgFanGIQCWLYxRrK2HV9eBpao/AycbmuoHgLd/f0sa4hZFoQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.387.0.tgz", - "integrity": "sha512-ZF45T785ru8OwvYZw6awD9Z76OwSMM1eZzj2eY+FDz1cHfkpLjxEiti2iIH1FxbyK7n9ZqDUx29lVlCv238YyQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.387.0.tgz", - "integrity": "sha512-7ZzRKOJ4V/JDQmKz9z+FjZqw59mrMATEMLR6ff0H0JHMX0Uk5IX8TQB058ss+ar14qeJ4UcteYzCqHNI0O1BHw==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/middleware-signing": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.387.0.tgz", - "integrity": "sha512-oJXlE0MES8gxNLo137PPNNiOICQGOaETTvq3kBSJgb/gtEAxQajMIlaNT7s1wsjOAruFHt4975nCXuY4lpx7GQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.387.0.tgz", - "integrity": "sha512-hTfFTwDtp86xS98BKa+RFuLfcvGftxwzrbZeisZV8hdb4ZhvNXjSxnvM3vetW0GUEnY9xHPSGyp2ERRTinPKFQ==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/token-providers": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.388.0.tgz", - "integrity": "sha512-2lo1gFJl624kfjo/YdU6zW+k6dEwhoqjNkDNbOZEFgS1KDofHe9GX8W4/ReKb0Ggho5/EcjzZ53/1CjkzUq4tA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/types": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.387.0.tgz", - "integrity": "sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/util-endpoints": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.387.0.tgz", - "integrity": "sha512-g7kvuCXehGXHHBw9PkSQdwVyDFmNUZLmfrRmqMyrMDG9QLQrxr4pyWcSaYgTE16yUzhQQOR+QSey+BL6W9/N6g==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.387.0.tgz", - "integrity": "sha512-lpgSVvDqx+JjHZCTYs/yQSS7J71dPlJeAlvxc7bmx5m+vfwKe07HAnIs+929DngS0QbAp/VaXbTiMFsInLkO4Q==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.387.0.tgz", - "integrity": "sha512-r9OVkcWpRYatjLhJacuHFgvO2T5s/Nu5DDbScMrkUD8b4aGIIqsrdZji0vZy9FCjsUFQMM92t9nt4SejrGjChA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-sdk/types": "3.387.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/abort-controller": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.2.tgz", - "integrity": "sha512-ln5Cob0mksym62sLr7NiPOSqJ0jKao4qjfcNLDdgINM1lQI12hXrZBlKdPHbXJqpKhKiECDgonMoqCM8bigq4g==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/config-resolver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.2.tgz", - "integrity": "sha512-0kdsqBL6BdmSbdU6YaDkodVBMua5MuQQluC3nocJ7OJ6PnOuM7i2FEQHE46LBadLqT+CimlDSM+6j91uHNL1ng==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/credential-provider-imds": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.2.tgz", - "integrity": "sha512-mbWFYEZ00LBRDk3WvcXViwpdpkJQcfrM3seuKzFxZnF6wIBLMwrcWcsj+OUC/1L+86m8aQY9imXMAaQsAoGxow==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/node-config-provider": "^2.0.2", - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/eventstream-codec": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.2.tgz", - "integrity": "sha512-PQZiKx7fMnNwx4zxcUCm82VjnqK6wV4MEHSmMy3taj5dKfXV782IjRGyaDT+8TsmNqVdZIkve5zLRAzh+7kOhA==", - "optional": true, - "peer": true, - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/fetch-http-handler": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.2.tgz", - "integrity": "sha512-Wo2m1RaiXNSLF4J3D62LpdSoj/YYb+6tn0H8is1tSrzr7eXAdiYVBc0wIa23N0wT4zmN0iG/yNY6gTCDQ6799A==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/querystring-builder": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/util-base64": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/hash-node": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.2.tgz", - "integrity": "sha512-JKDzZ1YVR7JzOBaJoWy3ToJCE86OQE6D4kOBvvVsu93a3lcF9kv6KYTKBYEWAjwOn/CpK4NH7mKB01OQ8H+aiA==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/invalid-dependency": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.2.tgz", - "integrity": "sha512-inQZQ5gCO3WRWuXpsc1YJ4KBjsvj2qsoU32yTIKznBWTCQe/D5Dp+sSaysqBqxe0VTZ+8nFEHdUMWUX2BxQThw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/credential-providers/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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/middleware-content-length": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.2.tgz", - "integrity": "sha512-FmHlNfuvYgDZE3fIx0G3rD/wLXfAmBYE4mVc/w6d7RllA7TygPzq2pfHL1iCMzWkWTdoAVnt3h4aavAZnhaxEQ==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/middleware-endpoint": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.2.tgz", - "integrity": "sha512-ropE7/c+g22QeluZ+By/B/WvVep0UFreX+IeRMGIO7EbOUPgqtJRXpbJFdG6JKB1uC+CdaJLn4MnZnVBpcyjuA==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/middleware-serde": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/middleware-retry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.2.tgz", - "integrity": "sha512-wtBUXqtZVriiXppYaFkUrybAPhFVX7vebnW/yVPliLMWMcguOMS58qhOYPZe3t9Wki2+mASfyu+kO3An8lAg2A==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/service-error-classification": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-retry": "^2.0.0", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/middleware-serde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.2.tgz", - "integrity": "sha512-Kw9xLdlueIaivUWslKB67WZ/cCUg3QnzYVIA3t5KfgsseEEuU4UxXw8NSTvIt71gqQloY+Um8ugS+idgxrWWnw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/middleware-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", - "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/node-config-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.2.tgz", - "integrity": "sha512-9wVJccASfuCctNWrzR0zrDkf0ox3HCHGEhFlWL2LBoghUYuK28pVRBbG69wvnkhlHnB8dDZHagxH+Nq9dm7eWw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/property-provider": "^2.0.2", - "@smithy/shared-ini-file-loader": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/node-http-handler": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.0.2.tgz", - "integrity": "sha512-lpZjmtmyZqSAtMPsbrLhb7XoAQ2kAHeuLY/csW6I2k+QyFvOk7cZeQsqEngWmZ9SJaeYiDCBINxAIM61i5WGLw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/abort-controller": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/querystring-builder": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/property-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.2.tgz", - "integrity": "sha512-DfaZ8cO+d/mgnMzIllcXcU4OYP+omiOl2LYdn/fTGpw/EAQSVzscYV2muV3sDDnuPYQ/r014hUqIxnF+pzh+SQ==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/protocol-http": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-2.0.2.tgz", - "integrity": "sha512-qWu8g1FUy+m36KpO1sREJSF7BaLmjw9AqOuwxLVVSdYz+nUQjc9tFAZ9LB6jJXKdsZFSjfkjHJBbhD78QdE7Rw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/querystring-builder": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.2.tgz", - "integrity": "sha512-H99LOMWEssfwqkOoTs4Y12UiZ7CTGQSX5Nrx5UkYgRbUEpC1GnnaprHiYrqclC58/xr4K76aNchdPyioxewMzA==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/querystring-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.2.tgz", - "integrity": "sha512-L4VtKQ8O4/aWPQJbiFymbhAmxdfLnEaROh/Vs0OstJ7jtOZeBl2QJmuWY2V7hjt64W7V+tEn2sv6vVvnxkm/xQ==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/service-error-classification": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", - "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", - "optional": true, - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/shared-ini-file-loader": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.2.tgz", - "integrity": "sha512-2VkNOM/82u4vatVdK5nfusgGIlvR48Fkq6me17Oc+V1iyxfR/1x0pG6LzW0br1qlGtzBYFZKmDyviBRcPVFTVw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/signature-v4": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.2.tgz", - "integrity": "sha512-YMooDEw/UmGxcXY4qWnSXkbPFsRloluSvyXVT678YPDN/K2AS1GzKfRsvSU7fbccOB4WF8MHZf2UqcRGEltE3Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/eventstream-codec": "^2.0.2", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/smithy-client": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.0.2.tgz", - "integrity": "sha512-mDfokI8WwLU5C0gcQ4ww/zJI/WLGSh2+vdIA42JRnjfYUjJNH/rKfX9YOnn2eBOxl3loATERVUqkHmKe+P8s2Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/middleware-stack": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-stream": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.1.0.tgz", - "integrity": "sha512-KLsCsqxX0j2l99iP8s0f7LBlcsp7a7ceXGn0LPYPyVOsqmIKvSaPQajq0YevlL4T9Bm+DtcyXfBTbtBcLX1I7A==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/url-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.2.tgz", - "integrity": "sha512-X1mHCzrSVDlhVy7d3S7Vq+dTfYzwh4n7xGHhyJumu77nJqIss0lazVug85Pwo0DKIoO314wAOvMnBxNYDa+7wA==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/querystring-parser": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/credential-providers/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==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/util-body-length-node": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.0.0.tgz", - "integrity": "sha512-ZV7Z/WHTMxHJe/xL/56qZwSUcl63/5aaPAGjkfynJm4poILjdD4GmFI+V+YWabh2WJIjwTKZ5PNsuvPQKt93Mg==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/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==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.2.tgz", - "integrity": "sha512-c2tMMjb624XLuzmlRoZpnFOkejVxcgw3WQKdmgdGZYZapcLzXyC0H9JhnXMjQCt30GqLTlsILRNVBYwFRbw/4Q==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.2.tgz", - "integrity": "sha512-gt7m5LLqUtEKldJLyc14DE4kb85vxwomvt9AfEMEvWM4VwfWS1kGJqiStZFb5KNqnQPXw8vvpgLTi8NrWAOXqg==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/config-resolver": "^2.0.2", - "@smithy/credential-provider-imds": "^2.0.2", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/util-middleware": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", - "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/util-retry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", - "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/service-error-classification": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/util-stream": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.2.tgz", - "integrity": "sha512-Mg9IJcKIu4YKlbzvpp1KLvh4JZLdcPgpxk+LICuDwzZCfxe47R9enVK8dNEiuyiIGK2ExbfvzCVT8IBru62vZw==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/types": "^2.1.0", - "@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" - } - }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/util-uri-escape": { - "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==", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers/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==", - "optional": true, - "peer": true, - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.370.0.tgz", - "integrity": "sha512-CPXOm/TnOFC7KyXcJglICC7OiA7Kj6mT3ChvEijr56TFOueNHvJdV4aNIFEQy0vGHOWtY12qOWLNto/wYR1BAQ==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.370.0.tgz", - "integrity": "sha512-cQMq9SaZ/ORmTJPCT6VzMML7OxFdQzNkhMAgKpTDl+tdPWynlHF29E5xGoSzROnThHlQPCjogU0NZ8AxI0SWPA==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.370.0.tgz", - "integrity": "sha512-L7ZF/w0lAAY/GK1khT8VdoU0XB7nWHk51rl/ecAg64J70dHnMOAg8n+5FZ9fBu/xH1FwUlHOkwlodJOgzLJjtg==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.370.0.tgz", - "integrity": "sha512-ykbsoVy0AJtVbuhAlTAMcaz/tCE3pT8nAp0L7CQQxSoanRCvOux7au0KwMIQVhxgnYid4dWVF6d00SkqU5MXRA==", - "dependencies": { - "@aws-sdk/middleware-signing": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.370.0.tgz", - "integrity": "sha512-Dwr/RTCWOXdm394wCwICGT2VNOTMRe4IGPsBRJAsM24pm+EEqQzSS3Xu/U/zF4exuxqpMta4wec4QpSarPNTxA==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/signature-v4": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-middleware": "^1.0.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.370.0.tgz", - "integrity": "sha512-2+3SB6MtMAq1+gVXhw0Y3ONXuljorh6ijnxgTpv+uQnBW5jHCUiAS8WDYiDEm7i9euJPbvJfM8WUrSMDMU6Cog==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.451.0.tgz", - "integrity": "sha512-3iMf4OwzrFb4tAAmoROXaiORUk2FvSejnHIw/XHvf/jjR4EqGGF95NZP/n/MeFZMizJWVssrwS412GmoEyoqhg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver/node_modules/@smithy/node-config-provider": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.5.tgz", - "integrity": "sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==", - "dependencies": { - "@smithy/property-provider": "^2.0.14", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver/node_modules/@smithy/property-provider": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.14.tgz", - "integrity": "sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver/node_modules/@smithy/shared-ini-file-loader": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.4.tgz", - "integrity": "sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver/node_modules/@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver/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" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver/node_modules/@smithy/util-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.6.tgz", - "integrity": "sha512-7W4uuwBvSLgKoLC1x4LfeArCVcbuHdtVaC4g30kKsD1erfICyQ45+tFhhs/dZNeQg+w392fhunCm/+oCcb6BSA==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.370.0.tgz", - "integrity": "sha512-EyR2ZYr+lJeRiZU2/eLR+mlYU9RXLQvNyGFSAekJKgN13Rpq/h0syzXVFLP/RSod/oZenh/fhVZ2HwlZxuGBtQ==", - "dependencies": { - "@aws-sdk/client-sso-oidc": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.370.0.tgz", - "integrity": "sha512-8PGMKklSkRKjunFhzM2y5Jm0H2TBu7YRNISdYzXLUHKSP9zlMEYagseKVdmox0zKHf1LXVNuSlUV2b6SRrieCQ==", - "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.370.0.tgz", - "integrity": "sha512-5ltVAnM79nRlywwzZN5i8Jp4tk245OCGkKwwXbnDU+gq7zT3CIOsct1wNZvmpfZEPGt/bv7/NyRcjP+7XNsX/g==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "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.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.370.0.tgz", - "integrity": "sha512-028LxYZMQ0DANKhW+AKFQslkScZUeYlPmSphrCIXgdIItRZh6ZJHGzE7J/jDsEntZOrZJsjI4z0zZ5W2idj04w==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/types": "^1.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.370.0.tgz", - "integrity": "sha512-33vxZUp8vxTT/DGYIR3PivQm07sSRGWI+4fCv63Rt7Q++fO24E0kQtmVAlikRY810I10poD6rwILVtITtFSzkg==", - "dependencies": { - "@aws-sdk/types": "3.370.0", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "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", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", - "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@casl/ability": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@casl/ability/-/ability-6.5.0.tgz", - "integrity": "sha512-3guc94ugr5ylZQIpJTLz0CDfwNi0mxKVECj1vJUPAvs+Lwunh/dcuUjwzc4MHM9D8JOYX0XUZMEPedpB3vIbOw==", - "dependencies": { - "@ucast/mongo2js": "^1.3.0" - }, - "funding": { - "url": "https://github.com/stalniy/casl/blob/master/BACKERS.md" - } - }, - "node_modules/@casl/mongoose": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@casl/mongoose/-/mongoose-7.2.1.tgz", - "integrity": "sha512-pojgSWYKNIwFM6wWDNct1YD0+8nIxhe2jp5jBbK8JGU60dEs2o0Yw3mCo2y7nBwbvRC2oEots/BlLMVb1Wdo8A==", - "peerDependencies": { - "@casl/ability": "^6.3.2", - "mongoose": "^6.0.13 || ^7.0.0" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@godaddy/terminus": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.12.1.tgz", - "integrity": "sha512-Tm+wVu1/V37uZXcT7xOhzdpFoovQReErff8x3y82k6YyWa1gzxWBjTyrx4G2enjEqoXPnUUmJ3MOmwH+TiP6Sw==", - "dependencies": { - "stoppable": "^1.1.0" - } - }, - "node_modules/@hapi/bourne": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.1.0.tgz", - "integrity": "sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", - "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", - "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", - "dev": true, - "dependencies": { - "@jest/console": "^29.6.1", - "@jest/reporters": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-resolve-dependencies": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "jest-watcher": "^29.6.1", - "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", - "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "jest-mock": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", - "dev": true, - "dependencies": { - "expect": "^29.6.1", - "jest-snapshot": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", - "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.4.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", - "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", - "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/types": "^29.6.1", - "jest-mock": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", - "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", - "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", - "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", - "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", - "dev": true, - "dependencies": { - "@jest/console": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", - "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.6.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", - "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.1", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", - "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@juanelas/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@juanelas/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-mr2pfRQpWap0Uq4tlrCgp3W+Yjx1/Bpq4QJsYeAQUh1mExgyQvXz7xUhmYT2HcLLspuAL5dpnos8P2QhaCSXsQ==" - }, - "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", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@maxmind/geoip2-node": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@maxmind/geoip2-node/-/geoip2-node-3.5.0.tgz", - "integrity": "sha512-WG2TNxMwDWDOrljLwyZf5bwiEYubaHuICvQRlgz74lE9OZA/z4o+ZT6OisjDBAZh/yRJVNK6mfHqmP5lLlAwsA==", - "dev": true, - "dependencies": { - "camelcase-keys": "^7.0.0", - "ip6addr": "^0.2.5", - "maxmind": "^4.2.0" - } - }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", - "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - } - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", - "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", - "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", - "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", - "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", - "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", - "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@napi-rs/snappy-android-arm-eabi": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm-eabi/-/snappy-android-arm-eabi-7.2.2.tgz", - "integrity": "sha512-H7DuVkPCK5BlAr1NfSU8bDEN7gYs+R78pSHhDng83QxRnCLmVIZk33ymmIwurmoA1HrdTxbkbuNl+lMvNqnytw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-android-arm64": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm64/-/snappy-android-arm64-7.2.2.tgz", - "integrity": "sha512-2R/A3qok+nGtpVK8oUMcrIi5OMDckGYNoBLFyli3zp8w6IArPRfg1yOfVUcHvpUDTo9T7LOS1fXgMOoC796eQw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-darwin-arm64": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-arm64/-/snappy-darwin-arm64-7.2.2.tgz", - "integrity": "sha512-USgArHbfrmdbuq33bD5ssbkPIoT7YCXCRLmZpDS6dMDrx+iM7eD2BecNbOOo7/v1eu6TRmQ0xOzeQ6I/9FIi5g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-darwin-x64": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-x64/-/snappy-darwin-x64-7.2.2.tgz", - "integrity": "sha512-0APDu8iO5iT0IJKblk2lH0VpWSl9zOZndZKnBYIc+ei1npw2L5QvuErFOTeTdHBtzvUHASB+9bvgaWnQo4PvTQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-freebsd-x64": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-freebsd-x64/-/snappy-freebsd-x64-7.2.2.tgz", - "integrity": "sha512-mRTCJsuzy0o/B0Hnp9CwNB5V6cOJ4wedDTWEthsdKHSsQlO7WU9W1yP7H3Qv3Ccp/ZfMyrmG98Ad7u7lG58WXA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-linux-arm-gnueabihf": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm-gnueabihf/-/snappy-linux-arm-gnueabihf-7.2.2.tgz", - "integrity": "sha512-v1uzm8+6uYjasBPcFkv90VLZ+WhLzr/tnfkZ/iD9mHYiULqkqpRuC8zvc3FZaJy5wLQE9zTDkTJN1IvUcZ+Vcg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-linux-arm64-gnu": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-gnu/-/snappy-linux-arm64-gnu-7.2.2.tgz", - "integrity": "sha512-LrEMa5pBScs4GXWOn6ZYXfQ72IzoolZw5txqUHVGs8eK4g1HR9HTHhb2oY5ySNaKakG5sOgMsb1rwaEnjhChmQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-linux-arm64-musl": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-musl/-/snappy-linux-arm64-musl-7.2.2.tgz", - "integrity": "sha512-3orWZo9hUpGQcB+3aTLW7UFDqNCQfbr0+MvV67x8nMNYj5eAeUtMmUE/HxLznHO4eZ1qSqiTwLbVx05/Socdlw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-linux-x64-gnu": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-gnu/-/snappy-linux-x64-gnu-7.2.2.tgz", - "integrity": "sha512-jZt8Jit/HHDcavt80zxEkDpH+R1Ic0ssiVCoueASzMXa7vwPJeF4ZxZyqUw4qeSy7n8UUExomu8G8ZbP6VKhgw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-linux-x64-musl": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-musl/-/snappy-linux-x64-musl-7.2.2.tgz", - "integrity": "sha512-Dh96IXgcZrV39a+Tej/owcd9vr5ihiZ3KRix11rr1v0MWtVb61+H1GXXlz6+Zcx9y8jM1NmOuiIuJwkV4vZ4WA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-win32-arm64-msvc": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-arm64-msvc/-/snappy-win32-arm64-msvc-7.2.2.tgz", - "integrity": "sha512-9No0b3xGbHSWv2wtLEn3MO76Yopn1U2TdemZpCaEgOGccz1V+a/1d16Piz3ofSmnA13HGFz3h9NwZH9EOaIgYA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-win32-ia32-msvc": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-ia32-msvc/-/snappy-win32-ia32-msvc-7.2.2.tgz", - "integrity": "sha512-QiGe+0G86J74Qz1JcHtBwM3OYdTni1hX1PFyLRo3HhQUSpmi13Bzc1En7APn+6Pvo7gkrcy81dObGLDSxFAkQQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/snappy-win32-x64-msvc": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-x64-msvc/-/snappy-win32-x64-msvc-7.2.2.tgz", - "integrity": "sha512-a43cyx1nK0daw6BZxVcvDEXxKMFLSBSDTAhsFD0VqSKcC7MGUBMaqyoWUcMiI7LBSz4bxUmxDWKfCYzpEmeb3w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-saml/node-saml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@node-saml/node-saml/-/node-saml-4.0.5.tgz", - "integrity": "sha512-J5DglElbY1tjOuaR1NPtjOXkXY5bpUhDoKVoeucYN98A3w4fwgjIOPqIGcb6cQsqFq2zZ6vTCeKn5C/hvefSaw==", - "dependencies": { - "@types/debug": "^4.1.7", - "@types/passport": "^1.0.11", - "@types/xml-crypto": "^1.4.2", - "@types/xml-encryption": "^1.2.1", - "@types/xml2js": "^0.4.11", - "@xmldom/xmldom": "^0.8.6", - "debug": "^4.3.4", - "xml-crypto": "^3.0.1", - "xml-encryption": "^3.0.2", - "xml2js": "^0.5.0", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@node-saml/passport-saml": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@node-saml/passport-saml/-/passport-saml-4.0.4.tgz", - "integrity": "sha512-xFw3gw0yo+K1mzlkW15NeBF7cVpRHN/4vpjmBKzov5YFImCWh/G0LcTZ8krH3yk2/eRPc3Or8LRPudVJBjmYaw==", - "dependencies": { - "@node-saml/node-saml": "^4.0.4", - "@types/express": "^4.17.14", - "@types/passport": "^1.0.11", - "@types/passport-strategy": "^0.2.35", - "passport": "^0.6.0", - "passport-strategy": "^1.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@octokit/auth-app": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-4.0.13.tgz", - "integrity": "sha512-NBQkmR/Zsc+8fWcVIFrwDgNXS7f4XDrkd9LHdi9DPQw1NdGHLviLzRO2ZBwTtepnwHXW5VTrVU9eFGijMUqllg==", - "dependencies": { - "@octokit/auth-oauth-app": "^5.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "deprecation": "^2.3.1", - "lru-cache": "^9.0.0", - "universal-github-app-jwt": "^1.1.1", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-app/node_modules/lru-cache": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", - "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/@octokit/auth-oauth-app": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-5.0.6.tgz", - "integrity": "sha512-SxyfIBfeFcWd9Z/m1xa4LENTQ3l1y6Nrg31k2Dcb1jS5ov7pmwMJZ6OGX8q3K9slRgVpeAjNA1ipOAMHkieqyw==", - "dependencies": { - "@octokit/auth-oauth-device": "^4.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "@types/btoa-lite": "^1.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-oauth-device": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-4.0.5.tgz", - "integrity": "sha512-XyhoWRTzf2ZX0aZ52a6Ew5S5VBAfwwx1QnC2Np6Et3MWQpZjlREIcbcvVZtkNuXp6Z9EeiSLSDUqm3C+aMEHzQ==", - "dependencies": { - "@octokit/oauth-methods": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-oauth-user": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-2.1.2.tgz", - "integrity": "sha512-kkRqNmFe7s5GQcojE3nSlF+AzYPpPv7kvP/xYEnE57584pixaFBH8Vovt+w5Y3E4zWUEOxjdLItmBTFAWECPAg==", - "dependencies": { - "@octokit/auth-oauth-device": "^4.0.0", - "@octokit/oauth-methods": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-token": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", - "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/auth-unauthenticated": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-3.0.5.tgz", - "integrity": "sha512-yH2GPFcjrTvDWPwJWWCh0tPPtTL5SMgivgKPA+6v/XmYN6hGQkAto8JtZibSKOpf8ipmeYhLNWQ2UgW0GYILCw==", - "dependencies": { - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", - "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", - "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/endpoint": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", - "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", - "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", - "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/oauth-authorization-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-5.0.0.tgz", - "integrity": "sha512-y1WhN+ERDZTh0qZ4SR+zotgsQUE1ysKnvBt1hvDRB2WRzYtVKQjn97HEPzoehh66Fj9LwNdlZh+p6TJatT0zzg==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/oauth-methods": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-2.0.6.tgz", - "integrity": "sha512-l9Uml2iGN2aTWLZcm8hV+neBiFXAQ9+3sKiQe/sgumHlL6HDg0AQ8/l16xX/5jJvfxueqTW5CWbzd0MjnlfHZw==", - "dependencies": { - "@octokit/oauth-authorization-url": "^5.0.0", - "@octokit/request": "^6.2.3", - "@octokit/request-error": "^3.0.3", - "@octokit/types": "^9.0.0", - "btoa-lite": "^1.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" - }, - "node_modules/@octokit/plugin-enterprise-compatibility": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-compatibility/-/plugin-enterprise-compatibility-1.3.0.tgz", - "integrity": "sha512-h34sMGdEOER/OKrZJ55v26ntdHb9OPfR1fwOx6Q4qYyyhWA104o11h9tFxnS/l41gED6WEI41Vu2G2zHDVC5lQ==", - "dependencies": { - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.0.3" - } - }, - "node_modules/@octokit/plugin-enterprise-compatibility/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/@octokit/plugin-enterprise-compatibility/node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/@octokit/plugin-enterprise-compatibility/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", - "dependencies": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=4" - } - }, - "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", - "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", - "dependencies": { - "@octokit/types": "^10.0.0" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", - "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", - "dependencies": { - "@octokit/openapi-types": "^18.0.0" - } - }, - "node_modules/@octokit/plugin-retry": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz", - "integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==", - "dependencies": { - "@octokit/types": "^6.0.3", - "bottleneck": "^2.15.3" - } - }, - "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/@octokit/request": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", - "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", - "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/rest": { - "version": "19.0.13", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", - "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", - "dependencies": { - "@octokit/core": "^4.2.1", - "@octokit/plugin-paginate-rest": "^6.1.2", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.1.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==" - }, - "node_modules/@octokit/types": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", - "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", - "dependencies": { - "@octokit/openapi-types": "^18.0.0" - } - }, - "node_modules/@octokit/webhooks": { - "version": "9.26.3", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.26.3.tgz", - "integrity": "sha512-DLGk+gzeVq5oK89Bo601txYmyrelMQ7Fi5EnjHE0Xs8CWicy2xkmnJMKptKJrBJpstqbd/9oeDFi/Zj2pudBDQ==", - "dependencies": { - "@octokit/request-error": "^2.0.2", - "@octokit/webhooks-methods": "^2.0.0", - "@octokit/webhooks-types": "5.8.0", - "aggregate-error": "^3.1.0" - } - }, - "node_modules/@octokit/webhooks-methods": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz", - "integrity": "sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig==" - }, - "node_modules/@octokit/webhooks-types": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.8.0.tgz", - "integrity": "sha512-8adktjIb76A7viIdayQSFuBEwOzwhDC+9yxZpKNHjfzrlostHCw0/N7JWpWMObfElwvJMk2fY2l1noENCk9wmw==" - }, - "node_modules/@octokit/webhooks/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/@octokit/webhooks/node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/@octokit/webhooks/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/@phc/format": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", - "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/@posthog/plugin-scaffold": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@posthog/plugin-scaffold/-/plugin-scaffold-1.4.2.tgz", - "integrity": "sha512-/VsRg3CfhQvYhxM2O9+gBOzj4K1QJZClY+yple0npL1Jd2nRn2nT4z7dlPSidTPZvdpFs0+hrnF+m4Kxf1NFvQ==", - "dev": true, - "dependencies": { - "@maxmind/geoip2-node": "^3.4.0" - } - }, - "node_modules/@probot/get-private-key": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@probot/get-private-key/-/get-private-key-1.1.1.tgz", - "integrity": "sha512-hOmBNSAhSZc6PaNkTvj6CO9R5J67ODJ+w5XQlDW9w/6mtcpHWK4L+PZcW0YwVM7PpetLZjN6rsKQIR9yqIaWlA==", - "dependencies": { - "@types/is-base64": "^1.1.0", - "is-base64": "^1.1.0" - } - }, - "node_modules/@probot/octokit-plugin-config": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@probot/octokit-plugin-config/-/octokit-plugin-config-1.1.6.tgz", - "integrity": "sha512-L29wmnFvilzSfWn9tUgItxdLv0LJh2ICjma3FmLr80Spu3wZ9nHyRrKMo9R5/K2m7VuWmgoKnkgRt2zPzAQBEQ==", - "dependencies": { - "@types/js-yaml": "^4.0.5", - "js-yaml": "^4.1.0" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@probot/pino": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@probot/pino/-/pino-2.3.5.tgz", - "integrity": "sha512-IiyiNZonMw1dHC4EAdD55y5owV733d9Gll/IKsrLikB7EJ54+eMCOtL/qo+OmgWN9XV3NTDfziEQF2og/OBKog==", - "dependencies": { - "@sentry/node": "^6.0.0", - "pino-pretty": "^6.0.0", - "pump": "^3.0.0", - "readable-stream": "^3.6.0", - "split2": "^4.0.0" - }, - "bin": { - "pino-probot": "cli.js" - } - }, - "node_modules/@probot/pino/node_modules/@sentry/core": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", - "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", - "dependencies": { - "@sentry/hub": "6.19.7", - "@sentry/minimal": "6.19.7", - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@probot/pino/node_modules/@sentry/node": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz", - "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==", - "dependencies": { - "@sentry/core": "6.19.7", - "@sentry/hub": "6.19.7", - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@probot/pino/node_modules/@sentry/types": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", - "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@probot/pino/node_modules/@sentry/utils": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", - "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", - "dependencies": { - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@probot/pino/node_modules/colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" - }, - "node_modules/@probot/pino/node_modules/jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/@probot/pino/node_modules/pino-pretty": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-6.0.0.tgz", - "integrity": "sha512-jyeR2fXXWc68st1DTTM5NhkHlx8p+1fKZMfm84Jwq+jSw08IwAjNaZBZR6ts69hhPOfOjg/NiE1HYW7vBRPL3A==", - "dependencies": { - "@hapi/bourne": "^2.0.0", - "args": "^5.0.1", - "colorette": "^1.3.0", - "dateformat": "^4.5.1", - "fast-safe-stringify": "^2.0.7", - "jmespath": "^0.15.0", - "joycon": "^3.0.0", - "pump": "^3.0.0", - "readable-stream": "^3.6.0", - "rfdc": "^1.3.0", - "split2": "^3.1.1", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/@probot/pino/node_modules/pino-pretty/node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/@probot/pino/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/@sentry-internal/tracing": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.59.3.tgz", - "integrity": "sha512-/RkBj/0zQKGsW/UYg6hufrLHHguncLfu4610FCPWpVp0K5Yu5ou8/Aw8D76G3ZxD2TiuSNGwX0o7TYN371ZqTQ==", - "dependencies": { - "@sentry/core": "7.59.3", - "@sentry/types": "7.59.3", - "@sentry/utils": "7.59.3", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/core": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.59.3.tgz", - "integrity": "sha512-cGBOwT9gziIn50fnlBH1WGQlGcHi7wrbvOCyrex4MxKnn1LSBYWBhwU0ymj8DI/9MyPrGDNGkrgpV0WJWBSClg==", - "dependencies": { - "@sentry/types": "7.59.3", - "@sentry/utils": "7.59.3", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/hub": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", - "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", - "dependencies": { - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/hub/node_modules/@sentry/types": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", - "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/hub/node_modules/@sentry/utils": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", - "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", - "dependencies": { - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/hub/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/@sentry/minimal": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", - "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", - "dependencies": { - "@sentry/hub": "6.19.7", - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/minimal/node_modules/@sentry/types": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", - "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/minimal/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/@sentry/node": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.77.0.tgz", - "integrity": "sha512-Ob5tgaJOj0OYMwnocc6G/CDLWC7hXfVvKX/ofkF98+BbN/tQa5poL+OwgFn9BA8ud8xKzyGPxGU6LdZ8Oh3z/g==", - "dependencies": { - "@sentry-internal/tracing": "7.77.0", - "@sentry/core": "7.77.0", - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0", - "https-proxy-agent": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/node/node_modules/@sentry-internal/tracing": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.77.0.tgz", - "integrity": "sha512-8HRF1rdqWwtINqGEdx8Iqs9UOP/n8E0vXUu3Nmbqj4p5sQPA7vvCfq+4Y4rTqZFc7sNdFpDsRION5iQEh8zfZw==", - "dependencies": { - "@sentry/core": "7.77.0", - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/core": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.77.0.tgz", - "integrity": "sha512-Tj8oTYFZ/ZD+xW8IGIsU6gcFXD/gfE+FUxUaeSosd9KHwBQNOLhZSsYo/tTVf/rnQI/dQnsd4onPZLiL+27aTg==", - "dependencies": { - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/types": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.77.0.tgz", - "integrity": "sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/utils": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.77.0.tgz", - "integrity": "sha512-NmM2kDOqVchrey3N5WSzdQoCsyDkQkiRxExPaNI2oKQ/jMWHs9yt0tSy7otPBcXs0AP59ihl75Bvm1tDRcsp5g==", - "dependencies": { - "@sentry/types": "7.77.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/tracing": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.59.3.tgz", - "integrity": "sha512-+gDsfhYdteAR4NyKl3B5JVQs/bXYT73ajoFrlprfDjAJCEVR9W1P4CULavoLtfASxVqBQcZyT87Hsb9/vbn6bg==", - "dependencies": { - "@sentry-internal/tracing": "7.59.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/types": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.59.3.tgz", - "integrity": "sha512-HQ/Pd3YHyIa4HM0bGfOsfI4ZF+sLVs6II9VtlS4hsVporm4ETl3Obld5HywO3aVYvWOk5j/bpAW9JYsxXjRG5A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/utils": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.59.3.tgz", - "integrity": "sha512-Q57xauMKuzd6S+POA1fmulfjzTsb/z118TNAfZZNkHqVB48hHBqgzdhbEBmN4jPCSKV2Cx7VJUoDZxJfzQyLUQ==", - "dependencies": { - "@sentry/types": "7.59.3", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@serdnam/pino-cloudwatch-transport": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@serdnam/pino-cloudwatch-transport/-/pino-cloudwatch-transport-1.0.4.tgz", - "integrity": "sha512-0wtILlFlO/qTFANM1oEMZLKa9REo+mluHN0VTDaOMh15H9Puc+qU4z4jAoZqggFz9Fw9EGG4c+UHpMduZ1EzeQ==", - "dependencies": { - "@aws-sdk/client-cloudwatch-logs": "^3.52.0", - "p-throttle": "^5.0.0", - "pino-abstract-transport": "^0.5.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@serdnam/pino-cloudwatch-transport/node_modules/pino-abstract-transport": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", - "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", - "dependencies": { - "duplexify": "^4.1.2", - "split2": "^4.0.0" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "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/@smithy/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-tb2h0b+JvMee+eAxTmhnyqyNk51UXIK949HnE14lFeezKsVJTB30maan+CO2IMwnig2wVYQH84B5qk6ylmKCuA==", - "dependencies": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-1.0.2.tgz", - "integrity": "sha512-8Bk7CgnVKg1dn5TgnjwPz2ebhxeR7CjGs5yhVYH3S8x0q8yPZZVWwpRIglwXaf5AZBzJlNO1lh+lUhMf2e73zQ==", - "dependencies": { - "@smithy/types": "^1.1.1", - "@smithy/util-config-provider": "^1.0.2", - "@smithy/util-middleware": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-1.0.2.tgz", - "integrity": "sha512-fLjCya+JOu2gPJpCiwSUyoLvT8JdNJmOaTOkKYBZoGf7CzqR6lluSyI+eboZnl/V0xqcfcqBG4tgqCISmWS3/w==", - "dependencies": { - "@smithy/node-config-provider": "^1.0.2", - "@smithy/property-provider": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/url-parser": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-1.0.2.tgz", - "integrity": "sha512-eW/XPiLauR1VAgHKxhVvgvHzLROUgTtqat2lgljztbH8uIYWugv7Nz+SgCavB+hWRazv2iYgqrSy74GvxXq/rg==", - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^1.1.1", - "@smithy/util-hex-encoding": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-1.0.2.tgz", - "integrity": "sha512-kynyofLf62LvR8yYphPPdyHb8fWG3LepFinM/vWUTG2Q1pVpmPCM530ppagp3+q2p+7Ox0UvSqldbKqV/d1BpA==", - "dependencies": { - "@smithy/protocol-http": "^1.1.1", - "@smithy/querystring-builder": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/util-base64": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-1.0.2.tgz", - "integrity": "sha512-K6PKhcUNrJXtcesyzhIvNlU7drfIU7u+EMQuGmPw6RQDAg/ufUcfKHz4EcUhFAodUmN+rrejhRG9U6wxjeBOQA==", - "dependencies": { - "@smithy/types": "^1.1.1", - "@smithy/util-buffer-from": "^1.0.2", - "@smithy/util-utf8": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-1.0.2.tgz", - "integrity": "sha512-B1Y3Tsa6dfC+Vvb+BJMhTHOfFieeYzY9jWQSTR1vMwKkxsymD0OIAnEw8rD/RiDj/4E4RPGFdx9Mdgnyd6Bv5Q==", - "dependencies": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-1.0.2.tgz", - "integrity": "sha512-pkyBnsBRpe+c/6ASavqIMRBdRtZNJEVJOEzhpxZ9JoAXiZYbkfaSMRA/O1dUxGdJ653GHONunnZ4xMo/LJ7utQ==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-1.0.2.tgz", - "integrity": "sha512-pa1/SgGIrSmnEr2c9Apw7CdU4l/HW0fK3+LKFCPDYJrzM0JdYpqjQzgxi31P00eAkL0EFBccpus/p1n2GF9urw==", - "dependencies": { - "@smithy/protocol-http": "^1.1.1", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-1.0.3.tgz", - "integrity": "sha512-GsWvTXMFjSgl617PCE2km//kIjjtvMRrR2GAuRDIS9sHiLwmkS46VWaVYy+XE7ubEsEtzZ5yK2e8TKDR6Qr5Lw==", - "dependencies": { - "@smithy/middleware-serde": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/url-parser": "^1.0.2", - "@smithy/util-middleware": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-1.0.4.tgz", - "integrity": "sha512-G7uRXGFL8c3F7APnoIMTtNAHH8vT4F2qVnAWGAZaervjupaUQuRRHYBLYubK0dWzOZz86BtAXKieJ5p+Ni2Xpg==", - "dependencies": { - "@smithy/protocol-http": "^1.1.1", - "@smithy/service-error-classification": "^1.0.3", - "@smithy/types": "^1.1.1", - "@smithy/util-middleware": "^1.0.2", - "@smithy/util-retry": "^1.0.4", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-1.0.2.tgz", - "integrity": "sha512-T4PcdMZF4xme6koUNfjmSZ1MLi7eoFeYCtodQNQpBNsS77TuJt1A6kt5kP/qxrTvfZHyFlj0AubACoaUqgzPeg==", - "dependencies": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-1.0.2.tgz", - "integrity": "sha512-H7/uAQEcmO+eDqweEFMJ5YrIpsBwmrXSP6HIIbtxKJSQpAcMGY7KrR2FZgZBi1FMnSUOh+rQrbOyj5HQmSeUBA==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-1.0.2.tgz", - "integrity": "sha512-HU7afWpTToU0wL6KseGDR2zojeyjECQfr8LpjAIeHCYIW7r360ABFf4EaplaJRMVoC3hD9FeltgI3/NtShOqCg==", - "dependencies": { - "@smithy/property-provider": "^1.0.2", - "@smithy/shared-ini-file-loader": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-1.0.3.tgz", - "integrity": "sha512-PcPUSzTbIb60VCJCiH0PU0E6bwIekttsIEf5Aoo/M0oTfiqsxHTn0Rcij6QoH6qJy6piGKXzLSegspXg5+Kq6g==", - "dependencies": { - "@smithy/abort-controller": "^1.0.2", - "@smithy/protocol-http": "^1.1.1", - "@smithy/querystring-builder": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-1.0.2.tgz", - "integrity": "sha512-pXDPyzKX8opzt38B205kDgaxda6LHcTfPvTYQZnwP6BAPp1o9puiCPjeUtkKck7Z6IbpXCPUmUQnzkUzWTA42Q==", - "dependencies": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.1.1.tgz", - "integrity": "sha512-mFLFa2sSvlUxm55U7B4YCIsJJIMkA6lHxwwqOaBkral1qxFz97rGffP/mmd4JDuin1EnygiO5eNJGgudiUgmDQ==", - "dependencies": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-1.0.2.tgz", - "integrity": "sha512-6P/xANWrtJhMzTPUR87AbXwSBuz1SDHIfL44TFd/GT3hj6rA+IEv7rftEpPjayUiWRocaNnrCPLvmP31mobOyA==", - "dependencies": { - "@smithy/types": "^1.1.1", - "@smithy/util-uri-escape": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-1.0.2.tgz", - "integrity": "sha512-IWxwxjn+KHWRRRB+K2Ngl+plTwo2WSgc2w+DvLy0DQZJh9UGOpw40d6q97/63GBlXIt4TEt5NbcFrO30CKlrsA==", - "dependencies": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-1.0.3.tgz", - "integrity": "sha512-2eglIYqrtcUnuI71yweu7rSfCgt6kVvRVf0C72VUqrd0LrV1M0BM0eYN+nitp2CHPSdmMI96pi+dU9U/UqAMSA==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-1.0.2.tgz", - "integrity": "sha512-bdQj95VN+lCXki+P3EsDyrkpeLn8xDYiOISBGnUG/AGPYJXN8dmp4EhRRR7XOoLoSs8anZHR4UcGEOzFv2jwGw==", - "dependencies": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-1.0.2.tgz", - "integrity": "sha512-rpKUhmCuPmpV5dloUkOb9w1oBnJatvKQEjIHGmkjRGZnC3437MTdzWej9TxkagcZ8NRRJavYnEUixzxM1amFig==", - "dependencies": { - "@smithy/eventstream-codec": "^1.0.2", - "@smithy/is-array-buffer": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/util-hex-encoding": "^1.0.2", - "@smithy/util-middleware": "^1.0.2", - "@smithy/util-uri-escape": "^1.0.2", - "@smithy/util-utf8": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-1.0.4.tgz", - "integrity": "sha512-gpo0Xl5Nyp9sgymEfpt7oa9P2q/GlM3VmQIdm+FeH0QEdYOQx3OtvwVmBYAMv2FIPWxkMZlsPYRTnEiBTK5TYg==", - "dependencies": { - "@smithy/middleware-stack": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/util-stream": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.1.1.tgz", - "integrity": "sha512-tMpkreknl2gRrniHeBtdgQwaOlo39df8RxSrwsHVNIGXULy5XP6KqgScUw2m12D15wnJCKWxVhCX+wbrBW/y7g==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-1.0.2.tgz", - "integrity": "sha512-0JRsDMQe53F6EHRWksdcavKDRjyqp8vrjakg8EcCUOa7PaFRRB1SO/xGZdzSlW1RSTWQDEksFMTCEcVEKmAoqA==", - "dependencies": { - "@smithy/querystring-parser": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/util-base64": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-1.0.2.tgz", - "integrity": "sha512-BCm15WILJ3SL93nusoxvJGMVfAMWHZhdeDZPtpAaskozuexd0eF6szdz4kbXaKp38bFCSenA6bkUHqaE3KK0dA==", - "dependencies": { - "@smithy/util-buffer-from": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-1.0.2.tgz", - "integrity": "sha512-Xh8L06H2anF5BHjSYTg8hx+Itcbf4SQZnVMl4PIkCOsKtneMJoGjPRLy17lEzfoh/GOaa0QxgCP6lRMQWzNl4w==", - "dependencies": { - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-1.0.2.tgz", - "integrity": "sha512-nXHbZsUtvZeyfL4Ceds9nmy2Uh2AhWXohG4vWHyjSdmT8cXZlJdmJgnH6SJKDjyUecbu+BpKeVvSrA4cWPSOPA==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-1.0.2.tgz", - "integrity": "sha512-lHAYIyrBO9RANrPvccnPjU03MJnWZ66wWuC5GjWWQVfsmPwU6m00aakZkzHdUT6tGCkGacXSgArP5wgTgA+oCw==", - "dependencies": { - "@smithy/is-array-buffer": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-config-provider": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-1.0.2.tgz", - "integrity": "sha512-HOdmDm+3HUbuYPBABLLHtn8ittuRyy+BSjKOA169H+EMc+IozipvXDydf+gKBRAxUa4dtKQkLraypwppzi+PRw==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-1.0.2.tgz", - "integrity": "sha512-J1u2PO235zxY7dg0+ZqaG96tFg4ehJZ7isGK1pCBEA072qxNPwIpDzUVGnLJkHZvjWEGA8rxIauDtXfB0qxeAg==", - "dependencies": { - "@smithy/property-provider": "^1.0.2", - "@smithy/types": "^1.1.1", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-1.0.2.tgz", - "integrity": "sha512-9/BN63rlIsFStvI+AvljMh873Xw6bbI6b19b+PVYXyycQ2DDQImWcjnzRlHW7eP65CCUNGQ6otDLNdBQCgMXqg==", - "dependencies": { - "@smithy/config-resolver": "^1.0.2", - "@smithy/credential-provider-imds": "^1.0.2", - "@smithy/node-config-provider": "^1.0.2", - "@smithy/property-provider": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.4.tgz", - "integrity": "sha512-FPry8j1xye5yzrdnf4xKUXVnkQErxdN7bUIaqC0OFoGsv2NfD9b2UUMuZSSt+pr9a8XWAqj0HoyVNUfPiZ/PvQ==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@smithy/util-endpoints/node_modules/@smithy/node-config-provider": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.5.tgz", - "integrity": "sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==", - "dependencies": { - "@smithy/property-provider": "^2.0.14", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-endpoints/node_modules/@smithy/property-provider": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.14.tgz", - "integrity": "sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-endpoints/node_modules/@smithy/shared-ini-file-loader": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.4.tgz", - "integrity": "sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==", - "dependencies": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-endpoints/node_modules/@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-hex-encoding": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-1.0.2.tgz", - "integrity": "sha512-Bxydb5rMJorMV6AuDDMOxro3BMDdIwtbQKHpwvQFASkmr52BnpDsWlxgpJi8Iq7nk1Bt4E40oE1Isy/7ubHGzg==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-middleware": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-1.0.2.tgz", - "integrity": "sha512-vtXK7GOR2BoseCX8NCGe9SaiZrm9M2lm/RVexFGyPuafTtry9Vyv7hq/vw8ifd/G/pSJ+msByfJVb1642oQHKw==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-retry": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-1.0.4.tgz", - "integrity": "sha512-RnZPVFvRoqdj2EbroDo3OsnnQU8eQ4AlnZTOGusbYKybH3269CFdrZfZJloe60AQjX7di3J6t/79PjwCLO5Khw==", - "dependencies": { - "@smithy/service-error-classification": "^1.0.3", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@smithy/util-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-1.0.2.tgz", - "integrity": "sha512-qyN2M9QFMTz4UCHi6GnBfLOGYKxQZD01Ga6nzaXFFC51HP/QmArU72e4kY50Z/EtW8binPxspP2TAsGbwy9l3A==", - "dependencies": { - "@smithy/fetch-http-handler": "^1.0.2", - "@smithy/node-http-handler": "^1.0.3", - "@smithy/types": "^1.1.1", - "@smithy/util-base64": "^1.0.2", - "@smithy/util-buffer-from": "^1.0.2", - "@smithy/util-hex-encoding": "^1.0.2", - "@smithy/util-utf8": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-uri-escape": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-1.0.2.tgz", - "integrity": "sha512-k8C0BFNS9HpBMHSgUDnWb1JlCQcFG+PPlVBq9keP4Nfwv6a9Q0yAfASWqUCtzjuMj1hXeLhn/5ADP6JxnID1Pg==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-utf8": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-1.0.2.tgz", - "integrity": "sha512-V4cyjKfJlARui0dMBfWJMQAmJzoW77i4N3EjkH/bwnE2Ngbl4tqD2Y0C/xzpzY/J1BdxeCKxAebVFk8aFCaSCw==", - "dependencies": { - "@smithy/util-buffer-from": "^1.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@swc/core": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.99.tgz", - "integrity": "sha512-8O996RfuPC4ieb4zbYMfbyCU9k4gSOpyCNnr7qBQ+o7IEmh8JCV6B8wwu+fT/Om/6Lp34KJe1IpJ/24axKS6TQ==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@swc/counter": "^0.1.1", - "@swc/types": "^0.1.5" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.99", - "@swc/core-darwin-x64": "1.3.99", - "@swc/core-linux-arm64-gnu": "1.3.99", - "@swc/core-linux-arm64-musl": "1.3.99", - "@swc/core-linux-x64-gnu": "1.3.99", - "@swc/core-linux-x64-musl": "1.3.99", - "@swc/core-win32-arm64-msvc": "1.3.99", - "@swc/core-win32-ia32-msvc": "1.3.99", - "@swc/core-win32-x64-msvc": "1.3.99" - }, - "peerDependencies": { - "@swc/helpers": "^0.5.0" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.99.tgz", - "integrity": "sha512-Qj7Jct68q3ZKeuJrjPx7k8SxzWN6PqLh+VFxzA+KwLDpQDPzOlKRZwkIMzuFjLhITO4RHgSnXoDk/Syz0ZeN+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.99.tgz", - "integrity": "sha512-wR7m9QVJjgiBu1PSOHy7s66uJPa45Kf9bZExXUL+JAa9OQxt5y+XVzr+n+F045VXQOwdGWplgPnWjgbUUHEVyw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.99.tgz", - "integrity": "sha512-gcGv1l5t0DScEONmw5OhdVmEI/o49HCe9Ik38zzH0NtDkc+PDYaCcXU5rvfZP2qJFaAAr8cua8iJcOunOSLmnA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.99.tgz", - "integrity": "sha512-XL1/eUsTO8BiKsWq9i3iWh7H99iPO61+9HYiWVKhSavknfj4Plbn+XyajDpxsauln5o8t+BRGitymtnAWJM4UQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.99.tgz", - "integrity": "sha512-fGrXYE6DbTfGNIGQmBefYxSk3rp/1lgbD0nVg4rl4mfFRQPi7CgGhrrqSuqZ/ezXInUIgoCyvYGWFSwjLXt/Qg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.99.tgz", - "integrity": "sha512-kvgZp/mqf3IJ806gUOL6gN6VU15+DfzM1Zv4Udn8GqgXiUAvbQehrtruid4Snn5pZTLj4PEpSCBbxgxK1jbssA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.99.tgz", - "integrity": "sha512-yt8RtZ4W/QgFF+JUemOUQAkVW58cCST7mbfKFZ1v16w3pl3NcWd9OrtppFIXpbjU1rrUX2zp2R7HZZzZ2Zk/aQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.99.tgz", - "integrity": "sha512-62p5fWnOJR/rlbmbUIpQEVRconICy5KDScWVuJg1v3GPLBrmacjphyHiJC1mp6dYvvoEWCk/77c/jcQwlXrDXw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.99.tgz", - "integrity": "sha512-PdppWhkoS45VGdMBxvClVgF1hVjqamtvYd82Gab1i4IV45OSym2KinoDCKE1b6j3LwBLOn2J9fvChGSgGfDCHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", - "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", - "dev": true - }, - "node_modules/@swc/helpers": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.3.tgz", - "integrity": "sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@swc/types": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", - "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/bcryptjs": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz", - "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==", - "dev": true - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==" - }, - "node_modules/@types/bull": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@types/bull/-/bull-4.10.0.tgz", - "integrity": "sha512-RkYW8K2H3J76HT6twmHYbzJ0GtLDDotpLP9ah9gtiA7zfF6peBH1l5fEiK0oeIZ3/642M7Jcb9sPmor8Vf4w6g==", - "deprecated": "This is a stub types definition. bull provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "bull": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cookie-parser": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz", - "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", - "dev": true - }, - "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==" - }, - "node_modules/@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" - }, - "node_modules/@types/ioredis": { - "version": "4.28.10", - "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", - "integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/is-base64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/is-base64/-/is-base64-1.1.1.tgz", - "integrity": "sha512-JgnGhP+MeSHEQmvxcobcwPEP4Ew56voiq9/0hmP/41lyQ/3gBw/ZCIRy2v+QkEOdeCl58lRcrf6+Y6WMlJGETA==" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.5.3", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", - "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", - "dev": true, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/jmespath": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@types/jmespath/-/jmespath-0.15.1.tgz", - "integrity": "sha512-RWN1HQ71Hjl2ixw4a8s7/Bcz6S9uaBTaoCQ5cJB7OsjgHBFi3GaWMy0vRgZBPSYXdsMKFNxGLUUEh9uRf00Spw==", - "dev": true - }, - "node_modules/@types/js-yaml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", - "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==" - }, - "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "node_modules/@types/jsonwebtoken": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz", - "integrity": "sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/libsodium-wrappers": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz", - "integrity": "sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA==" - }, - "node_modules/@types/lodash": { - "version": "4.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" - }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "node_modules/@types/node": { - "version": "18.16.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz", - "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==" - }, - "node_modules/@types/nodemailer": { - "version": "6.4.8", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.8.tgz", - "integrity": "sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/passport": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", - "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/passport-strategy": { - "version": "0.2.35", - "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", - "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", - "dependencies": { - "@types/express": "*", - "@types/passport": "*" - } - }, - "node_modules/@types/pg": { - "version": "8.10.7", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.7.tgz", - "integrity": "sha512-ksJqHipwYaSEHz9e1fr6H6erjoEdNNaOxwyJgPx9bNeaqOW3iWBQgVHfpwiSAoqGzchfc+ZyRLwEfeCcyYD3uQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - } - }, - "node_modules/@types/pg/node_modules/pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/pg/node_modules/postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "dependencies": { - "obuf": "~1.1.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/pg/node_modules/postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/pg/node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==", - "dev": true - }, - "node_modules/@types/pino": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-7.0.5.tgz", - "integrity": "sha512-wKoab31pknvILkxAF8ss+v9iNyhw5Iu/0jLtRkUD74cNfOOLJNnqfFKAv0r7wVaTQxRZtWrMpGfShwwBjOcgcg==", - "deprecated": "This is a stub types definition. pino provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "pino": "*" - } - }, - "node_modules/@types/pino-http": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/@types/pino-http/-/pino-http-5.8.1.tgz", - "integrity": "sha512-A9MW6VCnx5ii7s+Fs5aFIw+aSZcBCpsZ/atpxamu8tTsvWFacxSf2Hrn1Ohn1jkVRB/LiPGOapRXcFawDBnDnA==", - "dependencies": { - "@types/pino": "6.3" - } - }, - "node_modules/@types/pino-http/node_modules/@types/pino": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-6.3.12.tgz", - "integrity": "sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw==", - "dependencies": { - "@types/node": "*", - "@types/pino-pretty": "*", - "@types/pino-std-serializers": "*", - "sonic-boom": "^2.1.0" - } - }, - "node_modules/@types/pino-pretty": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/pino-pretty/-/pino-pretty-5.0.0.tgz", - "integrity": "sha512-N1uzqSzioqz8R3AkDbSJwcfDWeI3YMPNapSQQhnB2ISU4NYgUIcAh+hYT5ygqBM+klX4htpEhXMmoJv3J7GrdA==", - "deprecated": "This is a stub types definition. pino-pretty provides its own type definitions, so you do not need this installed.", - "dependencies": { - "pino-pretty": "*" - } - }, - "node_modules/@types/pino-std-serializers": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", - "integrity": "sha512-gXfUZx2xIBbFYozGms53fT0nvkacx/+62c8iTxrEqH5PkIGAQvDbXg2774VWOycMPbqn5YJBQ3BMsg4Li3dWbg==", - "deprecated": "This is a stub types definition. pino-std-serializers provides its own type definitions, so you do not need this installed.", - "dependencies": { - "pino-std-serializers": "*" - } - }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/superagent": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", - "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", - "dev": true, - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "node_modules/@types/supertest": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", - "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", - "dev": true, - "dependencies": { - "@types/superagent": "*" - } - }, - "node_modules/@types/swagger-jsdoc": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.1.tgz", - "integrity": "sha512-+MUpcbyxD528dECUBCEVm6abNuORdbuGjbrUdHDeAQ+rkPuo2a+L4N02WJHF3bonSSE6SJ3dUJwF2V6+cHnf0w==", - "dev": true - }, - "node_modules/@types/swagger-ui-express": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz", - "integrity": "sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA==", - "dev": true, - "dependencies": { - "@types/express": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" - }, - "node_modules/@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", - "dependencies": { - "@types/node": "*", - "@types/webidl-conversions": "*" - } - }, - "node_modules/@types/xml-crypto": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@types/xml-crypto/-/xml-crypto-1.4.2.tgz", - "integrity": "sha512-1kT+3gVkeBDg7Ih8NefxGYfCApwZViMIs5IEs5AXF6Fpsrnf9CLAEIRh0DYb1mIcRcvysVbe27cHsJD6rJi36w==", - "dependencies": { - "@types/node": "*", - "xpath": "0.0.27" - } - }, - "node_modules/@types/xml-encryption": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/xml-encryption/-/xml-encryption-1.2.1.tgz", - "integrity": "sha512-UeyZkfZFZSa9XCGU5uGgUmsSLwQESDJvF076bJGyDf2gkXJjKvK8fW/x4ckvEHB2M/5RHJEkMc5xI+JrdmCTKA==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/xml2js": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.11.tgz", - "integrity": "sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ucast/core": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@ucast/core/-/core-1.10.2.tgz", - "integrity": "sha512-ons5CwXZ/51wrUPfoduC+cO7AS1/wRb0ybpQJ9RrssossDxVy4t49QxWoWgfBDvVKsz9VXzBk9z0wqTdZ+Cq8g==" - }, - "node_modules/@ucast/js": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@ucast/js/-/js-3.0.3.tgz", - "integrity": "sha512-jBBqt57T5WagkAjqfCIIE5UYVdaXYgGkOFYv2+kjq2AVpZ2RIbwCo/TujJpDlwTVluUI+WpnRpoGU2tSGlEvFQ==", - "dependencies": { - "@ucast/core": "^1.0.0" - } - }, - "node_modules/@ucast/mongo": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@ucast/mongo/-/mongo-2.4.3.tgz", - "integrity": "sha512-XcI8LclrHWP83H+7H2anGCEeDq0n+12FU2mXCTz6/Tva9/9ddK/iacvvhCyW6cijAAOILmt0tWplRyRhVyZLsA==", - "dependencies": { - "@ucast/core": "^1.4.1" - } - }, - "node_modules/@ucast/mongo2js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@ucast/mongo2js/-/mongo2js-1.3.4.tgz", - "integrity": "sha512-ahazOr1HtelA5AC1KZ9x0UwPMqqimvfmtSm/PRRSeKKeE5G2SCqTgwiNzO7i9jS8zA3dzXpKVPpXMkcYLnyItA==", - "dependencies": { - "@ucast/core": "^1.6.1", - "@ucast/js": "^3.0.0", - "@ucast/mongo": "^2.4.0" - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argon2": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.30.3.tgz", - "integrity": "sha512-DoH/kv8c9127ueJSBxAVJXinW9+EuPA3EMUxoV2sAY1qDE5H9BjTyVF/aD2XyHqbqUWabgBkIfcP3ZZuGhbJdg==", - "hasInstallScript": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.10", - "@phc/format": "^1.0.0", - "node-addon-api": "^5.0.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/args": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz", - "integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==", - "dependencies": { - "camelcase": "5.0.0", - "chalk": "2.4.2", - "leven": "2.1.0", - "mri": "1.1.4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/args/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/args/node_modules/camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/args/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/args/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/args/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/args/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/args/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/args/node_modules/leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/args/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sdk": { - "version": "2.1419.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1419.0.tgz", - "integrity": "sha512-JcD8gb8I5fH/TGdObG8UYyyXfnqVYk50wx9TGao6G/xBYT3YoYeQXj020W568YQpO+dBKRuR4U2LRYdKBNmQ/g==", - "dependencies": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "util": "^0.12.4", - "uuid": "8.0.0", - "xml2js": "0.5.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/aws-sdk/node_modules/uuid": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", - "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axios-retry": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.5.1.tgz", - "integrity": "sha512-mQRJ4IyAUnYig14BQ4MnnNHHuH1cNH7NW4JxEUD6mNJwK6pwOY66wKLCwZ6Y0o3POpfStalqRC+J4+Hnn6Om7w==", - "dependencies": { - "@babel/runtime": "^7.15.4", - "is-retry-allowed": "^2.2.0" - } - }, - "node_modules/babel-jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", - "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", - "dev": true, - "dependencies": { - "@jest/transform": "^29.6.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", - "engines": { - "node": ">=6.0.0" - } - }, - "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.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", - "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", - "hasInstallScript": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.10", - "node-addon-api": "^5.0.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "node_modules/bigint-conversion": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.4.1.tgz", - "integrity": "sha512-/DTRevseMZoqN4KLkN5BryOiom0KbwYajiXG5Vo+ZcEPAO0WBZyZoYyDZSgfeq/v/oegLo9bjdndDBlExvAhBQ==", - "dependencies": { - "@juanelas/base64": "^1.1.2" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==" - }, - "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", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/bson": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", - "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", - "engines": { - "node": ">=14.20.1" - } - }, - "node_modules/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==" - }, - "node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "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==" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/bull": { - "version": "4.10.4", - "resolved": "https://registry.npmjs.org/bull/-/bull-4.10.4.tgz", - "integrity": "sha512-o9m/7HjS/Or3vqRd59evBlWCXd9Lp+ALppKseoSKHaykK46SmRjAilX98PgmOz1yeVaurt8D5UtvEt4bUjM3eA==", - "dev": true, - "dependencies": { - "cron-parser": "^4.2.1", - "debuglog": "^1.0.0", - "get-port": "^5.1.1", - "ioredis": "^5.0.0", - "lodash": "^4.17.21", - "msgpackr": "^1.5.2", - "semver": "^7.3.2", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", - "dev": true, - "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001517", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", - "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "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==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", - "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cookie-parser/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "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==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cron-parser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.8.1.tgz", - "integrity": "sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==", - "dev": true, - "dependencies": { - "luxon": "^3.2.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "engines": { - "node": "*" - } - }, - "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/debuglog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defaults/node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dev": true, - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" - } - }, - "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==", - "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", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.467", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.467.tgz", - "integrity": "sha512-2qI70O+rR4poYeF2grcuS/bCps5KJh6y1jtZMDDEteyKJQrzLOEhFyXCLcHW6DTBjKjWkk26JhWoAi+Ux9A0fg==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-unused-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", - "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", - "dev": true, - "dependencies": { - "eslint-rule-composer": "^0.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - } - } - }, - "node_modules/eslint-rule-composer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", - "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/eventsource": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", - "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.6.1", - "@types/node": "*", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express-async-errors": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", - "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==", - "peerDependencies": { - "express": "^4.16.2" - } - }, - "node_modules/express-handlebars": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.7.tgz", - "integrity": "sha512-iYeMFpc/hMD+E6FNAZA5fgWeXnXr4rslOSPkeEV6TwdmpJ5lEXuWX0u9vFYs31P2MURctQq2batR09oeNj0LIg==", - "dependencies": { - "glob": "^8.1.0", - "graceful-fs": "^4.2.10", - "handlebars": "^4.7.7" - }, - "engines": { - "node": ">=v12.22.9" - } - }, - "node_modules/express-handlebars/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==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/express-handlebars/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "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/express-handlebars/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/express-rate-limit": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.8.0.tgz", - "integrity": "sha512-yVeDWczkh8qgo9INJB1tT4j7LFu+n6ei/oqSMsqpsUIGYjTM+gk+Q3wv19TMUdo8chvus8XohAuOhG7RYRM9ZQ==", - "engines": { - "node": ">= 14.0.0" - }, - "peerDependencies": { - "express": "^4 || ^5" - } - }, - "node_modules/express-validator": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.15.0.tgz", - "integrity": "sha512-r05VYoBL3i2pswuehoFSy+uM8NBuVaY7avp5qrYjQBDzagx2Z5A77FZqPT8/gNLF3HopWkIzaTFaC4JysWXLqg==", - "dependencies": { - "lodash": "^4.17.21", - "validator": "^13.9.0" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-redact": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.2.0.tgz", - "integrity": "sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "dependencies": { - "punycode": "^1.3.2" - } - }, - "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", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formidable": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", - "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", - "dev": true, - "dependencies": { - "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", - "once": "^1.4.0", - "qs": "^6.11.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dependencies": { - "is-property": "^1.0.2" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/helmet": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-5.1.1.tgz", - "integrity": "sha512-/yX0oVZBggA9cLJh8aw3PPCfedBnbd7J2aowjzsaWwZh7/UFY0nccn/aHAggIgWUFfnykX8GKd3a1pSbrmlcVQ==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "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==", - "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==", - "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==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/infisical-node": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.3.2.tgz", - "integrity": "sha512-o1rxfOBAmpTiipka9Xnfa2AgTS8CkJHo0aRQwk6UGi+yEkKzXS7dDM7bZD56M/z+yKGLK15QkfFGZXp1VomlHw==", - "dependencies": { - "axios": "^1.3.3", - "dotenv": "^16.0.3", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/install": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", - "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ioredis": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", - "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", - "dependencies": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" - } - }, - "node_modules/ioredis/node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "node_modules/ip6addr": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/ip6addr/-/ip6addr-0.2.5.tgz", - "integrity": "sha512-9RGGSB6Zc9Ox5DpDGFnJdIeF0AsqXzdH+FspCfPPaU/L/4tI6P+5lIoFUFm9JXs9IrJv1boqAaNCQmoDADTSKQ==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-base64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-base64/-/is-base64-1.1.0.tgz", - "integrity": "sha512-Nlhg7Z2dVC4/PTvIFkgVVNvPHSO2eR/Yd0XzhGiXCXEvWnptXlXa/clQ8aePPiMuxEGcWfzWbGw2Fe3d+Y3v1g==", - "bin": { - "is_base64": "bin/is-base64", - "is-base64": "bin/is-base64" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" - }, - "node_modules/is-retry-allowed": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", - "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dependencies": { - "which-typed-array": "^1.1.11" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", - "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", - "dev": true, - "dependencies": { - "@jest/core": "^29.6.1", - "@jest/types": "^29.6.1", - "import-local": "^3.0.2", - "jest-cli": "^29.6.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "dependencies": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", - "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.1", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "p-limit": "^3.1.0", - "pretty-format": "^29.6.1", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", - "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", - "dev": true, - "dependencies": { - "@jest/core": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", - "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.1", - "@jest/types": "^29.6.1", - "babel-jest": "^29.6.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.1", - "jest-environment-node": "^29.6.1", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.6.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", - "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", - "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.6.1", - "pretty-format": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", - "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", - "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-junit": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-15.0.0.tgz", - "integrity": "sha512-Z5sVX0Ag3HZdMUnD5DFlG+1gciIFSy7yIVPhOdGUi8YJaI9iLvvBb530gtQL2CHmv0JJeiwRZenr0VrSR7frvg==", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "strip-ansi": "^6.0.1", - "uuid": "^8.3.2", - "xml": "^1.0.1" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", - "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", - "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.6.1", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", - "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", - "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "jest-util": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", - "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", - "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", - "dev": true, - "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", - "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", - "dev": true, - "dependencies": { - "@jest/console": "^29.6.1", - "@jest/environment": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-leak-detector": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-resolve": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-util": "^29.6.1", - "jest-watcher": "^29.6.1", - "jest-worker": "^29.6.1", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", - "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/globals": "^29.6.1", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", - "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.6.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.1", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "natural-compare": "^1.4.0", - "pretty-format": "^29.6.1", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", - "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", - "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "leven": "^3.1.0", - "pretty-format": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-watcher": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", - "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.6.1", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", - "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.6.1", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonwebtoken": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", - "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", - "dependencies": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "node_modules/jsrp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/jsrp/-/jsrp-0.2.4.tgz", - "integrity": "sha512-+CjGAhZaj3k2MMXEy+xWYv7xJGnise/SlL1IIvnRuJ1ZiLtNPJJln/dMDCgORQCq1ouXDnW1FBxW5bkBFhK/8g==", - "dependencies": { - "create-hash": "^1.0.0", - "jsbn": "^1.0.0", - "randombytes": "^2.0.0" - } - }, - "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==", - "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==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kareem": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", - "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libsodium": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.11.tgz", - "integrity": "sha512-WPfJ7sS53I2s4iM58QxY3Inb83/6mjlYgcmZs7DJsvDlnmVUwNinBCi5vBT43P6bHRy01O4zsMU2CoVR6xJ40A==" - }, - "node_modules/libsodium-wrappers": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.11.tgz", - "integrity": "sha512-SrcLtXj7BM19vUKtQuyQKiQCRJPgbpauzl3s0rSwD+60wtHqSUuqcoawlMDheCJga85nKOQwxNYQxf/CKAvs6Q==", - "dependencies": { - "libsodium": "^0.7.11" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dependencies": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, - "node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/luxon": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", - "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/maxmind": { - "version": "4.3.11", - "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.11.tgz", - "integrity": "sha512-tJDrKbUzN6PSA88tWgg0L2R4Ln00XwecYQJPFI+RvlF2k1sx6VQYtuQ1SVxm8+bw5tF7GWV4xyb+3/KyzEpPUw==", - "dev": true, - "dependencies": { - "mmdb-lib": "2.0.2", - "tiny-lru": "11.0.1" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mmdb-lib": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mmdb-lib/-/mmdb-lib-2.0.2.tgz", - "integrity": "sha512-shi1I+fCPQonhTi7qyb6hr7hi87R7YS69FlfJiMFuJ12+grx0JyL56gLNzGTYXPU7EhAPkMLliGeyHer0K+AVA==", - "dev": true, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, - "node_modules/mongodb": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", - "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==", - "dependencies": { - "bson": "^5.5.0", - "mongodb-connection-string-url": "^2.6.0", - "socks": "^2.7.1" - }, - "engines": { - "node": ">=14.20.1" - }, - "optionalDependencies": { - "@mongodb-js/saslprep": "^1.1.0" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.0.0", - "kerberos": "^1.0.0 || ^2.0.0", - "mongodb-client-encryption": ">=2.3.0 <3", - "snappy": "^7.2.2" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", - "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", - "dependencies": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" - } - }, - "node_modules/mongoose": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.3.tgz", - "integrity": "sha512-moYP2qWCOdWRDeBxqB/zYwQmQnTBsF5DoolX5uPyI218BkiA1ujGY27P0NTd4oWIX+LLkZPw0LDzlc/7oh1plg==", - "dependencies": { - "bson": "^5.5.0", - "kareem": "2.5.1", - "mongodb": "5.9.0", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "16.0.1" - }, - "engines": { - "node": ">=14.20.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" - } - }, - "node_modules/mongoose/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==" - }, - "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "dev": true, - "dependencies": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/morgan/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/morgan/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/morgan/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", - "dependencies": { - "debug": "4.x" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/mri": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", - "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==", - "engines": { - "node": ">=4" - } - }, - "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/msgpackr": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.9.6.tgz", - "integrity": "sha512-50rmb6+ZWvEm0vJn8R8CwI1Eavss3h5rgtKrcdUal3EkZcpqw82+xsmc7RoHb8fYB5V4EOU2NDaOitDAdO0t+w==", - "dev": true, - "optionalDependencies": { - "msgpackr-extract": "^3.0.2" - } - }, - "node_modules/msgpackr-extract": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", - "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-gyp-build-optional-packages": "5.0.7" - }, - "bin": { - "download-msgpackr-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2" - } - }, - "node_modules/mysql2": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.2.tgz", - "integrity": "sha512-m5erE6bMoWfPXW1D5UrVwlT8PowAoSX69KcZzPuARQ3wY1RJ52NW9PdvdPo076XiSIkQ5IBTis7hxdlrQTlyug==", - "dependencies": { - "denque": "^2.1.0", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.3", - "long": "^5.2.1", - "lru-cache": "^8.0.0", - "named-placeholders": "^1.1.3", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/mysql2/node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mysql2/node_modules/lru-cache": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", - "engines": { - "node": ">=16.14" - } - }, - "node_modules/mysql2/node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/named-placeholders": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", - "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", - "dependencies": { - "lru-cache": "^7.14.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - }, - "node_modules/node-cache": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", - "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", - "dependencies": { - "clone": "2.x" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", - "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", - "dev": true, - "optional": true, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true - }, - "node_modules/nodemailer": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", - "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/nodemon": { - "version": "2.0.22", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", - "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^3.2.7", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^5.7.1", - "simple-update-notifier": "^1.0.7", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm": { - "version": "8.19.4", - "resolved": "https://registry.npmjs.org/npm/-/npm-8.19.4.tgz", - "integrity": "sha512-3HANl8i9DKnUA89P4KEgVNN28EjSeDCmvEqbzOAuxCFDzdBZzjUl99zgnGpOUumvW5lvJo2HKcjrsc+tfyv1Hw==", - "bundleDependencies": [ - "@isaacs/string-locale-compare", - "@npmcli/arborist", - "@npmcli/ci-detect", - "@npmcli/config", - "@npmcli/fs", - "@npmcli/map-workspaces", - "@npmcli/package-json", - "@npmcli/run-script", - "abbrev", - "archy", - "cacache", - "chalk", - "chownr", - "cli-columns", - "cli-table3", - "columnify", - "fastest-levenshtein", - "fs-minipass", - "glob", - "graceful-fs", - "hosted-git-info", - "ini", - "init-package-json", - "is-cidr", - "json-parse-even-better-errors", - "libnpmaccess", - "libnpmdiff", - "libnpmexec", - "libnpmfund", - "libnpmhook", - "libnpmorg", - "libnpmpack", - "libnpmpublish", - "libnpmsearch", - "libnpmteam", - "libnpmversion", - "make-fetch-happen", - "minimatch", - "minipass", - "minipass-pipeline", - "mkdirp", - "mkdirp-infer-owner", - "ms", - "node-gyp", - "nopt", - "npm-audit-report", - "npm-install-checks", - "npm-package-arg", - "npm-pick-manifest", - "npm-profile", - "npm-registry-fetch", - "npm-user-validate", - "npmlog", - "opener", - "p-map", - "pacote", - "parse-conflict-json", - "proc-log", - "qrcode-terminal", - "read", - "read-package-json", - "read-package-json-fast", - "readdir-scoped-modules", - "rimraf", - "semver", - "ssri", - "tar", - "text-table", - "tiny-relative-date", - "treeverse", - "validate-npm-package-name", - "which", - "write-file-atomic" - ], - "dev": true, - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^5.6.3", - "@npmcli/ci-detect": "^2.0.0", - "@npmcli/config": "^4.2.1", - "@npmcli/fs": "^2.1.0", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/package-json": "^2.0.0", - "@npmcli/run-script": "^4.2.1", - "abbrev": "~1.1.1", - "archy": "~1.0.0", - "cacache": "^16.1.3", - "chalk": "^4.1.2", - "chownr": "^2.0.0", - "cli-columns": "^4.0.0", - "cli-table3": "^0.6.2", - "columnify": "^1.6.0", - "fastest-levenshtein": "^1.0.12", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "graceful-fs": "^4.2.10", - "hosted-git-info": "^5.2.1", - "ini": "^3.0.1", - "init-package-json": "^3.0.2", - "is-cidr": "^4.0.2", - "json-parse-even-better-errors": "^2.3.1", - "libnpmaccess": "^6.0.4", - "libnpmdiff": "^4.0.5", - "libnpmexec": "^4.0.14", - "libnpmfund": "^3.0.5", - "libnpmhook": "^8.0.4", - "libnpmorg": "^4.0.4", - "libnpmpack": "^4.1.3", - "libnpmpublish": "^6.0.5", - "libnpmsearch": "^5.0.4", - "libnpmteam": "^4.0.4", - "libnpmversion": "^3.0.7", - "make-fetch-happen": "^10.2.0", - "minimatch": "^5.1.0", - "minipass": "^3.1.6", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "ms": "^2.1.2", - "node-gyp": "^9.1.0", - "nopt": "^6.0.0", - "npm-audit-report": "^3.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.1.0", - "npm-pick-manifest": "^7.0.2", - "npm-profile": "^6.2.0", - "npm-registry-fetch": "^13.3.1", - "npm-user-validate": "^1.0.1", - "npmlog": "^6.0.2", - "opener": "^1.5.2", - "p-map": "^4.0.0", - "pacote": "^13.6.2", - "parse-conflict-json": "^2.0.2", - "proc-log": "^2.0.1", - "qrcode-terminal": "^0.12.0", - "read": "~1.0.7", - "read-package-json": "^5.0.2", - "read-package-json-fast": "^2.0.3", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.1", - "tar": "^6.1.11", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^2.0.0", - "validate-npm-package-name": "^4.0.0", - "which": "^2.0.2", - "write-file-atomic": "^4.0.1" - }, - "bin": { - "npm": "bin/npm-cli.js", - "npx": "bin/npx-cli.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/@colors/colors": { - "version": "1.5.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/npm/node_modules/@gar/promisify": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "5.6.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/metavuln-calculator": "^3.0.1", - "@npmcli/move-file": "^2.0.0", - "@npmcli/name-from-folder": "^1.0.1", - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/package-json": "^2.0.0", - "@npmcli/query": "^1.2.0", - "@npmcli/run-script": "^4.1.3", - "bin-links": "^3.0.3", - "cacache": "^16.1.3", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^5.2.1", - "json-parse-even-better-errors": "^2.3.1", - "json-stringify-nice": "^1.1.4", - "minimatch": "^5.1.0", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^6.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.0.0", - "npm-pick-manifest": "^7.0.2", - "npm-registry-fetch": "^13.0.0", - "npmlog": "^6.0.2", - "pacote": "^13.6.1", - "parse-conflict-json": "^2.0.1", - "proc-log": "^2.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^1.0.1", - "read-package-json-fast": "^2.0.2", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.0", - "treeverse": "^2.0.0", - "walk-up-path": "^1.0.0" - }, - "bin": { - "arborist": "bin/index.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/ci-detect": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/npm/node_modules/@npmcli/config": { - "version": "4.2.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/map-workspaces": "^2.0.2", - "ini": "^3.0.0", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^6.0.0", - "proc-log": "^2.0.0", - "read-package-json-fast": "^2.0.3", - "semver": "^7.3.5", - "walk-up-path": "^1.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/disparity-colors": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ansi-styles": "^4.3.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/fs": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/git": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^3.0.0", - "lru-cache": "^7.4.4", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^7.0.0", - "proc-log": "^2.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents": { - "version": "1.0.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - }, - "bin": { - "installed-package-contents": "index.js" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents/node_modules/npm-bundled": { - "version": "1.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "2.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/name-from-folder": "^1.0.1", - "glob": "^8.0.1", - "minimatch": "^5.0.1", - "read-package-json-fast": "^2.0.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cacache": "^16.0.0", - "json-parse-even-better-errors": "^2.3.1", - "pacote": "^13.0.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/move-file": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^2.3.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "infer-owner": "^1.0.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/query": { - "version": "1.2.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^9.1.0", - "postcss-selector-parser": "^6.0.10", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "4.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/@tootallnate/once": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/abbrev": { - "version": "1.1.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/agent-base": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/npm/node_modules/agentkeepalive": { - "version": "4.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/npm/node_modules/aggregate-error": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/aproba": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/archy": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/are-we-there-yet": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/asap": { - "version": "2.0.6", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/bin-links": { - "version": "3.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cmd-shim": "^5.0.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0", - "read-cmd-shim": "^3.0.0", - "rimraf": "^3.0.0", - "write-file-atomic": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/bin-links/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/binary-extensions": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/builtins": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/npm/node_modules/cacache": { - "version": "16.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/npm/node_modules/chownr": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/cidr-regex": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "ip-regex": "^4.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/clean-stack": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/cli-columns": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/cli-table3": { - "version": "0.6.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/npm/node_modules/clone": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/cmd-shim": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "mkdirp-infer-owner": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/npm/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/color-support": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/npm/node_modules/columnify": { - "version": "1.6.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/console-control-strings": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/debug": { - "version": "4.3.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/debuglog": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/defaults": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/npm/node_modules/delegates": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/depd": { - "version": "1.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/dezalgo": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "node_modules/npm/node_modules/diff": { - "version": "5.1.0", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/npm/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/encoding": { - "version": "0.1.13", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/npm/node_modules/env-paths": { - "version": "2.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/err-code": { - "version": "2.0.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/fastest-levenshtein": { - "version": "1.0.12", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/fs-minipass": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/function-bind": { - "version": "1.1.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/gauge": { - "version": "4.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/glob": { - "version": "8.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "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/npm/node_modules/graceful-fs": { - "version": "4.2.10", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/has": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/npm/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/has-unicode": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/hosted-git-info": { - "version": "5.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/http-proxy-agent": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/https-proxy-agent": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/humanize-ms": { - "version": "1.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/npm/node_modules/iconv-lite": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/ignore-walk": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minimatch": "^5.0.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/npm/node_modules/indent-string": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/infer-owner": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/npm/node_modules/inherits": { - "version": "2.0.4", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/ini": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/init-package-json": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^9.0.1", - "promzard": "^0.3.0", - "read": "^1.0.7", - "read-package-json": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/ip": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/ip-regex": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-cidr": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "cidr-regex": "^3.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/is-core-module": { - "version": "2.10.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/npm/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-lambda": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/json-stringify-nice": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff": { - "version": "5.1.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff-apply": { - "version": "5.4.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/libnpmaccess": { - "version": "6.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "minipass": "^3.1.1", - "npm-package-arg": "^9.0.1", - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmdiff": { - "version": "4.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/disparity-colors": "^2.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "binary-extensions": "^2.2.0", - "diff": "^5.1.0", - "minimatch": "^5.0.1", - "npm-package-arg": "^9.0.1", - "pacote": "^13.6.1", - "tar": "^6.1.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmexec": { - "version": "4.0.14", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^5.6.3", - "@npmcli/ci-detect": "^2.0.0", - "@npmcli/fs": "^2.1.1", - "@npmcli/run-script": "^4.2.0", - "chalk": "^4.1.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-package-arg": "^9.0.1", - "npmlog": "^6.0.2", - "pacote": "^13.6.1", - "proc-log": "^2.0.0", - "read": "^1.0.7", - "read-package-json-fast": "^2.0.2", - "semver": "^7.3.7", - "walk-up-path": "^1.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmfund": { - "version": "3.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^5.6.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "8.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmorg": { - "version": "4.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpack": { - "version": "4.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/run-script": "^4.1.3", - "npm-package-arg": "^9.0.1", - "pacote": "^13.6.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpublish": { - "version": "6.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "normalize-package-data": "^4.0.0", - "npm-package-arg": "^9.0.1", - "npm-registry-fetch": "^13.0.0", - "semver": "^7.3.7", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmsearch": { - "version": "5.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmteam": { - "version": "4.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/libnpmversion": { - "version": "3.0.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^3.0.0", - "@npmcli/run-script": "^4.1.3", - "json-parse-even-better-errors": "^2.3.1", - "proc-log": "^2.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/lru-cache": { - "version": "7.13.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/make-fetch-happen": { - "version": "10.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/minimatch": { - "version": "5.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/minipass": { - "version": "3.3.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-collect": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-fetch": { - "version": "2.1.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/minipass-flush": { - "version": "1.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-json-stream": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "node_modules/npm/node_modules/minipass-pipeline": { - "version": "1.2.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minizlib": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/mkdirp": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/mkdirp-infer-owner": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "infer-owner": "^1.0.4", - "mkdirp": "^1.0.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/mute-stream": { - "version": "0.0.8", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/negotiator": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/node-gyp": { - "version": "9.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.22 || ^14.13 || >=16" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/nopt": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/nopt": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "4.0.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-audit-report": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-bundled": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-bundled/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-install-checks": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/npm-package-arg": { - "version": "9.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-packlist": { - "version": "5.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^8.0.1", - "ignore-walk": "^5.0.1", - "npm-bundled": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "bin": { - "npm-packlist": "bin/index.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-packlist/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^5.0.0", - "npm-normalize-package-bin": "^2.0.0", - "npm-package-arg": "^9.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-profile": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "13.3.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "make-fetch-happen": "^10.0.6", - "minipass": "^3.1.6", - "minipass-fetch": "^2.0.3", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.1", - "proc-log": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/npm-user-validate": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/npmlog": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/once": { - "version": "1.4.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/npm/node_modules/opener": { - "version": "1.5.2", - "dev": true, - "inBundle": true, - "license": "(WTFPL OR MIT)", - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/npm/node_modules/p-map": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/pacote": { - "version": "13.6.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^3.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^4.1.0", - "cacache": "^16.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.6", - "mkdirp": "^1.0.4", - "npm-package-arg": "^9.0.0", - "npm-packlist": "^5.1.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^5.0.0", - "read-package-json-fast": "^2.0.3", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "lib/bin.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/parse-conflict-json": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^2.3.1", - "just-diff": "^5.0.1", - "just-diff-apply": "^5.2.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.0.10", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/proc-log": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/promise-all-reject-late": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-call-limit": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-inflight": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/promise-retry": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/promzard": { - "version": "0.3.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "read": "1" - } - }, - "node_modules/npm/node_modules/qrcode-terminal": { - "version": "0.12.0", - "dev": true, - "inBundle": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } - }, - "node_modules/npm/node_modules/read": { - "version": "1.0.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/read-cmd-shim": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/read-package-json": { - "version": "5.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^8.0.1", - "json-parse-even-better-errors": "^2.3.1", - "normalize-package-data": "^4.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "2.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/read-package-json/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/readdir-scoped-modules": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "node_modules/npm/node_modules/retry": { - "version": "0.12.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm/node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/safe-buffer": { - "version": "5.2.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/safer-buffer": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/npm/node_modules/semver": { - "version": "7.3.7", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/set-blocking": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/signal-exit": { - "version": "3.0.7", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/smart-buffer": { - "version": "4.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks": { - "version": "2.7.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/spdx-correct": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.3.0", - "dev": true, - "inBundle": true, - "license": "CC-BY-3.0" - }, - "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.11", - "dev": true, - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/npm/node_modules/ssri": { - "version": "9.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/string_decoder": { - "version": "1.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/npm/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/tar": { - "version": "6.1.11", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/treeverse": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/unique-filename": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/unique-slug": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/validate-npm-package-license": { - "version": "3.0.4", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/walk-up-path": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/wcwidth": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/npm/node_modules/which": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/wide-align": { - "version": "1.1.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/npm/node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/write-file-atomic": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/octokit-auth-probot": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/octokit-auth-probot/-/octokit-auth-probot-1.2.9.tgz", - "integrity": "sha512-mMjw6Y760EwJnW2tSVooJK8BMdsG6D40SoCclnefVf/5yWjaNVquEu8NREBVWb60OwbpnMEz4vREXHB5xdMFYQ==", - "dependencies": { - "@octokit/auth-app": "^4.0.2", - "@octokit/auth-token": "^3.0.0", - "@octokit/auth-unauthenticated": "^3.0.0", - "@octokit/types": "^8.0.0" - }, - "peerDependencies": { - "@octokit/core": ">=3.2" - } - }, - "node_modules/octokit-auth-probot/node_modules/@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" - }, - "node_modules/octokit-auth-probot/node_modules/@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "dependencies": { - "@octokit/openapi-types": "^14.0.0" - } - }, - "node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-throttle": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/p-throttle/-/p-throttle-5.1.0.tgz", - "integrity": "sha512-+N+s2g01w1Zch4D0K3OpnPDqLOKmLcQ4BvIFq3JC0K29R28vUOjWpO+OJZBNt8X9i3pFCksZJZ0YXkUGjaFE6g==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", - "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", - "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1", - "utils-merge": "^1.0.1" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/passport-github": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/passport-github/-/passport-github-1.1.0.tgz", - "integrity": "sha512-XARXJycE6fFh/dxF+Uut8OjlwbFEXgbPVj/+V+K7cvriRK7VcAOm+NgBmbiLM9Qv3SSxEAV+V6fIk89nYHXa8A==", - "dependencies": { - "passport-oauth2": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-gitlab2": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/passport-gitlab2/-/passport-gitlab2-5.0.0.tgz", - "integrity": "sha512-cXQMgM6JQx9wHVh7JLH30D8fplfwjsDwRz+zS0pqC8JS+4bNmc1J04NGp5g2M4yfwylH9kQRrMN98GxMw7q7cg==", - "dependencies": { - "passport-oauth2": "^1.4.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/passport-google-oauth20": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", - "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", - "dependencies": { - "passport-oauth2": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-oauth2": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", - "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", - "dependencies": { - "base64url": "3.x.x", - "oauth": "0.9.x", - "passport-strategy": "1.x.x", - "uid2": "0.0.x", - "utils-merge": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" - }, - "node_modules/pg": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", - "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dependencies": { - "split2": "^4.1.0" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/pino": { - "version": "8.16.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.16.1.tgz", - "integrity": "sha512-3bKsVhBmgPjGV9pyn4fO/8RtoVDR8ssW1ev819FsRXlRNgW8gR/9Kx+gCK4UPWd4JjrRDLWpzd/pb1AyWm3MGA==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "v1.1.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.7.0", - "thread-stream": "^2.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", - "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/pino-abstract-transport/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-abstract-transport/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/pino-abstract-transport/node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/pino-abstract-transport/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==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-http": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-8.5.1.tgz", - "integrity": "sha512-T/3d9YHKBYpv/QHjNy73P5BNYYkRrC2/D6CxKMecG4fKFLN+B2iC6LsKYzGRTRV+Ld3fjxFC1ca4TUGbPdzk+Q==", - "dependencies": { - "get-caller-file": "^2.0.5", - "pino": "^8.0.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0" - } - }, - "node_modules/pino-pretty": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.2.3.tgz", - "integrity": "sha512-4jfIUc8TC1GPUfDyMSlW1STeORqkoxec71yhxIpLDQapUu8WOuoz2TTCoidrIssyz78LZC69whBMPIKCMbi3cw==", - "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", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-pretty/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-pretty/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/pino-pretty/node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "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==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-pretty/node_modules/sonic-boom": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.7.0.tgz", - "integrity": "sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/pino-std-serializers": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" - }, - "node_modules/pino/node_modules/sonic-boom": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.7.0.tgz", - "integrity": "sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-conf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "dependencies": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "node_modules/posthog-node": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-2.6.0.tgz", - "integrity": "sha512-/BiFw/jwdP0uJSRAIoYqLoBTjZ612xv74b1L/a3T/p1nJVL8e0OrHuxbJW56c6WVW/IKm9gBF/zhbqfaz0XgJQ==", - "dependencies": { - "axios": "^0.27.0" - }, - "engines": { - "node": ">=15.0.0" - } - }, - "node_modules/posthog-node/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-format": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", - "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/probot": { - "version": "12.3.3", - "resolved": "https://registry.npmjs.org/probot/-/probot-12.3.3.tgz", - "integrity": "sha512-cdtKd+xISzi8sw6++BYBXleRknCA6hqUMoHj/sJqQBrjbNxQLhfeFCq9O2d0Z4eShsy5YFRR3MWwDKJ9uAE0CA==", - "dependencies": { - "@octokit/core": "^3.2.4", - "@octokit/plugin-enterprise-compatibility": "^1.2.8", - "@octokit/plugin-paginate-rest": "^2.6.2", - "@octokit/plugin-rest-endpoint-methods": "^5.0.1", - "@octokit/plugin-retry": "^3.0.6", - "@octokit/plugin-throttling": "^3.3.4", - "@octokit/types": "^8.0.0", - "@octokit/webhooks": "^9.26.3", - "@probot/get-private-key": "^1.1.0", - "@probot/octokit-plugin-config": "^1.0.0", - "@probot/pino": "^2.2.0", - "@types/express": "^4.17.9", - "@types/ioredis": "^4.27.1", - "@types/pino": "^6.3.4", - "@types/pino-http": "^5.0.6", - "commander": "^6.2.0", - "deepmerge": "^4.2.2", - "deprecation": "^2.3.1", - "dotenv": "^8.2.0", - "eventsource": "^2.0.2", - "express": "^4.17.1", - "express-handlebars": "^6.0.3", - "ioredis": "^4.27.8", - "js-yaml": "^3.14.1", - "lru-cache": "^6.0.0", - "octokit-auth-probot": "^1.2.2", - "pino": "^6.7.0", - "pino-http": "^5.3.0", - "pkg-conf": "^3.1.0", - "resolve": "^1.19.0", - "semver": "^7.3.4", - "update-dotenv": "^1.1.1", - "uuid": "^8.3.2" - }, - "bin": { - "probot": "bin/probot.js" - }, - "engines": { - "node": ">=10.21" - } - }, - "node_modules/probot/node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dependencies": { - "@octokit/types": "^6.0.3" - } - }, - "node_modules/probot/node_modules/@octokit/auth-token/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/auth-token/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/probot/node_modules/@octokit/core/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/core/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/probot/node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/endpoint/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/probot/node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/graphql/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" - }, - "node_modules/probot/node_modules/@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dependencies": { - "@octokit/types": "^6.40.0" - }, - "peerDependencies": { - "@octokit/core": ">=2" - } - }, - "node_modules/probot/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dependencies": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/probot/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/plugin-throttling": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz", - "integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==", - "dependencies": { - "@octokit/types": "^6.0.1", - "bottleneck": "^2.15.3" - }, - "peerDependencies": { - "@octokit/core": "^3.5.0" - } - }, - "node_modules/probot/node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/probot/node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/probot/node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/request-error/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/request/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/probot/node_modules/@octokit/request/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/probot/node_modules/@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "dependencies": { - "@octokit/openapi-types": "^14.0.0" - } - }, - "node_modules/probot/node_modules/@types/pino": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-6.3.12.tgz", - "integrity": "sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw==", - "dependencies": { - "@types/node": "*", - "@types/pino-pretty": "*", - "@types/pino-std-serializers": "*", - "sonic-boom": "^2.1.0" - } - }, - "node_modules/probot/node_modules/@types/pino/node_modules/sonic-boom": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", - "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/probot/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/probot/node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/probot/node_modules/ioredis": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz", - "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==", - "dependencies": { - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.1", - "denque": "^1.1.0", - "lodash.defaults": "^4.2.0", - "lodash.flatten": "^4.4.0", - "lodash.isarguments": "^3.1.0", - "p-map": "^2.1.0", - "redis-commands": "1.7.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" - } - }, - "node_modules/probot/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/probot/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/probot/node_modules/pino": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz", - "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", - "dependencies": { - "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.8", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", - "process-warning": "^1.0.0", - "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/probot/node_modules/pino-http": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-5.8.0.tgz", - "integrity": "sha512-YwXiyRb9y0WCD1P9PcxuJuh3Dc5qmXde/paJE86UGYRdiFOi828hR9iUGmk5gaw6NBT9gLtKANOHFimvh19U5w==", - "dependencies": { - "fast-url-parser": "^1.1.3", - "pino": "^6.13.0", - "pino-std-serializers": "^4.0.0" - } - }, - "node_modules/probot/node_modules/pino-http/node_modules/pino-std-serializers": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", - "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==" - }, - "node_modules/probot/node_modules/pino-std-serializers": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", - "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==" - }, - "node_modules/probot/node_modules/process-warning": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", - "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" - }, - "node_modules/probot/node_modules/sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" - } - }, - "node_modules/probot/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-warning": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.0.tgz", - "integrity": "sha512-N6mp1+2jpQr3oCFMz6SeHRGbv6Slb20bRhj4v3xR99HqNToAcOe1MFOp4tytyzOfJn+QtN8Rf7U/h2KAn4kC6g==" - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "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", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, - "node_modules/pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/query-string": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", - "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", - "dependencies": { - "decode-uri-component": "^0.2.2", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/rate-limit-mongo": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/rate-limit-mongo/-/rate-limit-mongo-2.3.2.tgz", - "integrity": "sha512-dLck0j5N/AX9ycVHn5lX9Ti2Wrrwi1LfbXitu/mMBZOo2nC26RgYKJVbcb2mYgb9VMaPI2IwJVzIa2hAQrMaDA==", - "dependencies": { - "mongodb": "^3.6.7", - "twostep": "0.4.2", - "underscore": "1.12.1" - } - }, - "node_modules/rate-limit-mongo/node_modules/mongodb": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.8.0.tgz", - "integrity": "sha512-xx4CXmxcj3bNe7iGBlhntVrUqrNARYhUZteXaz4epEESv4oXD/FONAovcyoCaEffdYlw25Yz284OxMfpnPLlgQ==", - "dependencies": { - "bson": "^5.4.0", - "mongodb-connection-string-url": "^2.6.0", - "socks": "^2.7.1" - }, - "engines": { - "node": ">=14.20.1" - }, - "optionalDependencies": { - "@mongodb-js/saslprep": "^1.1.0" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.0.0", - "kerberos": "^1.0.0 || ^2.0.0", - "mongodb-client-encryption": ">=2.3.0 <3", - "snappy": "^7.2.2" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "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==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/redis-commands": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", - "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" - }, - "node_modules/secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/send/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==" - }, - "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sift": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", - "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/simple-update-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", - "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", - "dev": true, - "dependencies": { - "semver": "~7.0.0" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/smee-client": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/smee-client/-/smee-client-1.2.3.tgz", - "integrity": "sha512-uDrU8u9/Ln7aRXyzGHgVaNUS8onHZZeSwQjCdkMoSL7U85xI+l+Y2NgjibkMJAyXkW7IAbb8rw9RMHIjS6lAwA==", - "dev": true, - "dependencies": { - "commander": "^2.19.0", - "eventsource": "^1.1.0", - "morgan": "^1.9.1", - "superagent": "^7.1.3", - "validator": "^13.7.0" - }, - "bin": { - "smee": "bin/smee.js" - } - }, - "node_modules/smee-client/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/smee-client/node_modules/eventsource": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.2.tgz", - "integrity": "sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/snappy": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/snappy/-/snappy-7.2.2.tgz", - "integrity": "sha512-iADMq1kY0v3vJmGTuKcFWSXt15qYUz7wFkArOrsSg0IFfI3nJqIJvK2/ZbEIndg7erIJLtAVX2nSOqPz7DcwbA==", - "optional": true, - "peer": true, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@napi-rs/snappy-android-arm-eabi": "7.2.2", - "@napi-rs/snappy-android-arm64": "7.2.2", - "@napi-rs/snappy-darwin-arm64": "7.2.2", - "@napi-rs/snappy-darwin-x64": "7.2.2", - "@napi-rs/snappy-freebsd-x64": "7.2.2", - "@napi-rs/snappy-linux-arm-gnueabihf": "7.2.2", - "@napi-rs/snappy-linux-arm64-gnu": "7.2.2", - "@napi-rs/snappy-linux-arm64-musl": "7.2.2", - "@napi-rs/snappy-linux-x64-gnu": "7.2.2", - "@napi-rs/snappy-linux-x64-musl": "7.2.2", - "@napi-rs/snappy-win32-arm64-msvc": "7.2.2", - "@napi-rs/snappy-win32-ia32-msvc": "7.2.2", - "@napi-rs/snappy-win32-x64-msvc": "7.2.2" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/sonic-boom": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", - "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "engines": { - "node": ">=4", - "npm": ">=6" - } - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "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": "7.1.5", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", - "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", - "dev": true, - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "^2.5.0", - "qs": "^6.10.3", - "readable-stream": "^3.6.0", - "semver": "^7.3.7" - }, - "engines": { - "node": ">=6.4.0 <13 || >=14" - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/supertest": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", - "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^8.0.5" - }, - "engines": { - "node": ">=6.4.0" - } - }, - "node_modules/supertest/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/supertest/node_modules/superagent": { - "version": "8.0.9", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.9.tgz", - "integrity": "sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==", - "dev": true, - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.1.2", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=6.4.0 <13 || >=14" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/swagger-autogen": { - "version": "2.23.5", - "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.23.5.tgz", - "integrity": "sha512-4Tl2+XhZMyHoBYkABnScHtQE0lKPKUD3NBt09mClrI6UKOUYljKlYw1xiFVwsHCTGR2hAXmhT4PpgjruCtt1ZA==", - "dev": true, - "dependencies": { - "acorn": "^7.4.1", - "deepmerge": "^4.2.2", - "glob": "^7.1.7", - "json5": "^2.2.3" - } - }, - "node_modules/swagger-autogen/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/swagger-ui-dist": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.1.3.tgz", - "integrity": "sha512-W/vZFeZHG+xTN4yu8LXdaIrcnT4Hbr7qRUILYlMEoIiG6nuTylnEGeRcvL64F2eHRA2Jo/fgCSTU06Qfh0lT3g==" - }, - "node_modules/swagger-ui-express": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.3.tgz", - "integrity": "sha512-CDje4PndhTD2HkgyKH3pab+LKspDeB/NhPN2OF1j+piYIamQqBYwAXWESOT1Yju2xFg51bRW9sUng2WxDjzArw==", - "dependencies": { - "swagger-ui-dist": ">=4.11.0" - }, - "engines": { - "node": ">= v0.10.32" - }, - "peerDependencies": { - "express": ">=4.0.0 || >=5.0.0-beta" - } - }, - "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/thread-stream": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", - "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/tiny-lru": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.0.1.tgz", - "integrity": "sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "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", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/touch/node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/tr46/node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "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==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" - }, - "node_modules/twostep": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/twostep/-/twostep-0.4.2.tgz", - "integrity": "sha512-O/wdPYk9ey04qcCiw8AQN74DbvLFZLAgnryrNTpV7T/sxB4lcGkCMHynx5xCcA6fCh739ZAqp3HcGhy770X1qA==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "node_modules/universal-github-app-jwt": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.1.tgz", - "integrity": "sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w==", - "dependencies": { - "@types/jsonwebtoken": "^9.0.0", - "jsonwebtoken": "^9.0.0" - } - }, - "node_modules/universal-github-app-jwt/node_modules/@types/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/update-dotenv": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-dotenv/-/update-dotenv-1.1.1.tgz", - "integrity": "sha512-3cIC18In/t0X/yH793c00qqxcKD8jVCgNOPif/fGQkFpYMGecM9YAc+kaAKXuZsM2dE9I9wFI7KvAuNX22SGMQ==", - "peerDependencies": { - "dotenv": "*" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "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/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/validator": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true - }, - "node_modules/xml-crypto": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-3.2.0.tgz", - "integrity": "sha512-qVurBUOQrmvlgmZqIVBqmb06TD2a/PpEUfFPgD7BuBfjmoH4zgkqaWSIJrnymlCvM2GGt9x+XtJFA+ttoAufqg==", - "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "xpath": "0.0.32" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xml-crypto/node_modules/xpath": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", - "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==", - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/xml-encryption": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-3.0.2.tgz", - "integrity": "sha512-VxYXPvsWB01/aqVLd6ZMPWZ+qaj0aIdF+cStrVJMcFj3iymwZeI0ABzB3VqMYv48DkSpRhnrXqTUkR34j+UDyg==", - "dependencies": { - "@xmldom/xmldom": "^0.8.5", - "escape-html": "^1.0.3", - "xpath": "0.0.32" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/xml-encryption/node_modules/xpath": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", - "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==", - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xml2js/node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "engines": { - "node": ">=8.0" - } - }, - "node_modules/xpath": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", - "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==", - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@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==", - "requires": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@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==", - "requires": { - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@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==", - "requires": { - "@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" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@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==", - "requires": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@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==", - "requires": { - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@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==", - "requires": { - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@aws-sdk/client-cloudwatch-logs": { - "version": "3.454.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.454.0.tgz", - "integrity": "sha512-anXMEIZvDvqsFAURYmNHaJU8SH85Rqkahkk0TsDiTLc6/J4Qh8xvcem358qTiXzRpPJmZe4m20XKqL0fXsJgIw==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.454.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/credential-provider-node": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "dependencies": { - "@aws-sdk/client-sso": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.451.0.tgz", - "integrity": "sha512-KkYSke3Pdv3MfVH/5fT528+MKjMyPKlcLcd4zQb0x6/7Bl7EHrPh1JZYjzPLHelb+UY5X0qN8+cb8iSu1eiwIQ==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/client-sts": { - "version": "3.454.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.454.0.tgz", - "integrity": "sha512-0fDvr8WeB6IYO8BUCzcivWmahgGl/zDbaYfakzGnt4mrl5ztYaXE875WI6b7+oFcKMRvN+KLvwu5TtyFuNY+GQ==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.451.0", - "@aws-sdk/credential-provider-node": "3.451.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-sdk-sts": "3.451.0", - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/protocol-http": "^3.0.9", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-utf8": "^2.0.2", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-env": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.451.0.tgz", - "integrity": "sha512-9dAav7DcRgaF7xCJEQR5ER9ErXxnu/tdnVJ+UPmb1NPeIZdESv1A3lxFDEq1Fs8c4/lzAj9BpshGyJVIZwZDKg==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-ini": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.451.0.tgz", - "integrity": "sha512-TySt64Ci5/ZbqFw1F9Z0FIGvYx5JSC9e6gqDnizIYd8eMnn8wFRUscRrD7pIHKfrhvVKN5h0GdYovmMO/FMCBw==", - "requires": { - "@aws-sdk/credential-provider-env": "3.451.0", - "@aws-sdk/credential-provider-process": "3.451.0", - "@aws-sdk/credential-provider-sso": "3.451.0", - "@aws-sdk/credential-provider-web-identity": "3.451.0", - "@aws-sdk/types": "3.451.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.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-node": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.451.0.tgz", - "integrity": "sha512-AEwM1WPyxUdKrKyUsKyFqqRFGU70e4qlDyrtBxJnSU9NRLZI8tfEZ67bN7fHSxBUBODgDXpMSlSvJiBLh5/3pw==", - "requires": { - "@aws-sdk/credential-provider-env": "3.451.0", - "@aws-sdk/credential-provider-ini": "3.451.0", - "@aws-sdk/credential-provider-process": "3.451.0", - "@aws-sdk/credential-provider-sso": "3.451.0", - "@aws-sdk/credential-provider-web-identity": "3.451.0", - "@aws-sdk/types": "3.451.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.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-process": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.451.0.tgz", - "integrity": "sha512-HQywSdKeD5PErcLLnZfSyCJO+6T+ZyzF+Lm/QgscSC+CbSUSIPi//s15qhBRVely/3KBV6AywxwNH+5eYgt4lQ==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-sso": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.451.0.tgz", - "integrity": "sha512-Usm/N51+unOt8ID4HnQzxIjUJDrkAQ1vyTOC0gSEEJ7h64NSSPGD5yhN7il5WcErtRd3EEtT1a8/GTC5TdBctg==", - "requires": { - "@aws-sdk/client-sso": "3.451.0", - "@aws-sdk/token-providers": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-web-identity": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.451.0.tgz", - "integrity": "sha512-Xtg3Qw65EfDjWNG7o2xD6sEmumPfsy3WDGjk2phEzVg8s7hcZGxf5wYwe6UY7RJvlEKrU0rFA+AMn6Hfj5oOzg==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-host-header": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.451.0.tgz", - "integrity": "sha512-j8a5jAfhWmsK99i2k8oR8zzQgXrsJtgrLxc3js6U+525mcZytoiDndkWTmD5fjJ1byU1U2E5TaPq+QJeDip05Q==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-logger": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.451.0.tgz", - "integrity": "sha512-0kHrYEyVeB2QBfP6TfbI240aRtatLZtcErJbhpiNUb+CQPgEL3crIjgVE8yYiJumZ7f0jyjo8HLPkwD1/2APaw==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-recursion-detection": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.451.0.tgz", - "integrity": "sha512-J6jL6gJ7orjHGM70KDRcCP7so/J2SnkN4vZ9YRLTeeZY6zvBuHDjX8GCIgSqPn/nXFXckZO8XSnA7u6+3TAT0w==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-sdk-sts": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.451.0.tgz", - "integrity": "sha512-UJ6UfVUEgp0KIztxpAeelPXI5MLj9wUtUCqYeIMP7C1ZhoEMNm3G39VLkGN43dNhBf1LqjsV9jkKMZbVfYXuwg==", - "requires": { - "@aws-sdk/middleware-signing": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-signing": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.451.0.tgz", - "integrity": "sha512-s5ZlcIoLNg1Huj4Qp06iKniE8nJt/Pj1B/fjhWc6cCPCM7XJYUCejCnRh6C5ZJoBEYodjuwZBejPc1Wh3j+znA==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-user-agent": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.451.0.tgz", - "integrity": "sha512-8NM/0JiKLNvT9wtAQVl1DFW0cEO7OvZyLSUBLNLTHqyvOZxKaZ8YFk7d8PL6l76LeUKRxq4NMxfZQlUIRe0eSA==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/token-providers": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.451.0.tgz", - "integrity": "sha512-ij1L5iUbn6CwxVOT1PG4NFjsrsKN9c4N1YEM0lkl6DwmaNOscjLKGSNyj9M118vSWsOs1ZDbTwtj++h0O/BWrQ==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.451.0", - "@aws-sdk/middleware-logger": "3.451.0", - "@aws-sdk/middleware-recursion-detection": "3.451.0", - "@aws-sdk/middleware-user-agent": "3.451.0", - "@aws-sdk/region-config-resolver": "3.451.0", - "@aws-sdk/types": "3.451.0", - "@aws-sdk/util-endpoints": "3.451.0", - "@aws-sdk/util-user-agent-browser": "3.451.0", - "@aws-sdk/util-user-agent-node": "3.451.0", - "@smithy/config-resolver": "^2.0.18", - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/hash-node": "^2.0.15", - "@smithy/invalid-dependency": "^2.0.13", - "@smithy/middleware-content-length": "^2.0.15", - "@smithy/middleware-endpoint": "^2.2.0", - "@smithy/middleware-retry": "^2.0.20", - "@smithy/middleware-serde": "^2.0.13", - "@smithy/middleware-stack": "^2.0.7", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.9", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.19", - "@smithy/util-defaults-mode-node": "^2.0.25", - "@smithy/util-endpoints": "^1.0.4", - "@smithy/util-retry": "^2.0.6", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/types": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.451.0.tgz", - "integrity": "sha512-rhK+qeYwCIs+laJfWCcrYEjay2FR/9VABZJ2NRM89jV/fKqGVQR52E5DQqrI+oEIL5JHMhhnr4N4fyECMS35lw==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-endpoints": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.451.0.tgz", - "integrity": "sha512-giqLGBTnRIcKkDqwU7+GQhKbtJ5Ku35cjGQIfMyOga6pwTBUbaK0xW1Sdd8sBQ1GhApscnChzI9o/R9x0368vw==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/util-endpoints": "^1.0.4", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-browser": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.451.0.tgz", - "integrity": "sha512-Ws5mG3J0TQifH7OTcMrCTexo7HeSAc3cBgjfhS/ofzPUzVCtsyg0G7I6T7wl7vJJETix2Kst2cpOsxygPgPD9w==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/types": "^2.5.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-node": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.451.0.tgz", - "integrity": "sha512-TBzm6P+ql4mkGFAjPlO1CI+w3yUT+NulaiALjl/jNX/nnUp6HsJsVxJf4nVFQTG5KRV0iqMypcs7I3KIhH+LmA==", - "requires": { - "@aws-sdk/types": "3.451.0", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/abort-controller": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", - "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/config-resolver": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.18.tgz", - "integrity": "sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==", - "requires": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - } - }, - "@smithy/credential-provider-imds": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.1.tgz", - "integrity": "sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==", - "requires": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/property-provider": "^2.0.14", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "tslib": "^2.5.0" - } - }, - "@smithy/eventstream-codec": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.13.tgz", - "integrity": "sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==", - "requires": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/fetch-http-handler": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.6.tgz", - "integrity": "sha512-PStY3XO1Ksjwn3wMKye5U6m6zxXpXrXZYqLy/IeCbh3nM9QB3Jgw/B0PUSLUWKdXg4U8qgEu300e3ZoBvZLsDg==", - "requires": { - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", - "@smithy/util-base64": "^2.0.1", - "tslib": "^2.5.0" - } - }, - "@smithy/hash-node": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.15.tgz", - "integrity": "sha512-t/qjEJZu/G46A22PAk1k/IiJZT4ncRkG5GOCNWN9HPPy5rCcSZUbh7gwp7CGKgJJ7ATMMg+0Td7i9o1lQTwOfQ==", - "requires": { - "@smithy/types": "^2.5.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/invalid-dependency": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.13.tgz", - "integrity": "sha512-XsGYhVhvEikX1Yz0kyIoLssJf2Rs6E0U2w2YuKdT4jSra5A/g8V2oLROC1s56NldbgnpesTYB2z55KCHHbKyjw==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-content-length": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.15.tgz", - "integrity": "sha512-xH4kRBw01gJgWiU+/mNTrnyFXeozpZHw39gLb3JKGsFDVmSrJZ8/tRqu27tU/ki1gKkxr2wApu+dEYjI3QwV1Q==", - "requires": { - "@smithy/protocol-http": "^3.0.9", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-endpoint": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.2.0.tgz", - "integrity": "sha512-tddRmaig5URk2106PVMiNX6mc5BnKIKajHHDxb7K0J5MLdcuQluHMGnjkv18iY9s9O0tF+gAcPd/pDXA5L9DZw==", - "requires": { - "@smithy/middleware-serde": "^2.0.13", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "@smithy/url-parser": "^2.0.13", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-retry": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.20.tgz", - "integrity": "sha512-X2yrF/SHDk2WDd8LflRNS955rlzQ9daz9UWSp15wW8KtzoTXg3bhHM78HbK1cjr48/FWERSJKh9AvRUUGlIawg==", - "requires": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/protocol-http": "^3.0.9", - "@smithy/service-error-classification": "^2.0.6", - "@smithy/types": "^2.5.0", - "@smithy/util-middleware": "^2.0.6", - "@smithy/util-retry": "^2.0.6", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - } - }, - "@smithy/middleware-serde": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.13.tgz", - "integrity": "sha512-tBGbeXw+XsE6pPr4UaXOh+UIcXARZeiA8bKJWxk2IjJcD1icVLhBSUQH9myCIZLNNzJIH36SDjUX8Wqk4xJCJg==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-stack": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.7.tgz", - "integrity": "sha512-L1KLAAWkXbGx1t2jjCI/mDJ2dDNq+rp4/ifr/HcC6FHngxho5O7A5bQLpKHGlkfATH6fUnOEx0VICEVFA4sUzw==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/node-config-provider": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.5.tgz", - "integrity": "sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==", - "requires": { - "@smithy/property-provider": "^2.0.14", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/node-http-handler": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.9.tgz", - "integrity": "sha512-+K0q3SlNcocmo9OZj+fz67gY4lwhOCvIJxVbo/xH+hfWObvaxrMTx7JEzzXcluK0thnnLz++K3Qe7Z/8MDUreA==", - "requires": { - "@smithy/abort-controller": "^2.0.13", - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/property-provider": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.14.tgz", - "integrity": "sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/protocol-http": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.9.tgz", - "integrity": "sha512-U1wl+FhYu4/BC+rjwh1lg2gcJChQhytiNQSggREgQ9G2FzmoK9sACBZvx7thyWMvRyHQTE22mO2d5UM8gMKDBg==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-builder": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.13.tgz", - "integrity": "sha512-JhXKwp3JtsFUe96XLHy/nUPEbaXqn6r7xE4sNaH8bxEyytE5q1fwt0ew/Ke6+vIC7gP87HCHgQpJHg1X1jN2Fw==", - "requires": { - "@smithy/types": "^2.5.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-parser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.13.tgz", - "integrity": "sha512-TEiT6o8CPZVxJ44Rly/rrsATTQsE+b/nyBVzsYn2sa75xAaZcurNxsFd8z1haoUysONiyex24JMHoJY6iCfLdA==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/service-error-classification": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.6.tgz", - "integrity": "sha512-fCQ36frtYra2fqY2/DV8+3/z2d0VB/1D1hXbjRcM5wkxTToxq6xHbIY/NGGY6v4carskMyG8FHACxgxturJ9Pg==", - "requires": { - "@smithy/types": "^2.5.0" - } - }, - "@smithy/shared-ini-file-loader": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.4.tgz", - "integrity": "sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/signature-v4": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.15.tgz", - "integrity": "sha512-SRTEJSEhQYVlBKIIdZ9SZpqW+KFqxqcNnEcBX+8xkDdWx+DItme9VcCDkdN32yTIrICC+irUufnUdV7mmHPjoA==", - "requires": { - "@smithy/eventstream-codec": "^2.0.13", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.5.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/smithy-client": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.15.tgz", - "integrity": "sha512-rngZcQu7Jvs9UbHihK1EI67RMPuzkc3CJmu4MBgB7D7yBnMGuFR86tq5rqHfL2gAkNnMelBN/8kzQVvZjNKefQ==", - "requires": { - "@smithy/middleware-stack": "^2.0.7", - "@smithy/types": "^2.5.0", - "@smithy/util-stream": "^2.0.20", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/url-parser": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.13.tgz", - "integrity": "sha512-okWx2P/d9jcTsZWTVNnRMpFOE7fMkzloSFyM53fA7nLKJQObxM2T4JlZ5KitKKuXq7pxon9J6SF2kCwtdflIrA==", - "requires": { - "@smithy/querystring-parser": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-base64": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.1.tgz", - "integrity": "sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==", - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-browser": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.19.tgz", - "integrity": "sha512-VHP8xdFR7/orpiABJwgoTB0t8Zhhwpf93gXhNfUBiwAE9O0rvsv7LwpQYjgvbOUDDO8JfIYQB2GYJNkqqGWsXw==", - "requires": { - "@smithy/property-provider": "^2.0.14", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-node": { - "version": "2.0.25", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.25.tgz", - "integrity": "sha512-jkmep6/JyWmn2ADw9VULDeGbugR4N/FJCKOt+gYyVswmN1BJOfzF2umaYxQ1HhQDvna3kzm1Dbo1qIfBW4iuHA==", - "requires": { - "@smithy/config-resolver": "^2.0.18", - "@smithy/credential-provider-imds": "^2.1.1", - "@smithy/node-config-provider": "^2.1.5", - "@smithy/property-provider": "^2.0.14", - "@smithy/smithy-client": "^2.1.15", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.6.tgz", - "integrity": "sha512-7W4uuwBvSLgKoLC1x4LfeArCVcbuHdtVaC4g30kKsD1erfICyQ45+tFhhs/dZNeQg+w392fhunCm/+oCcb6BSA==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-retry": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.6.tgz", - "integrity": "sha512-PSO41FofOBmyhPQJwBQJ6mVlaD7Sp9Uff9aBbnfBJ9eqXOE/obrqQjn0PNdkfdvViiPXl49BINfnGcFtSP4kYw==", - "requires": { - "@smithy/service-error-classification": "^2.0.6", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-stream": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.20.tgz", - "integrity": "sha512-tT8VASuD8jJu0yjHEMTCPt1o5E3FVzgdsxK6FQLAjXKqVv5V8InCnc0EOsYrijgspbfDqdAJg7r0o2sySfcHVg==", - "requires": { - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/types": "^2.5.0", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/util-uri-escape": { - "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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-utf8": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.2.tgz", - "integrity": "sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==", - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - } - } - }, - "@aws-sdk/client-cognito-identity": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.388.0.tgz", - "integrity": "sha512-5sCogMJ1utRlwLQiameyOrrcyhueknbsC2YK1G9Y7pgmgUl2zzUo7htQS2luW71SeBHiwkTQa3OZjbmGsotJvg==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.388.0", - "@aws-sdk/credential-provider-node": "3.388.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "@aws-sdk/client-sso": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.387.0.tgz", - "integrity": "sha512-E7uKSvbA0XMKSN5KLInf52hmMpe9/OKo6N9OPffGXdn3fNEQlvyQq3meUkqG7Is0ldgsQMz5EUBNtNybXzr3tQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/client-sts": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.388.0.tgz", - "integrity": "sha512-y9FAcAYHT8O6T/jqhgsIQUb4gLiSTKD3xtzudDvjmFi8gl0oRIY1npbeckSiK6k07VQugm2s64I0nDnDxtWsBg==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.388.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-sdk-sts": "3.387.0", - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-env": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.387.0.tgz", - "integrity": "sha512-PVqNk7XPIYe5CMYNvELkcALtkl/pIM8/uPtqEtTg+mgnZBeL4fAmgXZiZMahQo1DxP5t/JaK384f6JG+A0qDjA==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-ini": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.388.0.tgz", - "integrity": "sha512-3dg3A8AiZ5vXkSAYyyI3V/AW3Eo6KQJyE/glA+Nr2M0oAjT4z3vHhS3pf2B+hfKGZBTuKKgxusrrhrQABd/Diw==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-node": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.388.0.tgz", - "integrity": "sha512-BqWAkIG08gj/wevpesaZhAjALjfUNVjseHQRk+DNUoHIfyibW7Ahf3q/GIPs11dA2o8ECwR9/fo68Sq+sK799A==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-ini": "3.388.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-process": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.387.0.tgz", - "integrity": "sha512-tQScLHmDlqkQN+mqw4s3cxepEUeHYDhFl5eH+J8puvPqWjXMYpCEdY79SAtWs6SZd4CWiZ0VLeYU6xQBZengbQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-sso": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.388.0.tgz", - "integrity": "sha512-RH02+rntaO0UhnSBr42n+7q8HOztc+Dets/hh6cWovf3Yi9s9ghLgYLN9FXpSosfot3XkmT/HOCa+CphAmGN9A==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/client-sso": "3.387.0", - "@aws-sdk/token-providers": "3.388.0", - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-web-identity": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.387.0.tgz", - "integrity": "sha512-6ueMPl+J3KWv6ZaAWF4Z138QCuBVFZRVAgwbtP3BNqWrrs4Q6TPksOQJ79lRDMpv0EUoyVl04B6lldNlhN8RdA==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-host-header": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.387.0.tgz", - "integrity": "sha512-EWm9PXSr8dSp7hnRth1U7OfelXQp9dLf1yS1kUL+UhppYDJpjhdP7ql3NI4xJKw8e76sP2FuJYEuzWnJHuWoyQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-logger": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.387.0.tgz", - "integrity": "sha512-FjAvJr1XyaInT81RxUwgifnbXoFJrRBFc64XeFJgFanGIQCWLYxRrK2HV9eBpao/AycbmuoHgLd/f0sa4hZFoQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-recursion-detection": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.387.0.tgz", - "integrity": "sha512-ZF45T785ru8OwvYZw6awD9Z76OwSMM1eZzj2eY+FDz1cHfkpLjxEiti2iIH1FxbyK7n9ZqDUx29lVlCv238YyQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-sdk-sts": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.387.0.tgz", - "integrity": "sha512-7ZzRKOJ4V/JDQmKz9z+FjZqw59mrMATEMLR6ff0H0JHMX0Uk5IX8TQB058ss+ar14qeJ4UcteYzCqHNI0O1BHw==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-signing": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.387.0.tgz", - "integrity": "sha512-oJXlE0MES8gxNLo137PPNNiOICQGOaETTvq3kBSJgb/gtEAxQajMIlaNT7s1wsjOAruFHt4975nCXuY4lpx7GQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-user-agent": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.387.0.tgz", - "integrity": "sha512-hTfFTwDtp86xS98BKa+RFuLfcvGftxwzrbZeisZV8hdb4ZhvNXjSxnvM3vetW0GUEnY9xHPSGyp2ERRTinPKFQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/token-providers": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.388.0.tgz", - "integrity": "sha512-2lo1gFJl624kfjo/YdU6zW+k6dEwhoqjNkDNbOZEFgS1KDofHe9GX8W4/ReKb0Ggho5/EcjzZ53/1CjkzUq4tA==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/types": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.387.0.tgz", - "integrity": "sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-endpoints": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.387.0.tgz", - "integrity": "sha512-g7kvuCXehGXHHBw9PkSQdwVyDFmNUZLmfrRmqMyrMDG9QLQrxr4pyWcSaYgTE16yUzhQQOR+QSey+BL6W9/N6g==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-browser": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.387.0.tgz", - "integrity": "sha512-lpgSVvDqx+JjHZCTYs/yQSS7J71dPlJeAlvxc7bmx5m+vfwKe07HAnIs+929DngS0QbAp/VaXbTiMFsInLkO4Q==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-node": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.387.0.tgz", - "integrity": "sha512-r9OVkcWpRYatjLhJacuHFgvO2T5s/Nu5DDbScMrkUD8b4aGIIqsrdZji0vZy9FCjsUFQMM92t9nt4SejrGjChA==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/abort-controller": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.2.tgz", - "integrity": "sha512-ln5Cob0mksym62sLr7NiPOSqJ0jKao4qjfcNLDdgINM1lQI12hXrZBlKdPHbXJqpKhKiECDgonMoqCM8bigq4g==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/config-resolver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.2.tgz", - "integrity": "sha512-0kdsqBL6BdmSbdU6YaDkodVBMua5MuQQluC3nocJ7OJ6PnOuM7i2FEQHE46LBadLqT+CimlDSM+6j91uHNL1ng==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/credential-provider-imds": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.2.tgz", - "integrity": "sha512-mbWFYEZ00LBRDk3WvcXViwpdpkJQcfrM3seuKzFxZnF6wIBLMwrcWcsj+OUC/1L+86m8aQY9imXMAaQsAoGxow==", - "optional": true, - "peer": true, - "requires": { - "@smithy/node-config-provider": "^2.0.2", - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/eventstream-codec": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.2.tgz", - "integrity": "sha512-PQZiKx7fMnNwx4zxcUCm82VjnqK6wV4MEHSmMy3taj5dKfXV782IjRGyaDT+8TsmNqVdZIkve5zLRAzh+7kOhA==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/fetch-http-handler": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.2.tgz", - "integrity": "sha512-Wo2m1RaiXNSLF4J3D62LpdSoj/YYb+6tn0H8is1tSrzr7eXAdiYVBc0wIa23N0wT4zmN0iG/yNY6gTCDQ6799A==", - "optional": true, - "peer": true, - "requires": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/querystring-builder": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/util-base64": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/hash-node": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.2.tgz", - "integrity": "sha512-JKDzZ1YVR7JzOBaJoWy3ToJCE86OQE6D4kOBvvVsu93a3lcF9kv6KYTKBYEWAjwOn/CpK4NH7mKB01OQ8H+aiA==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/invalid-dependency": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.2.tgz", - "integrity": "sha512-inQZQ5gCO3WRWuXpsc1YJ4KBjsvj2qsoU32yTIKznBWTCQe/D5Dp+sSaysqBqxe0VTZ+8nFEHdUMWUX2BxQThw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-content-length": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.2.tgz", - "integrity": "sha512-FmHlNfuvYgDZE3fIx0G3rD/wLXfAmBYE4mVc/w6d7RllA7TygPzq2pfHL1iCMzWkWTdoAVnt3h4aavAZnhaxEQ==", - "optional": true, - "peer": true, - "requires": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-endpoint": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.2.tgz", - "integrity": "sha512-ropE7/c+g22QeluZ+By/B/WvVep0UFreX+IeRMGIO7EbOUPgqtJRXpbJFdG6JKB1uC+CdaJLn4MnZnVBpcyjuA==", - "optional": true, - "peer": true, - "requires": { - "@smithy/middleware-serde": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-retry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.2.tgz", - "integrity": "sha512-wtBUXqtZVriiXppYaFkUrybAPhFVX7vebnW/yVPliLMWMcguOMS58qhOYPZe3t9Wki2+mASfyu+kO3An8lAg2A==", - "optional": true, - "peer": true, - "requires": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/service-error-classification": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-retry": "^2.0.0", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - } - }, - "@smithy/middleware-serde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.2.tgz", - "integrity": "sha512-Kw9xLdlueIaivUWslKB67WZ/cCUg3QnzYVIA3t5KfgsseEEuU4UxXw8NSTvIt71gqQloY+Um8ugS+idgxrWWnw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", - "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/node-config-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.2.tgz", - "integrity": "sha512-9wVJccASfuCctNWrzR0zrDkf0ox3HCHGEhFlWL2LBoghUYuK28pVRBbG69wvnkhlHnB8dDZHagxH+Nq9dm7eWw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/property-provider": "^2.0.2", - "@smithy/shared-ini-file-loader": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/node-http-handler": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.0.2.tgz", - "integrity": "sha512-lpZjmtmyZqSAtMPsbrLhb7XoAQ2kAHeuLY/csW6I2k+QyFvOk7cZeQsqEngWmZ9SJaeYiDCBINxAIM61i5WGLw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/abort-controller": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/querystring-builder": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/property-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.2.tgz", - "integrity": "sha512-DfaZ8cO+d/mgnMzIllcXcU4OYP+omiOl2LYdn/fTGpw/EAQSVzscYV2muV3sDDnuPYQ/r014hUqIxnF+pzh+SQ==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/protocol-http": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-2.0.2.tgz", - "integrity": "sha512-qWu8g1FUy+m36KpO1sREJSF7BaLmjw9AqOuwxLVVSdYz+nUQjc9tFAZ9LB6jJXKdsZFSjfkjHJBbhD78QdE7Rw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-builder": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.2.tgz", - "integrity": "sha512-H99LOMWEssfwqkOoTs4Y12UiZ7CTGQSX5Nrx5UkYgRbUEpC1GnnaprHiYrqclC58/xr4K76aNchdPyioxewMzA==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.2.tgz", - "integrity": "sha512-L4VtKQ8O4/aWPQJbiFymbhAmxdfLnEaROh/Vs0OstJ7jtOZeBl2QJmuWY2V7hjt64W7V+tEn2sv6vVvnxkm/xQ==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/service-error-classification": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", - "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", - "optional": true, - "peer": true - }, - "@smithy/shared-ini-file-loader": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.2.tgz", - "integrity": "sha512-2VkNOM/82u4vatVdK5nfusgGIlvR48Fkq6me17Oc+V1iyxfR/1x0pG6LzW0br1qlGtzBYFZKmDyviBRcPVFTVw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/signature-v4": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.2.tgz", - "integrity": "sha512-YMooDEw/UmGxcXY4qWnSXkbPFsRloluSvyXVT678YPDN/K2AS1GzKfRsvSU7fbccOB4WF8MHZf2UqcRGEltE3Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/eventstream-codec": "^2.0.2", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/smithy-client": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.0.2.tgz", - "integrity": "sha512-mDfokI8WwLU5C0gcQ4ww/zJI/WLGSh2+vdIA42JRnjfYUjJNH/rKfX9YOnn2eBOxl3loATERVUqkHmKe+P8s2Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/middleware-stack": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-stream": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.1.0.tgz", - "integrity": "sha512-KLsCsqxX0j2l99iP8s0f7LBlcsp7a7ceXGn0LPYPyVOsqmIKvSaPQajq0YevlL4T9Bm+DtcyXfBTbtBcLX1I7A==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/url-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.2.tgz", - "integrity": "sha512-X1mHCzrSVDlhVy7d3S7Vq+dTfYzwh4n7xGHhyJumu77nJqIss0lazVug85Pwo0DKIoO314wAOvMnBxNYDa+7wA==", - "optional": true, - "peer": true, - "requires": { - "@smithy/querystring-parser": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-body-length-node": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.0.0.tgz", - "integrity": "sha512-ZV7Z/WHTMxHJe/xL/56qZwSUcl63/5aaPAGjkfynJm4poILjdD4GmFI+V+YWabh2WJIjwTKZ5PNsuvPQKt93Mg==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-browser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.2.tgz", - "integrity": "sha512-c2tMMjb624XLuzmlRoZpnFOkejVxcgw3WQKdmgdGZYZapcLzXyC0H9JhnXMjQCt30GqLTlsILRNVBYwFRbw/4Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-node": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.2.tgz", - "integrity": "sha512-gt7m5LLqUtEKldJLyc14DE4kb85vxwomvt9AfEMEvWM4VwfWS1kGJqiStZFb5KNqnQPXw8vvpgLTi8NrWAOXqg==", - "optional": true, - "peer": true, - "requires": { - "@smithy/config-resolver": "^2.0.2", - "@smithy/credential-provider-imds": "^2.0.2", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-middleware": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", - "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-retry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", - "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", - "optional": true, - "peer": true, - "requires": { - "@smithy/service-error-classification": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-stream": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.2.tgz", - "integrity": "sha512-Mg9IJcKIu4YKlbzvpp1KLvh4JZLdcPgpxk+LICuDwzZCfxe47R9enVK8dNEiuyiIGK2ExbfvzCVT8IBru62vZw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/types": "^2.1.0", - "@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" - } - }, - "@smithy/util-uri-escape": { - "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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - } - } - }, - "@aws-sdk/client-secrets-manager": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.370.0.tgz", - "integrity": "sha512-1o1mpWbI1RyzCQ4cVpHQJnm6PziAJ+ptLt4p+wlN74Z330/nnE0JkK3t9l3CxhPqCIW8VjGbTCno5IzwAXnjPw==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.370.0", - "@aws-sdk/credential-provider-node": "3.370.0", - "@aws-sdk/middleware-host-header": "3.370.0", - "@aws-sdk/middleware-logger": "3.370.0", - "@aws-sdk/middleware-recursion-detection": "3.370.0", - "@aws-sdk/middleware-signing": "3.370.0", - "@aws-sdk/middleware-user-agent": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@aws-sdk/util-user-agent-browser": "3.370.0", - "@aws-sdk/util-user-agent-node": "3.370.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.2", - "@smithy/middleware-retry": "^1.0.3", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - } - }, - "@aws-sdk/client-sso": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.370.0.tgz", - "integrity": "sha512-0Ty1iHuzNxMQtN7nahgkZr4Wcu1XvqGfrQniiGdKKif9jG/4elxsQPiydRuQpFqN6b+bg7wPP7crFP1uTxx2KQ==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.370.0", - "@aws-sdk/middleware-logger": "3.370.0", - "@aws-sdk/middleware-recursion-detection": "3.370.0", - "@aws-sdk/middleware-user-agent": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@aws-sdk/util-user-agent-browser": "3.370.0", - "@aws-sdk/util-user-agent-node": "3.370.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.2", - "@smithy/middleware-retry": "^1.0.3", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/client-sso-oidc": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.370.0.tgz", - "integrity": "sha512-jAYOO74lmVXylQylqkPrjLzxvUnMKw476JCUTvCO6Q8nv3LzCWd76Ihgv/m9Q4M2Tbqi1iP2roVK5bstsXzEjA==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.370.0", - "@aws-sdk/middleware-logger": "3.370.0", - "@aws-sdk/middleware-recursion-detection": "3.370.0", - "@aws-sdk/middleware-user-agent": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@aws-sdk/util-user-agent-browser": "3.370.0", - "@aws-sdk/util-user-agent-node": "3.370.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.2", - "@smithy/middleware-retry": "^1.0.3", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/client-sts": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.370.0.tgz", - "integrity": "sha512-utFxOPWIzbN+3kc415Je2o4J72hOLNhgR2Gt5EnRSggC3yOnkC4GzauxG8n7n5gZGBX45eyubHyPOXLOIyoqQA==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.370.0", - "@aws-sdk/middleware-host-header": "3.370.0", - "@aws-sdk/middleware-logger": "3.370.0", - "@aws-sdk/middleware-recursion-detection": "3.370.0", - "@aws-sdk/middleware-sdk-sts": "3.370.0", - "@aws-sdk/middleware-signing": "3.370.0", - "@aws-sdk/middleware-user-agent": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@aws-sdk/util-user-agent-browser": "3.370.0", - "@aws-sdk/util-user-agent-node": "3.370.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.2", - "@smithy/middleware-retry": "^1.0.3", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "@smithy/util-utf8": "^1.0.1", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/core": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.451.0.tgz", - "integrity": "sha512-SamWW2zHEf1ZKe3j1w0Piauryl8BQIlej0TBS18A4ACzhjhWXhCs13bO1S88LvPR5mBFXok3XOT6zPOnKDFktw==", - "requires": { - "@smithy/smithy-client": "^2.1.15", - "tslib": "^2.5.0" - }, - "dependencies": { - "@smithy/abort-controller": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.13.tgz", - "integrity": "sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/fetch-http-handler": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.6.tgz", - "integrity": "sha512-PStY3XO1Ksjwn3wMKye5U6m6zxXpXrXZYqLy/IeCbh3nM9QB3Jgw/B0PUSLUWKdXg4U8qgEu300e3ZoBvZLsDg==", - "requires": { - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", - "@smithy/util-base64": "^2.0.1", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-stack": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.7.tgz", - "integrity": "sha512-L1KLAAWkXbGx1t2jjCI/mDJ2dDNq+rp4/ifr/HcC6FHngxho5O7A5bQLpKHGlkfATH6fUnOEx0VICEVFA4sUzw==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/node-http-handler": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.9.tgz", - "integrity": "sha512-+K0q3SlNcocmo9OZj+fz67gY4lwhOCvIJxVbo/xH+hfWObvaxrMTx7JEzzXcluK0thnnLz++K3Qe7Z/8MDUreA==", - "requires": { - "@smithy/abort-controller": "^2.0.13", - "@smithy/protocol-http": "^3.0.9", - "@smithy/querystring-builder": "^2.0.13", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/protocol-http": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.9.tgz", - "integrity": "sha512-U1wl+FhYu4/BC+rjwh1lg2gcJChQhytiNQSggREgQ9G2FzmoK9sACBZvx7thyWMvRyHQTE22mO2d5UM8gMKDBg==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-builder": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.13.tgz", - "integrity": "sha512-JhXKwp3JtsFUe96XLHy/nUPEbaXqn6r7xE4sNaH8bxEyytE5q1fwt0ew/Ke6+vIC7gP87HCHgQpJHg1X1jN2Fw==", - "requires": { - "@smithy/types": "^2.5.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/smithy-client": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.15.tgz", - "integrity": "sha512-rngZcQu7Jvs9UbHihK1EI67RMPuzkc3CJmu4MBgB7D7yBnMGuFR86tq5rqHfL2gAkNnMelBN/8kzQVvZjNKefQ==", - "requires": { - "@smithy/middleware-stack": "^2.0.7", - "@smithy/types": "^2.5.0", - "@smithy/util-stream": "^2.0.20", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-base64": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.1.tgz", - "integrity": "sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==", - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-stream": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.20.tgz", - "integrity": "sha512-tT8VASuD8jJu0yjHEMTCPt1o5E3FVzgdsxK6FQLAjXKqVv5V8InCnc0EOsYrijgspbfDqdAJg7r0o2sySfcHVg==", - "requires": { - "@smithy/fetch-http-handler": "^2.2.6", - "@smithy/node-http-handler": "^2.1.9", - "@smithy/types": "^2.5.0", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/util-uri-escape": { - "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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-utf8": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.2.tgz", - "integrity": "sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==", - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - } - } - }, - "@aws-sdk/credential-provider-cognito-identity": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.388.0.tgz", - "integrity": "sha512-j1oyBc0/O76YouOC2wMZuQUfHOjfrKWgBibIwrwqEqacYWMx/IBxZkk9j2fFerIVaKhhMNkZHAGb+qBx0urR/Q==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/client-cognito-identity": "3.388.0", - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "@aws-sdk/types": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.387.0.tgz", - "integrity": "sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/property-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.2.tgz", - "integrity": "sha512-DfaZ8cO+d/mgnMzIllcXcU4OYP+omiOl2LYdn/fTGpw/EAQSVzscYV2muV3sDDnuPYQ/r014hUqIxnF+pzh+SQ==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.1.0.tgz", - "integrity": "sha512-KLsCsqxX0j2l99iP8s0f7LBlcsp7a7ceXGn0LPYPyVOsqmIKvSaPQajq0YevlL4T9Bm+DtcyXfBTbtBcLX1I7A==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - } - } - }, - "@aws-sdk/credential-provider-env": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.370.0.tgz", - "integrity": "sha512-raR3yP/4GGbKFRPP5hUBNkEmTnzxI9mEc2vJAJrcv4G4J4i/UP6ELiLInQ5eO2/VcV/CeKGZA3t7d1tsJ+jhCg==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-ini": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.370.0.tgz", - "integrity": "sha512-eJyapFKa4NrC9RfTgxlXnXfS9InG/QMEUPPVL+VhG7YS6nKqetC1digOYgivnEeu+XSKE0DJ7uZuXujN2Y7VAQ==", - "requires": { - "@aws-sdk/credential-provider-env": "3.370.0", - "@aws-sdk/credential-provider-process": "3.370.0", - "@aws-sdk/credential-provider-sso": "3.370.0", - "@aws-sdk/credential-provider-web-identity": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-node": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.370.0.tgz", - "integrity": "sha512-gkFiotBFKE4Fcn8CzQnMeab9TAR06FEAD02T4ZRYW1xGrBJOowmje9dKqdwQFHSPgnWAP+8HoTA8iwbhTLvjNA==", - "requires": { - "@aws-sdk/credential-provider-env": "3.370.0", - "@aws-sdk/credential-provider-ini": "3.370.0", - "@aws-sdk/credential-provider-process": "3.370.0", - "@aws-sdk/credential-provider-sso": "3.370.0", - "@aws-sdk/credential-provider-web-identity": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-process": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.370.0.tgz", - "integrity": "sha512-0BKFFZmUO779Xdw3u7wWnoWhYA4zygxJbgGVSyjkOGBvdkbPSTTcdwT1KFkaQy2kOXYeZPl+usVVRXs+ph4ejg==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-sso": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.370.0.tgz", - "integrity": "sha512-PFroYm5hcPSfC/jkZnCI34QFL3I7WVKveVk6/F3fud/cnP8hp6YjA9NiTNbqdFSzsyoiN/+e5fZgNKih8vVPTA==", - "requires": { - "@aws-sdk/client-sso": "3.370.0", - "@aws-sdk/token-providers": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-web-identity": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.370.0.tgz", - "integrity": "sha512-CFaBMLRudwhjv1sDzybNV93IaT85IwS+L8Wq6VRMa0mro1q9rrWsIZO811eF+k0NEPfgU1dLH+8Vc2qhw4SARQ==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-providers": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.388.0.tgz", - "integrity": "sha512-5opHLYjj6rHrw2OaxE+IcLhC9JfiopPH7hRknzKjFnSrJ+HjzcHCML5xghwHLJOLGcoWU40CCSlwJVPLlJluMw==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/client-cognito-identity": "3.388.0", - "@aws-sdk/client-sso": "3.387.0", - "@aws-sdk/client-sts": "3.388.0", - "@aws-sdk/credential-provider-cognito-identity": "3.388.0", - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-ini": "3.388.0", - "@aws-sdk/credential-provider-node": "3.388.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "@aws-sdk/client-sso": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.387.0.tgz", - "integrity": "sha512-E7uKSvbA0XMKSN5KLInf52hmMpe9/OKo6N9OPffGXdn3fNEQlvyQq3meUkqG7Is0ldgsQMz5EUBNtNybXzr3tQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/client-sts": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.388.0.tgz", - "integrity": "sha512-y9FAcAYHT8O6T/jqhgsIQUb4gLiSTKD3xtzudDvjmFi8gl0oRIY1npbeckSiK6k07VQugm2s64I0nDnDxtWsBg==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.388.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-sdk-sts": "3.387.0", - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-env": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.387.0.tgz", - "integrity": "sha512-PVqNk7XPIYe5CMYNvELkcALtkl/pIM8/uPtqEtTg+mgnZBeL4fAmgXZiZMahQo1DxP5t/JaK384f6JG+A0qDjA==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-ini": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.388.0.tgz", - "integrity": "sha512-3dg3A8AiZ5vXkSAYyyI3V/AW3Eo6KQJyE/glA+Nr2M0oAjT4z3vHhS3pf2B+hfKGZBTuKKgxusrrhrQABd/Diw==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-node": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.388.0.tgz", - "integrity": "sha512-BqWAkIG08gj/wevpesaZhAjALjfUNVjseHQRk+DNUoHIfyibW7Ahf3q/GIPs11dA2o8ECwR9/fo68Sq+sK799A==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/credential-provider-env": "3.387.0", - "@aws-sdk/credential-provider-ini": "3.388.0", - "@aws-sdk/credential-provider-process": "3.387.0", - "@aws-sdk/credential-provider-sso": "3.388.0", - "@aws-sdk/credential-provider-web-identity": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-process": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.387.0.tgz", - "integrity": "sha512-tQScLHmDlqkQN+mqw4s3cxepEUeHYDhFl5eH+J8puvPqWjXMYpCEdY79SAtWs6SZd4CWiZ0VLeYU6xQBZengbQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-sso": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.388.0.tgz", - "integrity": "sha512-RH02+rntaO0UhnSBr42n+7q8HOztc+Dets/hh6cWovf3Yi9s9ghLgYLN9FXpSosfot3XkmT/HOCa+CphAmGN9A==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/client-sso": "3.387.0", - "@aws-sdk/token-providers": "3.388.0", - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-web-identity": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.387.0.tgz", - "integrity": "sha512-6ueMPl+J3KWv6ZaAWF4Z138QCuBVFZRVAgwbtP3BNqWrrs4Q6TPksOQJ79lRDMpv0EUoyVl04B6lldNlhN8RdA==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-host-header": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.387.0.tgz", - "integrity": "sha512-EWm9PXSr8dSp7hnRth1U7OfelXQp9dLf1yS1kUL+UhppYDJpjhdP7ql3NI4xJKw8e76sP2FuJYEuzWnJHuWoyQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-logger": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.387.0.tgz", - "integrity": "sha512-FjAvJr1XyaInT81RxUwgifnbXoFJrRBFc64XeFJgFanGIQCWLYxRrK2HV9eBpao/AycbmuoHgLd/f0sa4hZFoQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-recursion-detection": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.387.0.tgz", - "integrity": "sha512-ZF45T785ru8OwvYZw6awD9Z76OwSMM1eZzj2eY+FDz1cHfkpLjxEiti2iIH1FxbyK7n9ZqDUx29lVlCv238YyQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-sdk-sts": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.387.0.tgz", - "integrity": "sha512-7ZzRKOJ4V/JDQmKz9z+FjZqw59mrMATEMLR6ff0H0JHMX0Uk5IX8TQB058ss+ar14qeJ4UcteYzCqHNI0O1BHw==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/middleware-signing": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-signing": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.387.0.tgz", - "integrity": "sha512-oJXlE0MES8gxNLo137PPNNiOICQGOaETTvq3kBSJgb/gtEAxQajMIlaNT7s1wsjOAruFHt4975nCXuY4lpx7GQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-user-agent": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.387.0.tgz", - "integrity": "sha512-hTfFTwDtp86xS98BKa+RFuLfcvGftxwzrbZeisZV8hdb4ZhvNXjSxnvM3vetW0GUEnY9xHPSGyp2ERRTinPKFQ==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/token-providers": { - "version": "3.388.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.388.0.tgz", - "integrity": "sha512-2lo1gFJl624kfjo/YdU6zW+k6dEwhoqjNkDNbOZEFgS1KDofHe9GX8W4/ReKb0Ggho5/EcjzZ53/1CjkzUq4tA==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.387.0", - "@aws-sdk/middleware-logger": "3.387.0", - "@aws-sdk/middleware-recursion-detection": "3.387.0", - "@aws-sdk/middleware-user-agent": "3.387.0", - "@aws-sdk/types": "3.387.0", - "@aws-sdk/util-endpoints": "3.387.0", - "@aws-sdk/util-user-agent-browser": "3.387.0", - "@aws-sdk/util-user-agent-node": "3.387.0", - "@smithy/config-resolver": "^2.0.2", - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/hash-node": "^2.0.2", - "@smithy/invalid-dependency": "^2.0.2", - "@smithy/middleware-content-length": "^2.0.2", - "@smithy/middleware-endpoint": "^2.0.2", - "@smithy/middleware-retry": "^2.0.2", - "@smithy/middleware-serde": "^2.0.2", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.2", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/smithy-client": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.0.0", - "@smithy/util-defaults-mode-browser": "^2.0.2", - "@smithy/util-defaults-mode-node": "^2.0.2", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/types": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.387.0.tgz", - "integrity": "sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-endpoints": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.387.0.tgz", - "integrity": "sha512-g7kvuCXehGXHHBw9PkSQdwVyDFmNUZLmfrRmqMyrMDG9QLQrxr4pyWcSaYgTE16yUzhQQOR+QSey+BL6W9/N6g==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-browser": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.387.0.tgz", - "integrity": "sha512-lpgSVvDqx+JjHZCTYs/yQSS7J71dPlJeAlvxc7bmx5m+vfwKe07HAnIs+929DngS0QbAp/VaXbTiMFsInLkO4Q==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/types": "^2.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-node": { - "version": "3.387.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.387.0.tgz", - "integrity": "sha512-r9OVkcWpRYatjLhJacuHFgvO2T5s/Nu5DDbScMrkUD8b4aGIIqsrdZji0vZy9FCjsUFQMM92t9nt4SejrGjChA==", - "optional": true, - "peer": true, - "requires": { - "@aws-sdk/types": "3.387.0", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/abort-controller": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.2.tgz", - "integrity": "sha512-ln5Cob0mksym62sLr7NiPOSqJ0jKao4qjfcNLDdgINM1lQI12hXrZBlKdPHbXJqpKhKiECDgonMoqCM8bigq4g==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/config-resolver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.2.tgz", - "integrity": "sha512-0kdsqBL6BdmSbdU6YaDkodVBMua5MuQQluC3nocJ7OJ6PnOuM7i2FEQHE46LBadLqT+CimlDSM+6j91uHNL1ng==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/credential-provider-imds": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.2.tgz", - "integrity": "sha512-mbWFYEZ00LBRDk3WvcXViwpdpkJQcfrM3seuKzFxZnF6wIBLMwrcWcsj+OUC/1L+86m8aQY9imXMAaQsAoGxow==", - "optional": true, - "peer": true, - "requires": { - "@smithy/node-config-provider": "^2.0.2", - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/eventstream-codec": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.2.tgz", - "integrity": "sha512-PQZiKx7fMnNwx4zxcUCm82VjnqK6wV4MEHSmMy3taj5dKfXV782IjRGyaDT+8TsmNqVdZIkve5zLRAzh+7kOhA==", - "optional": true, - "peer": true, - "requires": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/fetch-http-handler": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.2.tgz", - "integrity": "sha512-Wo2m1RaiXNSLF4J3D62LpdSoj/YYb+6tn0H8is1tSrzr7eXAdiYVBc0wIa23N0wT4zmN0iG/yNY6gTCDQ6799A==", - "optional": true, - "peer": true, - "requires": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/querystring-builder": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/util-base64": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/hash-node": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.2.tgz", - "integrity": "sha512-JKDzZ1YVR7JzOBaJoWy3ToJCE86OQE6D4kOBvvVsu93a3lcF9kv6KYTKBYEWAjwOn/CpK4NH7mKB01OQ8H+aiA==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/invalid-dependency": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.2.tgz", - "integrity": "sha512-inQZQ5gCO3WRWuXpsc1YJ4KBjsvj2qsoU32yTIKznBWTCQe/D5Dp+sSaysqBqxe0VTZ+8nFEHdUMWUX2BxQThw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-content-length": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.2.tgz", - "integrity": "sha512-FmHlNfuvYgDZE3fIx0G3rD/wLXfAmBYE4mVc/w6d7RllA7TygPzq2pfHL1iCMzWkWTdoAVnt3h4aavAZnhaxEQ==", - "optional": true, - "peer": true, - "requires": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-endpoint": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.2.tgz", - "integrity": "sha512-ropE7/c+g22QeluZ+By/B/WvVep0UFreX+IeRMGIO7EbOUPgqtJRXpbJFdG6JKB1uC+CdaJLn4MnZnVBpcyjuA==", - "optional": true, - "peer": true, - "requires": { - "@smithy/middleware-serde": "^2.0.2", - "@smithy/types": "^2.1.0", - "@smithy/url-parser": "^2.0.2", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-retry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.2.tgz", - "integrity": "sha512-wtBUXqtZVriiXppYaFkUrybAPhFVX7vebnW/yVPliLMWMcguOMS58qhOYPZe3t9Wki2+mASfyu+kO3An8lAg2A==", - "optional": true, - "peer": true, - "requires": { - "@smithy/protocol-http": "^2.0.2", - "@smithy/service-error-classification": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-retry": "^2.0.0", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - } - }, - "@smithy/middleware-serde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.2.tgz", - "integrity": "sha512-Kw9xLdlueIaivUWslKB67WZ/cCUg3QnzYVIA3t5KfgsseEEuU4UxXw8NSTvIt71gqQloY+Um8ugS+idgxrWWnw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", - "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/node-config-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.2.tgz", - "integrity": "sha512-9wVJccASfuCctNWrzR0zrDkf0ox3HCHGEhFlWL2LBoghUYuK28pVRBbG69wvnkhlHnB8dDZHagxH+Nq9dm7eWw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/property-provider": "^2.0.2", - "@smithy/shared-ini-file-loader": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/node-http-handler": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.0.2.tgz", - "integrity": "sha512-lpZjmtmyZqSAtMPsbrLhb7XoAQ2kAHeuLY/csW6I2k+QyFvOk7cZeQsqEngWmZ9SJaeYiDCBINxAIM61i5WGLw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/abort-controller": "^2.0.2", - "@smithy/protocol-http": "^2.0.2", - "@smithy/querystring-builder": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/property-provider": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.2.tgz", - "integrity": "sha512-DfaZ8cO+d/mgnMzIllcXcU4OYP+omiOl2LYdn/fTGpw/EAQSVzscYV2muV3sDDnuPYQ/r014hUqIxnF+pzh+SQ==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/protocol-http": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-2.0.2.tgz", - "integrity": "sha512-qWu8g1FUy+m36KpO1sREJSF7BaLmjw9AqOuwxLVVSdYz+nUQjc9tFAZ9LB6jJXKdsZFSjfkjHJBbhD78QdE7Rw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-builder": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.2.tgz", - "integrity": "sha512-H99LOMWEssfwqkOoTs4Y12UiZ7CTGQSX5Nrx5UkYgRbUEpC1GnnaprHiYrqclC58/xr4K76aNchdPyioxewMzA==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.2.tgz", - "integrity": "sha512-L4VtKQ8O4/aWPQJbiFymbhAmxdfLnEaROh/Vs0OstJ7jtOZeBl2QJmuWY2V7hjt64W7V+tEn2sv6vVvnxkm/xQ==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/service-error-classification": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", - "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", - "optional": true, - "peer": true - }, - "@smithy/shared-ini-file-loader": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.2.tgz", - "integrity": "sha512-2VkNOM/82u4vatVdK5nfusgGIlvR48Fkq6me17Oc+V1iyxfR/1x0pG6LzW0br1qlGtzBYFZKmDyviBRcPVFTVw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@smithy/signature-v4": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.2.tgz", - "integrity": "sha512-YMooDEw/UmGxcXY4qWnSXkbPFsRloluSvyXVT678YPDN/K2AS1GzKfRsvSU7fbccOB4WF8MHZf2UqcRGEltE3Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/eventstream-codec": "^2.0.2", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/smithy-client": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.0.2.tgz", - "integrity": "sha512-mDfokI8WwLU5C0gcQ4ww/zJI/WLGSh2+vdIA42JRnjfYUjJNH/rKfX9YOnn2eBOxl3loATERVUqkHmKe+P8s2Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/middleware-stack": "^2.0.0", - "@smithy/types": "^2.1.0", - "@smithy/util-stream": "^2.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.1.0.tgz", - "integrity": "sha512-KLsCsqxX0j2l99iP8s0f7LBlcsp7a7ceXGn0LPYPyVOsqmIKvSaPQajq0YevlL4T9Bm+DtcyXfBTbtBcLX1I7A==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/url-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.2.tgz", - "integrity": "sha512-X1mHCzrSVDlhVy7d3S7Vq+dTfYzwh4n7xGHhyJumu77nJqIss0lazVug85Pwo0DKIoO314wAOvMnBxNYDa+7wA==", - "optional": true, - "peer": true, - "requires": { - "@smithy/querystring-parser": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-body-length-node": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.0.0.tgz", - "integrity": "sha512-ZV7Z/WHTMxHJe/xL/56qZwSUcl63/5aaPAGjkfynJm4poILjdD4GmFI+V+YWabh2WJIjwTKZ5PNsuvPQKt93Mg==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-browser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.2.tgz", - "integrity": "sha512-c2tMMjb624XLuzmlRoZpnFOkejVxcgw3WQKdmgdGZYZapcLzXyC0H9JhnXMjQCt30GqLTlsILRNVBYwFRbw/4Q==", - "optional": true, - "peer": true, - "requires": { - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-node": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.2.tgz", - "integrity": "sha512-gt7m5LLqUtEKldJLyc14DE4kb85vxwomvt9AfEMEvWM4VwfWS1kGJqiStZFb5KNqnQPXw8vvpgLTi8NrWAOXqg==", - "optional": true, - "peer": true, - "requires": { - "@smithy/config-resolver": "^2.0.2", - "@smithy/credential-provider-imds": "^2.0.2", - "@smithy/node-config-provider": "^2.0.2", - "@smithy/property-provider": "^2.0.2", - "@smithy/types": "^2.1.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-middleware": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", - "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-retry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", - "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", - "optional": true, - "peer": true, - "requires": { - "@smithy/service-error-classification": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-stream": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.2.tgz", - "integrity": "sha512-Mg9IJcKIu4YKlbzvpp1KLvh4JZLdcPgpxk+LICuDwzZCfxe47R9enVK8dNEiuyiIGK2ExbfvzCVT8IBru62vZw==", - "optional": true, - "peer": true, - "requires": { - "@smithy/fetch-http-handler": "^2.0.2", - "@smithy/node-http-handler": "^2.0.2", - "@smithy/types": "^2.1.0", - "@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" - } - }, - "@smithy/util-uri-escape": { - "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==", - "optional": true, - "peer": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@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==", - "optional": true, - "peer": true, - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - } - } - }, - "@aws-sdk/middleware-host-header": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.370.0.tgz", - "integrity": "sha512-CPXOm/TnOFC7KyXcJglICC7OiA7Kj6mT3ChvEijr56TFOueNHvJdV4aNIFEQy0vGHOWtY12qOWLNto/wYR1BAQ==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-logger": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.370.0.tgz", - "integrity": "sha512-cQMq9SaZ/ORmTJPCT6VzMML7OxFdQzNkhMAgKpTDl+tdPWynlHF29E5xGoSzROnThHlQPCjogU0NZ8AxI0SWPA==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-recursion-detection": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.370.0.tgz", - "integrity": "sha512-L7ZF/w0lAAY/GK1khT8VdoU0XB7nWHk51rl/ecAg64J70dHnMOAg8n+5FZ9fBu/xH1FwUlHOkwlodJOgzLJjtg==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-sdk-sts": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.370.0.tgz", - "integrity": "sha512-ykbsoVy0AJtVbuhAlTAMcaz/tCE3pT8nAp0L7CQQxSoanRCvOux7au0KwMIQVhxgnYid4dWVF6d00SkqU5MXRA==", - "requires": { - "@aws-sdk/middleware-signing": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-signing": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.370.0.tgz", - "integrity": "sha512-Dwr/RTCWOXdm394wCwICGT2VNOTMRe4IGPsBRJAsM24pm+EEqQzSS3Xu/U/zF4exuxqpMta4wec4QpSarPNTxA==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/signature-v4": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-middleware": "^1.0.1", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-user-agent": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.370.0.tgz", - "integrity": "sha512-2+3SB6MtMAq1+gVXhw0Y3ONXuljorh6ijnxgTpv+uQnBW5jHCUiAS8WDYiDEm7i9euJPbvJfM8WUrSMDMU6Cog==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@aws-sdk/util-endpoints": "3.370.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/region-config-resolver": { - "version": "3.451.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.451.0.tgz", - "integrity": "sha512-3iMf4OwzrFb4tAAmoROXaiORUk2FvSejnHIw/XHvf/jjR4EqGGF95NZP/n/MeFZMizJWVssrwS412GmoEyoqhg==", - "requires": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.6", - "tslib": "^2.5.0" - }, - "dependencies": { - "@smithy/node-config-provider": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.5.tgz", - "integrity": "sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==", - "requires": { - "@smithy/property-provider": "^2.0.14", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/property-provider": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.14.tgz", - "integrity": "sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/shared-ini-file-loader": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.4.tgz", - "integrity": "sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.6.tgz", - "integrity": "sha512-7W4uuwBvSLgKoLC1x4LfeArCVcbuHdtVaC4g30kKsD1erfICyQ45+tFhhs/dZNeQg+w392fhunCm/+oCcb6BSA==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - } - } - }, - "@aws-sdk/token-providers": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.370.0.tgz", - "integrity": "sha512-EyR2ZYr+lJeRiZU2/eLR+mlYU9RXLQvNyGFSAekJKgN13Rpq/h0syzXVFLP/RSod/oZenh/fhVZ2HwlZxuGBtQ==", - "requires": { - "@aws-sdk/client-sso-oidc": "3.370.0", - "@aws-sdk/types": "3.370.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/types": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.370.0.tgz", - "integrity": "sha512-8PGMKklSkRKjunFhzM2y5Jm0H2TBu7YRNISdYzXLUHKSP9zlMEYagseKVdmox0zKHf1LXVNuSlUV2b6SRrieCQ==", - "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-endpoints": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.370.0.tgz", - "integrity": "sha512-5ltVAnM79nRlywwzZN5i8Jp4tk245OCGkKwwXbnDU+gq7zT3CIOsct1wNZvmpfZEPGt/bv7/NyRcjP+7XNsX/g==", - "requires": { - "@aws-sdk/types": "3.370.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-browser": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.370.0.tgz", - "integrity": "sha512-028LxYZMQ0DANKhW+AKFQslkScZUeYlPmSphrCIXgdIItRZh6ZJHGzE7J/jDsEntZOrZJsjI4z0zZ5W2idj04w==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/types": "^1.1.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-node": { - "version": "3.370.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.370.0.tgz", - "integrity": "sha512-33vxZUp8vxTT/DGYIR3PivQm07sSRGWI+4fCv63Rt7Q++fO24E0kQtmVAlikRY810I10poD6rwILVtITtFSzkg==", - "requires": { - "@aws-sdk/types": "3.370.0", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - } - }, - "@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==", - "requires": { - "tslib": "^2.3.1" - } - }, - "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", - "dev": true - }, - "@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.1" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "requires": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", - "dev": true - }, - "@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", - "dev": true, - "requires": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" - } - }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/runtime": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", - "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", - "requires": { - "regenerator-runtime": "^0.13.11" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - } - } - }, - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - }, - "@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@casl/ability": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@casl/ability/-/ability-6.5.0.tgz", - "integrity": "sha512-3guc94ugr5ylZQIpJTLz0CDfwNi0mxKVECj1vJUPAvs+Lwunh/dcuUjwzc4MHM9D8JOYX0XUZMEPedpB3vIbOw==", - "requires": { - "@ucast/mongo2js": "^1.3.0" - } - }, - "@casl/mongoose": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@casl/mongoose/-/mongoose-7.2.1.tgz", - "integrity": "sha512-pojgSWYKNIwFM6wWDNct1YD0+8nIxhe2jp5jBbK8JGU60dEs2o0Yw3mCo2y7nBwbvRC2oEots/BlLMVb1Wdo8A==", - "requires": {} - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", - "dev": true - }, - "@godaddy/terminus": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.12.1.tgz", - "integrity": "sha512-Tm+wVu1/V37uZXcT7xOhzdpFoovQReErff8x3y82k6YyWa1gzxWBjTyrx4G2enjEqoXPnUUmJ3MOmwH+TiP6Sw==", - "requires": { - "stoppable": "^1.1.0" - } - }, - "@hapi/bourne": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.1.0.tgz", - "integrity": "sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==" - }, - "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", - "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", - "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", - "dev": true, - "requires": { - "@jest/console": "^29.6.1", - "@jest/reporters": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-resolve-dependencies": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "jest-watcher": "^29.6.1", - "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "@jest/environment": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", - "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "jest-mock": "^29.6.1" - } - }, - "@jest/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", - "dev": true, - "requires": { - "expect": "^29.6.1", - "jest-snapshot": "^29.6.1" - } - }, - "@jest/expect-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", - "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", - "dev": true, - "requires": { - "jest-get-type": "^29.4.3" - } - }, - "@jest/fake-timers": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", - "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" - } - }, - "@jest/globals": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", - "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/types": "^29.6.1", - "jest-mock": "^29.6.1" - } - }, - "@jest/reporters": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", - "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - } - }, - "@jest/schemas": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", - "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/source-map": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", - "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", - "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", - "dev": true, - "requires": { - "@jest/console": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", - "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", - "dev": true, - "requires": { - "@jest/test-result": "^29.6.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "slash": "^3.0.0" - } - }, - "@jest/transform": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", - "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.1", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@jest/types": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", - "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - } - } - }, - "@juanelas/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@juanelas/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-mr2pfRQpWap0Uq4tlrCgp3W+Yjx1/Bpq4QJsYeAQUh1mExgyQvXz7xUhmYT2HcLLspuAL5dpnos8P2QhaCSXsQ==" - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - } - }, - "@maxmind/geoip2-node": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@maxmind/geoip2-node/-/geoip2-node-3.5.0.tgz", - "integrity": "sha512-WG2TNxMwDWDOrljLwyZf5bwiEYubaHuICvQRlgz74lE9OZA/z4o+ZT6OisjDBAZh/yRJVNK6mfHqmP5lLlAwsA==", - "dev": true, - "requires": { - "camelcase-keys": "^7.0.0", - "ip6addr": "^0.2.5", - "maxmind": "^4.2.0" - } - }, - "@mongodb-js/saslprep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", - "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", - "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", - "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", - "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", - "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", - "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", - "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", - "dev": true, - "optional": true - }, - "@napi-rs/snappy-android-arm-eabi": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm-eabi/-/snappy-android-arm-eabi-7.2.2.tgz", - "integrity": "sha512-H7DuVkPCK5BlAr1NfSU8bDEN7gYs+R78pSHhDng83QxRnCLmVIZk33ymmIwurmoA1HrdTxbkbuNl+lMvNqnytw==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-android-arm64": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm64/-/snappy-android-arm64-7.2.2.tgz", - "integrity": "sha512-2R/A3qok+nGtpVK8oUMcrIi5OMDckGYNoBLFyli3zp8w6IArPRfg1yOfVUcHvpUDTo9T7LOS1fXgMOoC796eQw==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-darwin-arm64": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-arm64/-/snappy-darwin-arm64-7.2.2.tgz", - "integrity": "sha512-USgArHbfrmdbuq33bD5ssbkPIoT7YCXCRLmZpDS6dMDrx+iM7eD2BecNbOOo7/v1eu6TRmQ0xOzeQ6I/9FIi5g==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-darwin-x64": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-x64/-/snappy-darwin-x64-7.2.2.tgz", - "integrity": "sha512-0APDu8iO5iT0IJKblk2lH0VpWSl9zOZndZKnBYIc+ei1npw2L5QvuErFOTeTdHBtzvUHASB+9bvgaWnQo4PvTQ==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-freebsd-x64": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-freebsd-x64/-/snappy-freebsd-x64-7.2.2.tgz", - "integrity": "sha512-mRTCJsuzy0o/B0Hnp9CwNB5V6cOJ4wedDTWEthsdKHSsQlO7WU9W1yP7H3Qv3Ccp/ZfMyrmG98Ad7u7lG58WXA==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-linux-arm-gnueabihf": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm-gnueabihf/-/snappy-linux-arm-gnueabihf-7.2.2.tgz", - "integrity": "sha512-v1uzm8+6uYjasBPcFkv90VLZ+WhLzr/tnfkZ/iD9mHYiULqkqpRuC8zvc3FZaJy5wLQE9zTDkTJN1IvUcZ+Vcg==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-linux-arm64-gnu": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-gnu/-/snappy-linux-arm64-gnu-7.2.2.tgz", - "integrity": "sha512-LrEMa5pBScs4GXWOn6ZYXfQ72IzoolZw5txqUHVGs8eK4g1HR9HTHhb2oY5ySNaKakG5sOgMsb1rwaEnjhChmQ==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-linux-arm64-musl": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-musl/-/snappy-linux-arm64-musl-7.2.2.tgz", - "integrity": "sha512-3orWZo9hUpGQcB+3aTLW7UFDqNCQfbr0+MvV67x8nMNYj5eAeUtMmUE/HxLznHO4eZ1qSqiTwLbVx05/Socdlw==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-linux-x64-gnu": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-gnu/-/snappy-linux-x64-gnu-7.2.2.tgz", - "integrity": "sha512-jZt8Jit/HHDcavt80zxEkDpH+R1Ic0ssiVCoueASzMXa7vwPJeF4ZxZyqUw4qeSy7n8UUExomu8G8ZbP6VKhgw==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-linux-x64-musl": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-musl/-/snappy-linux-x64-musl-7.2.2.tgz", - "integrity": "sha512-Dh96IXgcZrV39a+Tej/owcd9vr5ihiZ3KRix11rr1v0MWtVb61+H1GXXlz6+Zcx9y8jM1NmOuiIuJwkV4vZ4WA==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-win32-arm64-msvc": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-arm64-msvc/-/snappy-win32-arm64-msvc-7.2.2.tgz", - "integrity": "sha512-9No0b3xGbHSWv2wtLEn3MO76Yopn1U2TdemZpCaEgOGccz1V+a/1d16Piz3ofSmnA13HGFz3h9NwZH9EOaIgYA==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-win32-ia32-msvc": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-ia32-msvc/-/snappy-win32-ia32-msvc-7.2.2.tgz", - "integrity": "sha512-QiGe+0G86J74Qz1JcHtBwM3OYdTni1hX1PFyLRo3HhQUSpmi13Bzc1En7APn+6Pvo7gkrcy81dObGLDSxFAkQQ==", - "optional": true, - "peer": true - }, - "@napi-rs/snappy-win32-x64-msvc": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-x64-msvc/-/snappy-win32-x64-msvc-7.2.2.tgz", - "integrity": "sha512-a43cyx1nK0daw6BZxVcvDEXxKMFLSBSDTAhsFD0VqSKcC7MGUBMaqyoWUcMiI7LBSz4bxUmxDWKfCYzpEmeb3w==", - "optional": true, - "peer": true - }, - "@node-saml/node-saml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@node-saml/node-saml/-/node-saml-4.0.5.tgz", - "integrity": "sha512-J5DglElbY1tjOuaR1NPtjOXkXY5bpUhDoKVoeucYN98A3w4fwgjIOPqIGcb6cQsqFq2zZ6vTCeKn5C/hvefSaw==", - "requires": { - "@types/debug": "^4.1.7", - "@types/passport": "^1.0.11", - "@types/xml-crypto": "^1.4.2", - "@types/xml-encryption": "^1.2.1", - "@types/xml2js": "^0.4.11", - "@xmldom/xmldom": "^0.8.6", - "debug": "^4.3.4", - "xml-crypto": "^3.0.1", - "xml-encryption": "^3.0.2", - "xml2js": "^0.5.0", - "xmlbuilder": "^15.1.1" - } - }, - "@node-saml/passport-saml": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@node-saml/passport-saml/-/passport-saml-4.0.4.tgz", - "integrity": "sha512-xFw3gw0yo+K1mzlkW15NeBF7cVpRHN/4vpjmBKzov5YFImCWh/G0LcTZ8krH3yk2/eRPc3Or8LRPudVJBjmYaw==", - "requires": { - "@node-saml/node-saml": "^4.0.4", - "@types/express": "^4.17.14", - "@types/passport": "^1.0.11", - "@types/passport-strategy": "^0.2.35", - "passport": "^0.6.0", - "passport-strategy": "^1.0.0" - } - }, - "@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==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@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==", - "dev": true - }, - "@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==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@octokit/auth-app": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-4.0.13.tgz", - "integrity": "sha512-NBQkmR/Zsc+8fWcVIFrwDgNXS7f4XDrkd9LHdi9DPQw1NdGHLviLzRO2ZBwTtepnwHXW5VTrVU9eFGijMUqllg==", - "requires": { - "@octokit/auth-oauth-app": "^5.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "deprecation": "^2.3.1", - "lru-cache": "^9.0.0", - "universal-github-app-jwt": "^1.1.1", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", - "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==" - } - } - }, - "@octokit/auth-oauth-app": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-5.0.6.tgz", - "integrity": "sha512-SxyfIBfeFcWd9Z/m1xa4LENTQ3l1y6Nrg31k2Dcb1jS5ov7pmwMJZ6OGX8q3K9slRgVpeAjNA1ipOAMHkieqyw==", - "requires": { - "@octokit/auth-oauth-device": "^4.0.0", - "@octokit/auth-oauth-user": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "@types/btoa-lite": "^1.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/auth-oauth-device": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-4.0.5.tgz", - "integrity": "sha512-XyhoWRTzf2ZX0aZ52a6Ew5S5VBAfwwx1QnC2Np6Et3MWQpZjlREIcbcvVZtkNuXp6Z9EeiSLSDUqm3C+aMEHzQ==", - "requires": { - "@octokit/oauth-methods": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/auth-oauth-user": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-2.1.2.tgz", - "integrity": "sha512-kkRqNmFe7s5GQcojE3nSlF+AzYPpPv7kvP/xYEnE57584pixaFBH8Vovt+w5Y3E4zWUEOxjdLItmBTFAWECPAg==", - "requires": { - "@octokit/auth-oauth-device": "^4.0.0", - "@octokit/oauth-methods": "^2.0.0", - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "btoa-lite": "^1.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/auth-token": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", - "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==" - }, - "@octokit/auth-unauthenticated": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-3.0.5.tgz", - "integrity": "sha512-yH2GPFcjrTvDWPwJWWCh0tPPtTL5SMgivgKPA+6v/XmYN6hGQkAto8JtZibSKOpf8ipmeYhLNWQ2UgW0GYILCw==", - "requires": { - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0" - } - }, - "@octokit/core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", - "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", - "requires": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", - "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", - "requires": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", - "requires": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/oauth-authorization-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-5.0.0.tgz", - "integrity": "sha512-y1WhN+ERDZTh0qZ4SR+zotgsQUE1ysKnvBt1hvDRB2WRzYtVKQjn97HEPzoehh66Fj9LwNdlZh+p6TJatT0zzg==" - }, - "@octokit/oauth-methods": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-2.0.6.tgz", - "integrity": "sha512-l9Uml2iGN2aTWLZcm8hV+neBiFXAQ9+3sKiQe/sgumHlL6HDg0AQ8/l16xX/5jJvfxueqTW5CWbzd0MjnlfHZw==", - "requires": { - "@octokit/oauth-authorization-url": "^5.0.0", - "@octokit/request": "^6.2.3", - "@octokit/request-error": "^3.0.3", - "@octokit/types": "^9.0.0", - "btoa-lite": "^1.0.0" - } - }, - "@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" - }, - "@octokit/plugin-enterprise-compatibility": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-compatibility/-/plugin-enterprise-compatibility-1.3.0.tgz", - "integrity": "sha512-h34sMGdEOER/OKrZJ55v26ntdHb9OPfR1fwOx6Q4qYyyhWA104o11h9tFxnS/l41gED6WEI41Vu2G2zHDVC5lQ==", - "requires": { - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.0.3" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", - "requires": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" - } - }, - "@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "requires": {} - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", - "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", - "requires": { - "@octokit/types": "^10.0.0" - }, - "dependencies": { - "@octokit/types": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", - "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", - "requires": { - "@octokit/openapi-types": "^18.0.0" - } - } - } - }, - "@octokit/plugin-retry": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz", - "integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==", - "requires": { - "@octokit/types": "^6.0.3", - "bottleneck": "^2.15.3" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/request": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", - "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", - "requires": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "requires": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "19.0.13", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", - "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", - "requires": { - "@octokit/core": "^4.2.1", - "@octokit/plugin-paginate-rest": "^6.1.2", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.1.2" - } - }, - "@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==" - }, - "@octokit/types": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", - "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", - "requires": { - "@octokit/openapi-types": "^18.0.0" - } - }, - "@octokit/webhooks": { - "version": "9.26.3", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.26.3.tgz", - "integrity": "sha512-DLGk+gzeVq5oK89Bo601txYmyrelMQ7Fi5EnjHE0Xs8CWicy2xkmnJMKptKJrBJpstqbd/9oeDFi/Zj2pudBDQ==", - "requires": { - "@octokit/request-error": "^2.0.2", - "@octokit/webhooks-methods": "^2.0.0", - "@octokit/webhooks-types": "5.8.0", - "aggregate-error": "^3.1.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/webhooks-methods": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz", - "integrity": "sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig==" - }, - "@octokit/webhooks-types": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.8.0.tgz", - "integrity": "sha512-8adktjIb76A7viIdayQSFuBEwOzwhDC+9yxZpKNHjfzrlostHCw0/N7JWpWMObfElwvJMk2fY2l1noENCk9wmw==" - }, - "@phc/format": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", - "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==" - }, - "@posthog/plugin-scaffold": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@posthog/plugin-scaffold/-/plugin-scaffold-1.4.2.tgz", - "integrity": "sha512-/VsRg3CfhQvYhxM2O9+gBOzj4K1QJZClY+yple0npL1Jd2nRn2nT4z7dlPSidTPZvdpFs0+hrnF+m4Kxf1NFvQ==", - "dev": true, - "requires": { - "@maxmind/geoip2-node": "^3.4.0" - } - }, - "@probot/get-private-key": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@probot/get-private-key/-/get-private-key-1.1.1.tgz", - "integrity": "sha512-hOmBNSAhSZc6PaNkTvj6CO9R5J67ODJ+w5XQlDW9w/6mtcpHWK4L+PZcW0YwVM7PpetLZjN6rsKQIR9yqIaWlA==", - "requires": { - "@types/is-base64": "^1.1.0", - "is-base64": "^1.1.0" - } - }, - "@probot/octokit-plugin-config": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@probot/octokit-plugin-config/-/octokit-plugin-config-1.1.6.tgz", - "integrity": "sha512-L29wmnFvilzSfWn9tUgItxdLv0LJh2ICjma3FmLr80Spu3wZ9nHyRrKMo9R5/K2m7VuWmgoKnkgRt2zPzAQBEQ==", - "requires": { - "@types/js-yaml": "^4.0.5", - "js-yaml": "^4.1.0" - } - }, - "@probot/pino": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@probot/pino/-/pino-2.3.5.tgz", - "integrity": "sha512-IiyiNZonMw1dHC4EAdD55y5owV733d9Gll/IKsrLikB7EJ54+eMCOtL/qo+OmgWN9XV3NTDfziEQF2og/OBKog==", - "requires": { - "@sentry/node": "^6.0.0", - "pino-pretty": "^6.0.0", - "pump": "^3.0.0", - "readable-stream": "^3.6.0", - "split2": "^4.0.0" - }, - "dependencies": { - "@sentry/core": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", - "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", - "requires": { - "@sentry/hub": "6.19.7", - "@sentry/minimal": "6.19.7", - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "tslib": "^1.9.3" - } - }, - "@sentry/node": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz", - "integrity": "sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg==", - "requires": { - "@sentry/core": "6.19.7", - "@sentry/hub": "6.19.7", - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - } - }, - "@sentry/types": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", - "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==" - }, - "@sentry/utils": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", - "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", - "requires": { - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - } - }, - "colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" - }, - "jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==" - }, - "pino-pretty": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-6.0.0.tgz", - "integrity": "sha512-jyeR2fXXWc68st1DTTM5NhkHlx8p+1fKZMfm84Jwq+jSw08IwAjNaZBZR6ts69hhPOfOjg/NiE1HYW7vBRPL3A==", - "requires": { - "@hapi/bourne": "^2.0.0", - "args": "^5.0.1", - "colorette": "^1.3.0", - "dateformat": "^4.5.1", - "fast-safe-stringify": "^2.0.7", - "jmespath": "^0.15.0", - "joycon": "^3.0.0", - "pump": "^3.0.0", - "readable-stream": "^3.6.0", - "rfdc": "^1.3.0", - "split2": "^3.1.1", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "requires": { - "readable-stream": "^3.0.0" - } - } - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sentry-internal/tracing": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.59.3.tgz", - "integrity": "sha512-/RkBj/0zQKGsW/UYg6hufrLHHguncLfu4610FCPWpVp0K5Yu5ou8/Aw8D76G3ZxD2TiuSNGwX0o7TYN371ZqTQ==", - "requires": { - "@sentry/core": "7.59.3", - "@sentry/types": "7.59.3", - "@sentry/utils": "7.59.3", - "tslib": "^2.4.1 || ^1.9.3" - } - }, - "@sentry/core": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.59.3.tgz", - "integrity": "sha512-cGBOwT9gziIn50fnlBH1WGQlGcHi7wrbvOCyrex4MxKnn1LSBYWBhwU0ymj8DI/9MyPrGDNGkrgpV0WJWBSClg==", - "requires": { - "@sentry/types": "7.59.3", - "@sentry/utils": "7.59.3", - "tslib": "^2.4.1 || ^1.9.3" - } - }, - "@sentry/hub": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", - "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", - "requires": { - "@sentry/types": "6.19.7", - "@sentry/utils": "6.19.7", - "tslib": "^1.9.3" - }, - "dependencies": { - "@sentry/types": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", - "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==" - }, - "@sentry/utils": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", - "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", - "requires": { - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sentry/minimal": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", - "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", - "requires": { - "@sentry/hub": "6.19.7", - "@sentry/types": "6.19.7", - "tslib": "^1.9.3" - }, - "dependencies": { - "@sentry/types": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", - "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==" - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sentry/node": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.77.0.tgz", - "integrity": "sha512-Ob5tgaJOj0OYMwnocc6G/CDLWC7hXfVvKX/ofkF98+BbN/tQa5poL+OwgFn9BA8ud8xKzyGPxGU6LdZ8Oh3z/g==", - "requires": { - "@sentry-internal/tracing": "7.77.0", - "@sentry/core": "7.77.0", - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0", - "https-proxy-agent": "^5.0.0" - }, - "dependencies": { - "@sentry-internal/tracing": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.77.0.tgz", - "integrity": "sha512-8HRF1rdqWwtINqGEdx8Iqs9UOP/n8E0vXUu3Nmbqj4p5sQPA7vvCfq+4Y4rTqZFc7sNdFpDsRION5iQEh8zfZw==", - "requires": { - "@sentry/core": "7.77.0", - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0" - } - }, - "@sentry/core": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.77.0.tgz", - "integrity": "sha512-Tj8oTYFZ/ZD+xW8IGIsU6gcFXD/gfE+FUxUaeSosd9KHwBQNOLhZSsYo/tTVf/rnQI/dQnsd4onPZLiL+27aTg==", - "requires": { - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0" - } - }, - "@sentry/types": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.77.0.tgz", - "integrity": "sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA==" - }, - "@sentry/utils": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.77.0.tgz", - "integrity": "sha512-NmM2kDOqVchrey3N5WSzdQoCsyDkQkiRxExPaNI2oKQ/jMWHs9yt0tSy7otPBcXs0AP59ihl75Bvm1tDRcsp5g==", - "requires": { - "@sentry/types": "7.77.0" - } - } - } - }, - "@sentry/tracing": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.59.3.tgz", - "integrity": "sha512-+gDsfhYdteAR4NyKl3B5JVQs/bXYT73ajoFrlprfDjAJCEVR9W1P4CULavoLtfASxVqBQcZyT87Hsb9/vbn6bg==", - "requires": { - "@sentry-internal/tracing": "7.59.3" - } - }, - "@sentry/types": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.59.3.tgz", - "integrity": "sha512-HQ/Pd3YHyIa4HM0bGfOsfI4ZF+sLVs6II9VtlS4hsVporm4ETl3Obld5HywO3aVYvWOk5j/bpAW9JYsxXjRG5A==" - }, - "@sentry/utils": { - "version": "7.59.3", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.59.3.tgz", - "integrity": "sha512-Q57xauMKuzd6S+POA1fmulfjzTsb/z118TNAfZZNkHqVB48hHBqgzdhbEBmN4jPCSKV2Cx7VJUoDZxJfzQyLUQ==", - "requires": { - "@sentry/types": "7.59.3", - "tslib": "^2.4.1 || ^1.9.3" - } - }, - "@serdnam/pino-cloudwatch-transport": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@serdnam/pino-cloudwatch-transport/-/pino-cloudwatch-transport-1.0.4.tgz", - "integrity": "sha512-0wtILlFlO/qTFANM1oEMZLKa9REo+mluHN0VTDaOMh15H9Puc+qU4z4jAoZqggFz9Fw9EGG4c+UHpMduZ1EzeQ==", - "requires": { - "@aws-sdk/client-cloudwatch-logs": "^3.52.0", - "p-throttle": "^5.0.0", - "pino-abstract-transport": "^0.5.0" - }, - "dependencies": { - "pino-abstract-transport": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", - "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", - "requires": { - "duplexify": "^4.1.2", - "split2": "^4.0.0" - } - } - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@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, - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@smithy/abort-controller": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-1.0.2.tgz", - "integrity": "sha512-tb2h0b+JvMee+eAxTmhnyqyNk51UXIK949HnE14lFeezKsVJTB30maan+CO2IMwnig2wVYQH84B5qk6ylmKCuA==", - "requires": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/config-resolver": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-1.0.2.tgz", - "integrity": "sha512-8Bk7CgnVKg1dn5TgnjwPz2ebhxeR7CjGs5yhVYH3S8x0q8yPZZVWwpRIglwXaf5AZBzJlNO1lh+lUhMf2e73zQ==", - "requires": { - "@smithy/types": "^1.1.1", - "@smithy/util-config-provider": "^1.0.2", - "@smithy/util-middleware": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/credential-provider-imds": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-1.0.2.tgz", - "integrity": "sha512-fLjCya+JOu2gPJpCiwSUyoLvT8JdNJmOaTOkKYBZoGf7CzqR6lluSyI+eboZnl/V0xqcfcqBG4tgqCISmWS3/w==", - "requires": { - "@smithy/node-config-provider": "^1.0.2", - "@smithy/property-provider": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/url-parser": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/eventstream-codec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-1.0.2.tgz", - "integrity": "sha512-eW/XPiLauR1VAgHKxhVvgvHzLROUgTtqat2lgljztbH8uIYWugv7Nz+SgCavB+hWRazv2iYgqrSy74GvxXq/rg==", - "requires": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^1.1.1", - "@smithy/util-hex-encoding": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/fetch-http-handler": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-1.0.2.tgz", - "integrity": "sha512-kynyofLf62LvR8yYphPPdyHb8fWG3LepFinM/vWUTG2Q1pVpmPCM530ppagp3+q2p+7Ox0UvSqldbKqV/d1BpA==", - "requires": { - "@smithy/protocol-http": "^1.1.1", - "@smithy/querystring-builder": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/util-base64": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/hash-node": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-1.0.2.tgz", - "integrity": "sha512-K6PKhcUNrJXtcesyzhIvNlU7drfIU7u+EMQuGmPw6RQDAg/ufUcfKHz4EcUhFAodUmN+rrejhRG9U6wxjeBOQA==", - "requires": { - "@smithy/types": "^1.1.1", - "@smithy/util-buffer-from": "^1.0.2", - "@smithy/util-utf8": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/invalid-dependency": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-1.0.2.tgz", - "integrity": "sha512-B1Y3Tsa6dfC+Vvb+BJMhTHOfFieeYzY9jWQSTR1vMwKkxsymD0OIAnEw8rD/RiDj/4E4RPGFdx9Mdgnyd6Bv5Q==", - "requires": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/is-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-1.0.2.tgz", - "integrity": "sha512-pkyBnsBRpe+c/6ASavqIMRBdRtZNJEVJOEzhpxZ9JoAXiZYbkfaSMRA/O1dUxGdJ653GHONunnZ4xMo/LJ7utQ==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-content-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-1.0.2.tgz", - "integrity": "sha512-pa1/SgGIrSmnEr2c9Apw7CdU4l/HW0fK3+LKFCPDYJrzM0JdYpqjQzgxi31P00eAkL0EFBccpus/p1n2GF9urw==", - "requires": { - "@smithy/protocol-http": "^1.1.1", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-endpoint": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-1.0.3.tgz", - "integrity": "sha512-GsWvTXMFjSgl617PCE2km//kIjjtvMRrR2GAuRDIS9sHiLwmkS46VWaVYy+XE7ubEsEtzZ5yK2e8TKDR6Qr5Lw==", - "requires": { - "@smithy/middleware-serde": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/url-parser": "^1.0.2", - "@smithy/util-middleware": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-retry": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-1.0.4.tgz", - "integrity": "sha512-G7uRXGFL8c3F7APnoIMTtNAHH8vT4F2qVnAWGAZaervjupaUQuRRHYBLYubK0dWzOZz86BtAXKieJ5p+Ni2Xpg==", - "requires": { - "@smithy/protocol-http": "^1.1.1", - "@smithy/service-error-classification": "^1.0.3", - "@smithy/types": "^1.1.1", - "@smithy/util-middleware": "^1.0.2", - "@smithy/util-retry": "^1.0.4", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - } - }, - "@smithy/middleware-serde": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-1.0.2.tgz", - "integrity": "sha512-T4PcdMZF4xme6koUNfjmSZ1MLi7eoFeYCtodQNQpBNsS77TuJt1A6kt5kP/qxrTvfZHyFlj0AubACoaUqgzPeg==", - "requires": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-stack": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-1.0.2.tgz", - "integrity": "sha512-H7/uAQEcmO+eDqweEFMJ5YrIpsBwmrXSP6HIIbtxKJSQpAcMGY7KrR2FZgZBi1FMnSUOh+rQrbOyj5HQmSeUBA==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/node-config-provider": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-1.0.2.tgz", - "integrity": "sha512-HU7afWpTToU0wL6KseGDR2zojeyjECQfr8LpjAIeHCYIW7r360ABFf4EaplaJRMVoC3hD9FeltgI3/NtShOqCg==", - "requires": { - "@smithy/property-provider": "^1.0.2", - "@smithy/shared-ini-file-loader": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/node-http-handler": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-1.0.3.tgz", - "integrity": "sha512-PcPUSzTbIb60VCJCiH0PU0E6bwIekttsIEf5Aoo/M0oTfiqsxHTn0Rcij6QoH6qJy6piGKXzLSegspXg5+Kq6g==", - "requires": { - "@smithy/abort-controller": "^1.0.2", - "@smithy/protocol-http": "^1.1.1", - "@smithy/querystring-builder": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/property-provider": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-1.0.2.tgz", - "integrity": "sha512-pXDPyzKX8opzt38B205kDgaxda6LHcTfPvTYQZnwP6BAPp1o9puiCPjeUtkKck7Z6IbpXCPUmUQnzkUzWTA42Q==", - "requires": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/protocol-http": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.1.1.tgz", - "integrity": "sha512-mFLFa2sSvlUxm55U7B4YCIsJJIMkA6lHxwwqOaBkral1qxFz97rGffP/mmd4JDuin1EnygiO5eNJGgudiUgmDQ==", - "requires": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-builder": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-1.0.2.tgz", - "integrity": "sha512-6P/xANWrtJhMzTPUR87AbXwSBuz1SDHIfL44TFd/GT3hj6rA+IEv7rftEpPjayUiWRocaNnrCPLvmP31mobOyA==", - "requires": { - "@smithy/types": "^1.1.1", - "@smithy/util-uri-escape": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-parser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-1.0.2.tgz", - "integrity": "sha512-IWxwxjn+KHWRRRB+K2Ngl+plTwo2WSgc2w+DvLy0DQZJh9UGOpw40d6q97/63GBlXIt4TEt5NbcFrO30CKlrsA==", - "requires": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/service-error-classification": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-1.0.3.tgz", - "integrity": "sha512-2eglIYqrtcUnuI71yweu7rSfCgt6kVvRVf0C72VUqrd0LrV1M0BM0eYN+nitp2CHPSdmMI96pi+dU9U/UqAMSA==" - }, - "@smithy/shared-ini-file-loader": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-1.0.2.tgz", - "integrity": "sha512-bdQj95VN+lCXki+P3EsDyrkpeLn8xDYiOISBGnUG/AGPYJXN8dmp4EhRRR7XOoLoSs8anZHR4UcGEOzFv2jwGw==", - "requires": { - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/signature-v4": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-1.0.2.tgz", - "integrity": "sha512-rpKUhmCuPmpV5dloUkOb9w1oBnJatvKQEjIHGmkjRGZnC3437MTdzWej9TxkagcZ8NRRJavYnEUixzxM1amFig==", - "requires": { - "@smithy/eventstream-codec": "^1.0.2", - "@smithy/is-array-buffer": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/util-hex-encoding": "^1.0.2", - "@smithy/util-middleware": "^1.0.2", - "@smithy/util-uri-escape": "^1.0.2", - "@smithy/util-utf8": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/smithy-client": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-1.0.4.tgz", - "integrity": "sha512-gpo0Xl5Nyp9sgymEfpt7oa9P2q/GlM3VmQIdm+FeH0QEdYOQx3OtvwVmBYAMv2FIPWxkMZlsPYRTnEiBTK5TYg==", - "requires": { - "@smithy/middleware-stack": "^1.0.2", - "@smithy/types": "^1.1.1", - "@smithy/util-stream": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.1.1.tgz", - "integrity": "sha512-tMpkreknl2gRrniHeBtdgQwaOlo39df8RxSrwsHVNIGXULy5XP6KqgScUw2m12D15wnJCKWxVhCX+wbrBW/y7g==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/url-parser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-1.0.2.tgz", - "integrity": "sha512-0JRsDMQe53F6EHRWksdcavKDRjyqp8vrjakg8EcCUOa7PaFRRB1SO/xGZdzSlW1RSTWQDEksFMTCEcVEKmAoqA==", - "requires": { - "@smithy/querystring-parser": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/util-base64": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-1.0.2.tgz", - "integrity": "sha512-BCm15WILJ3SL93nusoxvJGMVfAMWHZhdeDZPtpAaskozuexd0eF6szdz4kbXaKp38bFCSenA6bkUHqaE3KK0dA==", - "requires": { - "@smithy/util-buffer-from": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/util-body-length-browser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-1.0.2.tgz", - "integrity": "sha512-Xh8L06H2anF5BHjSYTg8hx+Itcbf4SQZnVMl4PIkCOsKtneMJoGjPRLy17lEzfoh/GOaa0QxgCP6lRMQWzNl4w==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-body-length-node": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-1.0.2.tgz", - "integrity": "sha512-nXHbZsUtvZeyfL4Ceds9nmy2Uh2AhWXohG4vWHyjSdmT8cXZlJdmJgnH6SJKDjyUecbu+BpKeVvSrA4cWPSOPA==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-buffer-from": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-1.0.2.tgz", - "integrity": "sha512-lHAYIyrBO9RANrPvccnPjU03MJnWZ66wWuC5GjWWQVfsmPwU6m00aakZkzHdUT6tGCkGacXSgArP5wgTgA+oCw==", - "requires": { - "@smithy/is-array-buffer": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/util-config-provider": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-1.0.2.tgz", - "integrity": "sha512-HOdmDm+3HUbuYPBABLLHtn8ittuRyy+BSjKOA169H+EMc+IozipvXDydf+gKBRAxUa4dtKQkLraypwppzi+PRw==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-browser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-1.0.2.tgz", - "integrity": "sha512-J1u2PO235zxY7dg0+ZqaG96tFg4ehJZ7isGK1pCBEA072qxNPwIpDzUVGnLJkHZvjWEGA8rxIauDtXfB0qxeAg==", - "requires": { - "@smithy/property-provider": "^1.0.2", - "@smithy/types": "^1.1.1", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-node": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-1.0.2.tgz", - "integrity": "sha512-9/BN63rlIsFStvI+AvljMh873Xw6bbI6b19b+PVYXyycQ2DDQImWcjnzRlHW7eP65CCUNGQ6otDLNdBQCgMXqg==", - "requires": { - "@smithy/config-resolver": "^1.0.2", - "@smithy/credential-provider-imds": "^1.0.2", - "@smithy/node-config-provider": "^1.0.2", - "@smithy/property-provider": "^1.0.2", - "@smithy/types": "^1.1.1", - "tslib": "^2.5.0" - } - }, - "@smithy/util-endpoints": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.4.tgz", - "integrity": "sha512-FPry8j1xye5yzrdnf4xKUXVnkQErxdN7bUIaqC0OFoGsv2NfD9b2UUMuZSSt+pr9a8XWAqj0HoyVNUfPiZ/PvQ==", - "requires": { - "@smithy/node-config-provider": "^2.1.5", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "@smithy/node-config-provider": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.5.tgz", - "integrity": "sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==", - "requires": { - "@smithy/property-provider": "^2.0.14", - "@smithy/shared-ini-file-loader": "^2.2.4", - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/property-provider": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.14.tgz", - "integrity": "sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/shared-ini-file-loader": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.4.tgz", - "integrity": "sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==", - "requires": { - "@smithy/types": "^2.5.0", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.5.0.tgz", - "integrity": "sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==", - "requires": { - "tslib": "^2.5.0" - } - } - } - }, - "@smithy/util-hex-encoding": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-1.0.2.tgz", - "integrity": "sha512-Bxydb5rMJorMV6AuDDMOxro3BMDdIwtbQKHpwvQFASkmr52BnpDsWlxgpJi8Iq7nk1Bt4E40oE1Isy/7ubHGzg==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-middleware": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-1.0.2.tgz", - "integrity": "sha512-vtXK7GOR2BoseCX8NCGe9SaiZrm9M2lm/RVexFGyPuafTtry9Vyv7hq/vw8ifd/G/pSJ+msByfJVb1642oQHKw==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-retry": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-1.0.4.tgz", - "integrity": "sha512-RnZPVFvRoqdj2EbroDo3OsnnQU8eQ4AlnZTOGusbYKybH3269CFdrZfZJloe60AQjX7di3J6t/79PjwCLO5Khw==", - "requires": { - "@smithy/service-error-classification": "^1.0.3", - "tslib": "^2.5.0" - } - }, - "@smithy/util-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-1.0.2.tgz", - "integrity": "sha512-qyN2M9QFMTz4UCHi6GnBfLOGYKxQZD01Ga6nzaXFFC51HP/QmArU72e4kY50Z/EtW8binPxspP2TAsGbwy9l3A==", - "requires": { - "@smithy/fetch-http-handler": "^1.0.2", - "@smithy/node-http-handler": "^1.0.3", - "@smithy/types": "^1.1.1", - "@smithy/util-base64": "^1.0.2", - "@smithy/util-buffer-from": "^1.0.2", - "@smithy/util-hex-encoding": "^1.0.2", - "@smithy/util-utf8": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@smithy/util-uri-escape": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-1.0.2.tgz", - "integrity": "sha512-k8C0BFNS9HpBMHSgUDnWb1JlCQcFG+PPlVBq9keP4Nfwv6a9Q0yAfASWqUCtzjuMj1hXeLhn/5ADP6JxnID1Pg==", - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-utf8": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-1.0.2.tgz", - "integrity": "sha512-V4cyjKfJlARui0dMBfWJMQAmJzoW77i4N3EjkH/bwnE2Ngbl4tqD2Y0C/xzpzY/J1BdxeCKxAebVFk8aFCaSCw==", - "requires": { - "@smithy/util-buffer-from": "^1.0.2", - "tslib": "^2.5.0" - } - }, - "@swc/core": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.99.tgz", - "integrity": "sha512-8O996RfuPC4ieb4zbYMfbyCU9k4gSOpyCNnr7qBQ+o7IEmh8JCV6B8wwu+fT/Om/6Lp34KJe1IpJ/24axKS6TQ==", - "dev": true, - "requires": { - "@swc/core-darwin-arm64": "1.3.99", - "@swc/core-darwin-x64": "1.3.99", - "@swc/core-linux-arm64-gnu": "1.3.99", - "@swc/core-linux-arm64-musl": "1.3.99", - "@swc/core-linux-x64-gnu": "1.3.99", - "@swc/core-linux-x64-musl": "1.3.99", - "@swc/core-win32-arm64-msvc": "1.3.99", - "@swc/core-win32-ia32-msvc": "1.3.99", - "@swc/core-win32-x64-msvc": "1.3.99", - "@swc/counter": "^0.1.1", - "@swc/types": "^0.1.5" - } - }, - "@swc/core-darwin-arm64": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.99.tgz", - "integrity": "sha512-Qj7Jct68q3ZKeuJrjPx7k8SxzWN6PqLh+VFxzA+KwLDpQDPzOlKRZwkIMzuFjLhITO4RHgSnXoDk/Syz0ZeN+Q==", - "dev": true, - "optional": true - }, - "@swc/core-darwin-x64": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.99.tgz", - "integrity": "sha512-wR7m9QVJjgiBu1PSOHy7s66uJPa45Kf9bZExXUL+JAa9OQxt5y+XVzr+n+F045VXQOwdGWplgPnWjgbUUHEVyw==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm64-gnu": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.99.tgz", - "integrity": "sha512-gcGv1l5t0DScEONmw5OhdVmEI/o49HCe9Ik38zzH0NtDkc+PDYaCcXU5rvfZP2qJFaAAr8cua8iJcOunOSLmnA==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm64-musl": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.99.tgz", - "integrity": "sha512-XL1/eUsTO8BiKsWq9i3iWh7H99iPO61+9HYiWVKhSavknfj4Plbn+XyajDpxsauln5o8t+BRGitymtnAWJM4UQ==", - "dev": true, - "optional": true - }, - "@swc/core-linux-x64-gnu": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.99.tgz", - "integrity": "sha512-fGrXYE6DbTfGNIGQmBefYxSk3rp/1lgbD0nVg4rl4mfFRQPi7CgGhrrqSuqZ/ezXInUIgoCyvYGWFSwjLXt/Qg==", - "dev": true, - "optional": true - }, - "@swc/core-linux-x64-musl": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.99.tgz", - "integrity": "sha512-kvgZp/mqf3IJ806gUOL6gN6VU15+DfzM1Zv4Udn8GqgXiUAvbQehrtruid4Snn5pZTLj4PEpSCBbxgxK1jbssA==", - "dev": true, - "optional": true - }, - "@swc/core-win32-arm64-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.99.tgz", - "integrity": "sha512-yt8RtZ4W/QgFF+JUemOUQAkVW58cCST7mbfKFZ1v16w3pl3NcWd9OrtppFIXpbjU1rrUX2zp2R7HZZzZ2Zk/aQ==", - "dev": true, - "optional": true - }, - "@swc/core-win32-ia32-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.99.tgz", - "integrity": "sha512-62p5fWnOJR/rlbmbUIpQEVRconICy5KDScWVuJg1v3GPLBrmacjphyHiJC1mp6dYvvoEWCk/77c/jcQwlXrDXw==", - "dev": true, - "optional": true - }, - "@swc/core-win32-x64-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.99.tgz", - "integrity": "sha512-PdppWhkoS45VGdMBxvClVgF1hVjqamtvYd82Gab1i4IV45OSym2KinoDCKE1b6j3LwBLOn2J9fvChGSgGfDCHQ==", - "dev": true, - "optional": true - }, - "@swc/counter": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", - "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", - "dev": true - }, - "@swc/helpers": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.3.tgz", - "integrity": "sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==", - "dev": true, - "requires": { - "tslib": "^2.4.0" - } - }, - "@swc/types": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", - "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", - "dev": true, - "requires": { - "@babel/types": "^7.20.7" - } - }, - "@types/bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/bcryptjs": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz", - "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==", - "dev": true - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==" - }, - "@types/bull": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@types/bull/-/bull-4.10.0.tgz", - "integrity": "sha512-RkYW8K2H3J76HT6twmHYbzJ0GtLDDotpLP9ah9gtiA7zfF6peBH1l5fEiK0oeIZ3/642M7Jcb9sPmor8Vf4w6g==", - "dev": true, - "requires": { - "bull": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/cookie-parser": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz", - "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", - "dev": true - }, - "@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==" - }, - "@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", - "requires": { - "@types/ms": "*" - } - }, - "@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" - }, - "@types/ioredis": { - "version": "4.28.10", - "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", - "integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/is-base64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/is-base64/-/is-base64-1.1.1.tgz", - "integrity": "sha512-JgnGhP+MeSHEQmvxcobcwPEP4Ew56voiq9/0hmP/41lyQ/3gBw/ZCIRy2v+QkEOdeCl58lRcrf6+Y6WMlJGETA==" - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "29.5.3", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", - "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", - "dev": true, - "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "@types/jmespath": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@types/jmespath/-/jmespath-0.15.1.tgz", - "integrity": "sha512-RWN1HQ71Hjl2ixw4a8s7/Bcz6S9uaBTaoCQ5cJB7OsjgHBFi3GaWMy0vRgZBPSYXdsMKFNxGLUUEh9uRf00Spw==", - "dev": true - }, - "@types/js-yaml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", - "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==" - }, - "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "@types/jsonwebtoken": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz", - "integrity": "sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/libsodium-wrappers": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz", - "integrity": "sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA==" - }, - "@types/lodash": { - "version": "4.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", - "dev": true - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" - }, - "@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "@types/node": { - "version": "18.16.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz", - "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==" - }, - "@types/nodemailer": { - "version": "6.4.8", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.8.tgz", - "integrity": "sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/passport": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", - "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", - "requires": { - "@types/express": "*" - } - }, - "@types/passport-strategy": { - "version": "0.2.35", - "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", - "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", - "requires": { - "@types/express": "*", - "@types/passport": "*" - } - }, - "@types/pg": { - "version": "8.10.7", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.7.tgz", - "integrity": "sha512-ksJqHipwYaSEHz9e1fr6H6erjoEdNNaOxwyJgPx9bNeaqOW3iWBQgVHfpwiSAoqGzchfc+ZyRLwEfeCcyYD3uQ==", - "dev": true, - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - }, - "dependencies": { - "pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", - "dev": true, - "requires": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - } - }, - "postgres-array": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", - "dev": true - }, - "postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, - "requires": { - "obuf": "~1.1.2" - } - }, - "postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", - "dev": true - }, - "postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true - } - } - }, - "@types/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==", - "dev": true - }, - "@types/pino": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-7.0.5.tgz", - "integrity": "sha512-wKoab31pknvILkxAF8ss+v9iNyhw5Iu/0jLtRkUD74cNfOOLJNnqfFKAv0r7wVaTQxRZtWrMpGfShwwBjOcgcg==", - "dev": true, - "requires": { - "pino": "*" - } - }, - "@types/pino-http": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/@types/pino-http/-/pino-http-5.8.1.tgz", - "integrity": "sha512-A9MW6VCnx5ii7s+Fs5aFIw+aSZcBCpsZ/atpxamu8tTsvWFacxSf2Hrn1Ohn1jkVRB/LiPGOapRXcFawDBnDnA==", - "requires": { - "@types/pino": "6.3" - }, - "dependencies": { - "@types/pino": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-6.3.12.tgz", - "integrity": "sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw==", - "requires": { - "@types/node": "*", - "@types/pino-pretty": "*", - "@types/pino-std-serializers": "*", - "sonic-boom": "^2.1.0" - } - } - } - }, - "@types/pino-pretty": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/pino-pretty/-/pino-pretty-5.0.0.tgz", - "integrity": "sha512-N1uzqSzioqz8R3AkDbSJwcfDWeI3YMPNapSQQhnB2ISU4NYgUIcAh+hYT5ygqBM+klX4htpEhXMmoJv3J7GrdA==", - "requires": { - "pino-pretty": "*" - } - }, - "@types/pino-std-serializers": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", - "integrity": "sha512-gXfUZx2xIBbFYozGms53fT0nvkacx/+62c8iTxrEqH5PkIGAQvDbXg2774VWOycMPbqn5YJBQ3BMsg4Li3dWbg==", - "requires": { - "pino-std-serializers": "*" - } - }, - "@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "requires": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/superagent": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", - "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", - "dev": true, - "requires": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "@types/supertest": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", - "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", - "dev": true, - "requires": { - "@types/superagent": "*" - } - }, - "@types/swagger-jsdoc": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.1.tgz", - "integrity": "sha512-+MUpcbyxD528dECUBCEVm6abNuORdbuGjbrUdHDeAQ+rkPuo2a+L4N02WJHF3bonSSE6SJ3dUJwF2V6+cHnf0w==", - "dev": true - }, - "@types/swagger-ui-express": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz", - "integrity": "sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA==", - "dev": true, - "requires": { - "@types/express": "*", - "@types/serve-static": "*" - } - }, - "@types/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" - }, - "@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", - "requires": { - "@types/node": "*", - "@types/webidl-conversions": "*" - } - }, - "@types/xml-crypto": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@types/xml-crypto/-/xml-crypto-1.4.2.tgz", - "integrity": "sha512-1kT+3gVkeBDg7Ih8NefxGYfCApwZViMIs5IEs5AXF6Fpsrnf9CLAEIRh0DYb1mIcRcvysVbe27cHsJD6rJi36w==", - "requires": { - "@types/node": "*", - "xpath": "0.0.27" - } - }, - "@types/xml-encryption": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/xml-encryption/-/xml-encryption-1.2.1.tgz", - "integrity": "sha512-UeyZkfZFZSa9XCGU5uGgUmsSLwQESDJvF076bJGyDf2gkXJjKvK8fW/x4ckvEHB2M/5RHJEkMc5xI+JrdmCTKA==", - "requires": { - "@types/node": "*" - } - }, - "@types/xml2js": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.11.tgz", - "integrity": "sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==", - "requires": { - "@types/node": "*" - } - }, - "@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@ucast/core": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@ucast/core/-/core-1.10.2.tgz", - "integrity": "sha512-ons5CwXZ/51wrUPfoduC+cO7AS1/wRb0ybpQJ9RrssossDxVy4t49QxWoWgfBDvVKsz9VXzBk9z0wqTdZ+Cq8g==" - }, - "@ucast/js": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@ucast/js/-/js-3.0.3.tgz", - "integrity": "sha512-jBBqt57T5WagkAjqfCIIE5UYVdaXYgGkOFYv2+kjq2AVpZ2RIbwCo/TujJpDlwTVluUI+WpnRpoGU2tSGlEvFQ==", - "requires": { - "@ucast/core": "^1.0.0" - } - }, - "@ucast/mongo": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@ucast/mongo/-/mongo-2.4.3.tgz", - "integrity": "sha512-XcI8LclrHWP83H+7H2anGCEeDq0n+12FU2mXCTz6/Tva9/9ddK/iacvvhCyW6cijAAOILmt0tWplRyRhVyZLsA==", - "requires": { - "@ucast/core": "^1.4.1" - } - }, - "@ucast/mongo2js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@ucast/mongo2js/-/mongo2js-1.3.4.tgz", - "integrity": "sha512-ahazOr1HtelA5AC1KZ9x0UwPMqqimvfmtSm/PRRSeKKeE5G2SCqTgwiNzO7i9jS8zA3dzXpKVPpXMkcYLnyItA==", - "requires": { - "@ucast/core": "^1.6.1", - "@ucast/js": "^3.0.0", - "@ucast/mongo": "^2.4.0" - } - }, - "@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argon2": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.30.3.tgz", - "integrity": "sha512-DoH/kv8c9127ueJSBxAVJXinW9+EuPA3EMUxoV2sAY1qDE5H9BjTyVF/aD2XyHqbqUWabgBkIfcP3ZZuGhbJdg==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.10", - "@phc/format": "^1.0.0", - "node-addon-api": "^5.0.0" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "args": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz", - "integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==", - "requires": { - "camelcase": "5.0.0", - "chalk": "2.4.2", - "leven": "2.1.0", - "mri": "1.1.4" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" - }, - "aws-sdk": { - "version": "2.1419.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1419.0.tgz", - "integrity": "sha512-JcD8gb8I5fH/TGdObG8UYyyXfnqVYk50wx9TGao6G/xBYT3YoYeQXj020W568YQpO+dBKRuR4U2LRYdKBNmQ/g==", - "requires": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "util": "^0.12.4", - "uuid": "8.0.0", - "xml2js": "0.5.0" - }, - "dependencies": { - "uuid": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", - "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==" - } - } - }, - "axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "axios-retry": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.5.1.tgz", - "integrity": "sha512-mQRJ4IyAUnYig14BQ4MnnNHHuH1cNH7NW4JxEUD6mNJwK6pwOY66wKLCwZ6Y0o3POpfStalqRC+J4+Hnn6Om7w==", - "requires": { - "@babel/runtime": "^7.15.4", - "is-retry-allowed": "^2.2.0" - } - }, - "babel-jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", - "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", - "dev": true, - "requires": { - "@jest/transform": "^29.6.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" - }, - "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, - "requires": { - "safe-buffer": "5.1.2" - }, - "dependencies": { - "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 - } - } - }, - "bcrypt": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", - "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.10", - "node-addon-api": "^5.0.0" - } - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "bigint-conversion": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.4.1.tgz", - "integrity": "sha512-/DTRevseMZoqN4KLkN5BryOiom0KbwYajiXG5Vo+ZcEPAO0WBZyZoYyDZSgfeq/v/oegLo9bjdndDBlExvAhBQ==", - "requires": { - "@juanelas/base64": "^1.1.2" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - } - } - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==" - }, - "bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "bson": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", - "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==" - }, - "btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==" - }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "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==" - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "bull": { - "version": "4.10.4", - "resolved": "https://registry.npmjs.org/bull/-/bull-4.10.4.tgz", - "integrity": "sha512-o9m/7HjS/Or3vqRd59evBlWCXd9Lp+ALppKseoSKHaykK46SmRjAilX98PgmOz1yeVaurt8D5UtvEt4bUjM3eA==", - "dev": true, - "requires": { - "cron-parser": "^4.2.1", - "debuglog": "^1.0.0", - "get-port": "^5.1.1", - "ioredis": "^5.0.0", - "lodash": "^4.17.21", - "msgpackr": "^1.5.2", - "semver": "^7.3.2", - "uuid": "^8.3.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", - "dev": true, - "requires": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" - } - }, - "caniuse-lite": { - "version": "1.0.30001517", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", - "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==" - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" - }, - "cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", - "requires": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6" - }, - "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - } - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cron-parser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.8.1.tgz", - "integrity": "sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==", - "dev": true, - "requires": { - "luxon": "^3.2.1" - } - }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" - }, - "dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "debuglog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" - }, - "defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "requires": { - "clone": "^1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==" - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" - }, - "duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "requires": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" - } - }, - "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==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "electron-to-chromium": { - "version": "1.4.467", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.467.tgz", - "integrity": "sha512-2qI70O+rR4poYeF2grcuS/bCps5KJh6y1jtZMDDEteyKJQrzLOEhFyXCLcHW6DTBjKjWkk26JhWoAi+Ux9A0fg==", - "dev": true - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "eslint-scope": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", - "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "eslint-plugin-unused-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", - "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", - "dev": true, - "requires": { - "eslint-rule-composer": "^0.3.0" - } - }, - "eslint-rule-composer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" - }, - "eventsource": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", - "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==" - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.6.1", - "@types/node": "*", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1" - } - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "express-async-errors": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", - "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==", - "requires": {} - }, - "express-handlebars": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.7.tgz", - "integrity": "sha512-iYeMFpc/hMD+E6FNAZA5fgWeXnXr4rslOSPkeEV6TwdmpJ5lEXuWX0u9vFYs31P2MURctQq2batR09oeNj0LIg==", - "requires": { - "glob": "^8.1.0", - "graceful-fs": "^4.2.10", - "handlebars": "^4.7.7" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "express-rate-limit": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.8.0.tgz", - "integrity": "sha512-yVeDWczkh8qgo9INJB1tT4j7LFu+n6ei/oqSMsqpsUIGYjTM+gk+Q3wv19TMUdo8chvus8XohAuOhG7RYRM9ZQ==", - "requires": {} - }, - "express-validator": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.15.0.tgz", - "integrity": "sha512-r05VYoBL3i2pswuehoFSy+uM8NBuVaY7avp5qrYjQBDzagx2Z5A77FZqPT8/gNLF3HopWkIzaTFaC4JysWXLqg==", - "requires": { - "lodash": "^4.17.21", - "validator": "^13.9.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true - }, - "fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fast-redact": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.2.0.tgz", - "integrity": "sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==" - }, - "fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "requires": { - "punycode": "^1.3.2" - } - }, - "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==", - "requires": { - "strnum": "^1.0.5" - } - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==" - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", - "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", - "dev": true, - "requires": { - "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", - "once": "^1.4.0", - "qs": "^6.11.0" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "requires": { - "is-property": "^1.0.2" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - }, - "dependencies": { - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "helmet": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-5.1.1.tgz", - "integrity": "sha512-/yX0oVZBggA9cLJh8aw3PPCfedBnbd7J2aowjzsaWwZh7/UFY0nccn/aHAggIgWUFfnykX8GKd3a1pSbrmlcVQ==" - }, - "help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "requires": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "infisical-node": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.3.2.tgz", - "integrity": "sha512-o1rxfOBAmpTiipka9Xnfa2AgTS8CkJHo0aRQwk6UGi+yEkKzXS7dDM7bZD56M/z+yKGLK15QkfFGZXp1VomlHw==", - "requires": { - "axios": "^1.3.3", - "dotenv": "^16.0.3", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "install": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", - "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==", - "dev": true - }, - "ioredis": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", - "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", - "requires": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - }, - "dependencies": { - "denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" - } - } - }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "ip6addr": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/ip6addr/-/ip6addr-0.2.5.tgz", - "integrity": "sha512-9RGGSB6Zc9Ox5DpDGFnJdIeF0AsqXzdH+FspCfPPaU/L/4tI6P+5lIoFUFm9JXs9IrJv1boqAaNCQmoDADTSKQ==", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2" - } - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "is-base64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-base64/-/is-base64-1.1.0.tgz", - "integrity": "sha512-Nlhg7Z2dVC4/PTvIFkgVVNvPHSO2eR/Yd0XzhGiXCXEvWnptXlXa/clQ8aePPiMuxEGcWfzWbGw2Fe3d+Y3v1g==" - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" - }, - "is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "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==" - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" - }, - "is-retry-allowed": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", - "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "requires": { - "which-typed-array": "^1.1.11" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", - "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", - "dev": true, - "requires": { - "@jest/core": "^29.6.1", - "@jest/types": "^29.6.1", - "import-local": "^3.0.2", - "jest-cli": "^29.6.1" - } - }, - "jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - } - }, - "jest-circus": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", - "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.1", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "p-limit": "^3.1.0", - "pretty-format": "^29.6.1", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-cli": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", - "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", - "dev": true, - "requires": { - "@jest/core": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - } - }, - "jest-config": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", - "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.1", - "@jest/types": "^29.6.1", - "babel-jest": "^29.6.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.1", - "jest-environment-node": "^29.6.1", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.6.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-diff": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", - "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" - } - }, - "jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", - "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.6.1", - "pretty-format": "^29.6.1" - } - }, - "jest-environment-node": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", - "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" - } - }, - "jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", - "dev": true - }, - "jest-haste-map": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", - "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-junit": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-15.0.0.tgz", - "integrity": "sha512-Z5sVX0Ag3HZdMUnD5DFlG+1gciIFSy7yIVPhOdGUi8YJaI9iLvvBb530gtQL2CHmv0JJeiwRZenr0VrSR7frvg==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "strip-ansi": "^6.0.1", - "uuid": "^8.3.2", - "xml": "^1.0.1" - } - }, - "jest-leak-detector": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", - "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", - "dev": true, - "requires": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" - } - }, - "jest-matcher-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", - "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.6.1", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" - } - }, - "jest-message-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", - "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", - "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "jest-util": "^29.6.1" - } - }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", - "dev": true - }, - "jest-resolve": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", - "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", - "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", - "dev": true, - "requires": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.1" - } - }, - "jest-runner": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", - "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", - "dev": true, - "requires": { - "@jest/console": "^29.6.1", - "@jest/environment": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-leak-detector": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-resolve": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-util": "^29.6.1", - "jest-watcher": "^29.6.1", - "jest-worker": "^29.6.1", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - } - }, - "jest-runtime": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", - "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/globals": "^29.6.1", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - }, - "jest-snapshot": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", - "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.6.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.1", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "natural-compare": "^1.4.0", - "pretty-format": "^29.6.1", - "semver": "^7.5.3" - } - }, - "jest-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", - "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", - "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "leven": "^3.1.0", - "pretty-format": "^29.6.1" - } - }, - "jest-watcher": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", - "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", - "dev": true, - "requires": { - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.6.1", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", - "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.6.1", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" - }, - "joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "jsonwebtoken": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", - "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", - "requires": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - } - }, - "jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "jsrp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/jsrp/-/jsrp-0.2.4.tgz", - "integrity": "sha512-+CjGAhZaj3k2MMXEy+xWYv7xJGnise/SlL1IIvnRuJ1ZiLtNPJJln/dMDCgORQCq1ouXDnW1FBxW5bkBFhK/8g==", - "requires": { - "create-hash": "^1.0.0", - "jsbn": "^1.0.0", - "randombytes": "^2.0.0" - } - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "kareem": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", - "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==" - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "libsodium": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.11.tgz", - "integrity": "sha512-WPfJ7sS53I2s4iM58QxY3Inb83/6mjlYgcmZs7DJsvDlnmVUwNinBCi5vBT43P6bHRy01O4zsMU2CoVR6xJ40A==" - }, - "libsodium-wrappers": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.11.tgz", - "integrity": "sha512-SrcLtXj7BM19vUKtQuyQKiQCRJPgbpauzl3s0rSwD+60wtHqSUuqcoawlMDheCJga85nKOQwxNYQxf/CKAvs6Q==", - "requires": { - "libsodium": "^0.7.11" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" - }, - "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==" - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, - "lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "luxon": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", - "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==", - "dev": true - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - }, - "maxmind": { - "version": "4.3.11", - "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.11.tgz", - "integrity": "sha512-tJDrKbUzN6PSA88tWgg0L2R4Ln00XwecYQJPFI+RvlF2k1sx6VQYtuQ1SVxm8+bw5tF7GWV4xyb+3/KyzEpPUw==", - "dev": true, - "requires": { - "mmdb-lib": "2.0.2", - "tiny-lru": "11.0.1" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "mmdb-lib": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mmdb-lib/-/mmdb-lib-2.0.2.tgz", - "integrity": "sha512-shi1I+fCPQonhTi7qyb6hr7hi87R7YS69FlfJiMFuJ12+grx0JyL56gLNzGTYXPU7EhAPkMLliGeyHer0K+AVA==", - "dev": true - }, - "mongodb": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", - "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==", - "requires": { - "@mongodb-js/saslprep": "^1.1.0", - "bson": "^5.5.0", - "mongodb-connection-string-url": "^2.6.0", - "socks": "^2.7.1" - } - }, - "mongodb-connection-string-url": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", - "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", - "requires": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" - } - }, - "mongoose": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.3.tgz", - "integrity": "sha512-moYP2qWCOdWRDeBxqB/zYwQmQnTBsF5DoolX5uPyI218BkiA1ujGY27P0NTd4oWIX+LLkZPw0LDzlc/7oh1plg==", - "requires": { - "bson": "^5.5.0", - "kareem": "2.5.1", - "mongodb": "5.9.0", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "16.0.1" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "dev": true, - "requires": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" - }, - "mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", - "requires": { - "debug": "4.x" - } - }, - "mri": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", - "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "msgpackr": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.9.6.tgz", - "integrity": "sha512-50rmb6+ZWvEm0vJn8R8CwI1Eavss3h5rgtKrcdUal3EkZcpqw82+xsmc7RoHb8fYB5V4EOU2NDaOitDAdO0t+w==", - "dev": true, - "requires": { - "msgpackr-extract": "^3.0.2" - } - }, - "msgpackr-extract": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", - "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", - "dev": true, - "optional": true, - "requires": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2", - "node-gyp-build-optional-packages": "5.0.7" - } - }, - "mysql2": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.2.tgz", - "integrity": "sha512-m5erE6bMoWfPXW1D5UrVwlT8PowAoSX69KcZzPuARQ3wY1RJ52NW9PdvdPo076XiSIkQ5IBTis7hxdlrQTlyug==", - "requires": { - "denque": "^2.1.0", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.3", - "long": "^5.2.1", - "lru-cache": "^8.0.0", - "named-placeholders": "^1.1.3", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "dependencies": { - "denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "lru-cache": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==" - }, - "sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" - } - } - }, - "named-placeholders": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", - "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", - "requires": { - "lru-cache": "^7.14.1" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - } - } - }, - "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - }, - "node-cache": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", - "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", - "requires": { - "clone": "2.x" - } - }, - "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "requires": { - "whatwg-url": "^5.0.0" - }, - "dependencies": { - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } - }, - "node-gyp-build-optional-packages": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", - "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", - "dev": true, - "optional": true - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true - }, - "nodemailer": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", - "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==" - }, - "nodemon": { - "version": "2.0.22", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", - "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", - "dev": true, - "requires": { - "chokidar": "^3.5.2", - "debug": "^3.2.7", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^5.7.1", - "simple-update-notifier": "^1.0.7", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm": { - "version": "8.19.4", - "resolved": "https://registry.npmjs.org/npm/-/npm-8.19.4.tgz", - "integrity": "sha512-3HANl8i9DKnUA89P4KEgVNN28EjSeDCmvEqbzOAuxCFDzdBZzjUl99zgnGpOUumvW5lvJo2HKcjrsc+tfyv1Hw==", - "dev": true, - "requires": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^5.6.3", - "@npmcli/ci-detect": "^2.0.0", - "@npmcli/config": "^4.2.1", - "@npmcli/fs": "^2.1.0", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/package-json": "^2.0.0", - "@npmcli/run-script": "^4.2.1", - "abbrev": "~1.1.1", - "archy": "~1.0.0", - "cacache": "^16.1.3", - "chalk": "^4.1.2", - "chownr": "^2.0.0", - "cli-columns": "^4.0.0", - "cli-table3": "^0.6.2", - "columnify": "^1.6.0", - "fastest-levenshtein": "^1.0.12", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "graceful-fs": "^4.2.10", - "hosted-git-info": "^5.2.1", - "ini": "^3.0.1", - "init-package-json": "^3.0.2", - "is-cidr": "^4.0.2", - "json-parse-even-better-errors": "^2.3.1", - "libnpmaccess": "^6.0.4", - "libnpmdiff": "^4.0.5", - "libnpmexec": "^4.0.14", - "libnpmfund": "^3.0.5", - "libnpmhook": "^8.0.4", - "libnpmorg": "^4.0.4", - "libnpmpack": "^4.1.3", - "libnpmpublish": "^6.0.5", - "libnpmsearch": "^5.0.4", - "libnpmteam": "^4.0.4", - "libnpmversion": "^3.0.7", - "make-fetch-happen": "^10.2.0", - "minimatch": "^5.1.0", - "minipass": "^3.1.6", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "ms": "^2.1.2", - "node-gyp": "^9.1.0", - "nopt": "^6.0.0", - "npm-audit-report": "^3.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.1.0", - "npm-pick-manifest": "^7.0.2", - "npm-profile": "^6.2.0", - "npm-registry-fetch": "^13.3.1", - "npm-user-validate": "^1.0.1", - "npmlog": "^6.0.2", - "opener": "^1.5.2", - "p-map": "^4.0.0", - "pacote": "^13.6.2", - "parse-conflict-json": "^2.0.2", - "proc-log": "^2.0.1", - "qrcode-terminal": "^0.12.0", - "read": "~1.0.7", - "read-package-json": "^5.0.2", - "read-package-json-fast": "^2.0.3", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.1", - "tar": "^6.1.11", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^2.0.0", - "validate-npm-package-name": "^4.0.0", - "which": "^2.0.2", - "write-file-atomic": "^4.0.1" - }, - "dependencies": { - "@colors/colors": { - "version": "1.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "@gar/promisify": { - "version": "1.1.3", - "bundled": true, - "dev": true - }, - "@isaacs/string-locale-compare": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "@npmcli/arborist": { - "version": "5.6.3", - "bundled": true, - "dev": true, - "requires": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/metavuln-calculator": "^3.0.1", - "@npmcli/move-file": "^2.0.0", - "@npmcli/name-from-folder": "^1.0.1", - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/package-json": "^2.0.0", - "@npmcli/query": "^1.2.0", - "@npmcli/run-script": "^4.1.3", - "bin-links": "^3.0.3", - "cacache": "^16.1.3", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^5.2.1", - "json-parse-even-better-errors": "^2.3.1", - "json-stringify-nice": "^1.1.4", - "minimatch": "^5.1.0", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^6.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.0.0", - "npm-pick-manifest": "^7.0.2", - "npm-registry-fetch": "^13.0.0", - "npmlog": "^6.0.2", - "pacote": "^13.6.1", - "parse-conflict-json": "^2.0.1", - "proc-log": "^2.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^1.0.1", - "read-package-json-fast": "^2.0.2", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.0", - "treeverse": "^2.0.0", - "walk-up-path": "^1.0.0" - } - }, - "@npmcli/ci-detect": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "@npmcli/config": { - "version": "4.2.2", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/map-workspaces": "^2.0.2", - "ini": "^3.0.0", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^6.0.0", - "proc-log": "^2.0.0", - "read-package-json-fast": "^2.0.3", - "semver": "^7.3.5", - "walk-up-path": "^1.0.0" - } - }, - "@npmcli/disparity-colors": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "^4.3.0" - } - }, - "@npmcli/fs": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "requires": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - } - }, - "@npmcli/git": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/promise-spawn": "^3.0.0", - "lru-cache": "^7.4.4", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^7.0.0", - "proc-log": "^2.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" - } - }, - "@npmcli/installed-package-contents": { - "version": "1.0.7", - "bundled": true, - "dev": true, - "requires": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - }, - "dependencies": { - "npm-bundled": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - } - } - }, - "@npmcli/map-workspaces": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/name-from-folder": "^1.0.1", - "glob": "^8.0.1", - "minimatch": "^5.0.1", - "read-package-json-fast": "^2.0.3" - } - }, - "@npmcli/metavuln-calculator": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "requires": { - "cacache": "^16.0.0", - "json-parse-even-better-errors": "^2.3.1", - "pacote": "^13.0.3", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "@npmcli/name-from-folder": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "@npmcli/node-gyp": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "@npmcli/package-json": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.1" - } - }, - "@npmcli/promise-spawn": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "infer-owner": "^1.0.4" - } - }, - "@npmcli/query": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "npm-package-arg": "^9.1.0", - "postcss-selector-parser": "^6.0.10", - "semver": "^7.3.7" - } - }, - "@npmcli/run-script": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" - } - }, - "@tootallnate/once": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "bundled": true, - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ansi-regex": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "bundled": true, - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "aproba": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "archy": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "are-we-there-yet": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "asap": { - "version": "2.0.6", - "bundled": true, - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "bin-links": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "requires": { - "cmd-shim": "^5.0.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0", - "read-cmd-shim": "^3.0.0", - "rimraf": "^3.0.0", - "write-file-atomic": "^4.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "binary-extensions": { - "version": "2.2.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "builtins": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "cacache": { - "version": "16.1.3", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - } - }, - "chalk": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chownr": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "cidr-regex": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "requires": { - "ip-regex": "^4.1.0" - } - }, - "clean-stack": { - "version": "2.2.0", - "bundled": true, - "dev": true - }, - "cli-columns": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - } - }, - "cli-table3": { - "version": "0.6.2", - "bundled": true, - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "string-width": "^4.2.0" - } - }, - "clone": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "cmd-shim": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "mkdirp-infer-owner": "^2.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "bundled": true, - "dev": true - }, - "color-support": { - "version": "1.1.3", - "bundled": true, - "dev": true - }, - "columnify": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "requires": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - } - }, - "common-ancestor-path": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "debug": { - "version": "4.3.4", - "bundled": true, - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "defaults": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "depd": { - "version": "1.1.2", - "bundled": true, - "dev": true - }, - "dezalgo": { - "version": "1.0.4", - "bundled": true, - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "diff": { - "version": "5.1.0", - "bundled": true, - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "bundled": true, - "dev": true - }, - "encoding": { - "version": "0.1.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, - "env-paths": { - "version": "2.2.1", - "bundled": true, - "dev": true - }, - "err-code": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.12", - "bundled": true, - "dev": true - }, - "fs-minipass": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "bundled": true, - "dev": true - }, - "gauge": { - "version": "4.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "glob": { - "version": "8.0.3", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "bundled": true, - "dev": true - }, - "has": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "hosted-git-info": { - "version": "5.2.1", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "http-cache-semantics": { - "version": "4.1.1", - "bundled": true, - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "ignore-walk": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "requires": { - "minimatch": "^5.0.1" - } - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true, - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true - }, - "ini": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, - "init-package-json": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "npm-package-arg": "^9.0.1", - "promzard": "^0.3.0", - "read": "^1.0.7", - "read-package-json": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^4.0.0" - } - }, - "ip": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "ip-regex": { - "version": "4.3.0", - "bundled": true, - "dev": true - }, - "is-cidr": { - "version": "4.0.2", - "bundled": true, - "dev": true, - "requires": { - "cidr-regex": "^3.1.1" - } - }, - "is-core-module": { - "version": "2.10.0", - "bundled": true, - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "is-lambda": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "bundled": true, - "dev": true - }, - "json-stringify-nice": { - "version": "1.1.4", - "bundled": true, - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "bundled": true, - "dev": true - }, - "just-diff": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "just-diff-apply": { - "version": "5.4.1", - "bundled": true, - "dev": true - }, - "libnpmaccess": { - "version": "6.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "minipass": "^3.1.1", - "npm-package-arg": "^9.0.1", - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmdiff": { - "version": "4.0.5", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/disparity-colors": "^2.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "binary-extensions": "^2.2.0", - "diff": "^5.1.0", - "minimatch": "^5.0.1", - "npm-package-arg": "^9.0.1", - "pacote": "^13.6.1", - "tar": "^6.1.0" - } - }, - "libnpmexec": { - "version": "4.0.14", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/arborist": "^5.6.3", - "@npmcli/ci-detect": "^2.0.0", - "@npmcli/fs": "^2.1.1", - "@npmcli/run-script": "^4.2.0", - "chalk": "^4.1.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-package-arg": "^9.0.1", - "npmlog": "^6.0.2", - "pacote": "^13.6.1", - "proc-log": "^2.0.0", - "read": "^1.0.7", - "read-package-json-fast": "^2.0.2", - "semver": "^7.3.7", - "walk-up-path": "^1.0.0" - } - }, - "libnpmfund": { - "version": "3.0.5", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/arborist": "^5.6.3" - } - }, - "libnpmhook": { - "version": "8.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmorg": { - "version": "4.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmpack": { - "version": "4.1.3", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/run-script": "^4.1.3", - "npm-package-arg": "^9.0.1", - "pacote": "^13.6.1" - } - }, - "libnpmpublish": { - "version": "6.0.5", - "bundled": true, - "dev": true, - "requires": { - "normalize-package-data": "^4.0.0", - "npm-package-arg": "^9.0.1", - "npm-registry-fetch": "^13.0.0", - "semver": "^7.3.7", - "ssri": "^9.0.0" - } - }, - "libnpmsearch": { - "version": "5.0.4", - "bundled": true, - "dev": true, - "requires": { - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmteam": { - "version": "4.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^13.0.0" - } - }, - "libnpmversion": { - "version": "3.0.7", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/git": "^3.0.0", - "@npmcli/run-script": "^4.1.3", - "json-parse-even-better-errors": "^2.3.1", - "proc-log": "^2.0.0", - "semver": "^7.3.7" - } - }, - "lru-cache": { - "version": "7.13.2", - "bundled": true, - "dev": true - }, - "make-fetch-happen": { - "version": "10.2.1", - "bundled": true, - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - } - }, - "minimatch": { - "version": "5.1.0", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "3.3.4", - "bundled": true, - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "minipass-flush": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-json-stream": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "mkdirp-infer-owner": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "chownr": "^2.0.0", - "infer-owner": "^1.0.4", - "mkdirp": "^1.0.3" - } - }, - "ms": { - "version": "2.1.3", - "bundled": true, - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "bundled": true, - "dev": true - }, - "node-gyp": { - "version": "9.1.0", - "bundled": true, - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "nopt": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "abbrev": "1" - } - } - } - }, - "nopt": { - "version": "6.0.0", - "bundled": true, - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - }, - "normalize-package-data": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "npm-audit-report": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "chalk": "^4.0.0" - } - }, - "npm-bundled": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "npm-install-checks": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "semver": "^7.1.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "npm-package-arg": { - "version": "9.1.0", - "bundled": true, - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - } - }, - "npm-packlist": { - "version": "5.1.3", - "bundled": true, - "dev": true, - "requires": { - "glob": "^8.0.1", - "ignore-walk": "^5.0.1", - "npm-bundled": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "npm-pick-manifest": { - "version": "7.0.2", - "bundled": true, - "dev": true, - "requires": { - "npm-install-checks": "^5.0.0", - "npm-normalize-package-bin": "^2.0.0", - "npm-package-arg": "^9.0.0", - "semver": "^7.3.5" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "npm-profile": { - "version": "6.2.1", - "bundled": true, - "dev": true, - "requires": { - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0" - } - }, - "npm-registry-fetch": { - "version": "13.3.1", - "bundled": true, - "dev": true, - "requires": { - "make-fetch-happen": "^10.0.6", - "minipass": "^3.1.6", - "minipass-fetch": "^2.0.3", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.1", - "proc-log": "^2.0.0" - } - }, - "npm-user-validate": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "npmlog": { - "version": "6.0.2", - "bundled": true, - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.5.2", - "bundled": true, - "dev": true - }, - "p-map": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "pacote": { - "version": "13.6.2", - "bundled": true, - "dev": true, - "requires": { - "@npmcli/git": "^3.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^4.1.0", - "cacache": "^16.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.6", - "mkdirp": "^1.0.4", - "npm-package-arg": "^9.0.0", - "npm-packlist": "^5.1.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^5.0.0", - "read-package-json-fast": "^2.0.3", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11" - } - }, - "parse-conflict-json": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.1", - "just-diff": "^5.0.1", - "just-diff-apply": "^5.2.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "postcss-selector-parser": { - "version": "6.0.10", - "bundled": true, - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "proc-log": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "promise-all-reject-late": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "promise-call-limit": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "promise-retry": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "promzard": { - "version": "0.3.0", - "bundled": true, - "dev": true, - "requires": { - "read": "1" - } - }, - "qrcode-terminal": { - "version": "0.12.0", - "bundled": true, - "dev": true - }, - "read": { - "version": "1.0.7", - "bundled": true, - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "read-package-json": { - "version": "5.0.2", - "bundled": true, - "dev": true, - "requires": { - "glob": "^8.0.1", - "json-parse-even-better-errors": "^2.3.1", - "normalize-package-data": "^4.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "read-package-json-fast": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "readable-stream": { - "version": "3.6.0", - "bundled": true, - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdir-scoped-modules": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "retry": { - "version": "0.12.0", - "bundled": true, - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "safe-buffer": { - "version": "5.2.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "7.3.7", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "bundled": true, - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "bundled": true, - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "bundled": true, - "dev": true - }, - "socks": { - "version": "2.7.0", - "bundled": true, - "dev": true, - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "bundled": true, - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "spdx-correct": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "bundled": true, - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "bundled": true, - "dev": true - }, - "ssri": { - "version": "9.0.1", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-width": { - "version": "4.2.3", - "bundled": true, - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "bundled": true, - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "tar": { - "version": "6.1.11", - "bundled": true, - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true, - "dev": true - }, - "tiny-relative-date": { - "version": "1.3.0", - "bundled": true, - "dev": true - }, - "treeverse": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "unique-filename": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "unique-slug": "^3.0.0" - } - }, - "unique-slug": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - }, - "walk-up-path": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "write-file-atomic": { - "version": "4.0.2", - "bundled": true, - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "yallist": { - "version": "4.0.0", - "bundled": true, - "dev": true - } - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "octokit-auth-probot": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/octokit-auth-probot/-/octokit-auth-probot-1.2.9.tgz", - "integrity": "sha512-mMjw6Y760EwJnW2tSVooJK8BMdsG6D40SoCclnefVf/5yWjaNVquEu8NREBVWb60OwbpnMEz4vREXHB5xdMFYQ==", - "requires": { - "@octokit/auth-app": "^4.0.2", - "@octokit/auth-token": "^3.0.0", - "@octokit/auth-unauthenticated": "^3.0.0", - "@octokit/types": "^8.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" - }, - "@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "requires": { - "@octokit/openapi-types": "^14.0.0" - } - } - } - }, - "on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" - }, - "p-throttle": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/p-throttle/-/p-throttle-5.1.0.tgz", - "integrity": "sha512-+N+s2g01w1Zch4D0K3OpnPDqLOKmLcQ4BvIFq3JC0K29R28vUOjWpO+OJZBNt8X9i3pFCksZJZ0YXkUGjaFE6g==" - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "passport": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", - "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", - "requires": { - "passport-strategy": "1.x.x", - "pause": "0.0.1", - "utils-merge": "^1.0.1" - } - }, - "passport-github": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/passport-github/-/passport-github-1.1.0.tgz", - "integrity": "sha512-XARXJycE6fFh/dxF+Uut8OjlwbFEXgbPVj/+V+K7cvriRK7VcAOm+NgBmbiLM9Qv3SSxEAV+V6fIk89nYHXa8A==", - "requires": { - "passport-oauth2": "1.x.x" - } - }, - "passport-gitlab2": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/passport-gitlab2/-/passport-gitlab2-5.0.0.tgz", - "integrity": "sha512-cXQMgM6JQx9wHVh7JLH30D8fplfwjsDwRz+zS0pqC8JS+4bNmc1J04NGp5g2M4yfwylH9kQRrMN98GxMw7q7cg==", - "requires": { - "passport-oauth2": "^1.4.0" - } - }, - "passport-google-oauth20": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", - "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", - "requires": { - "passport-oauth2": "1.x.x" - } - }, - "passport-oauth2": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", - "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", - "requires": { - "base64url": "3.x.x", - "oauth": "0.9.x", - "passport-strategy": "1.x.x", - "uid2": "0.0.x", - "utils-merge": "1.x.x" - } - }, - "passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" - }, - "pg": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", - "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-cloudflare": "^1.1.1", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "optional": true - }, - "pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true - }, - "pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", - "requires": {} - }, - "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "requires": { - "split2": "^4.1.0" - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "pino": { - "version": "8.16.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.16.1.tgz", - "integrity": "sha512-3bKsVhBmgPjGV9pyn4fO/8RtoVDR8ssW1ev819FsRXlRNgW8gR/9Kx+gCK4UPWd4JjrRDLWpzd/pb1AyWm3MGA==", - "requires": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "v1.1.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.7.0", - "thread-stream": "^2.0.0" - }, - "dependencies": { - "sonic-boom": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.7.0.tgz", - "integrity": "sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==", - "requires": { - "atomic-sleep": "^1.0.0" - } - } - } - }, - "pino-abstract-transport": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", - "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", - "requires": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - } - } - }, - "pino-http": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-8.5.1.tgz", - "integrity": "sha512-T/3d9YHKBYpv/QHjNy73P5BNYYkRrC2/D6CxKMecG4fKFLN+B2iC6LsKYzGRTRV+Ld3fjxFC1ca4TUGbPdzk+Q==", - "requires": { - "get-caller-file": "^2.0.5", - "pino": "^8.0.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0" - } - }, - "pino-pretty": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.2.3.tgz", - "integrity": "sha512-4jfIUc8TC1GPUfDyMSlW1STeORqkoxec71yhxIpLDQapUu8WOuoz2TTCoidrIssyz78LZC69whBMPIKCMbi3cw==", - "requires": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - }, - "sonic-boom": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.7.0.tgz", - "integrity": "sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==", - "requires": { - "atomic-sleep": "^1.0.0" - } - } - } - }, - "pino-std-serializers": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" - }, - "pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true - }, - "pkg-conf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "requires": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" - } - } - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" - }, - "postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", - "dev": true - }, - "posthog-node": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-2.6.0.tgz", - "integrity": "sha512-/BiFw/jwdP0uJSRAIoYqLoBTjZ612xv74b1L/a3T/p1nJVL8e0OrHuxbJW56c6WVW/IKm9gBF/zhbqfaz0XgJQ==", - "requires": { - "axios": "^0.27.0" - }, - "dependencies": { - "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - } - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "pretty-format": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", - "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.0", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "probot": { - "version": "12.3.3", - "resolved": "https://registry.npmjs.org/probot/-/probot-12.3.3.tgz", - "integrity": "sha512-cdtKd+xISzi8sw6++BYBXleRknCA6hqUMoHj/sJqQBrjbNxQLhfeFCq9O2d0Z4eShsy5YFRR3MWwDKJ9uAE0CA==", - "requires": { - "@octokit/core": "^3.2.4", - "@octokit/plugin-enterprise-compatibility": "^1.2.8", - "@octokit/plugin-paginate-rest": "^2.6.2", - "@octokit/plugin-rest-endpoint-methods": "^5.0.1", - "@octokit/plugin-retry": "^3.0.6", - "@octokit/plugin-throttling": "^3.3.4", - "@octokit/types": "^8.0.0", - "@octokit/webhooks": "^9.26.3", - "@probot/get-private-key": "^1.1.0", - "@probot/octokit-plugin-config": "^1.0.0", - "@probot/pino": "^2.2.0", - "@types/express": "^4.17.9", - "@types/ioredis": "^4.27.1", - "@types/pino": "^6.3.4", - "@types/pino-http": "^5.0.6", - "commander": "^6.2.0", - "deepmerge": "^4.2.2", - "deprecation": "^2.3.1", - "dotenv": "^8.2.0", - "eventsource": "^2.0.2", - "express": "^4.17.1", - "express-handlebars": "^6.0.3", - "ioredis": "^4.27.8", - "js-yaml": "^3.14.1", - "lru-cache": "^6.0.0", - "octokit-auth-probot": "^1.2.2", - "pino": "^6.7.0", - "pino-http": "^5.3.0", - "pkg-conf": "^3.1.0", - "resolve": "^1.19.0", - "semver": "^7.3.4", - "update-dotenv": "^1.1.1", - "uuid": "^8.3.2" - }, - "dependencies": { - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "requires": { - "@octokit/types": "^6.0.3" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" - }, - "@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "requires": { - "@octokit/types": "^6.40.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "requires": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/plugin-throttling": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz", - "integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==", - "requires": { - "@octokit/types": "^6.0.1", - "bottleneck": "^2.15.3" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - } - } - }, - "@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "requires": { - "@octokit/openapi-types": "^14.0.0" - } - }, - "@types/pino": { - "version": "6.3.12", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-6.3.12.tgz", - "integrity": "sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw==", - "requires": { - "@types/node": "*", - "@types/pino-pretty": "*", - "@types/pino-std-serializers": "*", - "sonic-boom": "^2.1.0" - }, - "dependencies": { - "sonic-boom": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", - "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", - "requires": { - "atomic-sleep": "^1.0.0" - } - } - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" - }, - "ioredis": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz", - "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==", - "requires": { - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.1", - "denque": "^1.1.0", - "lodash.defaults": "^4.2.0", - "lodash.flatten": "^4.4.0", - "lodash.isarguments": "^3.1.0", - "p-map": "^2.1.0", - "redis-commands": "1.7.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "pino": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz", - "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", - "requires": { - "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.8", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", - "process-warning": "^1.0.0", - "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" - } - }, - "pino-http": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-5.8.0.tgz", - "integrity": "sha512-YwXiyRb9y0WCD1P9PcxuJuh3Dc5qmXde/paJE86UGYRdiFOi828hR9iUGmk5gaw6NBT9gLtKANOHFimvh19U5w==", - "requires": { - "fast-url-parser": "^1.1.3", - "pino": "^6.13.0", - "pino-std-serializers": "^4.0.0" - }, - "dependencies": { - "pino-std-serializers": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", - "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==" - } - } - }, - "pino-std-serializers": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", - "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==" - }, - "process-warning": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", - "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" - }, - "sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", - "requires": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "process-warning": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.0.tgz", - "integrity": "sha512-N6mp1+2jpQr3oCFMz6SeHRGbv6Slb20bRhj4v3xR99HqNToAcOe1MFOp4tytyzOfJn+QtN8Rf7U/h2KAn4kC6g==" - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "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==" - }, - "pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, - "pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "query-string": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", - "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", - "requires": { - "decode-uri-component": "^0.2.2", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "rate-limit-mongo": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/rate-limit-mongo/-/rate-limit-mongo-2.3.2.tgz", - "integrity": "sha512-dLck0j5N/AX9ycVHn5lX9Ti2Wrrwi1LfbXitu/mMBZOo2nC26RgYKJVbcb2mYgb9VMaPI2IwJVzIa2hAQrMaDA==", - "requires": { - "mongodb": "5.8.0", - "twostep": "0.4.2", - "underscore": "1.12.1" - }, - "dependencies": { - "mongodb": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.8.0.tgz", - "integrity": "sha512-xx4CXmxcj3bNe7iGBlhntVrUqrNARYhUZteXaz4epEESv4oXD/FONAovcyoCaEffdYlw25Yz284OxMfpnPLlgQ==", - "requires": { - "@mongodb-js/saslprep": "^1.1.0", - "bson": "^5.4.0", - "mongodb-connection-string-url": "^2.6.0", - "socks": "^2.7.1" - } - } - } - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==" - }, - "redis-commands": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", - "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" - }, - "redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "requires": { - "redis-errors": "^1.0.0" - } - }, - "regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" - }, - "resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "requires": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" - }, - "secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "sift": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", - "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "simple-update-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", - "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", - "dev": true, - "requires": { - "semver": "~7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" - }, - "smee-client": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/smee-client/-/smee-client-1.2.3.tgz", - "integrity": "sha512-uDrU8u9/Ln7aRXyzGHgVaNUS8onHZZeSwQjCdkMoSL7U85xI+l+Y2NgjibkMJAyXkW7IAbb8rw9RMHIjS6lAwA==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "eventsource": "^1.1.0", - "morgan": "^1.9.1", - "superagent": "^7.1.3", - "validator": "^13.7.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "eventsource": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.2.tgz", - "integrity": "sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==", - "dev": true - } - } - }, - "snappy": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/snappy/-/snappy-7.2.2.tgz", - "integrity": "sha512-iADMq1kY0v3vJmGTuKcFWSXt15qYUz7wFkArOrsSg0IFfI3nJqIJvK2/ZbEIndg7erIJLtAVX2nSOqPz7DcwbA==", - "optional": true, - "peer": true, - "requires": { - "@napi-rs/snappy-android-arm-eabi": "7.2.2", - "@napi-rs/snappy-android-arm64": "7.2.2", - "@napi-rs/snappy-darwin-arm64": "7.2.2", - "@napi-rs/snappy-darwin-x64": "7.2.2", - "@napi-rs/snappy-freebsd-x64": "7.2.2", - "@napi-rs/snappy-linux-arm-gnueabihf": "7.2.2", - "@napi-rs/snappy-linux-arm64-gnu": "7.2.2", - "@napi-rs/snappy-linux-arm64-musl": "7.2.2", - "@napi-rs/snappy-linux-x64-gnu": "7.2.2", - "@napi-rs/snappy-linux-x64-musl": "7.2.2", - "@napi-rs/snappy-win32-arm64-msvc": "7.2.2", - "@napi-rs/snappy-win32-ia32-msvc": "7.2.2", - "@napi-rs/snappy-win32-x64-msvc": "7.2.2" - } - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "sonic-boom": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", - "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", - "requires": { - "atomic-sleep": "^1.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" - }, - "split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==" - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - }, - "strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" - }, - "superagent": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", - "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", - "dev": true, - "requires": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "^2.5.0", - "qs": "^6.10.3", - "readable-stream": "^3.6.0", - "semver": "^7.3.7" - }, - "dependencies": { - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true - } - } - }, - "supertest": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", - "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^8.0.5" - }, - "dependencies": { - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true - }, - "superagent": { - "version": "8.0.9", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.9.tgz", - "integrity": "sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==", - "dev": true, - "requires": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.1.2", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" - } - } - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "swagger-autogen": { - "version": "2.23.5", - "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.23.5.tgz", - "integrity": "sha512-4Tl2+XhZMyHoBYkABnScHtQE0lKPKUD3NBt09mClrI6UKOUYljKlYw1xiFVwsHCTGR2hAXmhT4PpgjruCtt1ZA==", - "dev": true, - "requires": { - "acorn": "^7.4.1", - "deepmerge": "^4.2.2", - "glob": "^7.1.7", - "json5": "^2.2.3" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } - } - }, - "swagger-ui-dist": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.1.3.tgz", - "integrity": "sha512-W/vZFeZHG+xTN4yu8LXdaIrcnT4Hbr7qRUILYlMEoIiG6nuTylnEGeRcvL64F2eHRA2Jo/fgCSTU06Qfh0lT3g==" - }, - "swagger-ui-express": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.3.tgz", - "integrity": "sha512-CDje4PndhTD2HkgyKH3pab+LKspDeB/NhPN2OF1j+piYIamQqBYwAXWESOT1Yju2xFg51bRW9sUng2WxDjzArw==", - "requires": { - "swagger-ui-dist": ">=4.11.0" - } - }, - "tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "thread-stream": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", - "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", - "requires": { - "real-require": "^0.2.0" - } - }, - "tiny-lru": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.0.1.tgz", - "integrity": "sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==", - "dev": true - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "~1.0.10" - }, - "dependencies": { - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "requires": { - "abbrev": "1" - } - } - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "requires": { - "punycode": "^2.1.1" - }, - "dependencies": { - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" - } - } - }, - "ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - } - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" - }, - "twostep": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/twostep/-/twostep-0.4.2.tgz", - "integrity": "sha512-O/wdPYk9ey04qcCiw8AQN74DbvLFZLAgnryrNTpV7T/sxB4lcGkCMHynx5xCcA6fCh739ZAqp3HcGhy770X1qA==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" - }, - "uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "optional": true - }, - "uid2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", - "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" - }, - "undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "universal-github-app-jwt": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.1.tgz", - "integrity": "sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w==", - "requires": { - "@types/jsonwebtoken": "^9.0.0", - "jsonwebtoken": "^9.0.0" - }, - "dependencies": { - "@types/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", - "requires": { - "@types/node": "*" - } - } - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "update-dotenv": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-dotenv/-/update-dotenv-1.1.1.tgz", - "integrity": "sha512-3cIC18In/t0X/yH793c00qqxcKD8jVCgNOPif/fGQkFpYMGecM9YAc+kaAKXuZsM2dE9I9wFI7KvAuNX22SGMQ==", - "requires": {} - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" - } - } - }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - } - } - }, - "util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - } - } - }, - "validator": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "requires": { - "defaults": "^1.0.3" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true - }, - "xml-crypto": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-3.2.0.tgz", - "integrity": "sha512-qVurBUOQrmvlgmZqIVBqmb06TD2a/PpEUfFPgD7BuBfjmoH4zgkqaWSIJrnymlCvM2GGt9x+XtJFA+ttoAufqg==", - "requires": { - "@xmldom/xmldom": "^0.8.8", - "xpath": "0.0.32" - }, - "dependencies": { - "xpath": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", - "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==" - } - } - }, - "xml-encryption": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-3.0.2.tgz", - "integrity": "sha512-VxYXPvsWB01/aqVLd6ZMPWZ+qaj0aIdF+cStrVJMcFj3iymwZeI0ABzB3VqMYv48DkSpRhnrXqTUkR34j+UDyg==", - "requires": { - "@xmldom/xmldom": "^0.8.5", - "escape-html": "^1.0.3", - "xpath": "0.0.32" - }, - "dependencies": { - "xpath": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", - "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==" - } - } - }, - "xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "dependencies": { - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" - } - } - }, - "xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==" - }, - "xpath": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", - "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==" - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - }, - "zod": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==" - } - } -} diff --git a/backend-mongo/package.json b/backend-mongo/package.json deleted file mode 100644 index 395696272..000000000 --- a/backend-mongo/package.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.319.0", - "@casl/ability": "^6.5.0", - "@casl/mongoose": "^7.2.1", - "@godaddy/terminus": "^4.12.0", - "@node-saml/passport-saml": "^4.0.4", - "@octokit/rest": "^19.0.5", - "@sentry/node": "^7.77.0", - "@sentry/tracing": "^7.48.0", - "@serdnam/pino-cloudwatch-transport": "^1.0.4", - "@types/crypto-js": "^4.1.1", - "@types/libsodium-wrappers": "^0.7.10", - "@ucast/mongo2js": "^1.3.4", - "ajv": "^8.12.0", - "argon2": "^0.30.3", - "aws-sdk": "^2.1364.0", - "axios": "^1.6.0", - "axios-retry": "^3.4.0", - "bcrypt": "^5.1.0", - "bigint-conversion": "^2.4.0", - "cookie-parser": "^1.4.6", - "cors": "^2.8.5", - "crypto-js": "^4.2.0", - "dotenv": "^16.0.1", - "express": "^4.18.1", - "express-async-errors": "^3.1.1", - "express-rate-limit": "^6.7.0", - "express-validator": "^6.14.2", - "handlebars": "^4.7.7", - "helmet": "^5.1.1", - "infisical-node": "^1.2.1", - "ioredis": "^5.3.2", - "jmespath": "^0.16.0", - "js-yaml": "^4.1.0", - "jsonwebtoken": "^9.0.0", - "jsrp": "^0.2.4", - "libsodium-wrappers": "^0.7.10", - "lodash": "^4.17.21", - "mongoose": "^7.4.1", - "mysql2": "^3.6.2", - "nanoid": "^3.3.6", - "node-cache": "^5.1.2", - "nodemailer": "^6.8.0", - "ora": "^5.4.1", - "passport": "^0.6.0", - "passport-github": "^1.1.0", - "passport-gitlab2": "^5.0.0", - "passport-google-oauth20": "^2.0.0", - "pg": "^8.11.3", - "pino": "^8.16.1", - "pino-http": "^8.5.1", - "posthog-node": "^2.6.0", - "probot": "^12.3.3", - "query-string": "^7.1.3", - "rate-limit-mongo": "^2.3.2", - "rimraf": "^3.0.2", - "swagger-ui-express": "^4.6.2", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1", - "typescript": "^4.9.3", - "utility-types": "^3.10.0", - "zod": "^3.22.3" - }, - "overrides": { - "rate-limit-mongo": { - "mongodb": "5.8.0" - } - }, - "name": "infisical-api", - "version": "1.0.0", - "main": "src/index.js", - "scripts": { - "start": "node build/index.js", - "dev": "nodemon index.js", - "swagger-autogen": "node ./swagger/index.ts", - "build": "rimraf ./build && tsc && cp -R ./src/templates ./build && cp -R ./src/data ./build", - "lint": "eslint . --ext .ts", - "lint-and-fix": "eslint . --ext .ts --fix", - "lint-staged": "lint-staged", - "pretest": "docker compose -f test-resources/docker-compose.test.yml up -d", - "test": "cross-env NODE_ENV=test jest --verbose --testTimeout=10000 --detectOpenHandles; npm run posttest", - "test:ci": "npm test -- --watchAll=false --ci --reporters=default --reporters=jest-junit --reporters=github-actions --coverage --testLocationInResults --json --outputFile=coverage/report.json", - "posttest": "docker compose -f test-resources/docker-compose.test.yml down" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/Infisical/infisical-api.git" - }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/Infisical/infisical-api/issues" - }, - "homepage": "https://github.com/Infisical/infisical-api#readme", - "description": "", - "devDependencies": { - "@jest/globals": "^29.3.1", - "@posthog/plugin-scaffold": "^1.3.4", - "@swc/core": "^1.3.99", - "@swc/helpers": "^0.5.3", - "@types/bcrypt": "^5.0.0", - "@types/bcryptjs": "^2.4.2", - "@types/bull": "^4.10.0", - "@types/cookie-parser": "^1.4.3", - "@types/cors": "^2.8.12", - "@types/express": "^4.17.14", - "@types/jest": "^29.5.0", - "@types/jmespath": "^0.15.1", - "@types/jsonwebtoken": "^8.5.9", - "@types/lodash": "^4.14.191", - "@types/node": "^18.11.3", - "@types/nodemailer": "^6.4.6", - "@types/passport": "^1.0.12", - "@types/pg": "^8.10.7", - "@types/picomatch": "^2.3.0", - "@types/pino": "^7.0.5", - "@types/supertest": "^2.0.12", - "@types/swagger-jsdoc": "^6.0.1", - "@types/swagger-ui-express": "^4.1.3", - "@typescript-eslint/eslint-plugin": "^5.54.0", - "@typescript-eslint/parser": "^5.40.1", - "cross-env": "^7.0.3", - "eslint": "^8.26.0", - "eslint-plugin-unused-imports": "^2.0.0", - "install": "^0.13.0", - "jest": "^29.3.1", - "jest-junit": "^15.0.0", - "nodemon": "^2.0.19", - "npm": "^8.19.3", - "pino-pretty": "^10.2.3", - "regenerator-runtime": "^0.14.0", - "smee-client": "^1.2.3", - "supertest": "^6.3.3", - "swagger-autogen": "^2.23.5", - "ts-jest": "^29.0.3", - "ts-node": "^10.9.1" - }, - "jest-junit": { - "outputDirectory": "reports", - "outputName": "jest-junit.xml", - "ancestorSeparator": " › ", - "uniqueOutputName": "false", - "suiteNameTemplate": "{filepath}", - "classNameTemplate": "{classname}", - "titleTemplate": "{title}" - } -} diff --git a/backend-mongo/spec.json b/backend-mongo/spec.json deleted file mode 100644 index e5ecb5df0..000000000 --- a/backend-mongo/spec.json +++ /dev/null @@ -1,8047 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Infisical API", - "description": "List of all available APIs that can be consumed", - "version": "1.0.0" - }, - "servers": [ - { - "url": "https://app.infisical.com", - "description": "Production server" - }, - { - "url": "http://localhost:8080", - "description": "Local server" - } - ], - "paths": { - "/api/v1/identities/": { - "post": { - "summary": "Create identity", - "description": "Create identity", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identity": { - "$ref": "#/components/schemas/Identity" - } - }, - "description": "Details of the created identity" - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of entity to create", - "example": "development" - }, - "organizationId": { - "type": "string", - "description": "ID of organization where to create identity", - "example": "dev-environment" - }, - "role": { - "type": "string", - "description": "Role to assume for organization membership", - "example": "no-access" - } - }, - "required": [ - "name", - "organizationId", - "role" - ] - } - } - } - } - } - }, - "/api/v1/identities/{identityId}": { - "patch": { - "summary": "Update identity", - "description": "Update identity", - "parameters": [ - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity to update" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identity": { - "$ref": "#/components/schemas/Identity" - } - }, - "description": "Details of the updated identity" - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of entity to update to", - "example": "development" - }, - "role": { - "type": "string", - "description": "Role to update to for organization membership", - "example": "no-access" - } - } - } - } - } - } - }, - "delete": { - "summary": "Delete identity", - "description": "Delete identity", - "parameters": [ - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identity": { - "$ref": "#/components/schemas/Identity" - } - }, - "description": "Details of the deleted identity" - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - } - }, - "/api/v1/secret/{secretId}/secret-versions": { - "get": { - "summary": "Return secret versions", - "description": "Return secret versions", - "parameters": [ - { - "name": "secretId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of secret" - }, - { - "name": "offset", - "description": "Number of versions to skip", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "description": "Maximum number of versions to return", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretVersions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SecretVersion" - }, - "description": "Secret versions" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ] - } - }, - "/api/v1/secret/{secretId}/secret-versions/rollback": { - "post": { - "summary": "Roll back secret to a version.", - "description": "Roll back secret to a version.", - "parameters": [ - { - "name": "secretId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of secret" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secret": { - "type": "object", - "$ref": "#/components/schemas/Secret", - "description": "Secret rolled back to" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "version": { - "type": "integer", - "description": "Version of secret to roll back to" - } - } - } - } - } - } - } - }, - "/api/v1/secret-snapshot/{secretSnapshotId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "secretSnapshotId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/users/me/ip": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/secret-snapshots": { - "get": { - "summary": "Return project secret snapshot ids", - "description": "Return project secret snapshots ids", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project where to get secret snapshots for" - }, - { - "name": "environment", - "description": "Slug of environment where to get secret snapshots for", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "directory", - "description": "Path where to get secret snapshots for like / or /foo/bar. Default is /", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "offset", - "description": "Number of secret snapshots to skip", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "description": "Maximum number of secret snapshots to return", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretSnapshots": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SecretSnapshot" - }, - "description": "Project secret snapshots" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - } - }, - "/api/v1/workspace/{workspaceId}/secret-snapshots/count": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/secret-snapshots/rollback": { - "post": { - "summary": "Roll back project secrets to those captured in a secret snapshot version.", - "description": "Roll back project secrets to those captured in a secret snapshot version.", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project where to roll back" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Secret" - }, - "description": "Secrets rolled back to" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "environment": { - "type": "string", - "description": "Slug of environment where to roll back" - }, - "directory": { - "type": "string", - "description": "Path where to roll back for like / or /foo/bar. Default is /" - }, - "version": { - "type": "integer", - "description": "Version of secret snapshot to roll back to" - } - } - } - } - } - } - } - }, - "/api/v1/workspace/{workspaceId}/audit-logs": { - "get": { - "summary": "Return audit logs", - "description": "Return audit logs", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of the workspace where to get folders from" - }, - { - "name": "offset", - "description": "Number of logs to skip before starting to return logs for pagination", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "description": "Maximum number of logs to return for pagination", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "startDate", - "description": "Filter logs from this date in ISO-8601 format", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "endDate", - "description": "Filter logs till this date in ISO-8601 format", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "eventType", - "description": "Filter by type of event such as get-secrets, get-secret, create-secret, update-secret, delete-secret, etc.", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "userAgentType", - "description": "Filter by type of user agent such as web, cli, k8-operator, or other", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "actor", - "description": "Filter by actor such as user or service", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "auditLogs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AuditLog" - }, - "description": "List of audit log" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ] - } - }, - "/api/v1/workspace/{workspaceId}/audit-logs/filters/actors": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/trusted-ips": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/trusted-ips/{trustedIpId}": { - "patch": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "trustedIpId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "trustedIpId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/organizations/{organizationId}/plans/table": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/plan": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/session/trial": { - "post": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/plan/billing": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/plan/table": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/billing-details": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "patch": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/billing-details/payment-methods": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/billing-details/payment-methods/{pmtMethodId}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "pmtMethodId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/billing-details/tax-ids": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/billing-details/tax-ids/{taxId}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "taxId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/invoices": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organizations/{organizationId}/licenses": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/sso/redirect/saml2/{ssoIdentifier}": { - "get": { - "description": "", - "parameters": [ - { - "name": "ssoIdentifier", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "callback_port", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/sso/saml2/{ssoIdentifier}": { - "post": { - "description": "", - "parameters": [ - { - "name": "ssoIdentifier", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/sso/config": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - }, - "patch": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/cloud-products/": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/api-key/": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/api-key/{apiKeyDataId}": { - "patch": { - "description": "", - "parameters": [ - { - "name": "apiKeyDataId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "apiKeyDataId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-rotation-providers/{workspaceId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-rotations/": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-rotations/restart": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-rotations/{id}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/signup/email/signup": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "403": { - "description": "Forbidden" - } - } - } - }, - "/api/v1/signup/email/verify": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "403": { - "description": "Forbidden" - } - } - } - }, - "/api/v1/auth/token": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/auth/login1": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/auth/login2": { - "post": { - "description": "", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/auth/logout": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/auth/checkAuth": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/auth/sessions": { - "delete": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/auth/token/renew": { - "post": { - "summary": "Renew access token", - "description": "Renew access token", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "accessToken": { - "type": "string", - "description": "(Same) Access token after successful renewal" - }, - "expiresIn": { - "type": "number", - "description": "TTL of access token in seconds" - }, - "tokenType": { - "type": "string", - "description": "Type of access token (e.g. Bearer)" - } - }, - "description": "Access token and its details" - } - } - } - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "accessToken": { - "type": "string", - "description": "Access token to renew", - "example": "..." - } - } - } - } - } - } - } - }, - "/api/v1/auth/universal-auth/login": { - "post": { - "summary": "Login with Universal Auth", - "description": "Login with Universal Auth", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "accessToken": { - "type": "string", - "description": "Access token issued after successful login" - }, - "expiresIn": { - "type": "number", - "description": "TTL of access token in seconds" - }, - "tokenType": { - "type": "string", - "description": "Type of access token (e.g. Bearer)" - } - }, - "description": "Access token and its details" - } - } - } - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientId": { - "type": "string", - "description": "Client ID for identity to login with Universal Auth", - "example": "..." - }, - "clientSecret": { - "type": "string", - "description": "Client Secret for identity to login with Universal Auth", - "example": "..." - } - } - } - } - } - } - } - }, - "/api/v1/auth/universal-auth/identities/{identityId}": { - "post": { - "summary": "Attach Universal Auth configuration onto identity", - "description": "Attach Universal Auth configuration onto identity", - "parameters": [ - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity to attach Universal Auth onto" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityUniversalAuth": { - "$ref": "#/components/schemas/IdentityUniversalAuth" - } - }, - "description": "Details of attached Universal Auth" - } - } - } - }, - "400": { - "description": "Bad Request" - } - }, - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecretTrustedIps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "ipAddress": { - "type": "string", - "description": "IP address to trust", - "default": "0.0.0.0/0" - } - } - }, - "description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", - "example": "...", - "default": [ - { - "ipAddress": "0.0.0.0/0" - } - ] - }, - "accessTokenTTL": { - "type": "number", - "description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.", - "example": "...", - "default": 100 - }, - "accessTokenMaxTTL": { - "type": "number", - "description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.", - "example": "...", - "default": 2592000 - }, - "accessTokenNumUsesLimit": { - "type": "number", - "description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.", - "example": "...", - "default": 0 - }, - "accessTokenTrustedIps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "ipAddress": { - "type": "string", - "description": "IP address to trust", - "default": "0.0.0.0/0" - } - } - }, - "description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", - "example": "...", - "default": [ - { - "ipAddress": "0.0.0.0/0" - } - ] - } - } - } - } - } - } - }, - "patch": { - "summary": "Update Universal Auth configuration on identity", - "description": "Update Universal Auth configuration on identity", - "parameters": [ - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity to update Universal Auth on" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityUniversalAuth": { - "$ref": "#/components/schemas/IdentityUniversalAuth" - } - }, - "description": "Details of updated Universal Auth" - } - } - } - }, - "400": { - "description": "Bad Request" - } - }, - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecretTrustedIps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "ipAddress": { - "type": "string", - "description": "IP address to trust" - } - } - }, - "description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", - "example": "..." - }, - "accessTokenTTL": { - "type": "number", - "description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.", - "example": "..." - }, - "accessTokenMaxTTL": { - "type": "number", - "description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.", - "example": "..." - }, - "accessTokenNumUsesLimit": { - "type": "number", - "description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.", - "example": "..." - }, - "accessTokenTrustedIps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "ipAddress": { - "type": "string", - "description": "IP address to trust" - } - } - }, - "description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", - "example": "..." - } - } - } - } - } - } - }, - "get": { - "summary": "Retrieve Universal Auth configuration on identity", - "description": "Retrieve Universal Auth configuration on identity", - "parameters": [ - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity to retrieve Universal Auth on" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityUniversalAuth": { - "$ref": "#/components/schemas/IdentityUniversalAuth" - } - }, - "description": "Details of retrieved Universal Auth" - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - } - }, - "/api/v1/auth/universal-auth/identities/{identityId}/client-secrets": { - "post": { - "summary": "Create Universal Auth Client Secret for identity", - "description": "Create Universal Auth Client Secret for identity", - "parameters": [ - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity to create Universal Auth Client Secret for" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecret": { - "type": "string", - "description": "The created Client Secret" - }, - "clientSecretData": { - "$ref": "#/components/schemas/IdentityUniversalAuthClientSecretData" - } - }, - "description": "Details of the created Client Secret" - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "A description for the Client Secret to create.", - "example": "..." - }, - "ttl": { - "type": "number", - "description": "The time-to-live for the Client Secret to create. By default, the TTL will be set to 0 which implies that the Client Secret will never expire; a value of 0 implies an infinite lifetime.", - "example": "...", - "default": 0 - }, - "numUsesLimit": { - "type": "number", - "description": "The maximum number of times that the Client Secret can be used together with the Client ID to get back an access token; a value of 0 implies infinite number of uses.", - "example": "...", - "default": 0 - } - } - } - } - } - } - }, - "get": { - "summary": "List Universal Auth Client Secrets for identity", - "description": "List Universal Auth Client Secrets for identity", - "parameters": [ - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity for which to get Client Secrets for" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecretData": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IdentityUniversalAuthClientSecretData" - } - } - }, - "description": "Details of the Client Secrets" - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - } - }, - "/api/v1/auth/universal-auth/identities/{identityId}/client-secrets/{clientSecretId}/revoke": { - "post": { - "summary": "Revoke Universal Auth Client Secret for identity", - "description": "Revoke Universal Auth Client Secret for identity", - "parameters": [ - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity under which Client Secret was issued for" - }, - { - "name": "clientSecretId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of Client Secret to revoke" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecretData": { - "$ref": "#/components/schemas/IdentityUniversalAuthClientSecretData" - } - }, - "description": "Details of the revoked Client Secret" - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - } - }, - "/api/v1/admin/config": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "patch": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/admin/signup": { - "post": { - "description": "", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/bot/{workspaceId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/bot/{botId}/active": { - "patch": { - "description": "", - "parameters": [ - { - "name": "botId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/user/": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/user-action/": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organization/": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organization/{organizationId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organization/{organizationId}/users": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organization/{organizationId}/my-workspaces": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organization/{organizationId}/name": { - "patch": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organization/{organizationId}/incidentContactOrg": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organization/{organizationId}/customer-portal-session": { - "post": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/organization/{organizationId}/workspace-memberships": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/keys": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/users": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/workspace/{workspaceId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/name": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/invite-signup": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/integrations": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/authorizations": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/workspace/{workspaceId}/service-tokens": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/membership-org/membershipOrg/{membershipOrgId}/change-role": { - "post": { - "description": "", - "parameters": [ - { - "name": "membershipOrgId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/membership-org/{membershipOrgId}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "membershipOrgId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/membership/{workspaceId}/connect": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/membership/{membershipId}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "membershipId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/membership/{membershipId}/change-role": { - "post": { - "description": "", - "parameters": [ - { - "name": "membershipId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/key/{workspaceId}": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/key/{workspaceId}/latest": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/invite-org/signup": { - "post": { - "description": "", - "parameters": [ - { - "name": "host", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/invite-org/verify": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret/{workspaceId}": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "example": "any" - }, - "keys": { - "example": "any" - }, - "environment": { - "example": "any" - }, - "channel": { - "example": "any" - } - } - } - } - } - } - }, - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "channel", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret/{workspaceId}/service-token": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "channel", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/service-token/": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "name": { - "example": "any" - }, - "workspaceId": { - "example": "any" - }, - "environment": { - "example": "any" - }, - "expiresIn": { - "example": "any" - }, - "publicKey": { - "example": "any" - }, - "encryptedKey": { - "example": "any" - }, - "nonce": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v1/password/srp1": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/password/change-password": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/password/email/password-reset": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/password/email/password-reset-verify": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "403": { - "description": "Forbidden" - } - } - } - }, - "/api/v1/password/backup-private-key": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/password/password-reset": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration/": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration/{integrationId}": { - "patch": { - "description": "", - "parameters": [ - { - "name": "integrationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "integrationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration/manual-sync": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/integration-options": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/integration-auth/oauth-token": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/access-token": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/apps": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/teams": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/vercel/branches": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/checkly/groups": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/qovery/orgs": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/qovery/projects": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/qovery/environments": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/qovery/apps": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/qovery/containers": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/qovery/jobs": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/railway/environments": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/railway/services": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/bitbucket/workspaces": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/northflank/secret-groups": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/integration-auth/{integrationAuthId}/teamcity/build-configs": { - "get": { - "description": "", - "parameters": [ - { - "name": "integrationAuthId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/folders/": { - "post": { - "summary": "Create folder", - "description": "Create folder", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "folder": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "ID of folder", - "example": "someFolderId" - }, - "name": { - "type": "string", - "description": "Name of folder", - "example": "my_folder" - }, - "version": { - "type": "number", - "description": "Version of folder", - "example": 1 - } - }, - "description": "Details of created folder" - } - } - } - } - } - }, - "400": { - "description": "Bad Request. For example, 'Folder name cannot contain spaces. Only underscore and dashes'" - }, - "401": { - "description": "Unauthorized request. For example, 'Folder Permission Denied'" - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of the workspace where to create folder", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to create folder", - "example": "production" - }, - "folderName": { - "type": "string", - "description": "Name of folder to create", - "example": "my_folder" - }, - "directory": { - "type": "string", - "description": "Path where to create folder like / or /foo/bar. Default is /", - "example": "/foo/bar" - } - }, - "required": [ - "workspaceId", - "environment", - "folderName" - ] - } - } - } - } - }, - "get": { - "summary": "Get folders", - "description": "Get folders", - "parameters": [ - { - "name": "workspaceId", - "description": "ID of the workspace where to get folders from", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "description": "Slug of environment where to get folders from", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "directory", - "description": "Path where to get fodlers from like / or /foo/bar. Default is /", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "folders": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "someFolderId" - }, - "name": { - "type": "string", - "example": "someFolderName" - } - } - }, - "description": "List of folders" - } - } - } - } - } - }, - "400": { - "description": "Bad Request. For instance, 'The folder doesn't exist'" - }, - "401": { - "description": "Unauthorized request. For example, 'Folder Permission Denied'" - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - } - }, - "/api/v1/folders/{folderName}": { - "patch": { - "summary": "Update folder", - "description": "Update folder", - "parameters": [ - { - "name": "folderName", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "Name of folder to update" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "Successfully updated folder" - }, - "folder": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of updated folder", - "example": "updated_folder_name" - }, - "id": { - "type": "string", - "description": "ID of created folder", - "example": "abc123" - } - }, - "description": "Details of the updated folder" - } - } - } - } - } - }, - "400": { - "description": "Bad Request. Reasons can include 'The folder doesn't exist' or 'Folder name cannot contain spaces. Only underscore and dashes'" - }, - "401": { - "description": "Unauthorized request. For example, 'Folder Permission Denied'" - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of workspace where to update folder", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to update folder", - "example": "production" - }, - "name": { - "type": "string", - "description": "Name of folder to update to", - "example": "updated_folder_name" - }, - "directory": { - "type": "string", - "description": "Path where to update folder like / or /foo/bar. Default is /", - "example": "/foo/bar" - } - }, - "required": [ - "workspaceId", - "environment", - "name" - ] - } - } - } - } - }, - "delete": { - "summary": "Delete folder", - "description": "Delete folder", - "parameters": [ - { - "name": "folderName", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "Name of folder to delete" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "successfully deleted folders" - }, - "folders": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "ID of deleted folder", - "example": "abc123" - }, - "name": { - "type": "string", - "description": "Name of deleted folder", - "example": "someFolderName" - } - } - }, - "description": "List of IDs and names of deleted folders" - } - } - } - } - } - }, - "400": { - "description": "Bad Request. Reasons can include 'The folder doesn't exist'" - }, - "401": { - "description": "Unauthorized request. For example, 'Folder Permission Denied'" - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of the workspace where to delete folder", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to delete folder", - "example": "production" - }, - "directory": { - "type": "string", - "description": "Path where to delete folder like / or /foo/bar. Default is /", - "example": "/foo/bar" - } - }, - "required": [ - "workspaceId", - "environment" - ] - } - } - } - } - } - }, - "/api/v1/secret-scanning/create-installation-session/organization/{organizationId}": { - "post": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-scanning/link-installation": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-scanning/installation-status/organization/{organizationId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-scanning/organization/{organizationId}/risks": { - "get": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-scanning/organization/{organizationId}/risks/{riskId}/status": { - "post": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "riskId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/webhooks/": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/webhooks/{webhookId}": { - "patch": { - "description": "", - "parameters": [ - { - "name": "webhookId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "webhookId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/webhooks/{webhookId}/test": { - "post": { - "description": "", - "parameters": [ - { - "name": "webhookId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v1/secret-imports/": { - "post": { - "summary": "Create secret import", - "description": "Create secret import", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "example": "successfully created secret import" - } - }, - "description": "Confirmation of secret import creation" - } - } - } - }, - "400": { - "description": "Bad Request. For example, 'Secret import already exist'" - }, - "401": { - "description": "Unauthorized request. For example, 'Folder Permission Denied'" - }, - "404": { - "description": "Resource Not Found. For example, 'Failed to find folder'" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of workspace where to create secret import", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to create secret import", - "example": "dev" - }, - "directory": { - "type": "string", - "description": "Path where to create secret import like / or /foo/bar. Default is /", - "example": "/foo/bar" - }, - "secretImport": { - "type": "object", - "properties": { - "environment": { - "type": "string", - "description": "Slug of environment to import from", - "example": "development" - }, - "secretPath": { - "type": "string", - "description": "Path where to import from like / or /foo/bar.", - "example": "/user/oauth" - } - } - } - }, - "required": [ - "workspaceId", - "environment", - "directory", - "secretImport" - ] - } - } - } - } - }, - "get": { - "summary": "Get secret imports", - "description": "Get secret imports", - "parameters": [ - { - "name": "workspaceId", - "in": "query", - "description": "ID of workspace where to get secret imports from", - "required": true, - "example": "workspace12345", - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "in": "query", - "description": "Slug of environment where to get secret imports from", - "required": true, - "example": "production", - "schema": { - "type": "string" - } - }, - { - "name": "directory", - "in": "query", - "description": "Path where to get secret imports from like / or /foo/bar. Default is /", - "required": false, - "example": "folder12345", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved secret import", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretImport": { - "$ref": "#/components/schemas/SecretImport" - } - } - } - } - } - }, - "401": { - "description": "Unauthorized access due to invalid token or scope" - }, - "403": { - "description": "Forbidden access due to insufficient permissions" - } - } - } - }, - "/api/v1/secret-imports/{id}": { - "put": { - "summary": "Update secret import", - "description": "Update secret import", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of secret import to update", - "example": "import12345" - } - ], - "responses": { - "200": { - "description": "Successfully updated the secret import", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "example": "successfully updated secret import" - } - } - } - } - } - }, - "400": { - "description": "Bad Request - Import not found" - }, - "401": { - "description": "Unauthorized access due to invalid token or scope" - }, - "403": { - "description": "Forbidden access due to insufficient permissions" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretImports": { - "type": "array", - "description": "List of secret imports to update to", - "items": { - "type": "object", - "properties": { - "environment": { - "type": "string", - "description": "Slug of environment to import from", - "example": "dev" - }, - "secretPath": { - "type": "string", - "description": "Path where to import secrets from like / or /foo/bar", - "example": "/foo/bar" - } - }, - "required": [ - "environment", - "secretPath" - ] - } - } - }, - "required": [ - "secretImports" - ] - } - } - } - } - }, - "delete": { - "summary": "Delete secret import", - "description": "Delete secret import", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of parent secret import document from which to delete secret import", - "example": "12345abcde" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "example": "successfully delete secret import" - } - }, - "description": "Confirmation of secret import deletion" - } - } - } - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretImportEnv": { - "type": "string", - "description": "Slug of environment of import to delete", - "example": "someWorkspaceId" - }, - "secretImportPath": { - "type": "string", - "description": "Path like / or /foo/bar of import to delete", - "example": "production" - } - }, - "required": [ - "id", - "secretImportEnv", - "secretImportPath" - ] - } - } - } - } - } - }, - "/api/v1/secret-imports/secrets": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/roles/": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/roles/{id}": { - "patch": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/roles/organization/{orgId}/permissions": { - "get": { - "description": "", - "parameters": [ - { - "name": "orgId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/roles/workspace/{workspaceId}/permissions": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-approvals/": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-approvals/board": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-approvals/{id}": { - "patch": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/sso/redirect/google": { - "get": { - "description": "", - "parameters": [ - { - "name": "callback_port", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/sso/google": { - "get": { - "description": "", - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/sso/redirect/github": { - "get": { - "description": "", - "parameters": [ - { - "name": "callback_port", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/sso/github": { - "get": { - "description": "", - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/sso/redirect/gitlab": { - "get": { - "description": "", - "parameters": [ - { - "name": "callback_port", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/sso/gitlab": { - "get": { - "description": "", - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/v1/secret-approval-requests/": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-approval-requests/count": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-approval-requests/{id}": { - "get": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-approval-requests/{id}/merge": { - "post": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-approval-requests/{id}/review": { - "post": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v1/secret-approval-requests/{id}/status": { - "post": { - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/signup/complete-account/signup": { - "post": { - "description": "", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "403": { - "description": "Forbidden" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "email": { - "example": "any" - }, - "firstName": { - "example": "any" - }, - "lastName": { - "example": "any" - }, - "protectedKey": { - "example": "any" - }, - "protectedKeyIV": { - "example": "any" - }, - "protectedKeyTag": { - "example": "any" - }, - "publicKey": { - "example": "any" - }, - "encryptedPrivateKey": { - "example": "any" - }, - "encryptedPrivateKeyIV": { - "example": "any" - }, - "encryptedPrivateKeyTag": { - "example": "any" - }, - "salt": { - "example": "any" - }, - "verifier": { - "example": "any" - }, - "organizationName": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/signup/complete-account/invite": { - "post": { - "description": "", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "403": { - "description": "Forbidden" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "email": { - "example": "any" - }, - "firstName": { - "example": "any" - }, - "lastName": { - "example": "any" - }, - "protectedKey": { - "example": "any" - }, - "protectedKeyIV": { - "example": "any" - }, - "protectedKeyTag": { - "example": "any" - }, - "publicKey": { - "example": "any" - }, - "encryptedPrivateKey": { - "example": "any" - }, - "encryptedPrivateKeyIV": { - "example": "any" - }, - "encryptedPrivateKeyTag": { - "example": "any" - }, - "salt": { - "example": "any" - }, - "verifier": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/auth/login1": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "email": { - "example": "any" - }, - "clientPublicKey": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/auth/login2": { - "post": { - "description": "", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "email": { - "example": "any" - }, - "clientProof": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/auth/mfa/send": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/auth/mfa/verify": { - "post": { - "description": "", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/users/me/mfa": { - "patch": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/users/me/name": { - "patch": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/users/me/auth-methods": { - "put": { - "description": "", - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v2/users/me/organizations": { - "get": { - "summary": "Return organizations that current user is part of", - "description": "Return organizations that current user is part of", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "organizations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Organization" - }, - "description": "Organizations that user is part of" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ] - } - }, - "/api/v2/users/me/api-keys": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/users/me/api-keys/{apiKeyDataId}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "apiKeyDataId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/users/me/sessions": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/users/me": { - "get": { - "summary": "Retrieve the current user on the request", - "description": "Retrieve the current user on the request", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "user": { - "type": "object", - "$ref": "#/components/schemas/CurrentUser", - "description": "Current user on request" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ] - }, - "delete": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/organizations/{organizationId}/memberships": { - "get": { - "summary": "Return organization user memberships", - "description": "Return organization user memberships", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of organization" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "memberships": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MembershipOrg" - }, - "description": "Memberships of organization" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - } - }, - "/api/v2/organizations/{organizationId}/memberships/{membershipId}": { - "patch": { - "summary": "Update organization user membership", - "description": "Update organization user membership", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of organization" - }, - { - "name": "membershipId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of organization membership to update" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "membership": { - "$ref": "#/components/schemas/MembershipOrg", - "description": "Updated organization membership" - } - } - } - } - } - }, - "400": { - "description": "Bad Request" - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "Role of organization membership - either owner, admin, or member" - } - } - } - } - } - } - }, - "delete": { - "summary": "Delete organization user membership", - "description": "Delete organization user membership", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of organization" - }, - { - "name": "membershipId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of organization membership to delete" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "membership": { - "$ref": "#/components/schemas/MembershipOrg", - "description": "Deleted organization membership" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - } - }, - "/api/v2/organizations/{organizationId}/workspaces": { - "get": { - "summary": "Return projects in organization that user is part of", - "description": "Return projects in organization that user is part of", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of organization" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaces": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Project" - }, - "description": "Projects of organization" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - } - }, - "/api/v2/organizations/": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/organizations/{organizationId}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/organizations/{organizationId}/identity-memberships": { - "get": { - "summary": "Return organization identity memberships", - "description": "Return organization identity memberships", - "parameters": [ - { - "name": "organizationId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of organization" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityMemberships": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IdentityMembershipOrg" - }, - "description": "Identity memberships of organization" - } - } - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - } - }, - "/api/v2/workspace/{workspaceId}/memberships": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "get": { - "summary": "Return project user memberships", - "description": "Return project user memberships", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "memberships": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Membership" - }, - "description": "Memberships of project" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - } - }, - "/api/v2/workspace/{workspaceId}/environments": { - "post": { - "summary": "Create environment", - "description": "Create environment", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of workspace where to create environment" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Sucess message", - "example": "Successfully created environment" - }, - "workspace": { - "type": "string", - "description": "ID of workspace where environment was created", - "example": "abc123" - }, - "environment": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of created environment", - "example": "Staging" - }, - "slug": { - "type": "string", - "description": "Slug of created environment", - "example": "staging" - } - } - } - }, - "description": "Details of the created environment" - } - } - } - }, - "400": { - "description": "Bad Request" - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "environmentName": { - "type": "string", - "description": "Name of the environment to create", - "example": "development" - }, - "environmentSlug": { - "type": "string", - "description": "Slug of environment to create", - "example": "dev-environment" - } - }, - "required": [ - "environmentName", - "environmentSlug" - ] - } - } - } - } - }, - "put": { - "summary": "Update environment", - "description": "Update environment", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of workspace where to update environment" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "Successfully update environment" - }, - "workspace": { - "type": "string", - "description": "ID of workspace where environment was updated", - "example": "abc123" - }, - "environment": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of updated environment", - "example": "Staging-Renamed" - }, - "slug": { - "type": "string", - "description": "Slug of updated environment", - "example": "staging-renamed" - } - } - } - }, - "description": "Details of the renamed environment" - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "environmentName": { - "type": "string", - "description": "Name of environment to update to", - "example": "Staging-Renamed" - }, - "environmentSlug": { - "type": "string", - "description": "Slug of environment to update to", - "example": "staging-renamed" - }, - "oldEnvironmentSlug": { - "type": "string", - "description": "Current slug of environment", - "example": "staging-old" - } - }, - "required": [ - "environmentName", - "environmentSlug", - "oldEnvironmentSlug" - ] - } - } - } - } - }, - "patch": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "summary": "Delete environment", - "description": "Delete environment", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of workspace where to delete environment" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "Successfully deleted environment" - }, - "workspace": { - "type": "string", - "description": "ID of workspace where environment was deleted", - "example": "abc123" - }, - "environment": { - "type": "string", - "description": "Slug of deleted environment", - "example": "dev" - } - }, - "description": "Response after deleting an environment from a workspace" - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "environmentSlug": { - "type": "string", - "description": "Slug of environment to delete", - "example": "dev" - } - }, - "required": [ - "environmentSlug" - ] - } - } - } - } - } - }, - "/api/v2/workspace/{workspaceId}/tags": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/workspace/tags/{tagId}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "tagId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/workspace/{workspaceId}/secrets": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "example": "any" - }, - "keys": { - "example": "any" - }, - "environment": { - "example": "any" - }, - "channel": { - "example": "any" - } - } - } - } - } - } - }, - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "channel", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/workspace/{workspaceId}/encrypted-key": { - "get": { - "summary": "Return encrypted project key", - "description": "Return encrypted project key", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectKey" - }, - "description": "Encrypted project key for the given project" - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ] - } - }, - "/api/v2/workspace/{workspaceId}/service-token-data": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/workspace/{workspaceId}/memberships/{membershipId}": { - "patch": { - "summary": "Update project user membership", - "description": "Update project user membership", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project" - }, - { - "name": "membershipId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project membership to update" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "membership": { - "$ref": "#/components/schemas/Membership", - "description": "Updated membership" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "Role to update to for project membership" - } - } - } - } - } - } - }, - "delete": { - "summary": "Delete project user membership", - "description": "Delete project user membership", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project" - }, - { - "name": "membershipId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project membership to delete" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "membership": { - "$ref": "#/components/schemas/Membership", - "description": "Deleted membership" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - } - }, - "/api/v2/workspace/{workspaceId}/auto-capitalization": { - "patch": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/workspace/{workspaceId}/identity-memberships/{identityId}": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "patch": { - "summary": "Update project identity membership", - "description": "Update project identity membership", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project" - }, - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity whose membership to update in project" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityMembership": { - "$ref": "#/components/schemas/IdentityMembership", - "description": "Updated identity membership" - } - } - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "Role to update to for identity project membership" - } - } - } - } - } - } - }, - "delete": { - "summary": "Delete project identity membership", - "description": "Delete project identity membership", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project" - }, - { - "name": "identityId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of identity whose membership to delete in project" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityMembership": { - "$ref": "#/components/schemas/IdentityMembership", - "description": "Deleted identity membership" - } - } - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - } - }, - "/api/v2/workspace/{workspaceId}/identity-memberships": { - "get": { - "summary": "Return project identity memberships", - "description": "Return project identity memberships", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "ID of project" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityMemberships": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IdentityMembership" - }, - "description": "Identity memberships of project" - } - } - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - } - }, - "/api/v2/secret/batch-create/workspace/{workspaceId}/environment/{environment}": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/secret/workspace/{workspaceId}/environment/{environment}": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secret": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/secret/workspace/{workspaceId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/secret/{secretId}": { - "get": { - "description": "", - "parameters": [ - { - "name": "secretId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "secretId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/secret/batch/workspace/{workspaceId}/environment/{environmentName}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environmentName", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretIds": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/secret/batch-modify/workspace/{workspaceId}/environment/{environmentName}": { - "patch": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environmentName", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/secret/workspace/{workspaceId}/environment/{environmentName}": { - "patch": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environmentName", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secret": { - "example": "any" - } - } - } - } - } - } - } - }, - "/api/v2/secrets/batch": { - "post": { - "description": "", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/secrets/": { - "post": { - "summary": "Create new secret(s)", - "description": "Create one or many secrets for a given project and environment.", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Secret" - }, - "description": "Newly-created secrets for the given project and environment" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of project" - }, - "environment": { - "type": "string", - "description": "Environment within project" - }, - "secrets": { - "$ref": "#/components/schemas/CreateSecret", - "description": "Secret(s) to create - object or array of objects" - } - } - } - } - } - } - }, - "get": { - "summary": "Read secrets", - "description": "Read secrets from a project and environment", - "parameters": [ - { - "name": "workspaceId", - "description": "ID of project", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "description": "Environment within project", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Secret" - }, - "description": "Secrets for the given project and environment" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ] - }, - "patch": { - "summary": "Update secret(s)", - "description": "Update secret(s)", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Secret" - }, - "description": "Updated secrets" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "$ref": "#/components/schemas/UpdateSecret", - "description": "Secret(s) to update - object or array of objects" - } - } - } - } - } - } - }, - "delete": { - "summary": "Delete secret(s)", - "description": "Delete one or many secrets by their ID(s)", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Secret" - }, - "description": "Deleted secrets" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretIds": { - "type": "string", - "description": "ID(s) of secrets - string or array of strings" - } - } - } - } - } - } - } - }, - "/api/v2/service-token/": { - "get": { - "summary": "Return Infisical Token data", - "description": "Return Infisical Token data", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "serviceTokenData": { - "type": "object", - "$ref": "#/components/schemas/ServiceTokenData", - "description": "Details of service token" - } - } - } - } - } - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - }, - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v2/service-token/{serviceTokenDataId}": { - "delete": { - "description": "", - "parameters": [ - { - "name": "serviceTokenDataId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/auth/login1": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/auth/login2": { - "post": { - "description": "", - "parameters": [ - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/api/v3/secrets/raw": { - "get": { - "summary": "List secrets", - "description": "List secrets", - "parameters": [ - { - "name": "workspaceId", - "description": "ID of workspace where to get secrets from", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "description": "Slug of environment where to get secrets from", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "secretPath", - "description": "Path where to update secret like / or /foo/bar. Default is /", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "include_imports", - "description": "Whether or not to include imported secrets. Default is false", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RawSecret" - }, - "description": "List of secrets" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - } - }, - "/api/v3/secrets/raw/{secretName}": { - "get": { - "summary": "Get secret", - "description": "Get secret", - "parameters": [ - { - "name": "secretName", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "Name of secret to get" - }, - { - "name": "workspaceId", - "description": "ID of workspace where to get secret", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "description": "Slug of environment where to get secret", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "secretPath", - "description": "Path where to update secret like / or /foo/bar. Default is /", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "type", - "description": "Type of secret to get; either shared or personal. Default is shared.", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "include_imports", - "description": "Whether or not to include imported secrets. Default is false", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secret": { - "$ref": "#/components/schemas/RawSecret" - } - } - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ] - }, - "post": { - "summary": "Create secret", - "description": "Create secret", - "parameters": [ - { - "name": "secretName", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "Name of secret to create" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RawSecret" - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of the workspace where to create secret", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to create secret", - "example": "dev" - }, - "secretPath": { - "type": "string", - "description": "Path where to create secret. Default is /", - "example": "/foo/bar" - }, - "secretValue": { - "type": "string", - "description": "Value of secret to create", - "example": "Some value" - }, - "secretComment": { - "type": "string", - "description": "Comment for secret to create", - "example": "Some comment" - }, - "type": { - "type": "string", - "description": "Type of secret to create; either shared or personal. Default is shared.", - "example": "shared" - }, - "skipMultilineEncoding": { - "type": "boolean", - "description": "Convert multi line secrets into one line by wrapping", - "example": "true" - } - }, - "required": [ - "workspaceId", - "environment", - "secretValue" - ] - } - } - } - } - }, - "patch": { - "summary": "Update secret", - "description": "Update secret", - "parameters": [ - { - "name": "secretName", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "Name of secret to update" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RawSecret" - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of the workspace where to update secret", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to update secret", - "example": "dev" - }, - "secretPath": { - "type": "string", - "description": "Path where to update secret like / or /foo/bar. Default is /", - "example": "/foo/bar" - }, - "secretValue": { - "type": "string", - "description": "Value of secret to update to", - "example": "Some value" - }, - "type": { - "type": "string", - "description": "Type of secret to update; either shared or personal. Default is shared.", - "example": "shared" - }, - "skipMultilineEncoding": { - "type": "boolean", - "description": "Convert multi line secrets into one line by wrapping", - "example": "true" - } - }, - "required": [ - "workspaceId", - "environment", - "secretValue" - ] - } - } - } - } - }, - "delete": { - "summary": "Delete secret", - "description": "Delete secret", - "parameters": [ - { - "name": "secretName", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "Name of secret to delete" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secret": { - "$ref": "#/components/schemas/RawSecret" - } - }, - "description": "The deleted secret" - } - } - } - } - }, - "security": [ - { - "apiKeyAuth": [], - "bearerAuth": [] - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of workspace where to delete secret", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of Environment where to delete secret", - "example": "dev" - }, - "secretPath": { - "type": "string", - "description": "Path where to delete secret. Default is /", - "example": "/foo/bar" - }, - "type": { - "type": "string", - "description": "Type of secret to delete; either shared or personal. Default is shared", - "example": "shared" - } - }, - "required": [ - "workspaceId", - "environment" - ] - } - } - } - } - } - }, - "/api/v3/secrets/": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/secrets/batch": { - "post": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "patch": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/secrets/{secretName}": { - "post": { - "description": "", - "parameters": [ - { - "name": "secretName", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "get": { - "description": "", - "parameters": [ - { - "name": "secretName", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "patch": { - "description": "", - "parameters": [ - { - "name": "secretName", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "description": "", - "parameters": [ - { - "name": "secretName", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/workspaces/{workspaceId}/secrets/blind-index-status": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/workspaces/{workspaceId}/secrets": { - "get": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/workspaces/{workspaceId}/secrets/names": { - "post": { - "description": "", - "parameters": [ - { - "name": "workspaceId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/v3/signup/complete-account/signup": { - "post": { - "description": "", - "parameters": [ - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - }, - { - "name": "user-agent", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - }, - "403": { - "description": "Forbidden" - } - } - } - }, - "/api/v3/us/me/api-keys": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/api/status": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - } - } - }, - "components": { - "schemas": { - "CurrentUser": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "email": { - "type": "string", - "example": "johndoe@gmail.com" - }, - "firstName": { - "type": "string", - "example": "John" - }, - "lastName": { - "type": "string", - "example": "Doe" - }, - "publicKey": { - "type": "string", - "example": "johns_nacl_public_key" - }, - "encryptedPrivateKey": { - "type": "string", - "example": "johns_enc_nacl_private_key" - }, - "iv": { - "type": "string", - "example": "iv_of_enc_nacl_private_key" - }, - "tag": { - "type": "string", - "example": "tag_of_enc_nacl_private_key" - }, - "updatedAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "createdAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - } - } - }, - "Identity": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "name": { - "type": "string", - "example": "Machine 1" - }, - "authMethod": { - "type": "string", - "example": "universal-auth" - } - } - }, - "IdentityUniversalAuth": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "identity": { - "type": "string", - "example": "" - }, - "clientId": { - "type": "string", - "example": "..." - }, - "clientSecretTrustedIps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "ipAddress": { - "type": "string", - "example": "0.0.0.0" - }, - "type": { - "type": "string", - "example": "ipv4" - }, - "prefix": { - "type": "string", - "example": "0" - } - } - } - }, - "accessTokenTTL": { - "type": "number", - "example": 7200 - }, - "accessTokenMaxTTL": { - "type": "number", - "example": 2592000 - }, - "accessTokenNumUsesLimit": { - "type": "number", - "example": 0 - }, - "accessTokenTrustedIps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "ipAddress": { - "type": "string", - "example": "0.0.0.0" - }, - "type": { - "type": "string", - "example": "ipv4" - }, - "prefix": { - "type": "string", - "example": "0" - } - } - } - } - } - }, - "IdentityUniversalAuthClientSecretData": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "identityUniversalAuth": { - "type": "string", - "example": "" - }, - "isClientSecretRevoked": { - "type": "boolean", - "example": false - }, - "description": { - "type": "string", - "example": "" - }, - "clientSecretPrefix": { - "type": "string", - "example": "abc" - }, - "clientSecretNumUses": { - "type": "number", - "example": 0 - }, - "clientSecretNumUsesLimit": { - "type": "number", - "example": 0 - }, - "clientSecretTTL": { - "type": "number", - "example": 0 - }, - "createdAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "updatedAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - } - } - }, - "Membership": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "email": { - "type": "string", - "example": "johndoe@gmail.com" - }, - "firstName": { - "type": "string", - "example": "John" - }, - "lastName": { - "type": "string", - "example": "Doe" - }, - "publicKey": { - "type": "string", - "example": "johns_nacl_public_key" - }, - "updatedAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "createdAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - } - } - }, - "workspace": { - "type": "string", - "example": "" - }, - "role": { - "type": "string", - "example": "admin" - } - } - }, - "MembershipOrg": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "email": { - "type": "string", - "example": "johndoe@gmail.com" - }, - "firstName": { - "type": "string", - "example": "John" - }, - "lastName": { - "type": "string", - "example": "Doe" - }, - "publicKey": { - "type": "string", - "example": "johns_nacl_public_key" - }, - "updatedAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "createdAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - } - } - }, - "organization": { - "type": "string", - "example": "" - }, - "role": { - "type": "string", - "example": "owner" - }, - "status": { - "type": "string", - "example": "accepted" - } - } - }, - "IdentityMembership": { - "type": "object", - "properties": { - "identity": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "name": { - "type": "string", - "example": "Machine 1" - }, - "authMethod": { - "type": "string", - "example": "universal-auth" - } - } - }, - "workspace": { - "type": "string", - "example": "" - }, - "role": { - "type": "string", - "example": "member" - } - } - }, - "IdentityMembershipOrg": { - "type": "object", - "properties": { - "identity": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "name": { - "type": "string", - "example": "Machine 1" - }, - "authMethod": { - "type": "string", - "example": "universal-auth" - } - } - }, - "organization": { - "type": "string", - "example": "" - }, - "role": { - "type": "string", - "example": "member" - }, - "status": { - "type": "string", - "example": "accepted" - } - } - }, - "Organization": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "name": { - "type": "string", - "example": "Acme Corp." - }, - "customerId": { - "type": "string", - "example": "" - } - } - }, - "Project": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "My Project" - }, - "organization": { - "type": "string", - "example": "" - }, - "environments": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "development" - }, - "slug": { - "type": "string", - "example": "dev" - } - } - } - } - } - }, - "ProjectKey": { - "type": "object", - "properties": { - "encryptedkey": { - "type": "string", - "example": "" - }, - "nonce": { - "type": "string", - "example": "" - }, - "sender": { - "type": "object", - "properties": { - "publicKey": { - "type": "string", - "example": "senders_nacl_public_key" - } - } - }, - "receiver": { - "type": "string", - "example": "" - }, - "workspace": { - "type": "string", - "example": "" - } - } - }, - "CreateSecret": { - "type": "object", - "properties": { - "type": { - "type": "string", - "example": "shared" - }, - "secretKeyCiphertext": { - "type": "string", - "example": "" - }, - "secretKeyIV": { - "type": "string", - "example": "" - }, - "secretKeyTag": { - "type": "string", - "example": "" - }, - "secretValueCiphertext": { - "type": "string", - "example": "" - }, - "secretValueIV": { - "type": "string", - "example": "" - }, - "secretValueTag": { - "type": "string", - "example": "" - }, - "secretCommentCiphertext": { - "type": "string", - "example": "" - }, - "secretCommentIV": { - "type": "string", - "example": "" - }, - "secretCommentTag": { - "type": "string", - "example": "" - } - } - }, - "UpdateSecret": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "" - }, - "secretKeyCiphertext": { - "type": "string", - "example": "" - }, - "secretKeyIV": { - "type": "string", - "example": "" - }, - "secretKeyTag": { - "type": "string", - "example": "" - }, - "secretValueCiphertext": { - "type": "string", - "example": "" - }, - "secretValueIV": { - "type": "string", - "example": "" - }, - "secretValueTag": { - "type": "string", - "example": "" - }, - "secretCommentCiphertext": { - "type": "string", - "example": "" - }, - "secretCommentIV": { - "type": "string", - "example": "" - }, - "secretCommentTag": { - "type": "string", - "example": "" - } - } - }, - "Secret": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "version": { - "type": "number", - "example": 1 - }, - "workspace": { - "type": "string", - "example": "" - }, - "type": { - "type": "string", - "example": "shared" - }, - "user": {}, - "secretKeyCiphertext": { - "type": "string", - "example": "" - }, - "secretKeyIV": { - "type": "string", - "example": "" - }, - "secretKeyTag": { - "type": "string", - "example": "" - }, - "secretValueCiphertext": { - "type": "string", - "example": "" - }, - "secretValueIV": { - "type": "string", - "example": "" - }, - "secretValueTag": { - "type": "string", - "example": "" - }, - "secretCommentCiphertext": { - "type": "string", - "example": "" - }, - "secretCommentIV": { - "type": "string", - "example": "" - }, - "secretCommentTag": { - "type": "string", - "example": "" - }, - "updatedAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "createdAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - } - } - }, - "RawSecret": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "abc123" - }, - "version": { - "type": "number", - "example": 1 - }, - "workspace": { - "type": "string", - "example": "abc123" - }, - "environment": { - "type": "string", - "example": "dev" - }, - "secretKey": { - "type": "string", - "example": "STRIPE_KEY" - }, - "secretValue": { - "type": "string", - "example": "abc123" - }, - "secretComment": { - "type": "string", - "example": "Lorem ipsum" - } - } - }, - "SecretImport": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "workspace": { - "type": "string", - "example": "abc123" - }, - "environment": { - "type": "string", - "example": "dev" - }, - "folderId": { - "type": "string", - "example": "root" - }, - "imports": { - "type": "array", - "example": [], - "items": {} - }, - "updatedAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "createdAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - } - } - }, - "Log": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "user": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "email": { - "type": "string", - "example": "johndoe@gmail.com" - }, - "firstName": { - "type": "string", - "example": "John" - }, - "lastName": { - "type": "string", - "example": "Doe" - } - } - }, - "workspace": { - "type": "string", - "example": "" - }, - "actionNames": { - "type": "array", - "example": [ - "addSecrets" - ], - "items": { - "type": "string" - } - }, - "actions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "addSecrets" - }, - "user": { - "type": "string", - "example": "" - }, - "workspace": { - "type": "string", - "example": "" - }, - "payload": { - "type": "array", - "items": { - "type": "object", - "properties": { - "oldSecretVersion": { - "type": "string", - "example": "" - }, - "newSecretVersion": { - "type": "string", - "example": "" - } - } - } - } - } - } - }, - "channel": { - "type": "string", - "example": "cli" - }, - "ipAddress": { - "type": "string", - "example": "192.168.0.1" - }, - "updatedAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "createdAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - } - } - }, - "SecretSnapshot": { - "type": "object", - "properties": { - "workspace": { - "type": "string", - "example": "" - }, - "version": { - "type": "number", - "example": 1 - }, - "secretVersions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - } - } - } - } - } - }, - "SecretVersion": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "secret": { - "type": "string", - "example": "" - }, - "version": { - "type": "number", - "example": 1 - }, - "workspace": { - "type": "string", - "example": "" - }, - "type": { - "type": "string", - "example": "shared" - }, - "user": { - "type": "string", - "example": "" - }, - "environment": { - "type": "string", - "example": "dev" - }, - "isDeleted": { - "type": "string", - "example": "" - }, - "secretKeyCiphertext": { - "type": "string", - "example": "" - }, - "secretKeyIV": { - "type": "string", - "example": "" - }, - "secretKeyTag": { - "type": "string", - "example": "" - }, - "secretValueCiphertext": { - "type": "string", - "example": "" - }, - "secretValueIV": { - "type": "string", - "example": "" - }, - "secretValueTag": { - "type": "string", - "example": "" - } - } - }, - "ServiceTokenData": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "name": { - "type": "string", - "example": "" - }, - "workspace": { - "type": "string", - "example": "" - }, - "environment": { - "type": "string", - "example": "" - }, - "user": { - "type": "object", - "properties": { - "_id": { - "type": "string", - "example": "" - }, - "firstName": { - "type": "string", - "example": "" - }, - "lastName": { - "type": "string", - "example": "" - } - } - }, - "expiresAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "encryptedKey": { - "type": "string", - "example": "" - }, - "iv": { - "type": "string", - "example": "" - }, - "tag": { - "type": "string", - "example": "" - }, - "updatedAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - }, - "createdAt": { - "type": "string", - "example": "2023-01-13T14:16:12.210Z" - } - } - }, - "AuditLog": { - "type": "object", - "properties": { - "actor": { - "type": "object", - "properties": { - "type": { - "type": "string", - "example": "" - }, - "metadata": { - "type": "object", - "properties": {} - } - } - }, - "organization": { - "type": "string", - "example": "" - }, - "workspace": { - "type": "string", - "example": "" - }, - "ipAddress": { - "type": "string", - "example": "" - }, - "event": { - "type": "object", - "properties": { - "type": { - "type": "string", - "example": "" - }, - "metadata": { - "type": "object", - "properties": {} - } - } - }, - "userAgent": { - "type": "string", - "example": "" - }, - "userAgentType": { - "type": "string", - "example": "" - }, - "expiresAt": { - "type": "string", - "example": "" - } - } - } - }, - "securitySchemes": { - "bearerAuth": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT", - "description": "An access token in Infisical" - }, - "apiKeyAuth": { - "type": "apiKey", - "in": "header", - "name": "X-API-Key", - "description": "An API Key in Infisical" - } - } - } -} \ No newline at end of file diff --git a/backend-mongo/src/bootstrap.ts b/backend-mongo/src/bootstrap.ts deleted file mode 100644 index a1ea148c2..000000000 --- a/backend-mongo/src/bootstrap.ts +++ /dev/null @@ -1,43 +0,0 @@ -import ora from "ora"; -import nodemailer from "nodemailer"; -import { getSmtpHost, getSmtpPort } from "./config"; -import { logger } from "./utils/logging"; -import mongoose from "mongoose"; -import { redisClient } from "./services/RedisService"; - -type BootstrapOpt = { - transporter: nodemailer.Transporter; -}; - -export const bootstrap = async ({ transporter }: BootstrapOpt) => { - const spinner = ora().start(); - spinner.info("Checking configurations..."); - spinner.info("Testing smtp connection"); - - await transporter - .verify() - .then(async () => { - spinner.succeed("SMTP successfully connected"); - }) - .catch(async (err) => { - spinner.fail(`SMTP - Failed to connect to ${await getSmtpHost()}:${await getSmtpPort()}`); - logger.error(err); - }); - - spinner.info("Testing mongodb connection"); - if (mongoose.connection.readyState !== mongoose.ConnectionStates.connected) { - spinner.fail("Mongo DB - Failed to connect"); - } else { - spinner.succeed("Mongodb successfully connected"); - } - - spinner.info("Testing redis connection"); - const redisPing = await redisClient?.ping(); - if (!redisPing) { - spinner.fail("Redis - Failed to connect"); - } else { - spinner.succeed("Redis successfully connected"); - } - - spinner.stop(); -}; diff --git a/backend-mongo/src/config/index.ts b/backend-mongo/src/config/index.ts deleted file mode 100644 index 8ba445f99..000000000 --- a/backend-mongo/src/config/index.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { GITLAB_URL } from "../variables"; - -import InfisicalClient from "infisical-node"; - -export const client = new InfisicalClient({ - token: process.env.INFISICAL_TOKEN! -}); - -export const getIsMigrationMode = async () => - (await client.getSecret("MIGRATION_MODE")).secretValue === "true"; - -export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000; -export const getEncryptionKey = async () => { - const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue; - return secretValue === "" ? undefined : secretValue; -}; -export const getRootEncryptionKey = async () => { - const secretValue = (await client.getSecret("ROOT_ENCRYPTION_KEY")).secretValue; - return secretValue === "" ? undefined : secretValue; -}; -export const getInviteOnlySignup = async () => - (await client.getSecret("INVITE_ONLY_SIGNUP")).secretValue === "true"; -export const getSaltRounds = async () => - parseInt((await client.getSecret("SALT_ROUNDS")).secretValue) || 10; -export const getAuthSecret = async () => - (await client.getSecret("JWT_AUTH_SECRET")).secretValue ?? - (await client.getSecret("AUTH_SECRET")).secretValue; -export const getJwtAuthLifetime = async () => - (await client.getSecret("JWT_AUTH_LIFETIME")).secretValue || "10d"; -export const getJwtMfaLifetime = async () => - (await client.getSecret("JWT_MFA_LIFETIME")).secretValue || "5m"; -export const getJwtRefreshLifetime = async () => - (await client.getSecret("JWT_REFRESH_LIFETIME")).secretValue || "90d"; -export const getJwtServiceSecret = async () => - (await client.getSecret("JWT_SERVICE_SECRET")).secretValue; // TODO: deprecate (related to ST V1) -export const getJwtSignupLifetime = async () => - (await client.getSecret("JWT_SIGNUP_LIFETIME")).secretValue || "15m"; -export const getJwtProviderAuthLifetime = async () => - (await client.getSecret("JWT_PROVIDER_AUTH_LIFETIME")).secretValue || "15m"; -export const getMongoURL = async () => (await client.getSecret("MONGO_URL")).secretValue; -export const getNodeEnv = async () => - (await client.getSecret("NODE_ENV")).secretValue || "production"; -export const getVerboseErrorOutput = async () => - (await client.getSecret("VERBOSE_ERROR_OUTPUT")).secretValue === "true" && true; -export const getLokiHost = async () => (await client.getSecret("LOKI_HOST")).secretValue; -export const getClientIdAzure = async () => (await client.getSecret("CLIENT_ID_AZURE")).secretValue; -export const getClientIdHeroku = async () => - (await client.getSecret("CLIENT_ID_HEROKU")).secretValue; -export const getClientIdVercel = async () => - (await client.getSecret("CLIENT_ID_VERCEL")).secretValue; -export const getClientIdNetlify = async () => - (await client.getSecret("CLIENT_ID_NETLIFY")).secretValue; -export const getClientIdGitHub = async () => - (await client.getSecret("CLIENT_ID_GITHUB")).secretValue; -export const getClientIdGitLab = async () => - (await client.getSecret("CLIENT_ID_GITLAB")).secretValue; -export const getClientIdBitBucket = async () => - (await client.getSecret("CLIENT_ID_BITBUCKET")).secretValue; -export const getClientIdGCPSecretManager = async () => - (await client.getSecret("CLIENT_ID_GCP_SECRET_MANAGER")).secretValue; -export const getClientSecretAzure = async () => - (await client.getSecret("CLIENT_SECRET_AZURE")).secretValue; -export const getClientSecretHeroku = async () => - (await client.getSecret("CLIENT_SECRET_HEROKU")).secretValue; -export const getClientSecretVercel = async () => - (await client.getSecret("CLIENT_SECRET_VERCEL")).secretValue; -export const getClientSecretNetlify = async () => - (await client.getSecret("CLIENT_SECRET_NETLIFY")).secretValue; -export const getClientSecretGitHub = async () => - (await client.getSecret("CLIENT_SECRET_GITHUB")).secretValue; -export const getClientSecretGitLab = async () => - (await client.getSecret("CLIENT_SECRET_GITLAB")).secretValue; -export const getClientSecretBitBucket = async () => - (await client.getSecret("CLIENT_SECRET_BITBUCKET")).secretValue; -export const getClientSecretGCPSecretManager = async () => - (await client.getSecret("CLIENT_SECRET_GCP_SECRET_MANAGER")).secretValue; -export const getClientSlugVercel = async () => - (await client.getSecret("CLIENT_SLUG_VERCEL")).secretValue; - -export const getClientIdGoogleLogin = async () => - (await client.getSecret("CLIENT_ID_GOOGLE_LOGIN")).secretValue; -export const getClientSecretGoogleLogin = async () => - (await client.getSecret("CLIENT_SECRET_GOOGLE_LOGIN")).secretValue; -export const getClientIdGitHubLogin = async () => - (await client.getSecret("CLIENT_ID_GITHUB_LOGIN")).secretValue; -export const getClientSecretGitHubLogin = async () => - (await client.getSecret("CLIENT_SECRET_GITHUB_LOGIN")).secretValue; -export const getClientIdGitLabLogin = async () => - (await client.getSecret("CLIENT_ID_GITLAB_LOGIN")).secretValue; -export const getClientSecretGitLabLogin = async () => - (await client.getSecret("CLIENT_SECRET_GITLAB_LOGIN")).secretValue; -export const getUrlGitLabLogin = async () => - (await client.getSecret("URL_GITLAB_LOGIN")).secretValue || GITLAB_URL; - -export const getAwsCloudWatchLog = async () => { - const logGroupName = - (await client.getSecret("AWS_CLOUDWATCH_LOG_GROUP_NAME")).secretValue || "infisical-log-stream"; - const region = (await client.getSecret("AWS_CLOUDWATCH_LOG_REGION")).secretValue; - const accessKeyId = (await client.getSecret("AWS_CLOUDWATCH_LOG_ACCESS_KEY_ID")).secretValue; - const accessKeySecret = (await client.getSecret("AWS_CLOUDWATCH_LOG_ACCESS_KEY_SECRET")) - .secretValue; - const interval = parseInt( - (await client.getSecret("AWS_CLOUDWATCH_LOG_INTERVAL")).secretValue || 1000, - 10 - ); - if (!region || !accessKeyId || !accessKeySecret) return; - return { logGroupName, region, accessKeySecret, accessKeyId, interval }; -}; - -export const getPostHogHost = async () => - (await client.getSecret("POSTHOG_HOST")).secretValue || "https://app.posthog.com"; -export const getPostHogProjectApiKey = async () => - (await client.getSecret("POSTHOG_PROJECT_API_KEY")).secretValue || - "phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE"; -export const getSentryDSN = async () => (await client.getSecret("SENTRY_DSN")).secretValue; -export const getSiteURL = async () => (await client.getSecret("SITE_URL")).secretValue; -export const getSmtpHost = async () => (await client.getSecret("SMTP_HOST")).secretValue; -export const getSmtpSecure = async () => - (await client.getSecret("SMTP_SECURE")).secretValue === "true" || false; -export const getSmtpPort = async () => - parseInt((await client.getSecret("SMTP_PORT")).secretValue) || 587; -export const getSmtpUsername = async () => (await client.getSecret("SMTP_USERNAME")).secretValue; -export const getSmtpPassword = async () => (await client.getSecret("SMTP_PASSWORD")).secretValue; -export const getSmtpFromAddress = async () => - (await client.getSecret("SMTP_FROM_ADDRESS")).secretValue; -export const getSmtpFromName = async () => - (await client.getSecret("SMTP_FROM_NAME")).secretValue || "Infisical"; - -export const getSecretScanningWebhookProxy = async () => - (await client.getSecret("SECRET_SCANNING_WEBHOOK_PROXY")).secretValue; -export const getSecretScanningWebhookSecret = async () => - (await client.getSecret("SECRET_SCANNING_WEBHOOK_SECRET")).secretValue; -export const getSecretScanningGitAppId = async () => - (await client.getSecret("SECRET_SCANNING_GIT_APP_ID")).secretValue; -export const getSecretScanningPrivateKey = async () => - (await client.getSecret("SECRET_SCANNING_PRIVATE_KEY")).secretValue; - -export const getRedisUrl = async () => (await client.getSecret("REDIS_URL")).secretValue; -export const getIsInfisicalCloud = async () => - (await client.getSecret("INFISICAL_CLOUD")).secretValue === "true"; - -export const getLicenseKey = async () => { - const secretValue = (await client.getSecret("LICENSE_KEY")).secretValue; - return secretValue === "" ? undefined : secretValue; -}; -export const getLicenseServerKey = async () => { - const secretValue = (await client.getSecret("LICENSE_SERVER_KEY")).secretValue; - return secretValue === "" ? undefined : secretValue; -}; -export const getLicenseServerUrl = async () => - (await client.getSecret("LICENSE_SERVER_URL")).secretValue || "https://portal.infisical.com"; - -export const getTelemetryEnabled = async () => - (await client.getSecret("TELEMETRY_ENABLED")).secretValue !== "false" && true; -export const getLoopsApiKey = async () => (await client.getSecret("LOOPS_API_KEY")).secretValue; -export const getSmtpConfigured = async () => - (await client.getSecret("SMTP_HOST")).secretValue == "" || - (await client.getSecret("SMTP_HOST")).secretValue == undefined - ? false - : true; -export const getHttpsEnabled = async () => { - if ((await getNodeEnv()) != "production") { - // no https for anything other than prod - return false; - } - - if ( - (await client.getSecret("HTTPS_ENABLED")).secretValue == undefined || - (await client.getSecret("HTTPS_ENABLED")).secretValue == "" - ) { - // default when no value present - return true; - } - - return (await client.getSecret("HTTPS_ENABLED")).secretValue === "true" && true; -}; diff --git a/backend-mongo/src/config/request.ts b/backend-mongo/src/config/request.ts deleted file mode 100644 index e69b1baff..000000000 --- a/backend-mongo/src/config/request.ts +++ /dev/null @@ -1,124 +0,0 @@ -import axios from "axios"; -import axiosRetry from "axios-retry"; -import { - getLicenseKeyAuthToken, - getLicenseServerKeyAuthToken, - setLicenseKeyAuthToken, - setLicenseServerKeyAuthToken, -} from "./storage"; -import { - getLicenseKey, - getLicenseServerKey, - getLicenseServerUrl, -} from "./index"; - -// should have JWT to interact with the license server -export const licenseServerKeyRequest = axios.create(); -export const licenseKeyRequest = axios.create(); -export const standardRequest = axios.create(); - -// add retry functionality to the axios instance -axiosRetry(standardRequest, { - retries: 3, - retryDelay: axiosRetry.exponentialDelay, // exponential back-off delay between retries - retryCondition: (error) => { - // only retry if the error is a network error or a 5xx server error - return axiosRetry.isNetworkError(error) || axiosRetry.isRetryableError(error); - }, -}); - -export const refreshLicenseServerKeyToken = async () => { - const licenseServerKey = await getLicenseServerKey(); - const licenseServerUrl = await getLicenseServerUrl(); - - const { data: { token } } = await standardRequest.post( - `${licenseServerUrl}/api/auth/v1/license-server-login`, {}, - { - headers: { - "X-API-KEY": licenseServerKey, - }, - } - ); - - setLicenseServerKeyAuthToken(token); - - return token; -} - -export const refreshLicenseKeyToken = async () => { - const licenseKey = await getLicenseKey(); - const licenseServerUrl = await getLicenseServerUrl(); - - const { data: { token } } = await standardRequest.post( - `${licenseServerUrl}/api/auth/v1/license-login`, {}, - { - headers: { - "X-API-KEY": licenseKey, - }, - } - ); - - setLicenseKeyAuthToken(token); - - return token; -} - -licenseServerKeyRequest.interceptors.request.use((config) => { - const token = getLicenseServerKeyAuthToken(); - - if (token && config.headers) { - // eslint-disable-next-line no-param-reassign - config.headers.Authorization = `Bearer ${token}`; - } - return config; -}, (err) => { - return Promise.reject(err); -}); - -licenseServerKeyRequest.interceptors.response.use((response) => { - return response -}, async function (err) { - const originalRequest = err.config; - - if (err.response.status === 401 && !originalRequest._retry) { - originalRequest._retry = true; - - // refresh - const token = await refreshLicenseServerKeyToken(); - - axios.defaults.headers.common["Authorization"] = "Bearer " + token; - return licenseServerKeyRequest(originalRequest); - } - - return Promise.reject(err); -}); - -licenseKeyRequest.interceptors.request.use((config) => { - const token = getLicenseKeyAuthToken(); - - if (token && config.headers) { - // eslint-disable-next-line no-param-reassign - config.headers.Authorization = `Bearer ${token}`; - } - return config; -}, (err) => { - return Promise.reject(err); -}); - -licenseKeyRequest.interceptors.response.use((response) => { - return response -}, async function (err) { - const originalRequest = err.config; - - if (err.response.status === 401 && !originalRequest._retry) { - originalRequest._retry = true; - - // refresh - const token = await refreshLicenseKeyToken(); - - axios.defaults.headers.common["Authorization"] = "Bearer " + token; - return licenseKeyRequest(originalRequest); - } - - return Promise.reject(err); -}); \ No newline at end of file diff --git a/backend-mongo/src/config/serverConfig.ts b/backend-mongo/src/config/serverConfig.ts deleted file mode 100644 index 0c63cf6e8..000000000 --- a/backend-mongo/src/config/serverConfig.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { IServerConfig, ServerConfig } from "../models/serverConfig"; - -let serverConfig: IServerConfig; - -export const serverConfigInit = async () => { - const cfg = await ServerConfig.findOne({}).lean(); - if (!cfg) { - const cfg = new ServerConfig(); - await cfg.save(); - serverConfig = cfg.toObject(); - } else { - serverConfig = cfg; - } - return serverConfig; -}; - -export const getServerConfig = () => serverConfig; - -export const updateServerConfig = async (data: Partial) => { - const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true }); - if (!cfg) throw new Error("Failed to update server config"); - serverConfig = cfg.toObject(); - return serverConfig; -}; diff --git a/backend-mongo/src/config/storage.ts b/backend-mongo/src/config/storage.ts deleted file mode 100644 index f3cf27196..000000000 --- a/backend-mongo/src/config/storage.ts +++ /dev/null @@ -1,30 +0,0 @@ -const MemoryLicenseServerKeyTokenStorage = () => { - let authToken: string; - - return { - setToken: (token: string) => { - authToken = token; - }, - getToken: () => authToken, - }; -}; - -const MemoryLicenseKeyTokenStorage = () => { - let authToken: string; - - return { - setToken: (token: string) => { - authToken = token; - }, - getToken: () => authToken, - }; -}; - -const licenseServerTokenStorage = MemoryLicenseServerKeyTokenStorage(); -const licenseTokenStorage = MemoryLicenseKeyTokenStorage(); - -export const getLicenseServerKeyAuthToken = licenseServerTokenStorage.getToken; -export const setLicenseServerKeyAuthToken = licenseServerTokenStorage.setToken; - -export const getLicenseKeyAuthToken = licenseTokenStorage.getToken; -export const setLicenseKeyAuthToken = licenseTokenStorage.setToken; \ No newline at end of file diff --git a/backend-mongo/src/controllers/v1/adminController.ts b/backend-mongo/src/controllers/v1/adminController.ts deleted file mode 100644 index ebe0d4aa7..000000000 --- a/backend-mongo/src/controllers/v1/adminController.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Request, Response } from "express"; -import { getHttpsEnabled, getIsMigrationMode } from "../../config"; -import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig"; -import { initializeDefaultOrg, issueAuthTokens } from "../../helpers"; -import { validateRequest } from "../../helpers/validation"; -import { User } from "../../models"; -import { TelemetryService } from "../../services"; -import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors"; -import * as reqValidator from "../../validation/admin"; - -export const getServerConfigInfo = async (_req: Request, res: Response) => { - const config = getServerConfig(); - const isMigrationModeOn = await getIsMigrationMode(); - return res.send({ config: { ...config, isMigrationModeOn } }); -}; - -export const updateServerConfig = async (req: Request, res: Response) => { - const { - body: { allowSignUp } - } = await validateRequest(reqValidator.UpdateServerConfigV1, req); - const config = await setServerConfig({ allowSignUp }); - return res.send({ config }); -}; - -export const adminSignUp = async (req: Request, res: Response) => { - const cfg = getServerConfig(); - if (cfg.initialized) throw UnauthorizedRequestError({ message: "Admin has been created" }); - const { - body: { - email, - publicKey, - salt, - lastName, - verifier, - firstName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag - } - } = await validateRequest(reqValidator.SignupV1, req); - let user = await User.findOne({ email }); - if (user) throw BadRequestError({ message: "User already exist" }); - user = new User({ - email, - firstName, - lastName, - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag, - salt, - verifier, - superAdmin: true - }); - await user.save(); - await initializeDefaultOrg({ organizationName: "Admin Org", user }); - - await setServerConfig({ initialized: true }); - - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - const token = tokens.token; - - const postHogClient = await TelemetryService.getPostHogClient(); - if (postHogClient) { - postHogClient.capture({ - event: "admin initialization", - properties: { - email: user.email, - lastName, - firstName - } - }); - } - - // store (refresh) token in httpOnly cookie - res.cookie("jid", tokens.refreshToken, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: await getHttpsEnabled() - }); - - return res.status(200).send({ - message: "Successfully set up admin account", - user, - token - }); -}; diff --git a/backend-mongo/src/controllers/v1/authController.ts b/backend-mongo/src/controllers/v1/authController.ts deleted file mode 100644 index c27175bb1..000000000 --- a/backend-mongo/src/controllers/v1/authController.ts +++ /dev/null @@ -1,277 +0,0 @@ -import { Request, Response } from "express"; -import jwt from "jsonwebtoken"; -import * as bigintConversion from "bigint-conversion"; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const jsrp = require("jsrp"); -import { - LoginSRPDetail, - TokenVersion, - User -} from "../../models"; -import { clearTokens, createToken, issueAuthTokens } from "../../helpers/auth"; -import { checkUserDevice } from "../../helpers/user"; -import { AuthTokenType } from "../../variables"; -import { - BadRequestError, - UnauthorizedRequestError -} from "../../utils/errors"; -import { - getAuthSecret, - getHttpsEnabled, - getJwtAuthLifetime, -} from "../../config"; -import { ActorType } from "../../ee/models"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/auth"; - -declare module "jsonwebtoken" { - export interface AuthnJwtPayload extends jwt.JwtPayload { - authTokenType: AuthTokenType; - } - export interface UserIDJwtPayload extends jwt.JwtPayload { - userId: string; - refreshVersion?: number; - } - export interface IdentityAccessTokenJwtPayload extends jwt.JwtPayload { - _id: string; - clientSecretId: string; - identityAccessTokenId: string; - authTokenType: string; - } -} - -/** - * Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol - * @param req - * @param res - * @returns - */ -export const login1 = async (req: Request, res: Response) => { - const { - body: { email, clientPublicKey } - } = await validateRequest(reqValidator.Login1V1, req); - - const user = await User.findOne({ - email - }).select("+salt +verifier"); - - if (!user) throw new Error("Failed to find user"); - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier - }, - async () => { - // generate server-side public key - const serverPublicKey = server.getPublicKey(); - - await LoginSRPDetail.findOneAndReplace( - { email: email }, - { - email: email, - clientPublicKey: clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt) - }, - { upsert: true, returnNewDocument: false } - ); - - return res.status(200).send({ - serverPublicKey, - salt: user.salt - }); - } - ); -}; - -/** - * Log in user step 2: complete step 2 of SRP protocol and return token and their (encrypted) - * private key - * @param req - * @param res - * @returns - */ -export const login2 = async (req: Request, res: Response) => { - const { - body: { email, clientProof } - } = await validateRequest(reqValidator.Login2V1, req); - - const user = await User.findOne({ - email - }).select("+salt +verifier +publicKey +encryptedPrivateKey +iv +tag"); - - if (!user) throw new Error("Failed to find user"); - - const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: email }); - - if (!loginSRPDetailFromDB) { - return BadRequestError( - Error( - "It looks like some details from the first login are not found. Please try login one again" - ) - ); - } - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetailFromDB.serverBInt - }, - async () => { - server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey); - - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - // issue tokens - - await checkUserDevice({ - user, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - const tokens = await issueAuthTokens({ - userId: user._id, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - // store (refresh) token in httpOnly cookie - res.cookie("jid", tokens.refreshToken, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: await getHttpsEnabled() - }); - - // return (access) token in response - return res.status(200).send({ - token: tokens.token, - publicKey: user.publicKey, - encryptedPrivateKey: user.encryptedPrivateKey, - iv: user.iv, - tag: user.tag - }); - } - - return res.status(400).send({ - message: "Failed to authenticate. Try again?" - }); - } - ); -}; - -/** - * Log out user - * @param req - * @param res - * @returns - */ -export const logout = async (req: Request, res: Response) => { - if (req.authData.actor.type === ActorType.USER && req.authData.tokenVersionId) { - await clearTokens(req.authData.tokenVersionId); - } - - // clear httpOnly cookie - res.cookie("jid", "", { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: (await getHttpsEnabled()) as boolean - }); - - return res.status(200).send({ - message: "Successfully logged out." - }); -}; - -export const revokeAllSessions = async (req: Request, res: Response) => { - await TokenVersion.updateMany( - { - user: req.user._id - }, - { - $inc: { - refreshVersion: 1, - accessVersion: 1 - } - } - ); - - return res.status(200).send({ - message: "Successfully revoked all sessions." - }); -}; - -/** - * Return user is authenticated - * @param req - * @param res - * @returns - */ -export const checkAuth = async (req: Request, res: Response) => { - return res.status(200).send({ - message: "Authenticated" - }); -}; - -/** - * Return new JWT access token by first validating the refresh token - * @param req - * @param res - * @returns - */ -export const getNewToken = async (req: Request, res: Response) => { - - const refreshToken = req.cookies.jid; - - if (!refreshToken) - throw BadRequestError({ - message: "Failed to find refresh token in request cookies" - }); - - const decodedToken = jwt.verify(refreshToken, await getAuthSecret()); - - if (decodedToken.authTokenType !== AuthTokenType.REFRESH_TOKEN) throw UnauthorizedRequestError(); - - const user = await User.findOne({ - _id: decodedToken.userId - }).select("+publicKey +refreshVersion +accessVersion"); - - if (!user) throw new Error("Failed to authenticate unfound user"); - if (!user?.publicKey) throw new Error("Failed to authenticate not fully set up account"); - - const tokenVersion = await TokenVersion.findById(decodedToken.tokenVersionId); - - if (!tokenVersion) - throw UnauthorizedRequestError({ - message: "Failed to validate refresh token" - }); - - if (decodedToken.refreshVersion !== tokenVersion.refreshVersion) - throw BadRequestError({ - message: "Failed to validate refresh token" - }); - - const token = createToken({ - payload: { - authTokenType: AuthTokenType.ACCESS_TOKEN, - userId: decodedToken.userId, - tokenVersionId: tokenVersion._id.toString(), - accessVersion: tokenVersion.refreshVersion - }, - expiresIn: await getJwtAuthLifetime(), - secret: await getAuthSecret() - }); - - return res.status(200).send({ - token - }); -}; - -export const handleAuthProviderCallback = (req: Request, res: Response) => { - res.redirect(`/login/provider/success?token=${encodeURIComponent(req.providerAuthToken)}`); -}; \ No newline at end of file diff --git a/backend-mongo/src/controllers/v1/botController.ts b/backend-mongo/src/controllers/v1/botController.ts deleted file mode 100644 index 3a2ff606a..000000000 --- a/backend-mongo/src/controllers/v1/botController.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { Bot, BotKey } from "../../models"; -import { createBot } from "../../helpers/bot"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/bot"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; -import { BadRequestError } from "../../utils/errors"; - -interface BotKey { - encryptedKey: string; - nonce: string; -} - -/** - * Return bot for workspace with id [workspaceId]. If a workspace bot doesn't exist, - * then create and return a new bot. - * @param req - * @param res - * @returns - */ -export const getBotByWorkspaceId = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetBotByWorkspaceIdV1, req); - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - let bot = await Bot.findOne({ - workspace: workspaceId - }); - - if (!bot) { - // case: bot doesn't exist for workspace with id [workspaceId] - // -> create a new bot and return it - bot = await createBot({ - name: "Infisical Bot", - workspaceId: new Types.ObjectId(workspaceId) - }); - } - - return res.status(200).send({ - bot - }); -}; - -/** - * Return bot with id [req.bot._id] with active state set to [isActive]. - * @param req - * @param res - * @returns - */ -export const setBotActiveState = async (req: Request, res: Response) => { - const { - body: { botKey, isActive }, - params: { botId } - } = await validateRequest(reqValidator.SetBotActiveStateV1, req); - - const bot = await Bot.findById(botId); - if (!bot) { - throw BadRequestError({ message: "Bot not found" }); - } - const userId = req.user._id; - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: bot.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Integrations - ); - - if (isActive) { - // bot state set to active -> share workspace key with bot - if (!botKey?.encryptedKey || !botKey?.nonce) { - return res.status(400).send({ - message: "Failed to set bot state to active - missing bot key" - }); - } - - await BotKey.findOneAndUpdate( - { - workspace: bot.workspace - }, - { - encryptedKey: botKey.encryptedKey, - nonce: botKey.nonce, - sender: userId, - bot: bot._id, - workspace: bot.workspace - }, - { - upsert: true, - new: true - } - ); - } else { - // case: bot state set to inactive -> delete bot's workspace key - await BotKey.deleteOne({ - bot: bot._id - }); - } - - const updatedBot = await Bot.findOneAndUpdate( - { - _id: bot._id - }, - { - isActive - }, - { - new: true - } - ); - - if (!updatedBot) throw new Error("Failed to update bot active state"); - - return res.status(200).send({ - bot - }); -}; diff --git a/backend-mongo/src/controllers/v1/index.ts b/backend-mongo/src/controllers/v1/index.ts deleted file mode 100644 index 937936416..000000000 --- a/backend-mongo/src/controllers/v1/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as authController from "./authController"; -import * as universalAuthController from "./universalAuthController"; -import * as botController from "./botController"; -import * as integrationAuthController from "./integrationAuthController"; -import * as integrationController from "./integrationController"; -import * as keyController from "./keyController"; -import * as membershipController from "./membershipController"; -import * as membershipOrgController from "./membershipOrgController"; -import * as organizationController from "./organizationController"; -import * as passwordController from "./passwordController"; -import * as secretController from "./secretController"; -import * as serviceTokenController from "./serviceTokenController"; -import * as signupController from "./signupController"; -import * as userActionController from "./userActionController"; -import * as userController from "./userController"; -import * as workspaceController from "./workspaceController"; -import * as secretScanningController from "./secretScanningController"; -import * as webhookController from "./webhookController"; -import * as secretImpsController from "./secretImpsController"; -import * as adminController from "./adminController"; - -export { - authController, - universalAuthController, - botController, - integrationAuthController, - integrationController, - keyController, - membershipController, - membershipOrgController, - organizationController, - passwordController, - secretController, - serviceTokenController, - signupController, - userActionController, - userController, - workspaceController, - secretScanningController, - webhookController, - secretImpsController, - adminController -}; diff --git a/backend-mongo/src/controllers/v1/integrationAuthController.ts b/backend-mongo/src/controllers/v1/integrationAuthController.ts deleted file mode 100644 index 857fadda5..000000000 --- a/backend-mongo/src/controllers/v1/integrationAuthController.ts +++ /dev/null @@ -1,1303 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { standardRequest } from "../../config/request"; -import { getApps, getTeams, revokeAccess } from "../../integrations"; -import { Bot, IIntegrationAuth, Integration, IntegrationAuth, Workspace } from "../../models"; -import { EventType } from "../../ee/models"; -import { IntegrationService } from "../../services"; -import { EEAuditLogService } from "../../ee/services"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_UTF8, - INTEGRATION_BITBUCKET_API_URL, - INTEGRATION_CHECKLY_API_URL, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_NORTHFLANK_API_URL, - INTEGRATION_QOVERY_API_URL, - INTEGRATION_RAILWAY_API_URL, - INTEGRATION_SET, - INTEGRATION_VERCEL_API_URL, - getIntegrationOptions as getIntegrationOptionsFunc -} from "../../variables"; -import { exchangeRefresh } from "../../integrations"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/integrationAuth"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; -import { getIntegrationAuthAccessHelper } from "../../helpers"; - -/*** - * Return integration authorization with id [integrationAuthId] - */ -export const getIntegrationAuth = async (req: Request, res: Response) => { - const { - params: { integrationAuthId } - } = await validateRequest(reqValidator.GetIntegrationAuthV1, req); - - const integrationAuth = await IntegrationAuth.findById(integrationAuthId); - - if (!integrationAuth) return res.status(400).send({ - message: "Failed to find integration authorization" - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - return res.status(200).send({ - integrationAuth - }); -}; - -export const getIntegrationOptions = async (req: Request, res: Response) => { - const INTEGRATION_OPTIONS = await getIntegrationOptionsFunc(); - - return res.status(200).send({ - integrationOptions: INTEGRATION_OPTIONS - }); -}; - -/** - * Perform OAuth2 code-token exchange as part of integration [integration] for workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const oAuthExchange = async (req: Request, res: Response) => { - const { - body: { integration, workspaceId, code, url } - } = await validateRequest(reqValidator.OauthExchangeV1, req); - if (!INTEGRATION_SET.has(integration)) throw new Error("Failed to validate integration"); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Integrations - ); - - const workspace = await Workspace.findById(workspaceId); - const environments = workspace?.environments || []; - if (environments.length === 0) { - throw new Error("Failed to get environments"); - } - - const integrationAuth = await IntegrationService.handleOAuthExchange({ - workspaceId, - integration, - code, - environment: environments[0].slug, - url - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.AUTHORIZE_INTEGRATION, - metadata: { - integration: integrationAuth.integration - } - }, - { - workspaceId: integrationAuth.workspace - } - ); - - return res.status(200).send({ - integrationAuth - }); -}; - -/** - * Save integration access token and (optionally) access id as part of integration - * [integration] for workspace with id [workspaceId] - * @param req - * @param res - */ -export const saveIntegrationToken = async (req: Request, res: Response) => { - // TODO: refactor - // TODO: check if access token is valid for each integration - const { - body: { workspaceId, integration, url, accessId, namespace, accessToken, refreshToken } - } = await validateRequest(reqValidator.SaveIntegrationAccessTokenV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Integrations - ); - - const bot = await Bot.findOne({ - workspace: new Types.ObjectId(workspaceId), - isActive: true - }); - - if (!bot) throw new Error("Bot must be enabled to save integration access token"); - - let integrationAuth = await new IntegrationAuth({ - workspace: new Types.ObjectId(workspaceId), - integration, - url, - namespace, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - ...(integration === INTEGRATION_GCP_SECRET_MANAGER - ? { - metadata: { - authMethod: "serviceAccount" - } - } - : {}) - }).save(); - - // encrypt and save integration access details - if (refreshToken) { - await exchangeRefresh({ - integrationAuth, - refreshToken - }); - } - - // encrypt and save integration access details - if (accessId || accessToken) { - integrationAuth = (await IntegrationService.setIntegrationAuthAccess({ - integrationAuthId: integrationAuth._id.toString(), - accessId, - accessToken, - accessExpiresAt: undefined - })) as IIntegrationAuth; - } - - if (!integrationAuth) throw new Error("Failed to save integration access token"); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.AUTHORIZE_INTEGRATION, - metadata: { - integration: integrationAuth.integration - } - }, - { - workspaceId: integrationAuth.workspace - } - ); - - return res.status(200).send({ - integrationAuth - }); -}; - -/** - * Return list of applications allowed for integration with integration authorization id [integrationAuthId] - * @param req - * @param res - * @returns - */ -export const getIntegrationAuthApps = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { teamId, workspaceSlug } - } = await validateRequest(reqValidator.GetIntegrationAuthAppsV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken, accessId } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - const apps = await getApps({ - integrationAuth: integrationAuth, - accessToken: accessToken, - accessId: accessId, - ...(teamId && { teamId }), - ...(workspaceSlug && { workspaceSlug }) - }); - - return res.status(200).send({ - apps - }); -}; - -/** - * Return list of teams allowed for integration with integration authorization id [integrationAuthId] - * @param req - * @param res - * @returns - */ -export const getIntegrationAuthTeams = async (req: Request, res: Response) => { - const { - params: { integrationAuthId } - } = await validateRequest(reqValidator.GetIntegrationAuthTeamsV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - const teams = await getTeams({ - integrationAuth: integrationAuth, - accessToken: accessToken - }); - - return res.status(200).send({ - teams - }); -}; - -/** - * Return list of available Vercel (preview) branches for Vercel project with - * id [appId] - * @param req - * @param res - */ -export const getIntegrationAuthVercelBranches = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { appId } - } = await validateRequest(reqValidator.GetIntegrationAuthVercelBranchesV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface VercelBranch { - ref: string; - lastCommit: string; - isProtected: boolean; - } - - const params = new URLSearchParams({ - projectId: appId, - ...(integrationAuth.teamId - ? { - teamId: integrationAuth.teamId - } - : {}) - }); - - let branches: string[] = []; - - if (appId && appId !== "") { - const { data }: { data: VercelBranch[] } = await standardRequest.get( - `${INTEGRATION_VERCEL_API_URL}/v1/integrations/git-branches`, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - branches = data.map((b) => b.ref); - } - - return res.status(200).send({ - branches - }); -}; - -/** - * Return list of Checkly groups for a specific user - * @param req - * @param res - */ -export const getIntegrationAuthChecklyGroups = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { accountId } - } = await validateRequest(reqValidator.GetIntegrationAuthChecklyGroupsV1, req); - - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface ChecklyGroup { - id: number; - name: string; - } - - if (accountId && accountId !== "") { - const { data }: { data: ChecklyGroup[] } = ( - await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/check-groups`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "X-Checkly-Account": accountId - } - }) - ); - - return res.status(200).send({ - groups: data.map((g: ChecklyGroup) => ({ - name: g.name, - groupId: g.id, - })) - }); - } - - return res.status(200).send({ - groups: [] - }); -} - -/** - * Return list of Qovery Orgs for a specific user - * @param req - * @param res - */ -export const getIntegrationAuthQoveryOrgs = async (req: Request, res: Response) => { - const { - params: { integrationAuthId } - } = await validateRequest(reqValidator.GetIntegrationAuthQoveryOrgsV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - const { data } = await standardRequest.get( - `${INTEGRATION_QOVERY_API_URL}/organization`, - { - headers: { - Authorization: `Token ${accessToken}`, - "Accept": "application/json", - }, - } - ); - - interface QoveryOrg { - id: string; - name: string; - } - - const orgs = data.results.map((a: QoveryOrg) => { - return { - name: a.name, - orgId: a.id, - }; - }); - - return res.status(200).send({ - orgs - }); -}; - -/** - * Return list of Qovery Projects for a specific orgId - * @param req - * @param res - */ -export const getIntegrationAuthQoveryProjects = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { orgId } - } = await validateRequest(reqValidator.GetIntegrationAuthQoveryProjectsV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface Project { - name: string; - projectId: string; - } - - interface QoveryProject { - id: string; - name: string; - } - - let projects: Project[] = []; - - if (orgId && orgId !== "") { - const { data } = await standardRequest.get( - `${INTEGRATION_QOVERY_API_URL}/organization/${orgId}/project`, - { - headers: { - Authorization: `Token ${accessToken}`, - "Accept": "application/json", - }, - } - ); - - projects = data.results.map((a: QoveryProject) => { - return { - name: a.name, - projectId: a.id, - }; - }); - } - - return res.status(200).send({ - projects - }); -}; - -/** - * Return list of Qovery environments for project with id [projectId] - * @param req - * @param res - */ -export const getIntegrationAuthQoveryEnvironments = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { projectId } - } = await validateRequest(reqValidator.GetIntegrationAuthQoveryEnvironmentsV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface Environment { - name: string; - environmentId: string; - } - - interface QoveryEnvironment { - id: string; - name: string; - } - - let environments: Environment[] = []; - - if (projectId && projectId !== "" && projectId !== "none") { // TODO: fix - const { data } = await standardRequest.get( - `${INTEGRATION_QOVERY_API_URL}/project/${projectId}/environment`, - { - headers: { - Authorization: `Token ${accessToken}`, - "Accept": "application/json", - }, - } - ); - - environments = data.results.map((a: QoveryEnvironment) => { - return { - name: a.name, - environmentId: a.id, - }; - }); - } - - return res.status(200).send({ - environments - }); -}; - -/** - * Return list of Qovery apps for environment with id [environmentId] - * @param req - * @param res - */ -export const getIntegrationAuthQoveryApps = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { environmentId } - } = await validateRequest(reqValidator.GetIntegrationAuthQoveryScopesV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface App { - name: string; - appId: string; - } - - interface QoveryApp { - id: string; - name: string; - } - - let apps: App[] = []; - - if (environmentId && environmentId !== "") { - const { data } = await standardRequest.get( - `${INTEGRATION_QOVERY_API_URL}/environment/${environmentId}/application`, - { - headers: { - Authorization: `Token ${accessToken}`, - "Accept": "application/json", - }, - } - ); - - apps = data.results.map((a: QoveryApp) => { - return { - name: a.name, - appId: a.id, - }; - }); - } - - return res.status(200).send({ - apps - }); -}; - -/** - * Return list of Qovery containers for environment with id [environmentId] - * @param req - * @param res - */ -export const getIntegrationAuthQoveryContainers = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { environmentId } - } = await validateRequest(reqValidator.GetIntegrationAuthQoveryScopesV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface Container { - name: string; - appId: string; - } - - interface QoveryContainer { - id: string; - name: string; - } - - let containers: Container[] = []; - - if (environmentId && environmentId !== "") { - const { data } = await standardRequest.get( - `${INTEGRATION_QOVERY_API_URL}/environment/${environmentId}/container`, - { - headers: { - Authorization: `Token ${accessToken}`, - "Accept": "application/json", - }, - } - ); - - containers = data.results.map((a: QoveryContainer) => { - return { - name: a.name, - appId: a.id, - }; - }); - } - - return res.status(200).send({ - containers - }); -}; - -/** - * Return list of Qovery jobs for environment with id [environmentId] - * @param req - * @param res - */ -export const getIntegrationAuthQoveryJobs = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { environmentId } - } = await validateRequest(reqValidator.GetIntegrationAuthQoveryScopesV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface Job { - name: string; - appId: string; - } - - interface QoveryJob { - id: string; - name: string; - } - - let jobs: Job[] = []; - - if (environmentId && environmentId !== "") { - const { data } = await standardRequest.get( - `${INTEGRATION_QOVERY_API_URL}/environment/${environmentId}/job`, - { - headers: { - Authorization: `Token ${accessToken}`, - "Accept": "application/json", - }, - } - ); - - jobs = data.results.map((a: QoveryJob) => { - return { - name: a.name, - appId: a.id, - }; - }); - } - - return res.status(200).send({ - jobs - }); -}; - -/** - * Return list of Railway environments for Railway project with - * id [appId] - * @param req - * @param res - */ -export const getIntegrationAuthRailwayEnvironments = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { appId } - } = await validateRequest(reqValidator.GetIntegrationAuthRailwayEnvironmentsV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface RailwayEnvironment { - node: { - id: string; - name: string; - isEphemeral: boolean; - }; - } - - interface Environment { - environmentId: string; - name: string; - } - - let environments: Environment[] = []; - - if (appId && appId !== "") { - const query = ` - query GetEnvironments($projectId: String!, $after: String, $before: String, $first: Int, $isEphemeral: Boolean, $last: Int) { - environments(projectId: $projectId, after: $after, before: $before, first: $first, isEphemeral: $isEphemeral, last: $last) { - edges { - node { - id - name - isEphemeral - } - } - } - } - `; - - const variables = { - projectId: appId - }; - - const { - data: { - data: { - environments: { edges } - } - } - } = await standardRequest.post( - INTEGRATION_RAILWAY_API_URL, - { - query, - variables - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json" - } - } - ); - - environments = edges.map((e: RailwayEnvironment) => { - return { - name: e.node.name, - environmentId: e.node.id - }; - }); - } - - return res.status(200).send({ - environments - }); -}; - -/** - * Return list of Railway services for Railway project with id - * [appId] - * @param req - * @param res - */ -export const getIntegrationAuthRailwayServices = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { appId } - } = await validateRequest(reqValidator.GetIntegrationAuthRailwayServicesV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface RailwayService { - node: { - id: string; - name: string; - }; - } - - interface Service { - name: string; - serviceId: string; - } - - let services: Service[] = []; - - const query = ` - query project($id: String!) { - project(id: $id) { - createdAt - deletedAt - id - description - expiredAt - isPublic - isTempProject - isUpdatable - name - prDeploys - teamId - updatedAt - upstreamUrl - services { - edges { - node { - id - name - } - } - } - } - } - `; - - if (appId && appId !== "") { - const variables = { - id: appId - }; - - const { - data: { - data: { - project: { - services: { edges } - } - } - } - } = await standardRequest.post( - INTEGRATION_RAILWAY_API_URL, - { - query, - variables - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json" - } - } - ); - - services = edges.map((e: RailwayService) => ({ - name: e.node.name, - serviceId: e.node.id - })); - } - - return res.status(200).send({ - services - }); -}; - -/** - * Return list of workspaces allowed for Bitbucket integration - * @param req - * @param res - * @returns - */ -export const getIntegrationAuthBitBucketWorkspaces = async (req: Request, res: Response) => { - interface WorkspaceResponse { - size: number; - page: number; - pageLen: number; - next: string; - previous: string; - values: Array; - } - - interface Workspace { - type: string; - uuid: string; - name: string; - slug: string; - is_private: boolean; - created_on: string; - updated_on: string; - } - - const { - params: { integrationAuthId } - } = await validateRequest(reqValidator.GetIntegrationAuthBitbucketWorkspacesV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - const workspaces: Workspace[] = []; - let hasNextPage = true; - let workspaceUrl = `${INTEGRATION_BITBUCKET_API_URL}/2.0/workspaces`; - - while (hasNextPage) { - const { data }: { data: WorkspaceResponse } = await standardRequest.get(workspaceUrl, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }); - - if (data?.values.length > 0) { - data.values.forEach((workspace) => { - workspaces.push(workspace); - }); - } - - if (data.next) { - workspaceUrl = data.next; - } else { - hasNextPage = false; - } - } - - return res.status(200).send({ - workspaces - }); -}; - -/** - * Return list of secret groups for Northflank project with id [appId] - * @param req - * @param res - * @returns - */ -export const getIntegrationAuthNorthflankSecretGroups = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { appId } - } = await validateRequest(reqValidator.GetIntegrationAuthNorthflankSecretGroupsV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface NorthflankSecretGroup { - id: string; - name: string; - description: string; - priority: number; - projectId: string; - } - - interface SecretGroup { - name: string; - groupId: string; - } - - const secretGroups: SecretGroup[] = []; - - if (appId && appId !== "") { - let page = 1; - const perPage = 10; - let hasMorePages = true; - - while (hasMorePages) { - const params = new URLSearchParams({ - page: String(page), - per_page: String(perPage), - filter: "all" - }); - - const { - data: { - data: { secrets } - } - } = await standardRequest.get<{ data: { secrets: NorthflankSecretGroup[] } }>( - `${INTEGRATION_NORTHFLANK_API_URL}/v1/projects/${appId}/secrets`, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - secrets.forEach((a: any) => { - secretGroups.push({ - name: a.name, - groupId: a.id - }); - }); - - if (secrets.length < perPage) { - hasMorePages = false; - } - - page++; - } - } - - return res.status(200).send({ - secretGroups - }); -}; - -/** - * Return list of build configs for TeamCity project with id [appId] - * @param req - * @param res - * @returns - */ -export const getIntegrationAuthTeamCityBuildConfigs = async (req: Request, res: Response) => { - const { - params: { integrationAuthId }, - query: { appId } - } = await validateRequest(reqValidator.GetIntegrationAuthTeamCityBuildConfigsV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - interface TeamCityBuildConfig { - id: string; - name: string; - projectName: string; - projectId: string; - href: string; - webUrl: string; - } - - interface GetTeamCityBuildConfigsRes { - count: number; - href: string; - buildType: TeamCityBuildConfig[]; - } - - if (appId && appId !== "") { - const { - data: { buildType } - } = await standardRequest.get( - `${integrationAuth.url}/app/rest/buildTypes`, - { - params: { - locator: `project:${appId}` - }, - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - - return res.status(200).send({ - buildConfigs: buildType.map((buildConfig) => ({ - name: buildConfig.name, - buildConfigId: buildConfig.id - })) - }); - } - - return res.status(200).send({ - buildConfigs: [] - }); -}; - -/** - * Delete all integration authorizations and integrations for workspace with id [workspaceId] - * with integration name [integration] - * @param req - * @param res - * @returns - */ -export const deleteIntegrationAuths = async (req: Request, res: Response) => { - const { - query: { integration, workspaceId } - } = await validateRequest(reqValidator.DeleteIntegrationAuthsV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Integrations - ); - - const integrationAuths = await IntegrationAuth.deleteMany({ - integration, - workspace: new Types.ObjectId(workspaceId) - }); - - const integrations = await Integration.deleteMany({ - integration, - workspace: new Types.ObjectId(workspaceId) - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UNAUTHORIZE_INTEGRATION, - metadata: { - integration - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.status(200).send({ - integrationAuths, - integrations - }); -} - -/** - * Delete integration authorization with id [integrationAuthId] - * @param req - * @param res - * @returns - */ -export const deleteIntegrationAuthById = async (req: Request, res: Response) => { - const { - params: { integrationAuthId } - } = await validateRequest(reqValidator.DeleteIntegrationAuthV1, req); - - // TODO(akhilmhdh): remove class -> static function path and makes these into reusable independent functions - const { integrationAuth, accessToken } = await getIntegrationAuthAccessHelper({ - integrationAuthId: new Types.ObjectId(integrationAuthId) - }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Integrations - ); - - const deletedIntegrationAuth = await revokeAccess({ - integrationAuth: integrationAuth, - accessToken: accessToken - }); - - if (!deletedIntegrationAuth) - return res.status(400).send({ - message: "Failed to find integration authorization" - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UNAUTHORIZE_INTEGRATION, - metadata: { - integration: deletedIntegrationAuth.integration - } - }, - { - workspaceId: deletedIntegrationAuth.workspace - } - ); - - return res.status(200).send({ - integrationAuth: deletedIntegrationAuth - }); -}; diff --git a/backend-mongo/src/controllers/v1/integrationController.ts b/backend-mongo/src/controllers/v1/integrationController.ts deleted file mode 100644 index 837936af7..000000000 --- a/backend-mongo/src/controllers/v1/integrationController.ts +++ /dev/null @@ -1,322 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { Folder, IWorkspace, Integration, IntegrationAuth } from "../../models"; -import { EventService } from "../../services"; -import { eventStartIntegration } from "../../events"; -import { getFolderByPath } from "../../services/FolderService"; -import { BadRequestError } from "../../utils/errors"; -import { EEAuditLogService } from "../../ee/services"; -import { EventType } from "../../ee/models"; -import { syncSecretsToActiveIntegrationsQueue } from "../../queues/integrations/syncSecretsToThirdPartyServices"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/integration"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; - -/** - * Create/initialize an (empty) integration for integration authorization - * @param req - * @param res - * @returns - */ -export const createIntegration = async (req: Request, res: Response) => { - const { - body: { - isActive, - sourceEnvironment, - secretPath, - app, - path, - appId, - owner, - region, - scope, - targetService, - targetServiceId, - integrationAuthId, - targetEnvironment, - targetEnvironmentId, - metadata - } - } = await validateRequest(reqValidator.CreateIntegrationV1, req); - - const integrationAuth = await IntegrationAuth.findById(integrationAuthId) - .populate<{ workspace: IWorkspace }>("workspace") - .select( - "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt" - ); - - if (!integrationAuth) throw BadRequestError({ message: "Integration auth not found" }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integrationAuth.workspace._id - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Integrations - ); - - const folders = await Folder.findOne({ - workspace: integrationAuth.workspace._id, - environment: sourceEnvironment - }); - - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) { - throw BadRequestError({ - message: "Folder path doesn't exist" - }); - } - } - - // TODO: validate [sourceEnvironment] and [targetEnvironment] - - // initialize new integration after saving integration access token - const integration = await new Integration({ - workspace: integrationAuth.workspace._id, - environment: sourceEnvironment, - isActive, - app, - appId, - targetEnvironment, - targetEnvironmentId, - targetService, - targetServiceId, - owner, - path, - region, - scope, - secretPath, - integration: integrationAuth.integration, - integrationAuth: new Types.ObjectId(integrationAuthId), - metadata - }).save(); - - if (integration) { - // trigger event - push secrets - EventService.handleEvent({ - event: eventStartIntegration({ - workspaceId: integration.workspace, - environment: sourceEnvironment - }) - }); - } - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_INTEGRATION, - metadata: { - integrationId: integration._id.toString(), - integration: integration.integration, - environment: integration.environment, - secretPath, - url: integration.url, - app: integration.app, - appId: integration.appId, - targetEnvironment: integration.targetEnvironment, - targetEnvironmentId: integration.targetEnvironmentId, - targetService: integration.targetService, - targetServiceId: integration.targetServiceId, - path: integration.path, - region: integration.region - } - }, - { - workspaceId: integration.workspace - } - ); - - return res.status(200).send({ - integration - }); -}; - -/** - * Change environment or name of integration with id [integrationId] - * @param req - * @param res - * @returns - */ -export const updateIntegration = async (req: Request, res: Response) => { - // TODO: add integration-specific validation to ensure that each - // integration has the correct fields populated in [Integration] - - const { - body: { - environment, - isActive, - app, - appId, - targetEnvironment, - owner, // github-specific integration param - secretPath - }, - params: { integrationId } - } = await validateRequest(reqValidator.UpdateIntegrationV1, req); - - const integration = await Integration.findById(integrationId); - if (!integration) throw BadRequestError({ message: "Integration not found" }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integration.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Integrations - ); - - const folders = await Folder.findOne({ - workspace: integration.workspace, - environment - }); - - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) { - throw BadRequestError({ - message: "Path for service token does not exist" - }); - } - } - - const updatedIntegration = await Integration.findOneAndUpdate( - { - _id: integration._id - }, - { - environment, - isActive, - app, - appId, - targetEnvironment, - owner, - secretPath - }, - { - new: true - } - ); - - if (updatedIntegration) { - // trigger event - push secrets - EventService.handleEvent({ - event: eventStartIntegration({ - workspaceId: updatedIntegration.workspace, - environment - }) - }); - } - - return res.status(200).send({ - integration: updatedIntegration - }); -}; - -/** - * Delete integration with id [integrationId] - * @param req - * @param res - * @returns - */ -export const deleteIntegration = async (req: Request, res: Response) => { - const { - params: { integrationId } - } = await validateRequest(reqValidator.DeleteIntegrationV1, req); - - const integration = await Integration.findById(integrationId); - if (!integration) throw BadRequestError({ message: "Integration not found" }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: integration.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Integrations - ); - - const deletedIntegration = await Integration.findOneAndDelete({ - _id: integrationId - }); - - if (!deletedIntegration) throw new Error("Failed to find integration"); - - const numOtherIntegrationsUsingSameAuth = await Integration.countDocuments({ - integrationAuth: deletedIntegration.integrationAuth, - _id: { - $nin: [deletedIntegration._id] - } - }); - - if (numOtherIntegrationsUsingSameAuth === 0) { - // no other integrations are using the same integration auth - // -> delete integration auth associated with the integration being deleted - await IntegrationAuth.deleteOne({ - _id: deletedIntegration.integrationAuth - }); - } - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_INTEGRATION, - metadata: { - integrationId: integration._id.toString(), - integration: integration.integration, - environment: integration.environment, - secretPath: integration.secretPath, - url: integration.url, - app: integration.app, - appId: integration.appId, - targetEnvironment: integration.targetEnvironment, - targetEnvironmentId: integration.targetEnvironmentId, - targetService: integration.targetService, - targetServiceId: integration.targetServiceId, - path: integration.path, - region: integration.region - } - }, - { - workspaceId: integration.workspace - } - ); - - return res.status(200).send({ - integration - }); -}; - -// Will trigger sync for all integrations within the given env and workspace id -export const manualSync = async (req: Request, res: Response) => { - const { - body: { workspaceId, environment } - } = await validateRequest(reqValidator.ManualSyncV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Integrations - ); - - syncSecretsToActiveIntegrationsQueue({ - workspaceId, - environment - }); - - res.status(200).send(); -}; diff --git a/backend-mongo/src/controllers/v1/keyController.ts b/backend-mongo/src/controllers/v1/keyController.ts deleted file mode 100644 index 956487814..000000000 --- a/backend-mongo/src/controllers/v1/keyController.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Types } from "mongoose"; -import { Request, Response } from "express"; -import { Key } from "../../models"; -import { findMembership } from "../../helpers/membership"; -import { EventType } from "../../ee/models"; -import { EEAuditLogService } from "../../ee/services"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/key"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; - -/** - * Add (encrypted) copy of workspace key for workspace with id [workspaceId] for user with - * id [key.userId] - * @param req - * @param res - * @returns - */ -export const uploadKey = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - body: { key } - } = await validateRequest(reqValidator.UploadKeyV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Member - ); - - // validate membership of receiver - const receiverMembership = await findMembership({ - user: key.userId, - workspace: workspaceId - }); - - if (!receiverMembership) { - throw new Error("Failed receiver membership validation for workspace"); - } - - await new Key({ - encryptedKey: key.encryptedKey, - nonce: key.nonce, - sender: req.user._id, - receiver: key.userId, - workspace: workspaceId - }).save(); - - return res.status(200).send({ - message: "Successfully uploaded key to workspace" - }); -}; - -/** - * Return latest (encrypted) copy of workspace key for user - * @param req - * @param res - * @returns - */ -export const getLatestKey = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetLatestKeyV1, req); - - // get latest key - const latestKey = await Key.find({ - workspace: workspaceId, - receiver: req.user._id - }) - .sort({ createdAt: -1 }) - .limit(1) - .populate("sender", "+publicKey"); - - const resObj: any = {}; - - if (latestKey.length > 0) { - resObj["latestKey"] = latestKey[0]; - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.GET_WORKSPACE_KEY, - metadata: { - keyId: latestKey[0]._id.toString() - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - } - - return res.status(200).send(resObj); -}; diff --git a/backend-mongo/src/controllers/v1/membershipController.ts b/backend-mongo/src/controllers/v1/membershipController.ts deleted file mode 100644 index 350cddc5f..000000000 --- a/backend-mongo/src/controllers/v1/membershipController.ts +++ /dev/null @@ -1,286 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { IUser, Key, Membership, MembershipOrg, User, Workspace } from "../../models"; -import { EventType, Role } from "../../ee/models"; -import { deleteMembership as deleteMember, findMembership } from "../../helpers/membership"; -import { sendMail } from "../../helpers/nodemailer"; -import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables"; -import { getSiteURL } from "../../config"; -import { EEAuditLogService, EELicenseService } from "../../ee/services"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/membership"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; -import { BadRequestError } from "../../utils/errors"; -import { InviteUserToWorkspaceV1 } from "../../validation/workspace"; - -/** - * Check that user is a member of workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const validateMembership = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.ValidateMembershipV1, req); - - // validate membership - const membership = await findMembership({ - user: req.user._id, - workspace: workspaceId - }); - - if (!membership) { - throw new Error("Failed to validate membership"); - } - - return res.status(200).send({ - message: "Workspace membership confirmed" - }); -}; - -/** - * Delete membership with id [membershipId] - * @param req - * @param res - * @returns - */ -export const deleteMembership = async (req: Request, res: Response) => { - const { - params: { membershipId } - } = await validateRequest(reqValidator.DeleteMembershipV1, req); - - // check if membership to delete exists - const membershipToDelete = await Membership.findOne({ - _id: membershipId - }).populate<{ user: IUser }>("user"); - - if (!membershipToDelete) { - throw new Error("Failed to delete workspace membership that doesn't exist"); - } - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: membershipToDelete.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Member - ); - - // delete workspace membership - const deletedMembership = await deleteMember({ - membershipId: membershipToDelete._id.toString() - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.REMOVE_WORKSPACE_MEMBER, - metadata: { - userId: membershipToDelete.user._id.toString(), - email: membershipToDelete.user.email - } - }, - { - workspaceId: membershipToDelete.workspace - } - ); - - return res.status(200).send({ - deletedMembership - }); -}; - -/** - * Change and return workspace membership role - * @param req - * @param res - * @returns - */ -export const changeMembershipRole = async (req: Request, res: Response) => { - const { - body: { role }, - params: { membershipId } - } = await validateRequest(reqValidator.ChangeMembershipRoleV1, req); - - // validate target membership - const membershipToChangeRole = await Membership.findById(membershipId).populate<{ user: IUser }>( - "user" - ); - - if (!membershipToChangeRole) { - throw new Error("Failed to find membership to change role"); - } - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: membershipToChangeRole.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Member - ); - - const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role); - if (isCustomRole) { - const wsRole = await Role.findOne({ - slug: role, - isOrgRole: false, - workspace: membershipToChangeRole.workspace - }); - if (!wsRole) throw BadRequestError({ message: "Role not found" }); - - const plan = await EELicenseService.getPlan(wsRole.organization); - - if (!plan.rbac) return res.status(400).send({ - message: "Failed to assign custom role due to RBAC restriction. Upgrade plan to assign custom role to member." - }); - - const membership = await Membership.findByIdAndUpdate(membershipId, { - role: CUSTOM, - customRole: wsRole - }); - return res.status(200).send({ - membership - }); - } - - const membership = await Membership.findByIdAndUpdate( - membershipId, - { - $set: { - role - }, - $unset: { - customRole: 1 - } - }, - { - new: true - } - ); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_USER_WORKSPACE_ROLE, - metadata: { - userId: membershipToChangeRole.user._id.toString(), - email: membershipToChangeRole.user.email, - oldRole: membershipToChangeRole.role, - newRole: role - } - }, - { - workspaceId: membershipToChangeRole.workspace - } - ); - - return res.status(200).send({ - membership - }); -}; - -/** - * Add user with email [email] to workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const inviteUserToWorkspace = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - body: { email } - } = await validateRequest(InviteUserToWorkspaceV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Member - ); - - const invitee = await User.findOne({ - email - }).select("+publicKey"); - - if (!invitee || !invitee?.publicKey) throw new Error("Failed to validate invitee"); - - // validate invitee's workspace membership - ensure member isn't - // already a member of the workspace - const inviteeMembership = await Membership.findOne({ - user: invitee._id, - workspace: workspaceId - }).populate<{ user: IUser }>("user"); - - if (inviteeMembership) throw new Error("Failed to add existing member of workspace"); - - const workspace = await Workspace.findById(workspaceId); - if (!workspace) throw new Error("Failed to find workspace"); - // validate invitee's organization membership - ensure that only - // (accepted) organization members can be added to the workspace - const membershipOrg = await MembershipOrg.findOne({ - user: invitee._id, - organization: workspace.organization, - status: ACCEPTED - }); - - if (!membershipOrg) throw new Error("Failed to validate invitee's organization membership"); - - // get latest key - const latestKey = await Key.findOne({ - workspace: workspaceId, - receiver: req.user._id - }) - .sort({ createdAt: -1 }) - .populate("sender", "+publicKey"); - - // create new workspace membership - await new Membership({ - user: invitee._id, - workspace: workspaceId, - role: MEMBER - }).save(); - - await sendMail({ - template: "workspaceInvitation.handlebars", - subjectLine: "Infisical workspace invitation", - recipients: [invitee.email], - substitutions: { - inviterFirstName: req.user.firstName, - inviterEmail: req.user.email, - workspaceName: workspace.name, - callback_url: (await getSiteURL()) + "/login" - } - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.ADD_WORKSPACE_MEMBER, - metadata: { - userId: invitee._id.toString(), - email: invitee.email - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.status(200).send({ - invitee, - latestKey - }); -}; diff --git a/backend-mongo/src/controllers/v1/membershipOrgController.ts b/backend-mongo/src/controllers/v1/membershipOrgController.ts deleted file mode 100644 index f212892ee..000000000 --- a/backend-mongo/src/controllers/v1/membershipOrgController.ts +++ /dev/null @@ -1,292 +0,0 @@ -import { Types } from "mongoose"; -import { Request, Response } from "express"; -import { MembershipOrg, Organization, User } from "../../models"; -import { SSOConfig } from "../../ee/models"; -import { deleteMembershipOrg as deleteMemberFromOrg } from "../../helpers/membershipOrg"; -import { createToken } from "../../helpers/auth"; -import { updateSubscriptionOrgQuantity } from "../../helpers/organization"; -import { sendMail } from "../../helpers/nodemailer"; -import { TokenService } from "../../services"; -import { EELicenseService } from "../../ee/services"; -import { ACCEPTED, AuthTokenType, INVITED, MEMBER, TOKEN_EMAIL_ORG_INVITATION } from "../../variables"; -import * as reqValidator from "../../validation/membershipOrg"; -import { - getAuthSecret, - getJwtSignupLifetime, - getSiteURL, - getSmtpConfigured -} from "../../config"; -import { validateUserEmail } from "../../validation"; -import { validateRequest } from "../../helpers/validation"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions -} from "../../ee/services/RoleService"; -import { ForbiddenError } from "@casl/ability"; - -/** - * Delete organization membership with id [membershipOrgId] from organization - * @param req - * @param res - * @returns - */ -export const deleteMembershipOrg = async (req: Request, _res: Response) => { - const { - params: { membershipOrgId } - } = await validateRequest(reqValidator.DelOrgMembershipv1, req); - - // check if organization membership to delete exists - const membershipOrgToDelete = await MembershipOrg.findOne({ - _id: membershipOrgId - }).populate("user"); - - if (!membershipOrgToDelete) { - throw new Error("Failed to delete organization membership that doesn't exist"); - } - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: membershipOrgToDelete.organization - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Delete, - OrgPermissionSubjects.Member - ); - - // delete organization membership - await deleteMemberFromOrg({ - membershipOrgId: membershipOrgToDelete._id.toString() - }); - - await updateSubscriptionOrgQuantity({ - organizationId: membershipOrgToDelete.organization.toString() - }); - - return membershipOrgToDelete; -}; - -/** - * Change and return organization membership role - * @param req - * @param res - * @returns - */ -export const changeMembershipOrgRole = async (req: Request, res: Response) => { - // change role for (target) organization membership with id - // [membershipOrgId] - - let membershipToChangeRole; - - return res.status(200).send({ - membershipOrg: membershipToChangeRole - }); -}; - -/** - * Organization invitation step 1: Send email invitation to user with email [email] - * for organization with id [organizationId] containing magic link - * @param req - * @param res - * @returns - */ -export const inviteUserToOrganization = async (req: Request, res: Response) => { - let inviteeMembershipOrg, completeInviteLink; - const { - body: { inviteeEmail, organizationId } - } = await validateRequest(reqValidator.InviteUserToOrgv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Member - ); - - const host = req.headers.host; - const siteUrl = `${req.protocol}://${host}`; - const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId)); - - const ssoConfig = await SSOConfig.findOne({ - organization: new Types.ObjectId(organizationId) - }); - - if (ssoConfig && ssoConfig.isActive) { - // case: SAML SSO is enabled for the organization - return res.status(400).send({ - message: "Failed to invite member due to SAML SSO configured for organization" - }); - } - - if (plan.memberLimit !== null) { - // case: limit imposed on number of members allowed - - if (plan.membersUsed >= plan.memberLimit) { - // case: number of members used exceeds the number of members allowed - return res.status(400).send({ - message: - "Failed to invite member due to member limit reached. Upgrade plan to invite more members." - }); - } - } - - const invitee = await User.findOne({ - email: inviteeEmail - }).select("+publicKey"); - - if (invitee) { - // case: invitee is an existing user - - inviteeMembershipOrg = await MembershipOrg.findOne({ - user: invitee._id, - organization: organizationId - }); - - if (inviteeMembershipOrg && inviteeMembershipOrg.status === ACCEPTED) { - throw new Error("Failed to invite an existing member of the organization"); - } - - if (!inviteeMembershipOrg) { - await new MembershipOrg({ - user: invitee, - inviteEmail: inviteeEmail, - organization: organizationId, - role: MEMBER, - status: INVITED - }).save(); - } - } else { - // check if invitee has been invited before - inviteeMembershipOrg = await MembershipOrg.findOne({ - inviteEmail: inviteeEmail, - organization: organizationId - }); - - if (!inviteeMembershipOrg) { - // case: invitee has never been invited before - - // validate that email is not disposable - validateUserEmail(inviteeEmail); - - await new MembershipOrg({ - inviteEmail: inviteeEmail, - organization: organizationId, - role: MEMBER, - status: INVITED - }).save(); - } - } - - const organization = await Organization.findOne({ _id: organizationId }); - - if (organization) { - const token = await TokenService.createToken({ - type: TOKEN_EMAIL_ORG_INVITATION, - email: inviteeEmail, - organizationId: organization._id - }); - - await sendMail({ - template: "organizationInvitation.handlebars", - subjectLine: "Infisical organization invitation", - recipients: [inviteeEmail], - substitutions: { - inviterFirstName: req.user.firstName, - inviterEmail: req.user.email, - organizationName: organization.name, - email: inviteeEmail, - organizationId: organization._id.toString(), - token, - callback_url: (await getSiteURL()) + "/signupinvite" - } - }); - - if (!(await getSmtpConfigured())) { - completeInviteLink = `${ - siteUrl + "/signupinvite" - }?token=${token}&to=${inviteeEmail}&organization_id=${organization._id}`; - } - } - - await updateSubscriptionOrgQuantity({ organizationId }); - - return res.status(200).send({ - message: `Sent an invite link to ${req.body.inviteeEmail}`, - completeInviteLink - }); -}; - -/** - * Organization invitation step 2: Verify that code [code] was sent to email [email] as part of - * magic link and issue a temporary signup token for user to complete setting up their account - * @param req - * @param res - * @returns - */ -export const verifyUserToOrganization = async (req: Request, res: Response) => { - let user; - - const { - body: { organizationId, email, code } - } = await validateRequest(reqValidator.VerifyUserToOrgv1, req); - - user = await User.findOne({ email }).select("+publicKey"); - - const membershipOrg = await MembershipOrg.findOne({ - inviteEmail: email, - status: INVITED, - organization: new Types.ObjectId(organizationId) - }); - - if (!membershipOrg) throw new Error("Failed to find any invitations for email"); - - await TokenService.validateToken({ - type: TOKEN_EMAIL_ORG_INVITATION, - email, - organizationId: membershipOrg.organization, - token: code - }); - - if (user && user?.publicKey) { - // case: user has already completed account - // membership can be approved and redirected to login/dashboard - membershipOrg.status = ACCEPTED; - await membershipOrg.save(); - - await updateSubscriptionOrgQuantity({ - organizationId - }); - - return res.status(200).send({ - message: "Successfully verified email", - user - }); - } - - if (!user) { - // initialize user account - user = await new User({ - email - }).save(); - } - - // generate temporary signup token - const token = createToken({ - payload: { - authTokenType: AuthTokenType.SIGNUP_TOKEN, - userId: user._id.toString() - }, - expiresIn: await getJwtSignupLifetime(), - secret: await getAuthSecret() - }); - - return res.status(200).send({ - message: "Successfully verified email", - user, - token - }); -}; diff --git a/backend-mongo/src/controllers/v1/organizationController.ts b/backend-mongo/src/controllers/v1/organizationController.ts deleted file mode 100644 index 676cb5572..000000000 --- a/backend-mongo/src/controllers/v1/organizationController.ts +++ /dev/null @@ -1,387 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { - IncidentContactOrg, - Membership, - MembershipOrg, - Organization, - Workspace -} from "../../models"; -import { getLicenseServerUrl, getSiteURL } from "../../config"; -import { licenseServerKeyRequest } from "../../config/request"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/organization"; -import { ACCEPTED } from "../../variables"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions -} from "../../ee/services/RoleService"; -import { OrganizationNotFoundError } from "../../utils/errors"; -import { ForbiddenError } from "@casl/ability"; - -export const getOrganizations = async (req: Request, res: Response) => { - const organizations = ( - await MembershipOrg.find({ - user: req.user._id, - status: ACCEPTED - }).populate("organization") - ).map((m) => m.organization); - - return res.status(200).send({ - organizations - }); -}; - -/** - * Return organization with id [organizationId] - * @param req - * @param res - * @returns - */ -export const getOrganization = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgv1, req); - - // ensure user has membership - await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }) - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - return res.status(200).send({ - organization - }); -}; - -/** - * Return organization memberships for organization with id [organizationId] - * @param req - * @param res - * @returns - */ -export const getOrganizationMembers = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgMembersv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Member - ); - - const users = await MembershipOrg.find({ - organization: organizationId - }).populate("user", "+publicKey"); - - return res.status(200).send({ - users - }); -}; - -/** - * Return workspaces that user is part of in organization with id [organizationId] - * @param req - * @param res - * @returns - */ -export const getOrganizationWorkspaces = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgWorkspacesv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }) - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Workspace - ); - - const workspacesSet = new Set( - ( - await Workspace.find( - { - organization: organizationId - }, - "_id" - ) - ).map((w) => w._id.toString()) - ); - - const workspaces = ( - await Membership.find({ - user: req.user._id - }).populate("workspace") - ) - .filter((m) => workspacesSet.has(m.workspace._id.toString())) - .map((m) => m.workspace); - - return res.status(200).send({ - workspaces - }); -}; - -/** - * Change name of organization with id [organizationId] to [name] - * @param req - * @param res - * @returns - */ -export const changeOrganizationName = async (req: Request, res: Response) => { - const { - params: { organizationId }, - body: { name } - } = await validateRequest(reqValidator.ChangeOrgNamev1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.Settings - ); - - const organization = await Organization.findOneAndUpdate( - { - _id: organizationId - }, - { - name - }, - { - new: true - } - ); - - return res.status(200).send({ - message: "Successfully changed organization name", - organization - }); -}; - -/** - * Return incident contacts of organization with id [organizationId] - * @param req - * @param res - * @returns - */ -export const getOrganizationIncidentContacts = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgIncidentContactv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.IncidentAccount - ); - - const incidentContactsOrg = await IncidentContactOrg.find({ - organization: organizationId - }); - - return res.status(200).send({ - incidentContactsOrg - }); -}; - -/** - * Add and return new incident contact with email [email] for organization with id [organizationId] - * @param req - * @param res - * @returns - */ -export const addOrganizationIncidentContact = async (req: Request, res: Response) => { - const { - params: { organizationId }, - body: { email } - } = await validateRequest(reqValidator.CreateOrgIncideContact, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.IncidentAccount - ); - - const incidentContactOrg = await IncidentContactOrg.findOneAndUpdate( - { email, organization: organizationId }, - { email, organization: organizationId }, - { upsert: true, new: true } - ); - - return res.status(200).send({ - incidentContactOrg - }); -}; - -/** - * Delete incident contact with email [email] for organization with id [organizationId] - * @param req - * @param res - * @returns - */ -export const deleteOrganizationIncidentContact = async (req: Request, res: Response) => { - const { - params: { organizationId }, - body: { email } - } = await validateRequest(reqValidator.DelOrgIncideContact, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Delete, - OrgPermissionSubjects.IncidentAccount - ); - - const incidentContactOrg = await IncidentContactOrg.findOneAndDelete({ - email, - organization: organizationId - }); - - return res.status(200).send({ - message: "Successfully deleted organization incident contact", - incidentContactOrg - }); -}; - -/** - * Redirect user to billing portal or add card page depending on - * if there is a card on file - * @param req - * @param res - * @returns - */ -export const createOrganizationPortalSession = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgPlanBillingInfov1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { - data: { pmtMethods } - } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/payment-methods` - ); - - if (pmtMethods.length < 1) { - // case: organization has no payment method on file - // -> redirect to add payment method portal - const { - data: { url } - } = await licenseServerKeyRequest.post( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/payment-methods`, - { - success_url: (await getSiteURL()) + "/dashboard", - cancel_url: (await getSiteURL()) + "/dashboard" - } - ); - return res.status(200).send({ url }); - } else { - // case: organization has payment method on file - // -> redirect to billing portal - const { - data: { url } - } = await licenseServerKeyRequest.post( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/billing-portal`, - { - return_url: (await getSiteURL()) + "/dashboard" - } - ); - return res.status(200).send({ url }); - } -}; - -/** - * Given a org id, return the projects each member of the org belongs to - * @param req - * @param res - * @returns - */ -export const getOrganizationMembersAndTheirWorkspaces = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgMembersv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Member - ); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Workspace - ); - - const workspacesSet = ( - await Workspace.find( - { - organization: organizationId - }, - "_id" - ) - ).map((w) => w._id.toString()); - - const memberships = await Membership.find({ - workspace: { $in: workspacesSet } - }).populate("workspace"); - const userToWorkspaceIds: any = {}; - - memberships.forEach((membership) => { - const user = membership.user.toString(); - if (userToWorkspaceIds[user]) { - userToWorkspaceIds[user].push(membership.workspace); - } else { - userToWorkspaceIds[user] = [membership.workspace]; - } - }); - - return res.json(userToWorkspaceIds); -}; diff --git a/backend-mongo/src/controllers/v1/passwordController.ts b/backend-mongo/src/controllers/v1/passwordController.ts deleted file mode 100644 index d0b59f317..000000000 --- a/backend-mongo/src/controllers/v1/passwordController.ts +++ /dev/null @@ -1,370 +0,0 @@ -import { Request, Response } from "express"; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const jsrp = require("jsrp"); -import * as bigintConversion from "bigint-conversion"; -import { BackupPrivateKey, LoginSRPDetail, User } from "../../models"; -import { clearTokens, createToken, sendMail } from "../../helpers"; -import { TokenService } from "../../services"; -import { AuthTokenType, TOKEN_EMAIL_PASSWORD_RESET } from "../../variables"; -import { BadRequestError } from "../../utils/errors"; -import { - getAuthSecret, - getHttpsEnabled, - getJwtSignupLifetime, - getSiteURL -} from "../../config"; -import { ActorType } from "../../ee/models"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/auth"; - -/** - * Password reset step 1: Send email verification link to email [email] - * for account recovery. - * @param req - * @param res - * @returns - */ -export const emailPasswordReset = async (req: Request, res: Response) => { - const { - body: { email } - } = await validateRequest(reqValidator.EmailPasswordResetV1, req); - - const user = await User.findOne({ email }).select("+publicKey"); - if (!user || !user?.publicKey) { - // case: user has already completed account - - return res.status(200).send({ - message: "If an account exists with this email, a password reset link has been sent" - }); - } - - const token = await TokenService.createToken({ - type: TOKEN_EMAIL_PASSWORD_RESET, - email - }); - - await sendMail({ - template: "passwordReset.handlebars", - subjectLine: "Infisical password reset", - recipients: [email], - substitutions: { - email, - token, - callback_url: (await getSiteURL()) + "/password-reset" - } - }); - - return res.status(200).send({ - message: "If an account exists with this email, a password reset link has been sent" - }); -}; - -/** - * Password reset step 2: Verify email verification link sent to email [email] - * @param req - * @param res - * @returns - */ -export const emailPasswordResetVerify = async (req: Request, res: Response) => { - const { - body: { email, code } - } = await validateRequest(reqValidator.EmailPasswordResetVerifyV1, req); - - const user = await User.findOne({ email }).select("+publicKey"); - if (!user || !user?.publicKey) { - // case: user doesn't exist with email [email] or - // hasn't even completed their account - return res.status(403).send({ - error: "Failed email verification for password reset" - }); - } - - await TokenService.validateToken({ - type: TOKEN_EMAIL_PASSWORD_RESET, - email, - token: code - }); - - // generate temporary password-reset token - const token = createToken({ - payload: { - authTokenType: AuthTokenType.SIGNUP_TOKEN, - userId: user._id.toString() - }, - expiresIn: await getJwtSignupLifetime(), - secret: await getAuthSecret() - }); - - return res.status(200).send({ - message: "Successfully verified email", - user, - token - }); -}; - -/** - * Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol - * @param req - * @param res - * @returns - */ -export const srp1 = async (req: Request, res: Response) => { - // return salt, serverPublicKey as part of first step of SRP protocol - const { - body: { clientPublicKey } - } = await validateRequest(reqValidator.Srp1V1, req); - - const user = await User.findOne({ - email: req.user.email - }).select("+salt +verifier"); - - if (!user) throw new Error("Failed to find user"); - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier - }, - async () => { - // generate server-side public key - const serverPublicKey = server.getPublicKey(); - - await LoginSRPDetail.findOneAndReplace( - { email: req.user.email }, - { - email: req.user.email, - clientPublicKey: clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt) - }, - { upsert: true, returnNewDocument: false } - ); - - return res.status(200).send({ - serverPublicKey, - salt: user.salt - }); - } - ); -}; - -/** - * Change account SRP authentication information for user - * Requires verifying [clientProof] as part of step 2 of SRP protocol - * as initiated in POST /srp1 - * @param req - * @param res - * @returns - */ -export const changePassword = async (req: Request, res: Response) => { - const { - body: { - clientProof, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - } - } = await validateRequest(reqValidator.ChangePasswordV1, req); - - const user = await User.findOne({ - email: req.user.email - }).select("+salt +verifier"); - - if (!user) throw new Error("Failed to find user"); - - const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email }); - - if (!loginSRPDetailFromDB) { - return BadRequestError( - Error( - "It looks like some details from the first login are not found. Please try login one again" - ) - ); - } - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetailFromDB.serverBInt - }, - async () => { - server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey); - - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - // change password - - await User.findByIdAndUpdate( - req.user._id.toString(), - { - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag, - salt, - verifier - }, - { - new: true - } - ); - - if (req.authData.actor.type === ActorType.USER && req.authData.tokenVersionId) { - await clearTokens(req.authData.tokenVersionId); - } - - // clear httpOnly cookie - - res.cookie("jid", "", { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: (await getHttpsEnabled()) as boolean - }); - - return res.status(200).send({ - message: "Successfully changed password" - }); - } - - return res.status(400).send({ - error: "Failed to change password. Try again?" - }); - } - ); -}; - -/** - * Create or change backup private key for user - * @param req - * @param res - * @returns - */ -export const createBackupPrivateKey = async (req: Request, res: Response) => { - // create/change backup private key - // requires verifying [clientProof] as part of second step of SRP protocol - // as initiated in /srp1 - const { - body: { clientProof, encryptedPrivateKey, salt, verifier, iv, tag } - } = await validateRequest(reqValidator.CreateBackupPrivateKeyV1, req); - const user = await User.findOne({ - email: req.user.email - }).select("+salt +verifier"); - - if (!user) throw new Error("Failed to find user"); - - const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email }); - - if (!loginSRPDetailFromDB) { - return BadRequestError( - Error( - "It looks like some details from the first login are not found. Please try login one again" - ) - ); - } - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetailFromDB.serverBInt - }, - async () => { - server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey); - - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - // create new or replace backup private key - - const backupPrivateKey = await BackupPrivateKey.findOneAndUpdate( - { user: req.user._id }, - { - user: req.user._id, - encryptedPrivateKey, - iv, - tag, - salt, - verifier - }, - { upsert: true, new: true } - ).select("+user, encryptedPrivateKey"); - - // issue tokens - return res.status(200).send({ - message: "Successfully updated backup private key", - backupPrivateKey - }); - } - - return res.status(400).send({ - message: "Failed to update backup private key" - }); - } - ); -}; - -/** - * Return backup private key for user - * @param req - * @param res - * @returns - */ -export const getBackupPrivateKey = async (req: Request, res: Response) => { - const backupPrivateKey = await BackupPrivateKey.findOne({ - user: req.user._id - }).select("+encryptedPrivateKey +iv +tag"); - - if (!backupPrivateKey) throw new Error("Failed to find backup private key"); - - return res.status(200).send({ - backupPrivateKey - }); -}; - -export const resetPassword = async (req: Request, res: Response) => { - const { - body: { - encryptedPrivateKey, - protectedKeyTag, - protectedKey, - protectedKeyIV, - salt, - verifier, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag - } - } = await validateRequest(reqValidator.ResetPasswordV1, req); - - await User.findByIdAndUpdate( - req.user._id.toString(), - { - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag, - salt, - verifier - }, - { - new: true - } - ); - - return res.status(200).send({ - message: "Successfully reset password" - }); -}; diff --git a/backend-mongo/src/controllers/v1/secretController.ts b/backend-mongo/src/controllers/v1/secretController.ts deleted file mode 100644 index cda7b5576..000000000 --- a/backend-mongo/src/controllers/v1/secretController.ts +++ /dev/null @@ -1,209 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { Key } from "../../models"; -import { - pullSecrets as pull, - v1PushSecrets as push, - reformatPullSecrets -} from "../../helpers/secret"; -import { pushKeys } from "../../helpers/key"; -import { eventPushSecrets } from "../../events"; -import { EventService } from "../../services"; -import { TelemetryService } from "../../services"; - -interface PushSecret { - ciphertextKey: string; - ivKey: string; - tagKey: string; - hashKey: string; - ciphertextValue: string; - ivValue: string; - tagValue: string; - hashValue: string; - ciphertextComment: string; - ivComment: string; - tagComment: string; - hashComment: string; - type: "shared" | "personal"; -} - -/** - * Upload (encrypted) secrets to workspace with id [workspaceId] - * for environment [environment] - * @param req - * @param res - * @returns - */ -export const pushSecrets = async (req: Request, res: Response) => { - // upload (encrypted) secrets to workspace with id [workspaceId] - const postHogClient = await TelemetryService.getPostHogClient(); - let { secrets }: { secrets: PushSecret[] } = req.body; - const { keys, environment, channel } = req.body; - const { workspaceId } = req.params; - - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error("Failed to validate environment"); - } - - // sanitize secrets - secrets = secrets.filter((s: PushSecret) => s.ciphertextKey !== "" && s.ciphertextValue !== ""); - - await push({ - userId: req.user._id, - workspaceId, - environment, - secrets - }); - - await pushKeys({ - userId: req.user._id, - workspaceId, - keys - }); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets pushed", - distinctId: req.user.email, - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : "cli" - } - }); - } - - // trigger event - push secrets - EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath: "/" - }) - }); - - return res.status(200).send({ - message: "Successfully uploaded workspace secrets" - }); -}; - -/** - * Return (encrypted) secrets for workspace with id [workspaceId] - * for environment [environment] and (encrypted) workspace key - * @param req - * @param res - * @returns - */ -export const pullSecrets = async (req: Request, res: Response) => { - let secrets; - - const postHogClient = await TelemetryService.getPostHogClient(); - const environment: string = req.query.environment as string; - const channel: string = req.query.channel as string; - const { workspaceId } = req.params; - - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error("Failed to validate environment"); - } - - secrets = await pull({ - userId: req.user._id.toString(), - workspaceId, - environment, - channel: channel ? channel : "cli", - ipAddress: req.realIP - }); - - const key = await Key.findOne({ - workspace: workspaceId, - receiver: req.user._id - }) - .sort({ createdAt: -1 }) - .populate("sender", "+publicKey"); - - if (channel !== "cli") { - secrets = reformatPullSecrets({ secrets }); - } - - if (postHogClient) { - // capture secrets pushed event in production - postHogClient.capture({ - distinctId: req.user.email, - event: "secrets pulled", - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : "cli" - } - }); - } - - return res.status(200).send({ - secrets, - key - }); -}; - -/** - * Return (encrypted) secrets for workspace with id [workspaceId] - * for environment [environment] and (encrypted) workspace key - * via service token - * @param req - * @param res - * @returns - */ -export const pullSecretsServiceToken = async (req: Request, res: Response) => { - const postHogClient = await TelemetryService.getPostHogClient(); - const environment: string = req.query.environment as string; - const channel: string = req.query.channel as string; - const { workspaceId } = req.params; - - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error("Failed to validate environment"); - } - - const secrets = await pull({ - userId: req.serviceToken.user._id.toString(), - workspaceId, - environment, - channel: "cli", - ipAddress: req.realIP - }); - - const key = { - encryptedKey: req.serviceToken.encryptedKey, - nonce: req.serviceToken.nonce, - sender: { - publicKey: req.serviceToken.publicKey - }, - receiver: req.serviceToken.user, - workspace: req.serviceToken.workspace - }; - - if (postHogClient) { - // capture secrets pulled event in production - postHogClient.capture({ - distinctId: req.serviceToken.user.email, - event: "secrets pulled", - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : "cli" - } - }); - } - - return res.status(200).send({ - secrets: reformatPullSecrets({ secrets }), - key - }); -}; diff --git a/backend-mongo/src/controllers/v1/secretImpsController.ts b/backend-mongo/src/controllers/v1/secretImpsController.ts deleted file mode 100644 index 5db7a2f0a..000000000 --- a/backend-mongo/src/controllers/v1/secretImpsController.ts +++ /dev/null @@ -1,734 +0,0 @@ - -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { isValidScope } from "../../helpers"; -import { Folder, IServiceTokenData, SecretImport, ServiceTokenData } from "../../models"; -import { getAllImportedSecrets } from "../../services/SecretImportService"; -import { getFolderByPath, getFolderWithPathFromId } from "../../services/FolderService"; -import { - BadRequestError, - ResourceNotFoundError, - UnauthorizedRequestError -} from "../../utils/errors"; -import { EEAuditLogService } from "../../ee/services"; -import { EventType } from "../../ee/models"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/secretImports"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError, subject } from "@casl/ability"; - -export const createSecretImp = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Create secret import' - #swagger.description = 'Create secret import' - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of workspace where to create secret import", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to create secret import", - "example": "dev" - }, - "directory": { - "type": "string", - "description": "Path where to create secret import like / or /foo/bar. Default is /", - "example": "/foo/bar" - }, - "secretImport": { - "type": "object", - "properties": { - "environment": { - "type": "string", - "description": "Slug of environment to import from", - "example": "development" - }, - "secretPath": { - "type": "string", - "description": "Path where to import from like / or /foo/bar.", - "example": "/user/oauth" - } - } - } - }, - "required": ["workspaceId", "environment", "directory", "secretImport"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "example": "successfully created secret import" - } - }, - "description": "Confirmation of secret import creation" - } - } - } - } - #swagger.responses[400] = { - description: "Bad Request. For example, 'Secret import already exist'" - } - #swagger.responses[401] = { - description: "Unauthorized request. For example, 'Folder Permission Denied'" - } - #swagger.responses[404] = { - description: "Resource Not Found. For example, 'Failed to find folder'" - } - */ - - const { - body: { workspaceId, environment, directory, secretImport } - } = await validateRequest(reqValidator.CreateSecretImportV1, req); - - if (req.authData.authPayload instanceof ServiceTokenData) { - // root check - const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory }) - ); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - subject(ProjectPermissionSub.Secrets, { environment: secretImport.environment, secretPath: secretImport.secretPath }) - ); - - } - - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }).lean(); - - if (!folders && directory !== "/") - throw ResourceNotFoundError({ message: "Failed to find folder" }); - - let folderId = "root"; - if (folders) { - const folder = getFolderByPath(folders.nodes, directory); - if (!folder) throw BadRequestError({ message: "Folder not found" }); - folderId = folder.id; - } - - const importSecDoc = await SecretImport.findOne({ - workspace: workspaceId, - environment, - folderId - }); - - if (!importSecDoc) { - const doc = new SecretImport({ - workspace: workspaceId, - environment, - folderId, - imports: [{ environment: secretImport.environment, secretPath: secretImport.secretPath }] - }); - - await doc.save(); - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_SECRET_IMPORT, - metadata: { - secretImportId: doc._id.toString(), - folderId: doc.folderId.toString(), - importFromEnvironment: secretImport.environment, - importFromSecretPath: secretImport.secretPath, - importToEnvironment: environment, - importToSecretPath: directory - } - }, - { - workspaceId: doc.workspace - } - ); - return res.status(200).json({ message: "successfully created secret import" }); - } - - const doesImportExist = importSecDoc.imports.find( - (el) => el.environment === secretImport.environment && el.secretPath === secretImport.secretPath - ); - if (doesImportExist) { - throw BadRequestError({ message: "Secret import already exist" }); - } - - importSecDoc.imports.push({ - environment: secretImport.environment, - secretPath: secretImport.secretPath - }); - await importSecDoc.save(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_SECRET_IMPORT, - metadata: { - secretImportId: importSecDoc._id.toString(), - folderId: importSecDoc.folderId.toString(), - importFromEnvironment: secretImport.environment, - importFromSecretPath: secretImport.secretPath, - importToEnvironment: environment, - importToSecretPath: directory - } - }, - { - workspaceId: importSecDoc.workspace - } - ); - return res.status(200).json({ message: "successfully created secret import" }); -}; - -// to keep the ordering, you must pass all the imports in here not the only updated one -// this is because the order decide which import gets overriden - -/** - * Update secret import - * @param req - * @param res - * @returns - */ -export const updateSecretImport = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update secret import' - #swagger.description = 'Update secret import' - - #swagger.parameters['id'] = { - in: 'path', - description: 'ID of secret import to update', - required: true, - type: 'string', - example: 'import12345' - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretImports": { - "type": "array", - "description": "List of secret imports to update to", - "items": { - "type": "object", - "properties": { - "environment": { - "type": "string", - "description": "Slug of environment to import from", - "example": "dev" - }, - "secretPath": { - "type": "string", - "description": "Path where to import secrets from like / or /foo/bar", - "example": "/foo/bar" - } - }, - "required": ["environment", "secretPath"] - } - } - }, - "required": ["secretImports"] - } - } - } - } - - #swagger.responses[200] = { - description: 'Successfully updated the secret import', - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "example": "successfully updated secret import" - } - } - } - } - } - } - - #swagger.responses[400] = { - description: 'Bad Request - Import not found', - } - - #swagger.responses[403] = { - description: 'Forbidden access due to insufficient permissions', - } - - #swagger.responses[401] = { - description: 'Unauthorized access due to invalid token or scope', - } - */ - const { - body: { secretImports }, - params: { id } - } = await validateRequest(reqValidator.UpdateSecretImportV1, req); - - const importSecDoc = await SecretImport.findById(id); - if (!importSecDoc) { - throw BadRequestError({ message: "Import not found" }); - } - - // check for service token validity - const folders = await Folder.findOne({ - workspace: importSecDoc.workspace, - environment: importSecDoc.environment - }).lean(); - - let secretPath = "/"; - if (folders) { - const { folderPath } = getFolderWithPathFromId(folders.nodes, importSecDoc.folderId); - secretPath = folderPath; - } - - if (req.authData.authPayload instanceof ServiceTokenData) { - // token permission check - const isValidScopeAccess = isValidScope( - req.authData.authPayload, - importSecDoc.environment, - secretPath - ); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - // non token entry check - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: importSecDoc.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - subject(ProjectPermissionSub.Secrets, { - environment: importSecDoc.environment, - secretPath - }) - ); - - secretImports.forEach(({ environment, secretPath }) => { - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - subject(ProjectPermissionSub.Secrets, { environment, secretPath }) - ); - }) - } - - const orderBefore = importSecDoc.imports; - importSecDoc.imports = secretImports; - - await importSecDoc.save(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_SECRET_IMPORT, - metadata: { - importToEnvironment: importSecDoc.environment, - importToSecretPath: secretPath, - secretImportId: importSecDoc._id.toString(), - folderId: importSecDoc.folderId.toString(), - orderBefore, - orderAfter: secretImports - } - }, - { - workspaceId: importSecDoc.workspace - } - ); - return res.status(200).json({ message: "successfully updated secret import" }); -}; - -/** - * Delete secret import - * @param req - * @param res - * @returns - */ -export const deleteSecretImport = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete secret import' - #swagger.description = 'Delete secret import' - - #swagger.parameters['id'] = { - in: 'path', - description: 'ID of parent secret import document from which to delete secret import', - required: true, - type: 'string', - example: '12345abcde' - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretImportEnv": { - "type": "string", - "description": "Slug of environment of import to delete", - "example": "someWorkspaceId" - }, - "secretImportPath": { - "type": "string", - "description": "Path like / or /foo/bar of import to delete", - "example": "production" - } - }, - "required": ["id", "secretImportEnv", "secretImportPath"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "example": "successfully delete secret import" - } - }, - "description": "Confirmation of secret import deletion" - } - } - } - } - */ - const { - params: { id }, - body: { secretImportEnv, secretImportPath } - } = await validateRequest(reqValidator.DeleteSecretImportV1, req); - - const importSecDoc = await SecretImport.findById(id); - if (!importSecDoc) { - throw BadRequestError({ message: "Import not found" }); - } - - // check for service token validity - const folders = await Folder.findOne({ - workspace: importSecDoc.workspace, - environment: importSecDoc.environment - }).lean(); - - let secretPath = "/"; - if (folders) { - const { folderPath } = getFolderWithPathFromId(folders.nodes, importSecDoc.folderId); - secretPath = folderPath; - } - - if (req.authData.authPayload instanceof ServiceTokenData) { - const isValidScopeAccess = isValidScope( - req.authData.authPayload, - importSecDoc.environment, - secretPath - ); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: importSecDoc.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - subject(ProjectPermissionSub.Secrets, { - environment: importSecDoc.environment, - secretPath - }) - ); - } - importSecDoc.imports = importSecDoc.imports.filter( - ({ environment, secretPath }) => - !(environment === secretImportEnv && secretPath === secretImportPath) - ); - await importSecDoc.save(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_SECRET_IMPORT, - metadata: { - secretImportId: importSecDoc._id.toString(), - folderId: importSecDoc.folderId.toString(), - importFromEnvironment: secretImportEnv, - importFromSecretPath: secretImportPath, - importToEnvironment: importSecDoc.environment, - importToSecretPath: secretPath - } - }, - { - workspaceId: importSecDoc.workspace - } - ); - - return res.status(200).json({ message: "successfully delete secret import" }); -}; - -/** - * Get secret imports - * @param req - * @param res - * @returns - */ -export const getSecretImports = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Get secret imports' - #swagger.description = 'Get secret imports' - - #swagger.parameters['workspaceId'] = { - in: 'query', - description: 'ID of workspace where to get secret imports from', - required: true, - type: 'string', - example: 'workspace12345' - } - - #swagger.parameters['environment'] = { - in: 'query', - description: 'Slug of environment where to get secret imports from', - required: true, - type: 'string', - example: 'production' - } - - #swagger.parameters['directory'] = { - in: 'query', - description: 'Path where to get secret imports from like / or /foo/bar. Default is /', - required: false, - type: 'string', - example: 'folder12345' - } - - #swagger.responses[200] = { - description: 'Successfully retrieved secret import', - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretImport": { - $ref: '#/definitions/SecretImport' - } - } - } - } - } - } - - #swagger.responses[403] = { - description: 'Forbidden access due to insufficient permissions', - } - - #swagger.responses[401] = { - description: 'Unauthorized access due to invalid token or scope', - } - */ - const { - query: { workspaceId, environment, directory } - } = await validateRequest(reqValidator.GetSecretImportsV1, req); - - if (req.authData.authPayload instanceof ServiceTokenData) { - const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - subject(ProjectPermissionSub.Secrets, { - environment, - secretPath: directory - }) - ); - } - - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }).lean(); - if (!folders && directory !== "/") throw BadRequestError({ message: "Folder not found" }); - - let folderId = "root"; - if (folders) { - const folder = getFolderByPath(folders.nodes, directory); - if (!folder) throw BadRequestError({ message: "Folder not found" }); - folderId = folder.id; - } - - const importSecDoc = await SecretImport.findOne({ - workspace: workspaceId, - environment, - folderId - }); - - if (!importSecDoc) { - return res.status(200).json({ secretImport: {} }); - } - - return res.status(200).json({ secretImport: importSecDoc }); -}; - -/** - * Get all secret imports - * @param req - * @param res - * @returns - */ -export const getAllSecretsFromImport = async (req: Request, res: Response) => { - const { - query: { workspaceId, environment, directory } - } = await validateRequest(reqValidator.GetAllSecretsFromImportV1, req); - - if (req.authData.authPayload instanceof ServiceTokenData) { - // check for service token validity - const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - subject(ProjectPermissionSub.Secrets, { - environment, - secretPath: directory - }) - ); - } - - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }).lean(); - if (!folders && directory !== "/") throw BadRequestError({ message: "Folder not found" }); - - let folderId = "root"; - if (folders) { - const folder = getFolderByPath(folders.nodes, directory); - if (!folder) throw BadRequestError({ message: "Folder not found" }); - folderId = folder.id; - } - - const importSecDoc = await SecretImport.findOne({ - workspace: workspaceId, - environment, - folderId - }); - - if (!importSecDoc) { - return res.status(200).json({ secrets: [] }); - } - - let secretPath = "/"; - if (folders) { - const { folderPath } = getFolderWithPathFromId(folders.nodes, importSecDoc.folderId); - secretPath = folderPath; - } - - let permissionCheckFn: (env: string, secPath: string) => boolean; // used to pass as callback function to import secret - if (req.authData.authPayload instanceof ServiceTokenData) { - // check for service token validity - const isValidScopeAccess = isValidScope( - req.authData.authPayload, - importSecDoc.environment, - secretPath - ); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - permissionCheckFn = (env: string, secPath: string) => - isValidScope(req.authData.authPayload as IServiceTokenData, env, secPath); - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: importSecDoc.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - subject(ProjectPermissionSub.Secrets, { - environment: importSecDoc.environment, - secretPath - }) - ); - permissionCheckFn = (env: string, secPath: string) => - permission.can( - ProjectPermissionActions.Read, - subject(ProjectPermissionSub.Secrets, { - environment: env, - secretPath: secPath - }) - ); - } - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.GET_SECRET_IMPORTS, - metadata: { - environment, - secretImportId: importSecDoc._id.toString(), - folderId, - numberOfImports: importSecDoc.imports.length - } - }, - { - workspaceId: importSecDoc.workspace - } - ); - - const secrets = await getAllImportedSecrets( - workspaceId, - environment, - folderId, - permissionCheckFn - ); - return res.status(200).json({ secrets }); -}; diff --git a/backend-mongo/src/controllers/v1/secretScanningController.ts b/backend-mongo/src/controllers/v1/secretScanningController.ts deleted file mode 100644 index 292ce94b3..000000000 --- a/backend-mongo/src/controllers/v1/secretScanningController.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { Request, Response } from "express"; -import { - GitAppInstallationSession, - GitAppOrganizationInstallation, - GitRisks -} from "../../ee/models"; -import crypto from "crypto"; -import { Types } from "mongoose"; -import { OrganizationNotFoundError, UnauthorizedRequestError } from "../../utils/errors"; -import { scanGithubFullRepoForSecretLeaks } from "../../queues/secret-scanning/githubScanFullRepository"; -import { getSecretScanningGitAppId, getSecretScanningPrivateKey } from "../../config"; -import { - STATUS_RESOLVED_FALSE_POSITIVE, - STATUS_RESOLVED_NOT_REVOKED, - STATUS_RESOLVED_REVOKED -} from "../../ee/models/gitRisks"; -import { ProbotOctokit } from "probot"; -import { Organization } from "../../models"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/secretScanning"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions -} from "../../ee/services/RoleService"; -import { ForbiddenError } from "@casl/ability"; - -export const createInstallationSession = async (req: Request, res: Response) => { - const sessionId = crypto.randomBytes(16).toString("hex"); - const { - params: { organizationId } - } = await validateRequest(reqValidator.CreateInstalLSessionv1, req); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.SecretScanning - ); - - await GitAppInstallationSession.findByIdAndUpdate( - organization, - { - organization: organization.id, - sessionId: sessionId, - user: new Types.ObjectId(req.user._id) - }, - { upsert: true } - ).lean(); - - res.send({ - sessionId: sessionId - }); -}; - -export const linkInstallationToOrganization = async (req: Request, res: Response) => { - const { - body: { sessionId, installationId } - } = await validateRequest(reqValidator.LinkInstallationToOrgv1, req); - - const installationSession = await GitAppInstallationSession.findOneAndDelete({ - sessionId: sessionId - }); - if (!installationSession) { - throw UnauthorizedRequestError(); - } - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: installationSession.organization - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.SecretScanning - ); - - const installationLink = await GitAppOrganizationInstallation.findOneAndUpdate( - { - organizationId: installationSession.organization - }, - { - installationId: installationId, - organizationId: installationSession.organization, - user: installationSession.user - }, - { - upsert: true - } - ).lean(); - - const octokit = new ProbotOctokit({ - auth: { - appId: await getSecretScanningGitAppId(), - privateKey: await getSecretScanningPrivateKey(), - installationId: installationId.toString() - } - }); - - const { - data: { repositories } - } = await octokit.apps.listReposAccessibleToInstallation(); - for (const repository of repositories) { - scanGithubFullRepoForSecretLeaks({ - organizationId: installationSession.organization.toString(), - installationId, - repository: { id: repository.id, fullName: repository.full_name } - }); - } - res.json(installationLink); -}; - -export const getCurrentOrganizationInstallationStatus = async (req: Request, res: Response) => { - const { organizationId } = req.params; - try { - const appInstallation = await GitAppOrganizationInstallation.findOne({ - organizationId: organizationId - }).lean(); - if (!appInstallation) { - res.json({ - appInstallationComplete: false - }); - } - - res.json({ - appInstallationComplete: true - }); - } catch { - res.json({ - appInstallationComplete: false - }); - } -}; - -export const getRisksForOrganization = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgRisksv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.SecretScanning - ); - - const risks = await GitRisks.find({ organization: organizationId }) - .sort({ createdAt: -1 }) - .lean(); - res.json({ - risks: risks - }); -}; - -export const updateRisksStatus = async (req: Request, res: Response) => { - const { - params: { organizationId, riskId }, - body: { status } - } = await validateRequest(reqValidator.UpdateRiskStatusv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.SecretScanning - ); - - const isRiskResolved = - status == STATUS_RESOLVED_FALSE_POSITIVE || - status == STATUS_RESOLVED_REVOKED || - status == STATUS_RESOLVED_NOT_REVOKED - ? true - : false; - const risk = await GitRisks.findByIdAndUpdate(riskId, { - status: status, - isResolved: isRiskResolved - }).lean(); - - res.json(risk); -}; diff --git a/backend-mongo/src/controllers/v1/secretsFolderController.ts b/backend-mongo/src/controllers/v1/secretsFolderController.ts deleted file mode 100644 index 52627b2e3..000000000 --- a/backend-mongo/src/controllers/v1/secretsFolderController.ts +++ /dev/null @@ -1,680 +0,0 @@ -import { ForbiddenError, subject } from "@casl/ability"; -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { EventType, FolderVersion } from "../../ee/models"; -import { EEAuditLogService, EESecretService } from "../../ee/services"; -import { isValidScope } from "../../helpers/secrets"; -import { validateRequest } from "../../helpers/validation"; -import { Secret, ServiceTokenData } from "../../models"; -import { Folder } from "../../models/folder"; -import { - appendFolder, - getAllFolderIds, - getFolderByPath, - getFolderWithPathFromId, - validateFolderName -} from "../../services/FolderService"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors"; -import * as reqValidator from "../../validation/folders"; - -const ERR_FOLDER_NOT_FOUND = BadRequestError({ message: "The folder doesn't exist" }); - -// verify workspace id/environment -export const createFolder = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Create folder' - #swagger.description = 'Create folder' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of the workspace where to create folder", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to create folder", - "example": "production" - }, - "folderName": { - "type": "string", - "description": "Name of folder to create", - "example": "my_folder" - }, - "directory": { - "type": "string", - "description": "Path where to create folder like / or /foo/bar. Default is /", - "example": "/foo/bar" - } - }, - "required": ["workspaceId", "environment", "folderName"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "folder": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "ID of folder", - "example": "someFolderId" - }, - "name": { - "type": "string", - "description": "Name of folder", - "example": "my_folder" - }, - "version": { - "type": "number", - "description": "Version of folder", - "example": 1 - } - }, - "description": "Details of created folder" - } - } - } - } - } - } - #swagger.responses[400] = { - description: "Bad Request. For example, 'Folder name cannot contain spaces. Only underscore and dashes'" - } - #swagger.responses[401] = { - description: "Unauthorized request. For example, 'Folder Permission Denied'" - } - */ - const { - body: { workspaceId, environment, folderName, directory } - } = await validateRequest(reqValidator.CreateFolderV1, req); - - if (!validateFolderName(folderName)) { - throw BadRequestError({ - message: "Folder name cannot contain spaces. Only underscore and dashes" - }); - } - - if (req.authData.authPayload instanceof ServiceTokenData) { - // token check - const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - // user check - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory }) - ); - } - - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }).lean(); - - // space has no folders initialized - if (!folders) { - const folder = new Folder({ - workspace: workspaceId, - environment, - nodes: { - id: "root", - name: "root", - version: 1, - children: [] - } - }); - const { parent, child } = appendFolder(folder.nodes, { folderName, directory }); - await folder.save(); - const folderVersion = new FolderVersion({ - workspace: workspaceId, - environment, - nodes: parent - }); - await folderVersion.save(); - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_FOLDER, - metadata: { - environment, - folderId: child.id, - folderName, - folderPath: directory - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.json({ folder: { id: child.id, name: folderName } }); - } - - const { parent, child, hasCreated } = appendFolder(folders.nodes, { folderName, directory }); - - if (!hasCreated) return res.json({ folder: child }); - - await Folder.findByIdAndUpdate(folders._id, folders); - - const folderVersion = new FolderVersion({ - workspace: workspaceId, - environment, - nodes: parent - }); - await folderVersion.save(); - - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - folderId: child.id - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_FOLDER, - metadata: { - environment, - folderId: child.id, - folderName, - folderPath: directory - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.json({ folder: child }); -}; - -/** - * Update folder with id [folderId] - * @param req - * @param res - * @returns - */ -export const updateFolderById = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update folder' - #swagger.description = 'Update folder' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['folderName'] = { - "description": "Name of folder to update", - "required": true, - "type": "string" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of workspace where to update folder", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to update folder", - "example": "production" - }, - "name": { - "type": "string", - "description": "Name of folder to update to", - "example": "updated_folder_name" - }, - "directory": { - "type": "string", - "description": "Path where to update folder like / or /foo/bar. Default is /", - "example": "/foo/bar" - } - }, - "required": ["workspaceId", "environment", "name"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "Successfully updated folder" - }, - "folder": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of updated folder", - "example": "updated_folder_name" - }, - "id": { - "type": "string", - "description": "ID of created folder", - "example": "abc123" - } - }, - "description": "Details of the updated folder" - } - } - } - } - } - } - - #swagger.responses[400] = { - description: "Bad Request. Reasons can include 'The folder doesn't exist' or 'Folder name cannot contain spaces. Only underscore and dashes'" - } - - #swagger.responses[401] = { - description: "Unauthorized request. For example, 'Folder Permission Denied'" - } - */ - const { - body: { workspaceId, environment, name, directory }, - params: { folderName } - } = await validateRequest(reqValidator.UpdateFolderV1, req); - - if (!validateFolderName(name)) { - throw BadRequestError({ - message: "Folder name cannot contain spaces. Only underscore and dashes" - }); - } - - if (req.authData.authPayload instanceof ServiceTokenData) { - const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory }) - ); - } - - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - if (!folders) { - throw BadRequestError({ message: "The folder doesn't exist" }); - } - - const parentFolder = getFolderByPath(folders.nodes, directory); - if (!parentFolder) { - throw BadRequestError({ message: "The folder doesn't exist" }); - } - - const folder = parentFolder.children.find(({ name }) => name === folderName); - if (!folder) throw ERR_FOLDER_NOT_FOUND; - - const oldFolderName = folder.name; - parentFolder.version += 1; - folder.name = name; - - await Folder.findByIdAndUpdate(folders._id, folders); - const folderVersion = new FolderVersion({ - workspace: workspaceId, - environment, - nodes: parentFolder - }); - await folderVersion.save(); - - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - folderId: parentFolder.id - }); - - const { folderPath } = getFolderWithPathFromId(folders.nodes, folder.id); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_FOLDER, - metadata: { - environment, - folderId: folder.id, - oldFolderName, - newFolderName: name, - folderPath - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.json({ - message: "Successfully updated folder", - folder: { name: folder.name, id: folder.id } - }); -}; - -/** - * Delete folder with id [folderId] - * @param req - * @param res - * @returns - */ -export const deleteFolder = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete folder' - #swagger.description = 'Delete folder' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['folderName'] = { - "description": "Name of folder to delete", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of the workspace where to delete folder", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to delete folder", - "example": "production" - }, - "directory": { - "type": "string", - "description": "Path where to delete folder like / or /foo/bar. Default is /", - "example": "/foo/bar" - } - }, - "required": ["workspaceId", "environment"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "successfully deleted folders" - }, - "folders": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "ID of deleted folder", - "example": "abc123" - }, - "name": { - "type": "string", - "description": "Name of deleted folder", - "example": "someFolderName" - } - } - }, - "description": "List of IDs and names of deleted folders" - } - } - } - } - } - } - - #swagger.responses[400] = { - description: "Bad Request. Reasons can include 'The folder doesn't exist'" - } - - #swagger.responses[401] = { - description: "Unauthorized request. For example, 'Folder Permission Denied'" - } - */ - const { - params: { folderName }, - body: { environment, workspaceId, directory } - } = await validateRequest(reqValidator.DeleteFolderV1, req); - - if (req.authData.authPayload instanceof ServiceTokenData) { - const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - // check that user is a member of the workspace - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory }) - ); - } - - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - if (!folders) throw ERR_FOLDER_NOT_FOUND; - - const parentFolder = getFolderByPath(folders.nodes, directory); - if (!parentFolder) throw ERR_FOLDER_NOT_FOUND; - - const index = parentFolder.children.findIndex(({ name }) => name === folderName); - if (index === -1) throw ERR_FOLDER_NOT_FOUND; - - const deletedFolder = parentFolder.children.splice(index, 1)[0]; - - parentFolder.version += 1; - const delFolderIds = getAllFolderIds(deletedFolder); - - await Folder.findByIdAndUpdate(folders._id, folders); - const folderVersion = new FolderVersion({ - workspace: workspaceId, - environment, - nodes: parentFolder - }); - await folderVersion.save(); - if (delFolderIds.length) { - await Secret.deleteMany({ - folder: { $in: delFolderIds.map(({ id }) => id) }, - workspace: workspaceId, - environment - }); - } - - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - folderId: parentFolder.id - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_FOLDER, - metadata: { - environment, - folderId: deletedFolder.id, - folderName: deletedFolder.name, - folderPath: directory - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.send({ message: "successfully deleted folders", folders: delFolderIds }); -}; - -/** - * Get folders for workspace with id [workspaceId] and environment [environment] - * considering directory/path [directory] - * @param req - * @param res - * @returns - */ -export const getFolders = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Get folders' - #swagger.description = 'Get folders' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of the workspace where to get folders from", - "required": true, - "type": "string", - "in": "query" - } - - #swagger.parameters['environment'] = { - "description": "Slug of environment where to get folders from", - "required": true, - "type": "string", - "in": "query" - } - - #swagger.parameters['directory'] = { - "description": "Path where to get fodlers from like / or /foo/bar. Default is /", - "required": false, - "type": "string", - "in": "query" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "folders": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "someFolderId" - }, - "name": { - "type": "string", - "example": "someFolderName" - } - } - }, - "description": "List of folders" - } - } - } - } - } - } - - #swagger.responses[400] = { - description: "Bad Request. For instance, 'The folder doesn't exist'" - } - - #swagger.responses[401] = { - description: "Unauthorized request. For example, 'Folder Permission Denied'" - } - */ - const { - query: { workspaceId, environment, directory } - } = await validateRequest(reqValidator.GetFoldersV1, req); - - if (req.authData.authPayload instanceof ServiceTokenData) { - const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory); - if (!isValidScopeAccess) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } else { - // check that user is a member of the workspace - await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - } - - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - if (!folders) { - return res.send({ folders: [], dir: [] }); - } - - const folder = getFolderByPath(folders.nodes, directory); - - return res.send({ - folders: folder?.children?.map(({ id, name }) => ({ id, name })) || [] - }); -}; diff --git a/backend-mongo/src/controllers/v1/serviceTokenController.ts b/backend-mongo/src/controllers/v1/serviceTokenController.ts deleted file mode 100644 index c1b753a90..000000000 --- a/backend-mongo/src/controllers/v1/serviceTokenController.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Request, Response } from "express"; -import { ServiceToken } from "../../models"; -import { createToken } from "../../helpers/auth"; -import { getJwtServiceSecret } from "../../config"; - -/** - * Return service token on request - * @param req - * @param res - * @returns - */ -export const getServiceToken = async (req: Request, res: Response) => { - return res.status(200).send({ - serviceToken: req.serviceToken, - }); -}; - -/** - * Create and return a new service token - * @param req - * @param res - * @returns - */ -export const createServiceToken = async (req: Request, res: Response) => { - let token; - try { - const { - name, - workspaceId, - environment, - expiresIn, - publicKey, - encryptedKey, - nonce, - } = req.body; - - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error("Failed to validate environment"); - } - - // compute access token expiration date - const expiresAt = new Date(); - expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); - - const serviceToken = await new ServiceToken({ - name, - user: req.user._id, - workspace: workspaceId, - environment, - expiresAt, - publicKey, - encryptedKey, - nonce, - }).save(); - - token = createToken({ - payload: { - serviceTokenId: serviceToken._id.toString(), - workspaceId, - }, - expiresIn: expiresIn, - secret: await getJwtServiceSecret(), - }); - } catch (err) { - return res.status(400).send({ - message: "Failed to create service token", - }); - } - - return res.status(200).send({ - token, - }); -}; \ No newline at end of file diff --git a/backend-mongo/src/controllers/v1/signupController.ts b/backend-mongo/src/controllers/v1/signupController.ts deleted file mode 100644 index 6422808ab..000000000 --- a/backend-mongo/src/controllers/v1/signupController.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Request, Response } from "express"; -import { AuthMethod, User } from "../../models"; -import { checkEmailVerification, sendEmailVerification } from "../../helpers/signup"; -import { createToken } from "../../helpers/auth"; -import { - getAuthSecret, - getJwtSignupLifetime, - getSmtpConfigured -} from "../../config"; -import { validateUserEmail } from "../../validation"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/auth"; -import { AuthTokenType } from "../../variables"; - -/** - * Signup step 1: Initialize account for user under email [email] and send a verification code - * to that email - * @param req - * @param res - * @returns - */ -export const beginEmailSignup = async (req: Request, res: Response) => { - const { - body: { email } - } = await validateRequest(reqValidator.BeginEmailSignUpV1, req); - - // validate that email is not disposable - validateUserEmail(email); - - const user = await User.findOne({ email }).select("+publicKey"); - if (user && user?.publicKey) { - // case: user has already completed account - - return res.status(403).send({ - error: "Failed to send email verification code for complete account" - }); - } - - // send send verification email - await sendEmailVerification({ email }); - - return res.status(200).send({ - message: `Sent an email verification code to ${email}` - }); -}; - -/** - * Signup step 2: Verify that code [code] was sent to email [email] and issue - * a temporary signup token for user to complete setting up their account - * @param req - * @param res - * @returns - */ -export const verifyEmailSignup = async (req: Request, res: Response) => { - let user; - const { - body: { email, code } - } = await validateRequest(reqValidator.VerifyEmailSignUpV1, req); - - // initialize user account - user = await User.findOne({ email }).select("+publicKey"); - if (user && user?.publicKey) { - // case: user has already completed account - return res.status(403).send({ - error: "Failed email verification for complete user" - }); - } - - // verify email - if (await getSmtpConfigured()) { - await checkEmailVerification({ - email, - code - }); - } - - if (!user) { - user = await new User({ - email, - authMethods: [AuthMethod.EMAIL] - }).save(); - } - - // generate temporary signup token - const token = createToken({ - payload: { - authTokenType: AuthTokenType.SIGNUP_TOKEN, - userId: user._id.toString() - }, - expiresIn: await getJwtSignupLifetime(), - secret: await getAuthSecret() - }); - - return res.status(200).send({ - message: "Successfuly verified email", - user, - token - }); -}; diff --git a/backend-mongo/src/controllers/v1/universalAuthController.ts b/backend-mongo/src/controllers/v1/universalAuthController.ts deleted file mode 100644 index 9e5bba715..000000000 --- a/backend-mongo/src/controllers/v1/universalAuthController.ts +++ /dev/null @@ -1,1269 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import jwt from "jsonwebtoken"; -import crypto from "crypto"; -import bcrypt from "bcrypt"; -import { - IIdentity, - IIdentityTrustedIp, - IIdentityUniversalAuthClientSecret, - Identity, - IdentityAccessToken, - IdentityAuthMethod, - IdentityMembershipOrg, - IdentityUniversalAuth, - IdentityUniversalAuthClientSecret, -} from "../../models"; -import { createToken } from "../../helpers/auth"; -import { AuthTokenType } from "../../variables"; -import { - BadRequestError, - ForbiddenRequestError, - ResourceNotFoundError, - UnauthorizedRequestError -} from "../../utils/errors"; -import { - getAuthSecret, - getSaltRounds -} from "../../config"; -import { ActorType, EventType, IRole } from "../../ee/models"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/auth"; -import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr } from "../../utils/ip"; -import { getUserAgentType } from "../../utils/posthog"; -import { EEAuditLogService, EELicenseService } from "../../ee/services"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions, - getOrgRolePermissions, - isAtLeastAsPrivilegedOrg -} from "../../ee/services/RoleService"; -import { ForbiddenError } from "@casl/ability"; - -const packageUniversalAuthClientSecretData = (identityUniversalAuthClientSecret: IIdentityUniversalAuthClientSecret) => ({ - _id: identityUniversalAuthClientSecret._id, - identityUniversalAuth: identityUniversalAuthClientSecret.identityUniversalAuth, - isClientSecretRevoked: identityUniversalAuthClientSecret.isClientSecretRevoked, - description: identityUniversalAuthClientSecret.description, - clientSecretPrefix: identityUniversalAuthClientSecret.clientSecretPrefix, - clientSecretNumUses: identityUniversalAuthClientSecret.clientSecretNumUses, - clientSecretNumUsesLimit: identityUniversalAuthClientSecret.clientSecretNumUsesLimit, - clientSecretTTL: identityUniversalAuthClientSecret.clientSecretTTL, - createdAt: identityUniversalAuthClientSecret.createdAt, - updatedAt: identityUniversalAuthClientSecret.updatedAt -}); - -/** - * Renews an access token by its TTL - * @param req - * @param res - */ -export const renewAccessToken = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Renew access token' - #swagger.description = 'Renew access token' - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "accessToken": { - "type": "string", - "description": "Access token to renew", - "example": "..." - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "accessToken": { - "type": "string", - "description": "(Same) Access token after successful renewal" - }, - "expiresIn": { - "type": "number", - "description": "TTL of access token in seconds" - }, - "tokenType": { - "type": "string", - "description": "Type of access token (e.g. Bearer)" - } - }, - "description": "Access token and its details" - } - } - } - } - */ - const { - body: { - accessToken - } - } = await validateRequest(reqValidator.RenewAccessTokenV1, req); - - const decodedToken = ( - jwt.verify(accessToken, await getAuthSecret()) - ); - - if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) throw UnauthorizedRequestError(); - - const identityAccessToken = await IdentityAccessToken.findOne({ - _id: decodedToken.identityAccessTokenId, - isAccessTokenRevoked: false - }); - - if (!identityAccessToken) throw UnauthorizedRequestError(); - - const { - accessTokenTTL, - accessTokenLastRenewedAt, - accessTokenMaxTTL, - createdAt: accessTokenCreatedAt, - accessTokenNumUses, - accessTokenNumUsesLimit - } = identityAccessToken; - - if (accessTokenNumUses >= accessTokenNumUsesLimit) { - throw BadRequestError({ message: "Unable to renew because access token number of uses limit reached" }) - } - - // ttl check - if (accessTokenTTL > 0) { - const currentDate = new Date(); - if (accessTokenLastRenewedAt) { - // access token has been renewed - const accessTokenRenewed = new Date(accessTokenLastRenewedAt); - const ttlInMilliseconds = accessTokenTTL * 1000; - const expirationDate = new Date(accessTokenRenewed.getTime() + ttlInMilliseconds); - - if (currentDate > expirationDate) throw UnauthorizedRequestError({ - message: "Failed to renew MI access token due to TTL expiration" - }); - } else { - // access token has never been renewed - const accessTokenCreated = new Date(accessTokenCreatedAt); - const ttlInMilliseconds = accessTokenTTL * 1000; - const expirationDate = new Date(accessTokenCreated.getTime() + ttlInMilliseconds); - - if (currentDate > expirationDate) throw UnauthorizedRequestError({ - message: "Failed to renew MI access token due to TTL expiration" - }); - } - } - - // max ttl checks - if (accessTokenMaxTTL > 0) { - const accessTokenCreated = new Date(accessTokenCreatedAt); - const ttlInMilliseconds = accessTokenMaxTTL * 1000; - const currentDate = new Date(); - const expirationDate = new Date(accessTokenCreated.getTime() + ttlInMilliseconds); - - if (currentDate > expirationDate) throw UnauthorizedRequestError({ - message: "Failed to renew MI access token due to Max TTL expiration" - }); - - const extendToDate = new Date(currentDate.getTime() + accessTokenTTL); - if (extendToDate > expirationDate) throw UnauthorizedRequestError({ - message: "Failed to renew MI access token past its Max TTL expiration" - }); - } - - await IdentityAccessToken.findByIdAndUpdate( - identityAccessToken._id, - { - accessTokenLastRenewedAt: new Date() - } - ); - - return res.status(200).send({ - accessToken, - expiresIn: identityAccessToken.accessTokenTTL, - accessTokenMaxTTL: identityAccessToken.accessTokenMaxTTL, - tokenType: "Bearer" - }); -} - -/** - * Return access token for identity with client id [clientId] - * and client secret [clientSecret] - * @param req - * @param res - */ -export const loginIdentityUniversalAuth = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Login with Universal Auth' - #swagger.description = 'Login with Universal Auth' - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientId": { - "type": "string", - "description": "Client ID for identity to login with Universal Auth", - "example": "..." - }, - "clientSecret": { - "type": "string", - "description": "Client Secret for identity to login with Universal Auth", - "example": "..." - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "accessToken": { - "type": "string", - "description": "Access token issued after successful login" - }, - "expiresIn": { - "type": "number", - "description": "TTL of access token in seconds" - }, - "tokenType": { - "type": "string", - "description": "Type of access token (e.g. Bearer)" - } - }, - "description": "Access token and its details" - } - } - } - } - */ - const { - body: { - clientId, - clientSecret - } - } = await validateRequest(reqValidator.LoginUniversalAuthV1, req); - - const identityUniversalAuth = await IdentityUniversalAuth.findOne({ - clientId - }).populate<{ identity: IIdentity }>("identity"); - - if (!identityUniversalAuth) throw UnauthorizedRequestError(); - - checkIPAgainstBlocklist({ - ipAddress: req.realIP, - trustedIps: identityUniversalAuth.clientSecretTrustedIps - }); - - const clientSecretData = await IdentityUniversalAuthClientSecret.find({ - identity: identityUniversalAuth.identity, - isClientSecretRevoked: false - }); - - let validatedClientSecretDatum: IIdentityUniversalAuthClientSecret | undefined; - - for (const clientSecretDatum of clientSecretData) { - const isSecretValid = await bcrypt.compare( - clientSecret, - clientSecretDatum.clientSecretHash - ); - - if (isSecretValid) { - validatedClientSecretDatum = clientSecretDatum; - break; - } - } - - if (!validatedClientSecretDatum) throw UnauthorizedRequestError(); - - const { - clientSecretTTL, - clientSecretNumUses, - clientSecretNumUsesLimit, - } = validatedClientSecretDatum; - - if (clientSecretTTL > 0) { - const clientSecretCreated = new Date(validatedClientSecretDatum.createdAt) - const ttlInMilliseconds = clientSecretTTL * 1000; - const currentDate = new Date(); - const expirationTime = new Date(clientSecretCreated.getTime() + ttlInMilliseconds); - - if (currentDate > expirationTime) { - await IdentityUniversalAuthClientSecret.findByIdAndUpdate( - validatedClientSecretDatum._id, - { - isClientSecretRevoked: true - } - ); - - throw UnauthorizedRequestError({ - message: "Failed to authenticate identity credentials due to expired client secret" - }); - } - } - - if (clientSecretNumUsesLimit > 0 && clientSecretNumUses === clientSecretNumUsesLimit) { - // number of times client secret can be used for - // a login operation reached - await IdentityUniversalAuthClientSecret.findByIdAndUpdate( - validatedClientSecretDatum._id, - { - isClientSecretRevoked: true - }, - { - new: true - } - ); - - throw UnauthorizedRequestError({ - message: "Failed to authenticate identity credentials due to client secret number of uses limit reached" - }); - } - - // increment usage count by 1 - await IdentityUniversalAuthClientSecret - .findByIdAndUpdate( - validatedClientSecretDatum._id, - { - clientSecretLastUsedAt: new Date(), - $inc: { clientSecretNumUses: 1 } - }, - { - new: true - } - ); - - const identityAccessToken = await new IdentityAccessToken({ - identity: identityUniversalAuth.identity, - identityUniversalAuthClientSecret: validatedClientSecretDatum._id, - accessTokenNumUses: 0, - accessTokenNumUsesLimit: identityUniversalAuth.accessTokenNumUsesLimit, - accessTokenTTL: identityUniversalAuth.accessTokenTTL, - accessTokenMaxTTL: identityUniversalAuth.accessTokenMaxTTL, - accessTokenTrustedIps: identityUniversalAuth.accessTokenTrustedIps, - isAccessTokenRevoked: false - }).save(); - - // token version - const accessToken = createToken({ - payload: { - identityId: identityUniversalAuth.identity.toString(), - clientSecretId: validatedClientSecretDatum._id.toString(), - identityAccessTokenId: identityAccessToken._id.toString(), - authTokenType: AuthTokenType.IDENTITY_ACCESS_TOKEN - }, - secret: await getAuthSecret() - }); - - const userAgent = req.headers["user-agent"] ?? ""; - - await EEAuditLogService.createAuditLog( - { - actor: { - type: ActorType.IDENTITY, - metadata: { - identityId: identityUniversalAuth.identity._id.toString(), - name: identityUniversalAuth.identity.name - } - }, - authPayload: identityUniversalAuth.identity, - ipAddress: req.realIP, - userAgent, - userAgentType: getUserAgentType(userAgent) - }, - { - type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH, - metadata: { - identityId: identityUniversalAuth.identity._id.toString(), - identityUniversalAuthId: identityUniversalAuth._id.toString(), - clientSecretId: validatedClientSecretDatum._id.toString(), - identityAccessTokenId: identityAccessToken._id.toString() - } - } - ); - - return res.status(200).send({ - accessToken, - expiresIn: identityUniversalAuth.accessTokenTTL, - accessTokenMaxTTL: identityUniversalAuth.accessTokenMaxTTL, - tokenType: "Bearer", - }); -} - -/** - * Attach identity universal auth method onto identity with id [identityId] - * @param req - * @param res - */ -export const attachIdentityUniversalAuth = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Attach Universal Auth configuration onto identity' - #swagger.description = 'Attach Universal Auth configuration onto identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['identityId'] = { - "description": "ID of identity to attach Universal Auth onto", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecretTrustedIps": { - type: "array", - items: { - type: "object", - "properties": { - "ipAddress": { - type: "string", - description: "IP address to trust", - default: "0.0.0.0/0" - } - } - }, - "description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", - "example": "...", - "default": [{ ipAddress: "0.0.0.0/0" }] - }, - "accessTokenTTL": { - "type": "number", - "description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.", - "example": "...", - "default": 100 - }, - "accessTokenMaxTTL": { - "type": "number", - "description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.", - "example": "...", - "default": 2592000 - }, - "accessTokenNumUsesLimit": { - "type": "number", - "description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.", - "example": "...", - "default": 0 - }, - "accessTokenTrustedIps": { - type: "array", - items: { - type: "object", - "properties": { - "ipAddress": { - type: "string", - description: "IP address to trust", - default: "0.0.0.0/0" - } - } - }, - "description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", - "example": "...", - "default": [{ ipAddress: "0.0.0.0/0" }] - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityUniversalAuth": { - $ref: '#/definitions/IdentityUniversalAuth' - } - }, - "description": "Details of attached Universal Auth" - } - } - } - } - */ - const { - params: { identityId }, - body: { - clientSecretTrustedIps, - accessTokenTTL, - accessTokenMaxTTL, - accessTokenNumUsesLimit, - accessTokenTrustedIps, - } - } = await validateRequest(reqValidator.AddUniversalAuthToIdentityV1, req); - - const identityMembershipOrg = await IdentityMembershipOrg - .findOne({ - identity: new Types.ObjectId(identityId) - }) - .populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembershipOrg) throw ResourceNotFoundError({ - message: `Failed to find identity with id ${identityId}` - }); - - if (identityMembershipOrg.identity?.authMethod) throw BadRequestError({ - message: "Failed to add universal auth to already-configured identity" - }); - - if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) { - throw BadRequestError({ message: "Access token TTL cannot be greater than max TTL" }) - } - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: identityMembershipOrg.organization - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Identity - ); - - const plan = await EELicenseService.getPlan(identityMembershipOrg.organization); - - // validate trusted ips - const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => { - if (!plan.ipAllowlisting && (clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" && clientSecretTrustedIp.ipAddress !== "::/0")) return res.status(400).send({ - message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range." - }); - - const isValidIPOrCidr = isValidIpOrCidr(clientSecretTrustedIp.ipAddress); - - if (!isValidIPOrCidr) return res.status(400).send({ - message: "The IP is not a valid IPv4, IPv6, or CIDR block" - }); - - return extractIPDetails(clientSecretTrustedIp.ipAddress); - }); - - const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => { - if (!plan.ipAllowlisting && (accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" && accessTokenTrustedIp.ipAddress !== "::/0")) return res.status(400).send({ - message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range." - }); - - const isValidIPOrCidr = isValidIpOrCidr(accessTokenTrustedIp.ipAddress); - - if (!isValidIPOrCidr) return res.status(400).send({ - message: "The IP is not a valid IPv4, IPv6, or CIDR block" - }); - - return extractIPDetails(accessTokenTrustedIp.ipAddress); - }); - - const identityUniversalAuth = await new IdentityUniversalAuth({ - identity: identityMembershipOrg.identity._id, - clientId: crypto.randomUUID(), - clientSecretTrustedIps: reformattedClientSecretTrustedIps, - accessTokenTTL, - accessTokenMaxTTL, - accessTokenNumUsesLimit, - accessTokenTrustedIps: reformattedAccessTokenTrustedIps, - }).save(); - - await Identity.findByIdAndUpdate( - identityMembershipOrg.identity._id, - { - authMethod: IdentityAuthMethod.UNIVERSAL_AUTH - } - ); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.ADD_IDENTITY_UNIVERSAL_AUTH, - metadata: { - identityId: identityMembershipOrg.identity._id.toString(), - clientSecretTrustedIps: reformattedClientSecretTrustedIps as Array, - accessTokenTTL, - accessTokenMaxTTL, - accessTokenNumUsesLimit, - accessTokenTrustedIps: reformattedAccessTokenTrustedIps as Array - } - } - ); - - return res.status(200).send({ - identityUniversalAuth - }); -} - -/** - * Update identity universal auth method on identity with id [identityId] - * @param req - * @param res - */ -export const updateIdentityUniversalAuth = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update Universal Auth configuration on identity' - #swagger.description = 'Update Universal Auth configuration on identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['identityId'] = { - "description": "ID of identity to update Universal Auth on", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecretTrustedIps": { - type: "array", - items: { - type: "object", - "properties": { - "ipAddress": { - type: "string", - description: "IP address to trust" - } - } - }, - "description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", - "example": "...", - }, - "accessTokenTTL": { - "type": "number", - "description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.", - "example": "...", - }, - "accessTokenMaxTTL": { - "type": "number", - "description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.", - "example": "...", - }, - "accessTokenNumUsesLimit": { - "type": "number", - "description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.", - "example": "...", - }, - "accessTokenTrustedIps": { - type: "array", - items: { - type: "object", - "properties": { - "ipAddress": { - type: "string", - description: "IP address to trust" - } - } - }, - "description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", - "example": "...", - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityUniversalAuth": { - $ref: '#/definitions/IdentityUniversalAuth' - } - }, - "description": "Details of updated Universal Auth" - } - } - } - } - */ - const { - params: { identityId }, - body: { - clientSecretTrustedIps, - accessTokenTTL, // TODO: validate this and max TTL - accessTokenMaxTTL, - accessTokenNumUsesLimit, - accessTokenTrustedIps, - } - } = await validateRequest(reqValidator.UpdateUniversalAuthToIdentityV1, req); - - const identityMembershipOrg = await IdentityMembershipOrg - .findOne({ - identity: new Types.ObjectId(identityId) - }) - .populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembershipOrg) throw ResourceNotFoundError({ - message: `Failed to find identity with id ${identityId}` - }); - - if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.UNIVERSAL_AUTH) throw BadRequestError({ - message: "Failed to add universal auth to already-configured identity" - }); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: identityMembershipOrg.organization - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.Identity - ); - - const plan = await EELicenseService.getPlan(identityMembershipOrg.organization); - - // validate trusted ips - let reformattedClientSecretTrustedIps; - if (clientSecretTrustedIps) { - reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => { - if (!plan.ipAllowlisting && (clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" && clientSecretTrustedIp.ipAddress !== "::/0")) return res.status(400).send({ - message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range." - }); - - const isValidIPOrCidr = isValidIpOrCidr(clientSecretTrustedIp.ipAddress); - - if (!isValidIPOrCidr) return res.status(400).send({ - message: "The IP is not a valid IPv4, IPv6, or CIDR block" - }); - - return extractIPDetails(clientSecretTrustedIp.ipAddress); - }); - } - - let reformattedAccessTokenTrustedIps; - if (accessTokenTrustedIps) { - reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => { - if (!plan.ipAllowlisting && (accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" && accessTokenTrustedIp.ipAddress !== "::/0")) return res.status(400).send({ - message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range." - }); - - const isValidIPOrCidr = isValidIpOrCidr(accessTokenTrustedIp.ipAddress); - - if (!isValidIPOrCidr) return res.status(400).send({ - message: "The IP is not a valid IPv4, IPv6, or CIDR block" - }); - - return extractIPDetails(accessTokenTrustedIp.ipAddress); - }); - } - - const identityUniversalAuth = await IdentityUniversalAuth.findOneAndUpdate( - { - identity: identityMembershipOrg.identity._id, - }, - { - clientSecretTrustedIps: reformattedClientSecretTrustedIps, - accessTokenTTL, - accessTokenMaxTTL, - accessTokenNumUsesLimit, - accessTokenTrustedIps: reformattedAccessTokenTrustedIps, - }, - { - new: true - } - ); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_IDENTITY_UNIVERSAL_AUTH, - metadata: { - identityId: identityMembershipOrg.identity._id.toString(), - clientSecretTrustedIps: reformattedClientSecretTrustedIps as Array, - accessTokenTTL, - accessTokenMaxTTL, - accessTokenNumUsesLimit, - accessTokenTrustedIps: reformattedAccessTokenTrustedIps as Array - } - } - ); - - return res.status(200).send({ - identityUniversalAuth - }); -} - -/** - * Return identity universal auth method on identity with id [identityId] - * @param req - * @param res - */ -export const getIdentityUniversalAuth = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Retrieve Universal Auth configuration on identity' - #swagger.description = 'Retrieve Universal Auth configuration on identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['identityId'] = { - "description": "ID of identity to retrieve Universal Auth on", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityUniversalAuth": { - $ref: '#/definitions/IdentityUniversalAuth' - } - }, - "description": "Details of retrieved Universal Auth" - } - } - } - } - */ - const { - params: { identityId } - } = await validateRequest(reqValidator.GetUniversalAuthForIdentityV1, req); - - const identityMembershipOrg = await IdentityMembershipOrg - .findOne({ - identity: new Types.ObjectId(identityId) - }) - .populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembershipOrg) throw ResourceNotFoundError({ - message: `Failed to find identity with id ${identityId}` - }); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: identityMembershipOrg.organization - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Identity - ); - - if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.UNIVERSAL_AUTH) throw BadRequestError({ - message: "The identity does not have universal auth configured" - }); - - const identityUniversalAuth = await IdentityUniversalAuth.findOne({ - identity: identityMembershipOrg.identity._id, - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.GET_IDENTITY_UNIVERSAL_AUTH, - metadata: { - identityId: identityMembershipOrg.identity._id.toString(), - } - } - ); - - return res.status(200).send({ - identityUniversalAuth - }); -} - - -/** - * Create client secret for identity universal auth method on identity with id [identityId] - * @param req - * @param res - */ -export const createUniversalAuthClientSecret = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Create Universal Auth Client Secret for identity' - #swagger.description = 'Create Universal Auth Client Secret for identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['identityId'] = { - "description": "ID of identity to create Universal Auth Client Secret for", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "A description for the Client Secret to create.", - "example": "..." - }, - "ttl": { - "type": "number", - "description": "The time-to-live for the Client Secret to create. By default, the TTL will be set to 0 which implies that the Client Secret will never expire; a value of 0 implies an infinite lifetime.", - "example": "...", - "default": 0 - }, - "numUsesLimit": { - "type": "number", - "description": "The maximum number of times that the Client Secret can be used together with the Client ID to get back an access token; a value of 0 implies infinite number of uses.", - "example": "...", - "default": 0 - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecret": { - "type": "string", - "description": "The created Client Secret" - }, - "clientSecretData": { - $ref: '#/definitions/IdentityUniversalAuthClientSecretData' - } - }, - "description": "Details of the created Client Secret" - } - } - } - } - */ - const { - params: { identityId }, - body: { - description, - numUsesLimit, - ttl - } - } = await validateRequest(reqValidator.CreateUniversalAuthClientSecretV1, req); - - const identityMembershipOrg = await IdentityMembershipOrg.findOne({ - identity: new Types.ObjectId(identityId) - }).populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembershipOrg) throw ResourceNotFoundError({ - message: `Failed to find identity with id ${identityId}` - }); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: identityMembershipOrg.organization - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Identity - ); - - if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.UNIVERSAL_AUTH) throw BadRequestError({ - message: "The identity does not have universal auth configured" - }); - - const rolePermission = await getOrgRolePermissions( - identityMembershipOrg?.customRole?.slug ?? identityMembershipOrg.role, - identityMembershipOrg.organization.toString() - ); - const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, rolePermission); - - if (!hasRequiredPrivileges) throw ForbiddenRequestError({ - message: "Failed to create client secret for more privileged identity" - }); - - const clientSecret = crypto.randomBytes(32).toString("hex"); - const clientSecretHash = await bcrypt.hash(clientSecret, await getSaltRounds()); - - const identityUniversalAuth = await IdentityUniversalAuth.findOne({ - identity: identityMembershipOrg.identity._id - }); - - if (!identityUniversalAuth) throw ResourceNotFoundError(); - - const identityUniversalAuthClientSecret = await new IdentityUniversalAuthClientSecret({ - identity: identityMembershipOrg.identity._id, - identityUniversalAuth: identityUniversalAuth._id, - description, - clientSecretPrefix: clientSecret.slice(0, 4), - clientSecretHash, - clientSecretNumUses: 0, - clientSecretNumUsesLimit: numUsesLimit, - clientSecretTTL: ttl, - isClientSecretRevoked: false - }).save(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET, - metadata: { - identityId: identityMembershipOrg.identity._id.toString(), - clientSecretId: identityUniversalAuthClientSecret._id.toString() - } - } - ); - - return res.status(200).send({ - clientSecret, - clientSecretData: packageUniversalAuthClientSecretData(identityUniversalAuthClientSecret) - }); -} - -/** - * Return list of client secret details for identity universal auth method on identity with id [identityId] - * @param req - * @param res - */ -export const getUniversalAuthClientSecretsDetails = async (req: Request, res: Response) => { - /* - #swagger.summary = 'List Universal Auth Client Secrets for identity' - #swagger.description = 'List Universal Auth Client Secrets for identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['identityId'] = { - "description": "ID of identity for which to get Client Secrets for", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecretData": { - type: "array", - items: { - $ref: '#/definitions/IdentityUniversalAuthClientSecretData' - } - } - }, - "description": "Details of the Client Secrets" - } - } - } - } - */ - const { - params: { identityId } - } = await validateRequest(reqValidator.GetUniversalAuthClientSecretsV1, req); - - const identityMembershipOrg = await IdentityMembershipOrg.findOne({ - identity: new Types.ObjectId(identityId) - }).populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembershipOrg) throw ResourceNotFoundError(); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: identityMembershipOrg.organization - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Identity - ); - - if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.UNIVERSAL_AUTH) throw BadRequestError({ - message: "The identity does not have universal auth configured" - }); - - const rolePermission = await getOrgRolePermissions( - identityMembershipOrg?.customRole?.slug ?? identityMembershipOrg.role, - identityMembershipOrg.organization.toString() - ); - const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, rolePermission); - - if (!hasRequiredPrivileges) throw ForbiddenRequestError({ - message: "Failed to get client secrets for more privileged MI" - }); - - const clientSecretData = await IdentityUniversalAuthClientSecret - .find({ - identity: identityMembershipOrg.identity, - isClientSecretRevoked: false - }) - .sort({ createdAt: -1 }) - .limit(5); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS, - metadata: { - identityId: identityMembershipOrg.identity._id.toString() - } - } - ); - - return res.status(200).send({ - clientSecretData: clientSecretData.map((clientSecretDatum) => packageUniversalAuthClientSecretData(clientSecretDatum)) - }); -} - -/** - * Revoke client secret for identity universal auth method on identity with id [identityId] - * @param req - * @param res - */ -export const revokeUniversalAuthClientSecret = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Revoke Universal Auth Client Secret for identity' - #swagger.description = 'Revoke Universal Auth Client Secret for identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['identityId'] = { - "description": "ID of identity under which Client Secret was issued for", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.parameters['clientSecretId'] = { - "description": "ID of Client Secret to revoke", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clientSecretData": { - $ref: '#/definitions/IdentityUniversalAuthClientSecretData' - } - }, - "description": "Details of the revoked Client Secret" - } - } - } - } - */ - const { - params: { identityId, clientSecretId } - } = await validateRequest(reqValidator.RevokeUniversalAuthClientSecretV1, req); - - const identityMembershipOrg = await IdentityMembershipOrg - .findOne({ - identity: new Types.ObjectId(identityId) - }) - .populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembershipOrg) throw ResourceNotFoundError({ - message: `Failed to find identity with id ${identityId}` - }); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: identityMembershipOrg.organization - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Delete, - OrgPermissionSubjects.Identity - ); - - const rolePermission = await getOrgRolePermissions( - identityMembershipOrg?.customRole?.slug ?? identityMembershipOrg.role, - identityMembershipOrg.organization.toString() - ); - const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, rolePermission); - - if (!hasRequiredPrivileges) throw ForbiddenRequestError({ - message: "Failed to delete client secrets for more privileged identity" - }); - - const clientSecretData = await IdentityUniversalAuthClientSecret.findOneAndUpdate( - { - _id: new Types.ObjectId(clientSecretId), - identity: identityMembershipOrg.identity._id - }, - { - isClientSecretRevoked: true - }, - { - new: true - } - ); - - if (!clientSecretData) throw ResourceNotFoundError(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET, - metadata: { - identityId: identityMembershipOrg.identity._id.toString(), - clientSecretId: clientSecretId - } - } - ); - - return res.status(200).send({ - clientSecretData: packageUniversalAuthClientSecretData(clientSecretData) - }) -} \ No newline at end of file diff --git a/backend-mongo/src/controllers/v1/userActionController.ts b/backend-mongo/src/controllers/v1/userActionController.ts deleted file mode 100644 index 9a151f8dd..000000000 --- a/backend-mongo/src/controllers/v1/userActionController.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Request, Response } from "express"; -import { validateRequest } from "../../helpers/validation"; -import { UserAction } from "../../models"; -import * as reqValidator from "../../validation/action"; - -/** - * Add user action [action] - * @param req - * @param res - * @returns - */ -export const addUserAction = async (req: Request, res: Response) => { - // add/record new action [action] for user with id [req.user._id] - const { - body: { action } - } = await validateRequest(reqValidator.AddUserActionV1, req); - - const userAction = await UserAction.findOneAndUpdate( - { - user: req.user._id, - action - }, - { user: req.user._id, action }, - { - new: true, - upsert: true - } - ); - - return res.status(200).send({ - message: "Successfully recorded user action", - userAction - }); -}; - -/** - * Return user action [action] for user - * @param req - * @param res - * @returns - */ -export const getUserAction = async (req: Request, res: Response) => { - // get user action [action] for user with id [req.user._id] - const { - query: { action } - } = await validateRequest(reqValidator.GetUserActionV1, req); - - const userAction = await UserAction.findOne({ - user: req.user._id, - action - }); - - return res.status(200).send({ - userAction - }); -}; diff --git a/backend-mongo/src/controllers/v1/userController.ts b/backend-mongo/src/controllers/v1/userController.ts deleted file mode 100644 index 398b24f08..000000000 --- a/backend-mongo/src/controllers/v1/userController.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Request, Response } from "express"; - -/** - * Return user on request - * @param req - * @param res - * @returns - */ -export const getUser = async (req: Request, res: Response) => { - return res.status(200).send({ - user: req.user, - }); -}; diff --git a/backend-mongo/src/controllers/v1/webhookController.ts b/backend-mongo/src/controllers/v1/webhookController.ts deleted file mode 100644 index 852a3aeed..000000000 --- a/backend-mongo/src/controllers/v1/webhookController.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { client, getEncryptionKey, getRootEncryptionKey } from "../../config"; -import { Webhook } from "../../models"; -import { getWebhookPayload, triggerWebhookRequest } from "../../services/WebhookService"; -import { BadRequestError, ResourceNotFoundError } from "../../utils/errors"; -import { EEAuditLogService } from "../../ee/services"; -import { EventType } from "../../ee/models"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8 -} from "../../variables"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/webhooks"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; -import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; - -export const createWebhook = async (req: Request, res: Response) => { - const { - body: { webhookUrl, webhookSecretKey, environment, workspaceId, secretPath } - } = await validateRequest(reqValidator.CreateWebhookV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Webhooks - ); - - const webhook = new Webhook({ - workspace: workspaceId, - environment, - secretPath, - url: webhookUrl - }); - - if (webhookSecretKey) { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - if (rootEncryptionKey) { - const { ciphertext, iv, tag } = client.encryptSymmetric(webhookSecretKey, rootEncryptionKey); - webhook.iv = iv; - webhook.tag = tag; - webhook.encryptedSecretKey = ciphertext; - webhook.algorithm = ALGORITHM_AES_256_GCM; - webhook.keyEncoding = ENCODING_SCHEME_BASE64; - } else if (encryptionKey) { - const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: webhookSecretKey, - key: encryptionKey - }); - webhook.iv = iv; - webhook.tag = tag; - webhook.encryptedSecretKey = ciphertext; - webhook.algorithm = ALGORITHM_AES_256_GCM; - webhook.keyEncoding = ENCODING_SCHEME_UTF8; - } - } - - await webhook.save(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_WEBHOOK, - metadata: { - webhookId: webhook._id.toString(), - environment, - secretPath, - webhookUrl, - isDisabled: false - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.status(200).send({ - webhook, - message: "successfully created webhook" - }); -}; - -export const updateWebhook = async (req: Request, res: Response) => { - const { - body: { isDisabled }, - params: { webhookId } - } = await validateRequest(reqValidator.UpdateWebhookV1, req); - - const webhook = await Webhook.findById(webhookId); - if (!webhook) { - throw BadRequestError({ message: "Webhook not found!!" }); - } - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: webhook.workspace - }); - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Webhooks - ); - - if (typeof isDisabled !== undefined) { - webhook.isDisabled = isDisabled; - } - await webhook.save(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_WEBHOOK_STATUS, - metadata: { - webhookId: webhook._id.toString(), - environment: webhook.environment, - secretPath: webhook.secretPath, - webhookUrl: webhook.url, - isDisabled - } - }, - { - workspaceId: webhook.workspace - } - ); - - return res.status(200).send({ - webhook, - message: "successfully updated webhook" - }); -}; - -export const deleteWebhook = async (req: Request, res: Response) => { - const { - params: { webhookId } - } = await validateRequest(reqValidator.DeleteWebhookV1, req); - let webhook = await Webhook.findById(webhookId); - - if (!webhook) { - throw ResourceNotFoundError({ message: "Webhook not found!!" }); - } - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: webhook.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Webhooks - ); - - webhook = await Webhook.findByIdAndDelete(webhookId); - - if (!webhook) { - throw ResourceNotFoundError({ message: "Webhook not found!!" }); - } - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_WEBHOOK, - metadata: { - webhookId: webhook._id.toString(), - environment: webhook.environment, - secretPath: webhook.secretPath, - webhookUrl: webhook.url, - isDisabled: webhook.isDisabled - } - }, - { - workspaceId: webhook.workspace - } - ); - - return res.status(200).send({ - message: "successfully removed webhook" - }); -}; - -export const testWebhook = async (req: Request, res: Response) => { - const { - params: { webhookId } - } = await validateRequest(reqValidator.TestWebhookV1, req); - - const webhook = await Webhook.findById(webhookId); - if (!webhook) { - throw BadRequestError({ message: "Webhook not found!!" }); - } - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: webhook.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Webhooks - ); - - try { - await triggerWebhookRequest( - webhook, - getWebhookPayload( - "test", - webhook.workspace.toString(), - webhook.environment, - webhook.secretPath - ) - ); - await Webhook.findByIdAndUpdate(webhookId, { - lastStatus: "success", - lastRunErrorMessage: null - }); - } catch (err) { - await Webhook.findByIdAndUpdate(webhookId, { - lastStatus: "failed", - lastRunErrorMessage: (err as Error).message - }); - return res.status(400).send({ - message: "Failed to receive response", - error: (err as Error).message - }); - } - - return res.status(200).send({ - message: "Successfully received response" - }); -}; - -export const listWebhooks = async (req: Request, res: Response) => { - const { - query: { environment, workspaceId, secretPath } - } = await validateRequest(reqValidator.ListWebhooksV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Webhooks - ); - - const optionalFilters: Record = {}; - if (environment) optionalFilters.environment = environment as string; - if (secretPath) optionalFilters.secretPath = secretPath as string; - - const webhooks = await Webhook.find({ - workspace: new Types.ObjectId(workspaceId as string), - ...optionalFilters - }); - - return res.status(200).send({ - webhooks - }); -}; diff --git a/backend-mongo/src/controllers/v1/workspaceController.ts b/backend-mongo/src/controllers/v1/workspaceController.ts deleted file mode 100644 index 2d6e9776d..000000000 --- a/backend-mongo/src/controllers/v1/workspaceController.ts +++ /dev/null @@ -1,359 +0,0 @@ -import { Types } from "mongoose"; -import { Request, Response } from "express"; -import { - IUser, - Integration, - IntegrationAuth, - Membership, - Organization, - ServiceToken, - Workspace -} from "../../models"; -import { createWorkspace as create, deleteWorkspace as deleteWork } from "../../helpers/workspace"; -import { EELicenseService } from "../../ee/services"; -import { addMemberships } from "../../helpers/membership"; -import { ADMIN } from "../../variables"; -import { OrganizationNotFoundError } from "../../utils/errors"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions -} from "../../ee/services/RoleService"; -import { ForbiddenError } from "@casl/ability"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; - -/** - * Return public keys of members of workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const getWorkspacePublicKeys = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspacePublicKeysV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Member - ); - - const publicKeys = ( - await Membership.find({ - workspace: workspaceId - }).populate<{ user: IUser }>("user", "publicKey") - ).map((member) => { - return { - publicKey: member.user.publicKey, - userId: member.user._id - }; - }); - - return res.status(200).send({ - publicKeys - }); -}; - -/** - * Return memberships for workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const getWorkspaceMemberships = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceMembershipsV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Member - ); - - const users = await Membership.find({ - workspace: workspaceId - }).populate("user", "+publicKey"); - - return res.status(200).send({ - users - }); -}; - -/** - * Return workspaces that user is part of - * @param req - * @param res - * @returns - */ -export const getWorkspaces = async (req: Request, res: Response) => { - const workspaces = ( - await Membership.find({ - user: req.user._id - }).populate("workspace") - ).map((m) => m.workspace); - - return res.status(200).send({ - workspaces - }); -}; - -/** - * Return workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const getWorkspace = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceV1, req); - - const workspace = await Workspace.findOne({ - _id: workspaceId - }); - - return res.status(200).send({ - workspace - }); -}; - -/** - * Create new workspace named [workspaceName] under organization with id - * [organizationId] and add user as admin - * @param req - * @param res - * @returns - */ -export const createWorkspace = async (req: Request, res: Response) => { - const { - body: { organizationId, workspaceName } - } = await validateRequest(reqValidator.CreateWorkspaceV1, req); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Workspace - ); - - const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId)); - - if (plan.workspaceLimit !== null) { - // case: limit imposed on number of workspaces allowed - if (plan.workspacesUsed >= plan.workspaceLimit) { - // case: number of workspaces used exceeds the number of workspaces allowed - return res.status(400).send({ - message: - "Failed to create workspace due to plan limit reached. Upgrade plan to add more workspaces." - }); - } - } - - if (workspaceName.length < 1) { - throw new Error("Workspace names must be at least 1-character long"); - } - - // create workspace and add user as member - const workspace = await create({ - name: workspaceName, - organizationId: new Types.ObjectId(organizationId) - }); - - await addMemberships({ - userIds: [req.user._id], - workspaceId: workspace._id.toString(), - roles: [ADMIN] - }); - - return res.status(200).send({ - workspace - }); -}; - -/** - * Delete workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const deleteWorkspace = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.DeleteWorkspaceV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Workspace - ); - - // delete workspace - const workspace = await deleteWork({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - return res.status(200).send({ - workspace - }); -}; - -/** - * Change name of workspace with id [workspaceId] to [name] - * @param req - * @param res - * @returns - */ -export const changeWorkspaceName = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - body: { name } - } = await validateRequest(reqValidator.ChangeWorkspaceNameV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Workspace - ); - - const workspace = await Workspace.findOneAndUpdate( - { - _id: workspaceId - }, - { - name - }, - { - new: true - } - ); - - return res.status(200).send({ - message: "Successfully changed workspace name", - workspace - }); -}; - -/** - * Return integrations for workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const getWorkspaceIntegrations = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceIntegrationsV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - const integrations = await Integration.find({ - workspace: workspaceId - }); - - return res.status(200).send({ - integrations - }); -}; - -/** - * Return (integration) authorizations for workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const getWorkspaceIntegrationAuthorizations = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceIntegrationAuthorizationsV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Integrations - ); - - const authorizations = await IntegrationAuth.find({ - workspace: workspaceId - }); - - return res.status(200).send({ - authorizations - }); -}; - -/** - * Return service service tokens for workspace [workspaceId] belonging to user - * @param req - * @param res - * @returns - */ -export const getWorkspaceServiceTokens = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceServiceTokensV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.ServiceTokens - ); - - // ?? FIX. - const serviceTokens = await ServiceToken.find({ - user: req.user._id, - workspace: workspaceId - }); - - return res.status(200).send({ - serviceTokens - }); -}; diff --git a/backend-mongo/src/controllers/v2/authController.ts b/backend-mongo/src/controllers/v2/authController.ts deleted file mode 100644 index ce2fae34f..000000000 --- a/backend-mongo/src/controllers/v2/authController.ts +++ /dev/null @@ -1,315 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -import { Request, Response } from "express"; -import jwt from "jsonwebtoken"; -import * as bigintConversion from "bigint-conversion"; -const jsrp = require("jsrp"); -import { LoginSRPDetail, User } from "../../models"; -import { createToken, issueAuthTokens } from "../../helpers/auth"; -import { checkUserDevice } from "../../helpers/user"; -import { sendMail } from "../../helpers/nodemailer"; -import { TokenService } from "../../services"; -import { BadRequestError, InternalServerError } from "../../utils/errors"; -import { AuthTokenType, TOKEN_EMAIL_MFA } from "../../variables"; -import { getAuthSecret, getHttpsEnabled, getJwtMfaLifetime } from "../../config"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/auth"; - -declare module "jsonwebtoken" { - export interface UserIDJwtPayload extends jwt.JwtPayload { - userId: string; - } -} - -/** - * Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol - * @param req - * @param res - * @returns - */ -export const login1 = async (req: Request, res: Response) => { - const { email, clientPublicKey }: { email: string; clientPublicKey: string } = req.body; - - const user = await User.findOne({ - email - }).select("+salt +verifier"); - - if (!user) throw new Error("Failed to find user"); - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier - }, - async () => { - // generate server-side public key - const serverPublicKey = server.getPublicKey(); - - await LoginSRPDetail.findOneAndReplace( - { email: email }, - { - email: email, - clientPublicKey: clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt) - }, - { upsert: true, returnNewDocument: false } - ); - - return res.status(200).send({ - serverPublicKey, - salt: user.salt - }); - } - ); -}; - -/** - * Log in user step 2: complete step 2 of SRP protocol and return token and their (encrypted) - * private key - * @param req - * @param res - * @returns - */ -export const login2 = async (req: Request, res: Response) => { - if (!req.headers["user-agent"]) - throw InternalServerError({ message: "User-Agent header is required" }); - - const { email, clientProof } = req.body; - const user = await User.findOne({ - email - }).select( - "+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices" - ); - - if (!user) throw new Error("Failed to find user"); - - const loginSRPDetail = await LoginSRPDetail.findOneAndDelete({ email: email }); - - if (!loginSRPDetail) { - return BadRequestError(Error("Failed to find login details for SRP")); - } - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetail.serverBInt - }, - async () => { - server.setClientPublicKey(loginSRPDetail.clientPublicKey); - - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - if (user.isMfaEnabled) { - // case: user has MFA enabled - - // generate temporary MFA token - const token = createToken({ - payload: { - authTokenType: AuthTokenType.MFA_TOKEN, - userId: user._id.toString() - }, - expiresIn: await getJwtMfaLifetime(), - secret: await getAuthSecret() - }); - - const code = await TokenService.createToken({ - type: TOKEN_EMAIL_MFA, - email - }); - - // send MFA code [code] to [email] - await sendMail({ - template: "emailMfa.handlebars", - subjectLine: "Infisical MFA code", - recipients: [email], - substitutions: { - code - } - }); - - return res.status(200).send({ - mfaEnabled: true, - token - }); - } - - await checkUserDevice({ - user, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - // store (refresh) token in httpOnly cookie - res.cookie("jid", tokens.refreshToken, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: await getHttpsEnabled() - }); - - // case: user does not have MFA enabled - // return (access) token in response - - interface ResponseData { - mfaEnabled: boolean; - encryptionVersion: any; - protectedKey?: string; - protectedKeyIV?: string; - protectedKeyTag?: string; - token: string; - publicKey?: string; - encryptedPrivateKey?: string; - iv?: string; - tag?: string; - } - - const response: ResponseData = { - mfaEnabled: false, - encryptionVersion: user.encryptionVersion, - token: tokens.token, - publicKey: user.publicKey, - encryptedPrivateKey: user.encryptedPrivateKey, - iv: user.iv, - tag: user.tag - }; - - if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) { - response.protectedKey = user.protectedKey; - response.protectedKeyIV = user.protectedKeyIV; - response.protectedKeyTag = user.protectedKeyTag; - } - - return res.status(200).send(response); - } - - return res.status(400).send({ - message: "Failed to authenticate. Try again?" - }); - } - ); -}; - -/** - * Send MFA token to email [email] - * @param req - * @param res - */ -export const sendMfaToken = async (req: Request, res: Response) => { - const code = await TokenService.createToken({ - type: TOKEN_EMAIL_MFA, - email: req.user.email - }); - - // send MFA code [code] to [email] - await sendMail({ - template: "emailMfa.handlebars", - subjectLine: "Infisical MFA code", - recipients: [req.user.email], - substitutions: { - code - } - }); - - return res.status(200).send({ - message: "Successfully sent new MFA code" - }); -}; - -/** - * Verify MFA token [mfaToken] and issue JWT and refresh tokens if the - * MFA token [mfaToken] is valid - * @param req - * @param res - */ -export const verifyMfaToken = async (req: Request, res: Response) => { - const { - body: { mfaToken } - } = await validateRequest(reqValidator.VerifyMfaTokenV2, req); - - await TokenService.validateToken({ - type: TOKEN_EMAIL_MFA, - email: req.user.email, - token: mfaToken - }); - - const user = await User.findOne({ - email: req.user.email - }).select( - "+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices" - ); - - if (!user) throw new Error("Failed to find user"); - - await LoginSRPDetail.deleteOne({ userId: user.id }); - - await checkUserDevice({ - user, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - // store (refresh) token in httpOnly cookie - res.cookie("jid", tokens.refreshToken, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: await getHttpsEnabled() - }); - - interface VerifyMfaTokenRes { - encryptionVersion: number; - protectedKey?: string; - protectedKeyIV?: string; - protectedKeyTag?: string; - token: string; - publicKey: string; - encryptedPrivateKey: string; - iv: string; - tag: string; - } - - interface VerifyMfaTokenRes { - encryptionVersion: number; - protectedKey?: string; - protectedKeyIV?: string; - protectedKeyTag?: string; - token: string; - publicKey: string; - encryptedPrivateKey: string; - iv: string; - tag: string; - } - - const resObj: VerifyMfaTokenRes = { - encryptionVersion: user.encryptionVersion, - token: tokens.token, - publicKey: user.publicKey as string, - encryptedPrivateKey: user.encryptedPrivateKey as string, - iv: user.iv as string, - tag: user.tag as string - }; - - if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) { - resObj.protectedKey = user.protectedKey; - resObj.protectedKeyIV = user.protectedKeyIV; - resObj.protectedKeyTag = user.protectedKeyTag; - } - - return res.status(200).send(resObj); -}; diff --git a/backend-mongo/src/controllers/v2/environmentController.ts b/backend-mongo/src/controllers/v2/environmentController.ts deleted file mode 100644 index 3b412638b..000000000 --- a/backend-mongo/src/controllers/v2/environmentController.ts +++ /dev/null @@ -1,604 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { - Folder, - Integration, - Membership, - Secret, - ServiceToken, - ServiceTokenData, - Workspace -} from "../../models"; -import { EventType, SecretVersion } from "../../ee/models"; -import { EEAuditLogService, EELicenseService } from "../../ee/services"; -import { BadRequestError, WorkspaceNotFoundError } from "../../utils/errors"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/environments"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; -import { SecretImport } from "../../models"; -import { Webhook } from "../../models"; - -/** - * Create new workspace environment named [environmentName] - * with slug [environmentSlug] under workspace with id - * @param req - * @param res - * @returns - */ -export const createWorkspaceEnvironment = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Create environment' - #swagger.description = 'Create environment' - - #swagger.security = [{ - "apiKeyAuth": [], - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of workspace where to create environment", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "environmentName": { - "type": "string", - "description": "Name of the environment to create", - "example": "development" - }, - "environmentSlug": { - "type": "string", - "description": "Slug of environment to create", - "example": "dev-environment" - } - }, - "required": ["environmentName", "environmentSlug"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Sucess message", - "example": "Successfully created environment" - }, - "workspace": { - "type": "string", - "description": "ID of workspace where environment was created", - "example": "abc123" - }, - "environment": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of created environment", - "example": "Staging" - }, - "slug": { - "type": "string", - "description": "Slug of created environment", - "example": "staging" - } - } - } - }, - "description": "Details of the created environment" - } - } - } - } - */ - const { - params: { workspaceId }, - body: { environmentName, environmentSlug } - } = await validateRequest(reqValidator.CreateWorkspaceEnvironmentV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Environments - ); - - const workspace = await Workspace.findById(workspaceId).exec(); - - if (!workspace) throw WorkspaceNotFoundError(); - - const plan = await EELicenseService.getPlan(workspace.organization); - - if (plan.environmentLimit !== null) { - // case: limit imposed on number of environments allowed - if (workspace.environments.length >= plan.environmentLimit) { - // case: number of environments used exceeds the number of environments allowed - - return res.status(400).send({ - message: - "Failed to create environment due to environment limit reached. Upgrade plan to create more environments." - }); - } - } - - if ( - !workspace || - workspace?.environments.find( - ({ name, slug }) => slug === environmentSlug || environmentName === name - ) - ) { - throw new Error("Failed to create workspace environment"); - } - - workspace?.environments.push({ - name: environmentName, - slug: environmentSlug.toLowerCase() - }); - await workspace.save(); - - await EELicenseService.refreshPlan(workspace.organization, new Types.ObjectId(workspaceId)); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_ENVIRONMENT, - metadata: { - name: environmentName, - slug: environmentSlug - } - }, - { - workspaceId: workspace._id - } - ); - - return res.status(200).send({ - message: "Successfully created new environment", - workspace: workspaceId, - environment: { - name: environmentName, - slug: environmentSlug - } - }); -}; - -/** - * Swaps the ordering of two environments in the database. This is purely for aesthetic purposes. - * @param req - * @param res - * @returns - */ -export const reorderWorkspaceEnvironments = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - body: { environmentName, environmentSlug, otherEnvironmentSlug, otherEnvironmentName } - } = await validateRequest(reqValidator.ReorderWorkspaceEnvironmentsV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Environments - ); - - // atomic update the env to avoid conflict - const workspace = await Workspace.findById(workspaceId).exec(); - if (!workspace) { - throw BadRequestError({ message: "Couldn't load workspace" }); - } - - const environmentIndex = workspace.environments.findIndex( - (env) => env.name === environmentName && env.slug === environmentSlug - ); - const otherEnvironmentIndex = workspace.environments.findIndex( - (env) => env.name === otherEnvironmentName && env.slug === otherEnvironmentSlug - ); - - if (environmentIndex === -1 || otherEnvironmentIndex === -1) { - throw BadRequestError({ message: "environment or otherEnvironment couldn't be found" }); - } - - // swap the order of the environments - [workspace.environments[environmentIndex], workspace.environments[otherEnvironmentIndex]] = [ - workspace.environments[otherEnvironmentIndex], - workspace.environments[environmentIndex] - ]; - - await workspace.save(); - - return res.status(200).send({ - message: "Successfully reordered environments", - workspace: workspaceId - }); -}; - -/** - * Rename workspace environment with new name and slug of a workspace with [workspaceId] - * Old slug [oldEnvironmentSlug] must be provided - * @param req - * @param res - * @returns - */ -export const renameWorkspaceEnvironment = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update environment' - #swagger.description = 'Update environment' - - #swagger.security = [{ - "apiKeyAuth": [], - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of workspace where to update environment", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "environmentName": { - "type": "string", - "description": "Name of environment to update to", - "example": "Staging-Renamed" - }, - "environmentSlug": { - "type": "string", - "description": "Slug of environment to update to", - "example": "staging-renamed" - }, - "oldEnvironmentSlug": { - "type": "string", - "description": "Current slug of environment", - "example": "staging-old" - } - }, - "required": ["environmentName", "environmentSlug", "oldEnvironmentSlug"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "Successfully update environment" - }, - "workspace": { - "type": "string", - "description": "ID of workspace where environment was updated", - "example": "abc123" - }, - "environment": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of updated environment", - "example": "Staging-Renamed" - }, - "slug": { - "type": "string", - "description": "Slug of updated environment", - "example": "staging-renamed" - } - } - } - }, - "description": "Details of the renamed environment" - } - } - } - } - */ - const { - params: { workspaceId }, - body: { environmentName, environmentSlug, oldEnvironmentSlug } - } = await validateRequest(reqValidator.UpdateWorkspaceEnvironmentV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Environments - ); - - // user should pass both new slug and env name - if (!environmentSlug || !environmentName) { - throw new Error("Invalid environment given."); - } - - // atomic update the env to avoid conflict - const workspace = await Workspace.findById(workspaceId).exec(); - if (!workspace) { - throw new Error("Failed to create workspace environment"); - } - - const isEnvExist = workspace.environments.some( - ({ name, slug }) => - slug !== oldEnvironmentSlug && (name === environmentName || slug === environmentSlug) - ); - if (isEnvExist) { - throw new Error("Invalid environment given"); - } - - const envIndex = workspace?.environments.findIndex(({ slug }) => slug === oldEnvironmentSlug); - if (envIndex === -1) { - throw new Error("Invalid environment given"); - } - - const oldEnvironment = workspace.environments[envIndex]; - - workspace.environments[envIndex].name = environmentName; - workspace.environments[envIndex].slug = environmentSlug.toLowerCase(); - - await workspace.save(); - await Secret.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await SecretVersion.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await ServiceToken.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await ServiceTokenData.updateMany( - { - workspace: workspaceId, - "scopes.environment": oldEnvironmentSlug - }, - { $set: { "scopes.$[element].environment": environmentSlug } }, - { arrayFilters: [{ "element.environment": oldEnvironmentSlug }] } - ); - await Integration.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - - await Folder.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - - await SecretImport.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await SecretImport.updateMany( - { workspace: workspaceId, "imports.environment": oldEnvironmentSlug }, - { $set: { "imports.$[element].environment": environmentSlug } }, - { arrayFilters: [{ "element.environment": oldEnvironmentSlug }] }, - ); - - await Webhook.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - - await Membership.updateMany( - { - workspace: workspaceId, - "deniedPermissions.environmentSlug": oldEnvironmentSlug - }, - { $set: { "deniedPermissions.$[element].environmentSlug": environmentSlug } }, - { arrayFilters: [{ "element.environmentSlug": oldEnvironmentSlug }] } - ); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_ENVIRONMENT, - metadata: { - oldName: oldEnvironment.name, - newName: environmentName, - oldSlug: oldEnvironment.slug, - newSlug: environmentSlug.toLowerCase() - } - }, - { - workspaceId: workspace._id - } - ); - - return res.status(200).send({ - message: "Successfully update environment", - workspace: workspaceId, - environment: { - name: environmentName, - slug: environmentSlug - } - }); -}; - -/** - * Delete workspace environment by [environmentSlug] of workspace [workspaceId] and do the clean up - * @param req - * @param res - * @returns - */ -export const deleteWorkspaceEnvironment = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete environment' - #swagger.description = 'Delete environment' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of workspace where to delete environment", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "environmentSlug": { - "type": "string", - "description": "Slug of environment to delete", - "example": "dev" - } - }, - "required": ["environmentSlug"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Success message", - "example": "Successfully deleted environment" - }, - "workspace": { - "type": "string", - "description": "ID of workspace where environment was deleted", - "example": "abc123" - }, - "environment": { - "type": "string", - "description": "Slug of deleted environment", - "example": "dev" - } - }, - "description": "Response after deleting an environment from a workspace" - } - } - } - } -*/ - const { - params: { workspaceId }, - body: { environmentSlug } - } = await validateRequest(reqValidator.DeleteWorkspaceEnvironmentV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Environments - ); - - // atomic update the env to avoid conflict - const workspace = await Workspace.findById(workspaceId).exec(); - if (!workspace) { - throw new Error("Failed to create workspace environment"); - } - - const envIndex = workspace?.environments.findIndex(({ slug }) => slug === environmentSlug); - if (envIndex === -1) { - throw new Error("Invalid environment given"); - } - - const oldEnvironment = workspace.environments[envIndex]; - - workspace.environments.splice(envIndex, 1); - await workspace.save(); - - // clean up - await Secret.deleteMany({ - workspace: workspaceId, - environment: environmentSlug - }); - await SecretVersion.deleteMany({ - workspace: workspaceId, - environment: environmentSlug - }); - - // await ServiceToken.deleteMany({ - // workspace: workspaceId, - // environment: environmentSlug, - // }); - - const result = await ServiceTokenData.updateMany( - { workspace: workspaceId }, - { $pull: { scopes: { environment: environmentSlug } } } - ); - - if (result.modifiedCount > 0) { - await ServiceTokenData.deleteMany({ workspace: workspaceId, scopes: { $size: 0 } }); - } - - await Integration.deleteMany({ - workspace: workspaceId, - environment: environmentSlug - }); - await Membership.updateMany( - { workspace: workspaceId }, - { $pull: { deniedPermissions: { environmentSlug: environmentSlug } } } - ); - - await EELicenseService.refreshPlan(workspace.organization, new Types.ObjectId(workspaceId)); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_ENVIRONMENT, - metadata: { - name: oldEnvironment.name, - slug: oldEnvironment.slug - } - }, - { - workspaceId: workspace._id - } - ); - - return res.status(200).send({ - message: "Successfully deleted environment", - workspace: workspaceId, - environment: environmentSlug - }); -}; \ No newline at end of file diff --git a/backend-mongo/src/controllers/v2/index.ts b/backend-mongo/src/controllers/v2/index.ts deleted file mode 100644 index e06efe46c..000000000 --- a/backend-mongo/src/controllers/v2/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as authController from "./authController"; -import * as signupController from "./signupController"; -import * as usersController from "./usersController"; -import * as organizationsController from "./organizationsController"; -import * as workspaceController from "./workspaceController"; -import * as serviceTokenDataController from "./serviceTokenDataController"; -import * as secretController from "./secretController"; -import * as secretsController from "./secretsController"; -import * as environmentController from "./environmentController"; -import * as tagController from "./tagController"; -import * as membershipController from "./membershipController"; - -export { - authController, - signupController, - usersController, - organizationsController, - workspaceController, - serviceTokenDataController, - secretController, - secretsController, - environmentController, - tagController, - membershipController -}; diff --git a/backend-mongo/src/controllers/v2/membershipController.ts b/backend-mongo/src/controllers/v2/membershipController.ts deleted file mode 100644 index d6d25dad5..000000000 --- a/backend-mongo/src/controllers/v2/membershipController.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { ForbiddenError } from "@casl/ability"; -import { Request, Response } from "express"; -import { Types } from "mongoose"; - -import { getSiteURL } from "../../config"; -import { EventType } from "../../ee/models"; -import { EEAuditLogService } from "../../ee/services"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { sendMail } from "../../helpers"; -import { validateRequest } from "../../helpers/validation"; -import { IUser, Key, Membership, MembershipOrg, Workspace } from "../../models"; -import { BadRequestError } from "../../utils/errors"; -import * as reqValidator from "../../validation/membership"; -import { ACCEPTED, MEMBER } from "../../variables"; - -export const addUserToWorkspace = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - body: { members } - } = await validateRequest(reqValidator.AddUserToWorkspaceV2, req); - // check workspace - const workspace = await Workspace.findById(workspaceId); - if (!workspace) throw new Error("Failed to find workspace"); - - // check permission - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Member - ); - - // validate members are part of the organization - const orgMembers = await MembershipOrg.find({ - status: ACCEPTED, - _id: { $in: members.map(({ orgMembershipId }) => orgMembershipId) }, - organization: workspace.organization - }) - .populate<{ user: IUser }>("user") - .select({ _id: 1, user: 1 }) - .lean(); - if (orgMembers.length !== members.length) - throw BadRequestError({ message: "Org member not found" }); - - const existingMember = await Membership.find({ - workspace: workspaceId, - user: { $in: orgMembers.map(({ user }) => user) } - }); - if (existingMember?.length) - throw BadRequestError({ message: "Some users are already part of workspace" }); - - await Membership.insertMany( - orgMembers.map(({ user }) => ({ user: user._id, workspace: workspaceId, role: MEMBER })) - ); - - const encKeyGroupedByOrgMemberId = members.reduce>( - (prev, curr) => ({ ...prev, [curr.orgMembershipId]: curr }), - {} - ); - await Key.insertMany( - orgMembers.map(({ user, _id: id }) => ({ - encryptedKey: encKeyGroupedByOrgMemberId[id.toString()].workspaceEncryptedKey, - nonce: encKeyGroupedByOrgMemberId[id.toString()].workspaceEncryptedNonce, - sender: req.user._id, - receiver: user._id, - workspace: workspaceId - })) - ); - - await sendMail({ - template: "workspaceInvitation.handlebars", - subjectLine: "Infisical workspace invitation", - recipients: orgMembers.map(({ user }) => user.email), - substitutions: { - inviterFirstName: req.user.firstName, - inviterEmail: req.user.email, - workspaceName: workspace.name, - callback_url: (await getSiteURL()) + "/login" - } - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.ADD_BATCH_WORKSPACE_MEMBER, - metadata: orgMembers.map(({ user }) => ({ - userId: user._id.toString(), - email: user.email - })) - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.status(200).send({ - success: true, - data: orgMembers - }); -}; diff --git a/backend-mongo/src/controllers/v2/organizationsController.ts b/backend-mongo/src/controllers/v2/organizationsController.ts deleted file mode 100644 index c6c49e23d..000000000 --- a/backend-mongo/src/controllers/v2/organizationsController.ts +++ /dev/null @@ -1,505 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { - IWorkspace, - Identity, - IdentityMembership, - IdentityMembershipOrg, - Membership, - MembershipOrg, - User, - Workspace -} from "../../models"; -import { Role } from "../../ee/models"; -import { deleteMembershipOrg } from "../../helpers/membershipOrg"; -import { - createOrganization as create, - deleteOrganization, - updateSubscriptionOrgQuantity -} from "../../helpers/organization"; -import { addMembershipsOrg } from "../../helpers/membershipOrg"; -import { BadRequestError, ResourceNotFoundError, UnauthorizedRequestError } from "../../utils/errors"; -import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS } from "../../variables"; -import * as reqValidator from "../../validation/organization"; -import { validateRequest } from "../../helpers/validation"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions -} from "../../ee/services/RoleService"; -import { EELicenseService } from "../../ee/services"; -import { ForbiddenError } from "@casl/ability"; - -/** - * Return memberships for organization with id [organizationId] - * @param req - * @param res - */ -export const getOrganizationMemberships = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return organization user memberships' - #swagger.description = 'Return organization user memberships' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['organizationId'] = { - "description": "ID of organization", - "required": true, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "memberships": { - "type": "array", - "items": { - $ref: "#/components/schemas/MembershipOrg" - }, - "description": "Memberships of organization" - } - } - } - } - } - } - */ - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgMembersv2, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Member - ); - - const memberships = await MembershipOrg.find({ - organization: organizationId - }).populate("user", "+publicKey"); - - return res.status(200).send({ - memberships - }); -}; - -/** - * Update role of membership with id [membershipId] to role [role] - * @param req - * @param res - */ -export const updateOrganizationMembership = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update organization user membership' - #swagger.description = 'Update organization user membership' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['organizationId'] = { - "description": "ID of organization", - "required": true, - "type": "string" - } - - #swagger.parameters['membershipId'] = { - "description": "ID of organization membership to update", - "required": true, - "type": "string" - } - - #swagger.requestBody = { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "Role of organization membership - either owner, admin, or member", - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "membership": { - $ref: "#/components/schemas/MembershipOrg", - "description": "Updated organization membership" - } - } - } - } - } - } - */ - const { - params: { organizationId, membershipId }, - body: { role } - } = await validateRequest(reqValidator.UpdateOrgMemberv2, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.Member - ); - - const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role); - if (isCustomRole) { - const orgRole = await Role.findOne({ - slug: role, - isOrgRole: true, - organization: new Types.ObjectId(organizationId) - }); - - if (!orgRole) throw BadRequestError({ message: "Role not found" }); - - const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId)); - - if (!plan.rbac) return res.status(400).send({ - message: - "Failed to assign custom role due to RBAC restriction. Upgrade plan to assign custom role to member." - }); - - const membership = await MembershipOrg.findByIdAndUpdate(membershipId, { - role: CUSTOM, - customRole: orgRole - }); - return res.status(200).send({ - membership - }); - } - - const membership = await MembershipOrg.findByIdAndUpdate( - membershipId, - { - $set: { - role - }, - $unset: { - customRole: 1 - } - }, - { - new: true - } - ); - - return res.status(200).send({ - membership - }); -}; - -/** - * Delete organization membership with id [membershipId] - * @param req - * @param res - * @returns - */ -export const deleteOrganizationMembership = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete organization user membership' - #swagger.description = 'Delete organization user membership' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['organizationId'] = { - "description": "ID of organization", - "required": true, - "type": "string" - } - - #swagger.parameters['membershipId'] = { - "description": "ID of organization membership to delete", - "required": true, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "membership": { - $ref: "#/components/schemas/MembershipOrg", - "description": "Deleted organization membership" - } - } - } - } - } - } - */ - const { - params: { organizationId, membershipId } - } = await validateRequest(reqValidator.DeleteOrgMemberv2, req); - - const membershipOrg = await MembershipOrg.findOne({ - _id: new Types.ObjectId(membershipId), - organization: new Types.ObjectId(organizationId) - }); - - if (!membershipOrg) throw ResourceNotFoundError(); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: membershipOrg.organization - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Delete, - OrgPermissionSubjects.Member - ); - - // delete organization membership - const membership = await deleteMembershipOrg({ - membershipOrgId: membershipId - }); - - await updateSubscriptionOrgQuantity({ - organizationId: membership.organization.toString() - }); - - return res.status(200).send({ - membership - }); -}; - -/** - * Return workspaces for organization with id [organizationId] that user has - * access to - * @param req - * @param res - */ -export const getOrganizationWorkspaces = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return projects in organization that user is part of' - #swagger.description = 'Return projects in organization that user is part of' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['organizationId'] = { - "description": "ID of organization", - "required": true, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaces": { - "type": "array", - "items": { - $ref: "#/components/schemas/Project" - }, - "description": "Projects of organization" - } - } - } - } - } - } - */ - - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgWorkspacesv2, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Workspace - ); - - const workspacesSet = new Set( - ( - await Workspace.find( - { - organization: organizationId - }, - "_id" - ) - ).map((w) => w._id.toString()) - ); - - let workspaces: IWorkspace[] = []; - - if (req.authData.authPayload instanceof Identity) { - workspaces = ( - await IdentityMembership.find({ - identity: req.authData.authPayload._id - }).populate<{ workspace: IWorkspace }>("workspace") - ) - .filter((m) => workspacesSet.has(m.workspace._id.toString())) - .map((m) => m.workspace); - } - - if (req.authData.authPayload instanceof User) { - workspaces = ( - await Membership.find({ - user: req.authData.authPayload._id - }).populate<{ workspace: IWorkspace }>("workspace") - ) - .filter((m) => workspacesSet.has(m.workspace._id.toString())) - .map((m) => m.workspace); - } - - return res.status(200).send({ - workspaces - }); -}; - -/** - * Create new organization named [organizationName] - * and add user as owner - * @param req - * @param res - * @returns - */ -export const createOrganization = async (req: Request, res: Response) => { - const { - body: { name } - } = await validateRequest(reqValidator.CreateOrgv2, req); - - // create organization and add user as member - const organization = await create({ - email: req.user.email, - name - }); - - await addMembershipsOrg({ - userIds: [req.user._id.toString()], - organizationId: organization._id.toString(), - roles: [ADMIN], - statuses: [ACCEPTED] - }); - - return res.status(200).send({ - organization - }); -}; - -/** - * Delete organization with id [organizationId] - * @param req - * @param res - */ -export const deleteOrganizationById = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.DeleteOrgv2, req); - - const membershipOrg = await MembershipOrg.findOne({ - user: req.user._id, - organization: new Types.ObjectId(organizationId), - role: ADMIN - }); - - if (!membershipOrg) throw UnauthorizedRequestError(); - - const organization = await deleteOrganization({ - organizationId: new Types.ObjectId(organizationId) - }); - - return res.status(200).send({ - organization - }); -}; - -/** - * Return list of identity memberships for organization with id [organizationId] - * @param req - * @param res - * @returns - */ - export const getOrganizationIdentityMemberships = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return organization identity memberships' - #swagger.description = 'Return organization identity memberships' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['organizationId'] = { - "description": "ID of organization", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityMemberships": { - "type": "array", - "items": { - $ref: "#/components/schemas/IdentityMembershipOrg" - }, - "description": "Identity memberships of organization" - } - } - } - } - } - } - */ - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgIdentityMembershipsV2, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Identity - ); - - const identityMemberships = await IdentityMembershipOrg.find({ - organization: new Types.ObjectId(organizationId) - }).populate("identity customRole"); - - return res.status(200).send({ - identityMemberships - }); -} \ No newline at end of file diff --git a/backend-mongo/src/controllers/v2/secretController.ts b/backend-mongo/src/controllers/v2/secretController.ts deleted file mode 100644 index 28fab01a4..000000000 --- a/backend-mongo/src/controllers/v2/secretController.ts +++ /dev/null @@ -1,419 +0,0 @@ -import { Request, Response } from "express"; -import mongoose, { Types } from "mongoose"; -import { - CreateSecretRequestBody, - ModifySecretRequestBody, - SanitizedSecretForCreate, - SanitizedSecretModify -} from "../../types/secret"; -const { ValidationError } = mongoose.Error; -import { - ValidationError as RouteValidationError, - UnauthorizedRequestError -} from "../../utils/errors"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_UTF8, - SECRET_PERSONAL, - SECRET_SHARED -} from "../../variables"; -import { TelemetryService } from "../../services"; -import { Secret, User } from "../../models"; -import { AccountNotFoundError } from "../../utils/errors"; - -/** - * Create secret for workspace with id [workspaceId] and environment [environment] - * @param req - * @param res - */ -export const createSecret = async (req: Request, res: Response) => { - const postHogClient = await TelemetryService.getPostHogClient(); - const secretToCreate: CreateSecretRequestBody = req.body.secret; - const { workspaceId, environment } = req.params; - const sanitizedSecret: SanitizedSecretForCreate = { - secretKeyCiphertext: secretToCreate.secretKeyCiphertext, - secretKeyIV: secretToCreate.secretKeyIV, - secretKeyTag: secretToCreate.secretKeyTag, - secretKeyHash: secretToCreate.secretKeyHash, - secretValueCiphertext: secretToCreate.secretValueCiphertext, - secretValueIV: secretToCreate.secretValueIV, - secretValueTag: secretToCreate.secretValueTag, - secretValueHash: secretToCreate.secretValueHash, - secretCommentCiphertext: secretToCreate.secretCommentCiphertext, - secretCommentIV: secretToCreate.secretCommentIV, - secretCommentTag: secretToCreate.secretCommentTag, - secretCommentHash: secretToCreate.secretCommentHash, - workspace: new Types.ObjectId(workspaceId), - environment, - type: secretToCreate.type, - user: new Types.ObjectId(req.user._id), - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }; - - const secret = await new Secret(sanitizedSecret).save(); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets added", - distinctId: req.user.email, - properties: { - numberOfSecrets: 1, - workspaceId, - environment, - channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli", - userAgent: req.headers?.["user-agent"] - } - }); - } - - res.status(200).send({ - secret - }); -}; - -/** - * Create many secrets for workspace with id [workspaceId] and environment [environment] - * @param req - * @param res - */ -export const createSecrets = async (req: Request, res: Response) => { - const postHogClient = await TelemetryService.getPostHogClient(); - const secretsToCreate: CreateSecretRequestBody[] = req.body.secrets; - const { workspaceId, environment } = req.params; - const sanitizedSecretesToCreate: SanitizedSecretForCreate[] = []; - - secretsToCreate.forEach((rawSecret) => { - const safeUpdateFields: SanitizedSecretForCreate = { - secretKeyCiphertext: rawSecret.secretKeyCiphertext, - secretKeyIV: rawSecret.secretKeyIV, - secretKeyTag: rawSecret.secretKeyTag, - secretKeyHash: rawSecret.secretKeyHash, - secretValueCiphertext: rawSecret.secretValueCiphertext, - secretValueIV: rawSecret.secretValueIV, - secretValueTag: rawSecret.secretValueTag, - secretValueHash: rawSecret.secretValueHash, - secretCommentCiphertext: rawSecret.secretCommentCiphertext, - secretCommentIV: rawSecret.secretCommentIV, - secretCommentTag: rawSecret.secretCommentTag, - secretCommentHash: rawSecret.secretCommentHash, - workspace: new Types.ObjectId(workspaceId), - environment, - type: rawSecret.type, - user: new Types.ObjectId(req.user._id), - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }; - - sanitizedSecretesToCreate.push(safeUpdateFields); - }); - - const secrets = await Secret.insertMany(sanitizedSecretesToCreate); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets added", - distinctId: req.user.email, - properties: { - numberOfSecrets: (secretsToCreate ?? []).length, - workspaceId, - environment, - channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli", - userAgent: req.headers?.["user-agent"] - } - }); - } - - res.status(200).send({ - secrets - }); -}; - -/** - * Delete secrets in workspace with id [workspaceId] and environment [environment] - * @param req - * @param res - */ -export const deleteSecrets = async (req: Request, res: Response) => { - const postHogClient = await TelemetryService.getPostHogClient(); - const { workspaceId, environmentName } = req.params; - const secretIdsToDelete: string[] = req.body.secretIds; - - const secretIdsUserCanDelete = await Secret.find({ workspace: workspaceId, environment: environmentName }, { _id: 1 }); - - const secretsUserCanDeleteSet: Set = new Set( - secretIdsUserCanDelete.map((objectId) => objectId._id.toString()) - ); - - // Filter out IDs that user can delete and then map them to delete operations - const deleteOperationsToPerform = secretIdsToDelete - .filter(secretIdToDelete => { - if (!secretsUserCanDeleteSet.has(secretIdToDelete)) { - throw RouteValidationError({ - message: "You cannot delete secrets that you do not have access to" - }); - } - return true; - }) - .map(secretIdToDelete => ({ - deleteOne: { filter: { _id: new Types.ObjectId(secretIdToDelete) } } - })); - - const numSecretsDeleted = deleteOperationsToPerform.length; - - await Secret.bulkWrite(deleteOperationsToPerform); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets deleted", - distinctId: req.user.email, - properties: { - numberOfSecrets: numSecretsDeleted, - environment: environmentName, - workspaceId, - channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli", - userAgent: req.headers?.["user-agent"] - } - }); - } - - res.status(200).send(); -}; - -/** - * Delete secret with id [secretId] - * @param req - * @param res - */ -export const deleteSecret = async (req: Request, res: Response) => { - const postHogClient = await TelemetryService.getPostHogClient(); - await Secret.findByIdAndDelete(req._secret._id); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets deleted", - distinctId: req.user.email, - properties: { - numberOfSecrets: 1, - workspaceId: req._secret.workspace.toString(), - environment: req._secret.environment, - channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli", - userAgent: req.headers?.["user-agent"] - } - }); - } - - res.status(200).send({ - secret: req._secret - }); -}; - -/** - * Update secrets for workspace with id [workspaceId] and environment [environment] - * @param req - * @param res - * @returns - */ -export const updateSecrets = async (req: Request, res: Response) => { - const postHogClient = await TelemetryService.getPostHogClient(); - const { workspaceId, environmentName } = req.params; - const secretsModificationsRequested: ModifySecretRequestBody[] = req.body.secrets; - const secretIdsUserCanModify = await Secret.find({ workspace: workspaceId, environment: environmentName }, { _id: 1 }); - - const secretsUserCanModifySet: Set = new Set( - secretIdsUserCanModify.map((objectId) => objectId._id.toString()) - ); - const updateOperationsToPerform: any = []; - - secretsModificationsRequested.forEach((userModifiedSecret) => { - if (secretsUserCanModifySet.has(userModifiedSecret._id.toString())) { - const sanitizedSecret: SanitizedSecretModify = { - secretKeyCiphertext: userModifiedSecret.secretKeyCiphertext, - secretKeyIV: userModifiedSecret.secretKeyIV, - secretKeyTag: userModifiedSecret.secretKeyTag, - secretKeyHash: userModifiedSecret.secretKeyHash, - secretValueCiphertext: userModifiedSecret.secretValueCiphertext, - secretValueIV: userModifiedSecret.secretValueIV, - secretValueTag: userModifiedSecret.secretValueTag, - secretValueHash: userModifiedSecret.secretValueHash, - secretCommentCiphertext: userModifiedSecret.secretCommentCiphertext, - secretCommentIV: userModifiedSecret.secretCommentIV, - secretCommentTag: userModifiedSecret.secretCommentTag, - secretCommentHash: userModifiedSecret.secretCommentHash - }; - - const updateOperation = { - updateOne: { - filter: { _id: userModifiedSecret._id, workspace: workspaceId }, - update: { $inc: { version: 1 }, $set: sanitizedSecret } - } - }; - updateOperationsToPerform.push(updateOperation); - } else { - throw UnauthorizedRequestError({ - message: "You do not have permission to modify one or more of the requested secrets" - }); - } - }); - - await Secret.bulkWrite(updateOperationsToPerform); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets modified", - distinctId: req.user.email, - properties: { - numberOfSecrets: (secretsModificationsRequested ?? []).length, - environment: environmentName, - workspaceId, - channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli", - userAgent: req.headers?.["user-agent"] - } - }); - } - - return res.status(200).send(); -}; - -/** - * Update a secret within workspace with id [workspaceId] and environment [environment] - * @param req - * @param res - * @returns - */ -export const updateSecret = async (req: Request, res: Response) => { - const postHogClient = await TelemetryService.getPostHogClient(); - const { workspaceId, environmentName } = req.params; - const secretModificationsRequested: ModifySecretRequestBody = req.body.secret; - - await Secret.findOne({ workspace: workspaceId, environment: environmentName }, { _id: 1 }); - - const sanitizedSecret: SanitizedSecretModify = { - secretKeyCiphertext: secretModificationsRequested.secretKeyCiphertext, - secretKeyIV: secretModificationsRequested.secretKeyIV, - secretKeyTag: secretModificationsRequested.secretKeyTag, - secretKeyHash: secretModificationsRequested.secretKeyHash, - secretValueCiphertext: secretModificationsRequested.secretValueCiphertext, - secretValueIV: secretModificationsRequested.secretValueIV, - secretValueTag: secretModificationsRequested.secretValueTag, - secretValueHash: secretModificationsRequested.secretValueHash, - secretCommentCiphertext: secretModificationsRequested.secretCommentCiphertext, - secretCommentIV: secretModificationsRequested.secretCommentIV, - secretCommentTag: secretModificationsRequested.secretCommentTag, - secretCommentHash: secretModificationsRequested.secretCommentHash - }; - - const singleModificationUpdate = await Secret.updateOne( - { _id: secretModificationsRequested._id, workspace: workspaceId }, - { $inc: { version: 1 }, $set: sanitizedSecret } - ) - .catch((error) => { - if (error instanceof ValidationError) { - throw RouteValidationError({ - message: "Unable to apply modifications, please try again", - stack: error.stack - }); - } - - throw error; - }); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets modified", - distinctId: req.user.email, - properties: { - numberOfSecrets: 1, - environment: environmentName, - workspaceId, - channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli", - userAgent: req.headers?.["user-agent"] - } - }); - } - - return res.status(200).send(singleModificationUpdate); -}; - -/** - * Return secrets for workspace with id [workspaceId], environment [environment] and user - * with id [req.user._id] - * @param req - * @param res - * @returns - */ -export const getSecrets = async (req: Request, res: Response) => { - const postHogClient = await TelemetryService.getPostHogClient(); - const { environment } = req.query; - const { workspaceId } = req.params; - - let userId: Types.ObjectId | undefined = undefined; // used for getting personal secrets for user - let userEmail: string | undefined = undefined; // used for posthog - if (req.user) { - userId = req.user._id; - userEmail = req.user.email; - } - - if (req.serviceTokenData) { - userId = req.serviceTokenData.user; - - const user = await User.findById(req.serviceTokenData.user, "email"); - if (!user) throw AccountNotFoundError(); - userEmail = user.email; - } - - const secrets = await Secret.find({ - workspace: workspaceId, - environment, - $or: [{ user: userId }, { user: { $exists: false } }], - type: { $in: [SECRET_SHARED, SECRET_PERSONAL] } - }) - .catch((err) => { - throw RouteValidationError({ - message: "Failed to get secrets, please try again", - stack: err.stack - }); - }) - - if (postHogClient) { - postHogClient.capture({ - event: "secrets pulled", - distinctId: userEmail, - properties: { - numberOfSecrets: (secrets ?? []).length, - environment, - workspaceId, - channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli", - userAgent: req.headers?.["user-agent"] - } - }); - } - - return res.json(secrets); -}; - -/** - * Return secret with id [secretId] - * @param req - * @param res - * @returns - */ -export const getSecret = async (req: Request, res: Response) => { - // if (postHogClient) { - // postHogClient.capture({ - // event: 'secrets pulled', - // distinctId: req.user.email, - // properties: { - // numberOfSecrets: 1, - // workspaceId: req._secret.workspace.toString(), - // environment: req._secret.environment, - // channel: req.headers?.['user-agent']?.toLowerCase().includes('mozilla') ? 'web' : 'cli', - // userAgent: req.headers?.['user-agent'] - // } - // }); - // } - - return res.status(200).send({ - secret: req._secret - }); -}; diff --git a/backend-mongo/src/controllers/v2/secretsController.ts b/backend-mongo/src/controllers/v2/secretsController.ts deleted file mode 100644 index 362221bf4..000000000 --- a/backend-mongo/src/controllers/v2/secretsController.ts +++ /dev/null @@ -1,1300 +0,0 @@ -import { Types } from "mongoose"; -import { Request, Response } from "express"; -import { Folder, ISecret, Secret, ServiceTokenData, Tag } from "../../models"; -import { AuditLog, EventType, SecretVersion } from "../../ee/models"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_UTF8, - K8_USER_AGENT_NAME, - SECRET_PERSONAL -} from "../../variables"; -import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors"; -import { EventService } from "../../services"; -import { eventPushSecrets } from "../../events"; -import { EEAuditLogService, EESecretService } from "../../ee/services"; -import { SecretService, TelemetryService } from "../../services"; -import { getUserAgentType } from "../../utils/posthog"; -import { PERMISSION_WRITE_SECRETS } from "../../variables"; -import { - userHasNoAbility, - userHasWorkspaceAccess, - userHasWriteOnlyAbility -} from "../../ee/helpers/checkMembershipPermissions"; -import _ from "lodash"; -import { - getFolderByPath, - getFolderIdFromServiceToken, - searchByFolderId, - searchByFolderIdWithDir -} from "../../services/FolderService"; -import { isValidScope } from "../../helpers/secrets"; -import path from "path"; -import { getAllImportedSecrets } from "../../services/SecretImportService"; -import { validateRequest } from "../../helpers/validation"; -import { - BatchSecretsV2, - GetSecretsV2, - validateServiceTokenDataClientForWorkspace -} from "../../validation"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError, subject } from "@casl/ability"; - -/** - * Peform a batch of any specified CUD secret operations - * (used by dashboard) - * @param req - * @param res - */ -export const batchSecrets = async (req: Request, res: Response) => { - const channel = getUserAgentType(req.headers["user-agent"]); - const postHogClient = await TelemetryService.getPostHogClient(); - - const validatedData = await validateRequest(BatchSecretsV2, req); - const { - body: { workspaceId, environment, requests } - } = validatedData; - let { - body: { secretPath, folderId } - } = validatedData; - - const secretIds = requests - .filter(({ method }) => method !== "POST") - // akhilmhdh: ts is dumb - .map((el) => new Types.ObjectId((el.secret as any)._id)); - - const oldSecrets = await Secret.find({ - _id: { - $in: secretIds - } - }); - if (oldSecrets.length != secretIds.length) { - throw BadRequestError({ message: "Failed to validate non-existent secrets" }); - } - - const createSecrets: any[] = []; - const updateSecrets: any[] = []; - const deleteSecrets: { _id: Types.ObjectId; secretName: string }[] = []; - - // get secret blind index salt - const salt = await SecretService.getSecretBlindIndexSalt({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - if (secretPath !== "/") { - folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath); - } - - if (folderId !== "root") { - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - if (!folders) throw BadRequestError({ message: "Folder not found" }); - - const folder = searchByFolderIdWithDir(folders.nodes, folderId as string); - if (!folder?.folder) throw BadRequestError({ message: "Folder not found" }); - - secretPath = path.join( - "/", - ...folder.dir.map(({ name }) => name).filter((name) => name !== "root") - ); - } - - if (req.authData.authPayload instanceof ServiceTokenData) { - await validateServiceTokenDataClientForWorkspace({ - serviceTokenData: req.authData.authPayload, - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath, - requiredPermissions: [PERMISSION_WRITE_SECRETS] - }); - } - - for await (const request of requests) { - // do a validation - - let secretBlindIndex = ""; - switch (request.method) { - case "POST": - secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt({ - secretName: request.secret.secretName, - salt - }); - - createSecrets.push({ - ...request.secret, - version: 1, - user: request.secret.type === SECRET_PERSONAL ? req.user : undefined, - environment, - workspace: workspaceId, - folder: folderId, - secretBlindIndex, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }); - break; - case "PATCH": - secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt({ - secretName: request.secret.secretName, - salt - }); - - updateSecrets.push({ - ...request.secret, - _id: request.secret._id, - secretBlindIndex, - folder: folderId, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }); - break; - case "DELETE": - deleteSecrets.push({ - _id: new Types.ObjectId(request.secret._id), - secretName: request.secret.secretName - }); - break; - } - } - // not using service token using auth - if (!(req.authData.authPayload instanceof ServiceTokenData)) { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - if (createSecrets.length) - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - subject(ProjectPermissionSub.Secrets, { environment, secretPath }) - ); - - if (updateSecrets.length) - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - subject(ProjectPermissionSub.Secrets, { environment, secretPath }) - ); - - if (deleteSecrets.length) - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - subject(ProjectPermissionSub.Secrets, { environment, secretPath }) - ); - } - - // handle create secrets - let createdSecrets: ISecret[] = []; - if (createSecrets.length > 0) { - createdSecrets = (await Secret.insertMany(createSecrets)) as any; - // (EE) add secret versions for new secrets - await EESecretService.addSecretVersions({ - secretVersions: createdSecrets.map((n: any) => { - return { - ...n._doc, - _id: new Types.ObjectId(), - secret: n._id, - isDeleted: false - }; - }) - }); - - const auditLogs = await Promise.all( - createdSecrets.map((secret, index) => { - return EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_SECRET, - metadata: { - environment: secret.environment, - secretPath: secretPath ?? "/", - secretId: secret._id.toString(), - secretKey: createSecrets[index].secretName, - secretVersion: secret.version - } - }, - { - workspaceId: secret.workspace - }, - false - ); - }) - ); - - await AuditLog.insertMany(auditLogs); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets added", - distinctId: req.user.email, - properties: { - numberOfSecrets: createdSecrets.length, - environment, - workspaceId, - folderId, - channel, - userAgent: req.headers?.["user-agent"] - } - }); - } - } - - // handle update secrets - let updatedSecrets: ISecret[] = []; - if (updateSecrets.length > 0 && oldSecrets) { - // construct object containing all secrets - let listedSecretsObj: { - [key: string]: { - version: number; - type: string; - }; - } = {}; - - listedSecretsObj = oldSecrets.reduce( - (obj: any, secret: ISecret) => ({ - ...obj, - [secret._id.toString()]: secret - }), - {} - ); - - const updateOperations = updateSecrets.map((u) => ({ - updateOne: { - filter: { - _id: new Types.ObjectId(u._id), - workspace: new Types.ObjectId(workspaceId), - environment - }, - update: { - $inc: { - version: 1 - }, - $unset: { - "metadata.source": true as const - }, - ...u, - _id: new Types.ObjectId(u._id) - } - } - })); - await Secret.bulkWrite(updateOperations); - - const secretVersions = updateSecrets.map( - (u) => - new SecretVersion({ - secret: new Types.ObjectId(u._id), - version: listedSecretsObj[u._id.toString()].version, - workspace: new Types.ObjectId(workspaceId), - type: listedSecretsObj[u._id.toString()].type, - environment, - isDeleted: false, - secretBlindIndex: u.secretBlindIndex, - secretKeyCiphertext: u.secretKeyCiphertext, - secretKeyIV: u.secretKeyIV, - secretKeyTag: u.secretKeyTag, - secretValueCiphertext: u.secretValueCiphertext, - secretValueIV: u.secretValueIV, - secretValueTag: u.secretValueTag, - secretCommentCiphertext: u.secretCommentCiphertext, - secretCommentIV: u.secretCommentIV, - secretCommentTag: u.secretCommentTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - tags: u.tags, - folder: u.folder - }) - ); - - await EESecretService.addSecretVersions({ - secretVersions - }); - - updatedSecrets = await Secret.find({ - _id: { - $in: updateSecrets.map((u) => new Types.ObjectId(u._id)) - } - }); - - const auditLogs = await Promise.all( - updateSecrets.map((secret) => { - return EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_SECRET, - metadata: { - environment, - secretPath: secretPath ?? "/", - secretId: secret._id.toString(), - secretKey: secret.secretName, - secretVersion: listedSecretsObj[secret._id.toString()].version - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - }, - false - ); - }) - ); - - await AuditLog.insertMany(auditLogs); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets modified", - distinctId: req.user.email, - properties: { - numberOfSecrets: updateSecrets.length, - environment, - workspaceId, - folderId, - channel, - userAgent: req.headers?.["user-agent"] - } - }); - } - } - - // handle delete secrets - if (deleteSecrets.length > 0) { - const deleteSecretIds: Types.ObjectId[] = deleteSecrets.map((s) => s._id); - - const deletedSecretsObj = ( - await Secret.find({ - _id: { - $in: deleteSecretIds - } - }) - ).reduce( - (obj: any, secret: ISecret) => ({ - ...obj, - [secret._id.toString()]: secret - }), - {} - ); - - await Secret.deleteMany({ - _id: { - $in: deleteSecretIds - }, - workspace: new Types.ObjectId(workspaceId), - environment - }); - - await EESecretService.markDeletedSecretVersions({ - secretIds: deleteSecretIds - }); - - const auditLogs = await Promise.all( - deleteSecrets.map((secret) => { - return EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_SECRET, - metadata: { - environment, - secretPath: secretPath ?? "/", - secretId: secret._id.toString(), - secretKey: secret.secretName, - secretVersion: deletedSecretsObj[secret._id.toString()].version - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - }, - false - ); - }) - ); - - await AuditLog.insertMany(auditLogs); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets deleted", - distinctId: req.user.email, - properties: { - numberOfSecrets: deleteSecrets.length, - environment, - workspaceId, - channel: channel, - userAgent: req.headers?.["user-agent"] - } - }); - } - } - - // // trigger event - push secrets - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - // root condition else this will be filled according to the path or folderid - secretPath: secretPath || "/" - }) - }); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - folderId - }); - - const resObj: { [key: string]: ISecret[] | string[] } = {}; - - if (createSecrets.length > 0) { - resObj["createdSecrets"] = createdSecrets; - } - - if (updateSecrets.length > 0) { - resObj["updatedSecrets"] = updatedSecrets; - } - - if (deleteSecrets.length > 0) { - resObj["deletedSecrets"] = deleteSecrets.map((d) => d._id.toString()); - } - - return res.status(200).send(resObj); -}; - -/** - * Create secret(s) for workspace with id [workspaceId] and environment [environment] - * @param req - * @param res - */ -export const createSecrets = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Create new secret(s)' - #swagger.description = 'Create one or many secrets for a given project and environment.' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.requestBody = { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of project", - }, - "environment": { - "type": "string", - "description": "Environment within project" - }, - "secrets": { - $ref: "#/components/schemas/CreateSecret", - "description": "Secret(s) to create - object or array of objects" - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - $ref: "#/components/schemas/Secret" - }, - "description": "Newly-created secrets for the given project and environment" - } - } - } - } - } - } - */ - - const channel = getUserAgentType(req.headers["user-agent"]); - const { - workspaceId, - environment, - secretPath - }: { - workspaceId: string; - environment: string; - secretPath?: string; - } = req.body; - let folderId = req.body.folderId; - - if (req.user) { - const hasAccess = await userHasWorkspaceAccess( - req.user, - new Types.ObjectId(workspaceId), - environment, - PERMISSION_WRITE_SECRETS - ); - if (!hasAccess) { - throw UnauthorizedRequestError({ - message: "You do not have the necessary permission(s) perform this action" - }); - } - } - - let listOfSecretsToCreate; - if (Array.isArray(req.body.secrets)) { - // case: create multiple secrets - listOfSecretsToCreate = req.body.secrets; - } else if (typeof req.body.secrets === "object") { - // case: create 1 secret - listOfSecretsToCreate = [req.body.secrets]; - } - - if (req.authData.authPayload instanceof ServiceTokenData) { - const isValidScopeAccess = isValidScope( - req.authData.authPayload, - environment, - secretPath || "/" - ); - - // in service token when not giving secretpath folderid must be root - // this is to avoid giving folderid when service tokens are used - if ((!secretPath && folderId !== "root") || (secretPath && !isValidScopeAccess)) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } - if (secretPath) { - folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath); - } - - // get secret blind index salt - const salt = await SecretService.getSecretBlindIndexSalt({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - type secretsToCreateType = { - type: string; - secretName?: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - tags: string[]; - }; - - const secretsToInsert: ISecret[] = await Promise.all( - listOfSecretsToCreate.map( - async ({ - type, - secretName, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - tags - }: secretsToCreateType) => { - let secretBlindIndex; - if (secretName) { - secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt({ - secretName, - salt - }); - } - - return { - version: 1, - workspace: new Types.ObjectId(workspaceId), - type, - folderId, - ...(secretBlindIndex ? { secretBlindIndex } : {}), - user: req.user && type === SECRET_PERSONAL ? req.user : undefined, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - tags - }; - } - ) - ); - - const newlyCreatedSecrets: ISecret[] = (await Secret.insertMany(secretsToInsert)).map( - (insertedSecret) => insertedSecret.toObject() - ); - - setTimeout(async () => { - // trigger event - push secrets - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath: secretPath || "/" - }) - }); - }, 5000); - - // (EE) add secret versions for new secrets - await EESecretService.addSecretVersions({ - secretVersions: newlyCreatedSecrets.map( - ({ - _id, - version, - workspace, - type, - user, - environment, - secretBlindIndex, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag - }) => - new SecretVersion({ - secret: _id, - version, - workspace, - type, - user, - environment, - secretBlindIndex, - isDeleted: false, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - folder: folderId, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }) - ) - }); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - folderId - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - if (postHogClient) { - postHogClient.capture({ - event: "secrets added", - distinctId: await TelemetryService.getDistinctId({ - authData: req.authData - }), - properties: { - numberOfSecrets: listOfSecretsToCreate.length, - environment, - workspaceId, - channel: channel, - folderId, - userAgent: req.headers?.["user-agent"] - } - }); - } - - return res.status(200).send({ - secrets: newlyCreatedSecrets - }); -}; - -/** - * Return secret(s) for workspace with id [workspaceId], environment [environment] and user - * with id [req.user._id] - * @param req - * @param res - * @returns - */ -export const getSecrets = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Read secrets' - #swagger.description = 'Read secrets from a project and environment' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project", - "required": true, - "type": "string" - } - - #swagger.parameters['environment'] = { - "description": "Environment within project", - "required": true, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - $ref: "#/components/schemas/Secret" - }, - "description": "Secrets for the given project and environment" - } - } - } - } - } - } - */ - - const validatedData = await validateRequest(GetSecretsV2, req); - const { - query: { tagSlugs, secretPath, include_imports, workspaceId, environment } - } = validatedData; - let { - query: { folderId } - } = validatedData; - - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - - if ( - // if no folders and asking for a non root folder id or non root secret path - (!folders && folderId && folderId !== "root") || - (!folders && secretPath && secretPath !== "/") - ) { - res.send({ secrets: [] }); - return; - } - - if (folders && folderId !== "root") { - const folder = searchByFolderId(folders.nodes, folderId as string); - if (!folder) { - res.send({ secrets: [] }); - return; - } - } - - if (req.authData.authPayload instanceof ServiceTokenData) { - const isValidScopeAccess = isValidScope( - req.authData.authPayload, - environment, - (secretPath as string) || "/" - ); - - // in service token when not giving secretpath folderid must be root - // this is to avoid giving folderid when service tokens are used - if ((!secretPath && folderId !== "root") || (secretPath && !isValidScopeAccess)) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } - - if (folders && secretPath) { - // avoid throwing error and send empty list - const folder = getFolderByPath(folders.nodes, secretPath as string); - if (!folder) { - res.send({ secrets: [] }); - return; - } - folderId = folder.id; - } - - // secrets to return - let secrets: ISecret[] = []; - - // query tags table to get all tags ids for the tag names for the given workspace - let tagIds = []; - const tagNamesList = typeof tagSlugs === "string" && tagSlugs !== "" ? tagSlugs.split(",") : []; - if (tagNamesList != undefined && tagNamesList.length != 0) { - const workspaceFromDB = await Tag.find({ workspace: workspaceId }); - tagIds = _.map(tagNamesList, (tagName: string) => { - const tag = _.find(workspaceFromDB, { slug: tagName }); - return tag ? tag.id : null; - }); - } - - if (req.user) { - // case: client authorization is via JWT - const hasWriteOnlyAccess = await userHasWriteOnlyAbility( - req.user._id, - new Types.ObjectId(workspaceId), - environment - ); - const hasNoAccess = await userHasNoAbility( - req.user._id, - new Types.ObjectId(workspaceId), - environment - ); - if (hasNoAccess) { - throw UnauthorizedRequestError({ - message: "You do not have the necessary permission(s) perform this action" - }); - } - - const secretQuery: any = { - workspace: workspaceId, - environment, - folder: folderId, - $or: [ - { user: req.user._id }, // personal secrets for this user - { user: { $exists: false } } // shared secrets from workspace - ] - }; - - if (tagIds.length > 0) { - secretQuery.tags = { $in: tagIds }; - } - - if (hasWriteOnlyAccess) { - // only return the secret keys and not the values since user does not have right to see values - secrets = await Secret.find(secretQuery) - .select("secretKeyCiphertext secretKeyIV secretKeyTag") - .populate("tags"); - } else { - secrets = await Secret.find(secretQuery).populate("tags"); - } - } - - // case: client authorization is via service token - if (req.serviceTokenData) { - const userId = req.serviceTokenData.user; - - const secretQuery: any = { - workspace: workspaceId, - folder: folderId, - environment, - $or: [ - { user: userId }, // personal secrets for this user - { user: { $exists: false } } // shared secrets from workspace - ] - }; - - if (tagIds.length > 0) { - secretQuery.tags = { $in: tagIds }; - } - - // TODO check if service token has write only permission - - secrets = await Secret.find(secretQuery).populate("tags"); - } - - // TODO(akhilmhdh) - secret-imp change this to org type - let importedSecrets: any[] = []; - if (include_imports) { - // depreciated - importedSecrets = await getAllImportedSecrets( - workspaceId, - environment, - folderId as string, - () => false - ); - } - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.GET_SECRETS, - metadata: { - environment, - secretPath: (secretPath as string) ?? "/", - numberOfSecrets: secrets.length - } - }, - { - workspaceId: new Types.ObjectId(workspaceId as string) - } - ); - - const postHogClient = await TelemetryService.getPostHogClient(); - - // reduce the number of events captured - let shouldRecordK8Event = false; - if (req.authData.userAgent == K8_USER_AGENT_NAME) { - const randomNumber = Math.random(); - if (randomNumber > 0.9) { - shouldRecordK8Event = true; - } - } - - if (postHogClient) { - const shouldCapture = req.authData.userAgent !== K8_USER_AGENT_NAME || shouldRecordK8Event; - const approximateForNoneCapturedEvents = secrets.length * 10; - - if (shouldCapture) { - postHogClient.capture({ - event: "secrets pulled", - distinctId: await TelemetryService.getDistinctId({ - authData: req.authData - }), - properties: { - numberOfSecrets: shouldRecordK8Event ? approximateForNoneCapturedEvents : secrets.length, - environment, - workspaceId, - folderId, - channel: req.authData.userAgentType, - userAgent: req.authData.userAgent - } - }); - } - } - - return res.status(200).send({ - secrets, - ...(include_imports && { imports: importedSecrets }) - }); -}; - -/** - * Update secret(s) - * @param req - * @param res - */ -export const updateSecrets = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update secret(s)' - #swagger.description = 'Update secret(s)' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.requestBody = { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - $ref: "#/components/schemas/UpdateSecret", - "description": "Secret(s) to update - object or array of objects" - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - $ref: "#/components/schemas/Secret" - }, - "description": "Updated secrets" - } - } - } - } - } - } - */ - const channel = req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli"; - - interface PatchSecret { - id: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - tags: string[]; - } - - const updateOperationsToPerform = req.body.secrets.map((secret: PatchSecret) => { - const { - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - tags - } = secret; - - return { - updateOne: { - filter: { _id: new Types.ObjectId(secret.id) }, - update: { - $inc: { - version: 1 - }, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - tags, - ...(secretCommentCiphertext !== undefined && secretCommentIV && secretCommentTag - ? { - secretCommentCiphertext, - secretCommentIV, - secretCommentTag - } - : {}) - } - } - }; - }); - - await Secret.bulkWrite(updateOperationsToPerform); - - const secretModificationsBySecretId: { [key: string]: PatchSecret } = {}; - req.body.secrets.forEach((secret: PatchSecret) => { - secretModificationsBySecretId[secret.id] = secret; - }); - - const ListOfSecretsBeforeModifications = req.secrets; - const secretVersions = { - secretVersions: ListOfSecretsBeforeModifications.map((secret: ISecret) => { - const { - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - tags - } = secretModificationsBySecretId[secret._id.toString()]; - - return { - secret: secret._id, - version: secret.version + 1, - workspace: secret.workspace, - type: secret.type, - environment: secret.environment, - secretKeyCiphertext: secretKeyCiphertext ? secretKeyCiphertext : secret.secretKeyCiphertext, - secretKeyIV: secretKeyIV ? secretKeyIV : secret.secretKeyIV, - secretKeyTag: secretKeyTag ? secretKeyTag : secret.secretKeyTag, - secretValueCiphertext: secretValueCiphertext - ? secretValueCiphertext - : secret.secretValueCiphertext, - secretValueIV: secretValueIV ? secretValueIV : secret.secretValueIV, - secretValueTag: secretValueTag ? secretValueTag : secret.secretValueTag, - secretCommentCiphertext: secretCommentCiphertext - ? secretCommentCiphertext - : secret.secretCommentCiphertext, - secretCommentIV: secretCommentIV ? secretCommentIV : secret.secretCommentIV, - secretCommentTag: secretCommentTag ? secretCommentTag : secret.secretCommentTag, - tags: tags ? tags : secret.tags, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }; - }) - }; - - await EESecretService.addSecretVersions(secretVersions); - - // group secrets into workspaces so updated secrets can - // be logged and snapshotted separately for each workspace - const workspaceSecretObj: any = {}; - req.secrets.forEach((s: any) => { - if (s.workspace.toString() in workspaceSecretObj) { - workspaceSecretObj[s.workspace.toString()].push(s); - } else { - workspaceSecretObj[s.workspace.toString()] = [s]; - } - }); - - Object.keys(workspaceSecretObj).forEach(async (key) => { - // trigger event - push secrets - // This route is not used anymore thus keep it commented out as it does not expose environment - // it will end up creating a lot of requests from the server - // setTimeout(async () => { - // await EventService.handleEvent({ - // event: eventPushSecrets({ - // workspaceId: new Types.ObjectId(key), - // environment, - // }) - // }); - // }, 10000); - - // (EE) take a secret snapshot - // IMP(akhilmhdh): commented out due to unknown where the environment is - // await EESecretService.takeSecretSnapshot({ - // workspaceId: new Types.ObjectId(key), - // environment, - // folderId, - // }); - - const postHogClient = await TelemetryService.getPostHogClient(); - if (postHogClient) { - postHogClient.capture({ - event: "secrets modified", - distinctId: await TelemetryService.getDistinctId({ - authData: req.authData - }), - properties: { - numberOfSecrets: workspaceSecretObj[key].length, - environment: workspaceSecretObj[key][0].environment, - workspaceId: key, - channel: channel, - userAgent: req.headers?.["user-agent"] - } - }); - } - }); - - return res.status(200).send({ - secrets: await Secret.find({ - _id: { - $in: req.secrets.map((secret: ISecret) => secret._id) - } - }) - }); -}; - -/** - * Delete secret(s) - * @param req - * @param res - */ -export const deleteSecrets = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete secret(s)' - #swagger.description = 'Delete one or many secrets by their ID(s)' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.requestBody = { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secretIds": { - "type": "string", - "description": "ID(s) of secrets - string or array of strings" - }, - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - $ref: "#/components/schemas/Secret" - }, - "description": "Deleted secrets" - } - } - } - } - } - } - */ - - const channel = getUserAgentType(req.headers["user-agent"]); - const toDelete = req.secrets.map((s: any) => s._id); - - await Secret.deleteMany({ - _id: { - $in: toDelete - } - }); - - await EESecretService.markDeletedSecretVersions({ - secretIds: toDelete - }); - - // group secrets into workspaces so deleted secrets can - // be logged and snapshotted separately for each workspace - const workspaceSecretObj: any = {}; - req.secrets.forEach((s: any) => { - if (s.workspace.toString() in workspaceSecretObj) { - workspaceSecretObj[s.workspace.toString()].push(s); - } else { - workspaceSecretObj[s.workspace.toString()] = [s]; - } - }); - - Object.keys(workspaceSecretObj).forEach(async (key) => { - // trigger event - push secrets - // DEPRECIATED(akhilmhdh): as this would cause server to send so many request - // and this route is not used anymore thus like snapshot keeping it commented out - // await EventService.handleEvent({ - // event: eventPushSecrets({ - // workspaceId: new Types.ObjectId(key) - // }) - // }); - - // (EE) take a secret snapshot - // IMP(akhilmhdh): Not sure how to take secretSnapshot - // await EESecretService.takeSecretSnapshot({ - // workspaceId: new Types.ObjectId(key), - // }); - - const postHogClient = await TelemetryService.getPostHogClient(); - if (postHogClient) { - postHogClient.capture({ - event: "secrets deleted", - distinctId: await TelemetryService.getDistinctId({ - authData: req.authData - }), - properties: { - numberOfSecrets: workspaceSecretObj[key].length, - environment: workspaceSecretObj[key][0].environment, - workspaceId: key, - channel: channel, - userAgent: req.headers?.["user-agent"] - } - }); - } - }); - - return res.status(200).send({ - secrets: req.secrets - }); -}; diff --git a/backend-mongo/src/controllers/v2/serviceTokenDataController.ts b/backend-mongo/src/controllers/v2/serviceTokenDataController.ts deleted file mode 100644 index 19a412dce..000000000 --- a/backend-mongo/src/controllers/v2/serviceTokenDataController.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { Request, Response } from "express"; -import crypto from "crypto"; -import bcrypt from "bcrypt"; -import { ServiceTokenData } from "../../models"; -import { getSaltRounds } from "../../config"; -import { BadRequestError } from "../../utils/errors"; -import { ActorType, EventType } from "../../ee/models"; -import { EEAuditLogService } from "../../ee/services"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/serviceTokenData"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError, subject } from "@casl/ability"; -import { Types } from "mongoose"; - -/** - * Return service token data associated with service token on request - * @param req - * @param res - * @returns - */ -export const getServiceTokenData = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return Infisical Token data' - #swagger.description = 'Return Infisical Token data' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "serviceTokenData": { - "type": "object", - $ref: "#/components/schemas/ServiceTokenData", - "description": "Details of service token" - } - } - } - } - } - } - */ - - if (!(req.authData.authPayload instanceof ServiceTokenData)) - throw BadRequestError({ - message: "Failed accepted client validation for service token data" - }); - - const serviceTokenData = await ServiceTokenData.findById(req.authData.authPayload._id) - .select("+encryptedKey +iv +tag") - .populate("user") - .lean(); - - return res.status(200).json(serviceTokenData); -}; - -/** - * Create new service token data for workspace with id [workspaceId] and - * environment [environment]. - * @param req - * @param res - * @returns - */ -export const createServiceTokenData = async (req: Request, res: Response) => { - let serviceTokenData; - - const { - body: { workspaceId, permissions, tag, encryptedKey, scopes, name, expiresIn, iv } - } = await validateRequest(reqValidator.CreateServiceTokenV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.ServiceTokens - ); - - scopes.forEach(({ environment, secretPath }) => { - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - subject(ProjectPermissionSub.Secrets, { environment, secretPath: secretPath }) - ); - }) - - - const secret = crypto.randomBytes(16).toString("hex"); - const secretHash = await bcrypt.hash(secret, await getSaltRounds()); - - let expiresAt; - if (expiresIn) { - expiresAt = new Date(); - expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); - } - - let user; - - if (req.authData.actor.type === ActorType.USER) { - user = req.authData.authPayload._id; - } - - serviceTokenData = await new ServiceTokenData({ - name, - workspace: workspaceId, - user, - scopes, - lastUsed: new Date(), - expiresAt, - secretHash, - encryptedKey, - iv, - tag, - permissions - }).save(); - - // return service token data without sensitive data - serviceTokenData = await ServiceTokenData.findById(serviceTokenData._id); - - if (!serviceTokenData) throw new Error("Failed to find service token data"); - - const serviceToken = `st.${serviceTokenData._id.toString()}.${secret}`; - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_SERVICE_TOKEN, - metadata: { - name, - scopes - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.status(200).send({ - serviceToken, - serviceTokenData - }); -}; - -/** - * Delete service token data with id [serviceTokenDataId]. - * @param req - * @param res - * @returns - */ -export const deleteServiceTokenData = async (req: Request, res: Response) => { - const { - params: { serviceTokenDataId } - } = await validateRequest(reqValidator.DeleteServiceTokenV2, req); - - let serviceTokenData = await ServiceTokenData.findById(serviceTokenDataId); - if (!serviceTokenData) throw BadRequestError({ message: "Service token not found" }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: serviceTokenData.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.ServiceTokens - ); - - serviceTokenData = await ServiceTokenData.findByIdAndDelete(serviceTokenDataId); - - if (!serviceTokenData) - return res.status(200).send({ - message: "Failed to delete service token" - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_SERVICE_TOKEN, - metadata: { - name: serviceTokenData.name, - scopes: serviceTokenData?.scopes - } - }, - { - workspaceId: serviceTokenData.workspace - } - ); - - return res.status(200).send({ - serviceTokenData - }); -}; diff --git a/backend-mongo/src/controllers/v2/signupController.ts b/backend-mongo/src/controllers/v2/signupController.ts deleted file mode 100644 index 66daf5701..000000000 --- a/backend-mongo/src/controllers/v2/signupController.ts +++ /dev/null @@ -1,262 +0,0 @@ -import { Request, Response } from "express"; -import { MembershipOrg, User } from "../../models"; -import { completeAccount } from "../../helpers/user"; -import { - initializeDefaultOrg, -} from "../../helpers/signup"; -import { issueAuthTokens } from "../../helpers/auth"; -import { ACCEPTED, INVITED } from "../../variables"; -import { standardRequest } from "../../config/request"; -import { getHttpsEnabled, getLoopsApiKey } from "../../config"; -import { updateSubscriptionOrgQuantity } from "../../helpers/organization"; - -/** - * Complete setting up user by adding their personal and auth information as part of the - * signup flow - * @param req - * @param res - * @returns - */ -export const completeAccountSignup = async (req: Request, res: Response) => { - let user; - const { - email, - firstName, - lastName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - organizationName, - }: { - email: string; - firstName: string; - lastName: string; - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - publicKey: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; - salt: string; - verifier: string; - organizationName: string; - } = req.body; - - // get user - user = await User.findOne({ email }); - - if (!user || (user && user?.publicKey)) { - // case 1: user doesn't exist. - // case 2: user has already completed account - return res.status(403).send({ - error: "Failed to complete account for complete user", - }); - } - - // complete setting up user's account - user = await completeAccount({ - userId: user._id.toString(), - firstName, - lastName, - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - }); - - if (!user) - throw new Error("Failed to complete account for non-existent user"); // ensure user is non-null - - // initialize default organization and workspace - await initializeDefaultOrg({ - organizationName, - user, - }); - - // update organization membership statuses that are - // invited to completed with user attached - const membershipsToUpdate = await MembershipOrg.find({ - inviteEmail: email, - status: INVITED, - }); - - membershipsToUpdate.forEach(async (membership) => { - await updateSubscriptionOrgQuantity({ - organizationId: membership.organization.toString(), - }); - }); - - // update organization membership statuses that are - // invited to completed with user attached - await MembershipOrg.updateMany( - { - inviteEmail: email, - status: INVITED, - }, - { - user, - status: ACCEPTED, - } - ); - - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "", - }); - - const token = tokens.token; - - // sending a welcome email to new users - if (await getLoopsApiKey()) { - await standardRequest.post("https://app.loops.so/api/v1/events/send", { - "email": email, - "eventName": "Sign Up", - "firstName": firstName, - "lastName": lastName, - }, { - headers: { - "Accept": "application/json", - "Authorization": "Bearer " + (await getLoopsApiKey()), - }, - }); - } - - // store (refresh) token in httpOnly cookie - res.cookie("jid", tokens.refreshToken, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: await getHttpsEnabled(), - }); - - return res.status(200).send({ - message: "Successfully set up account", - user, - token, - }); -}; - -/** - * Complete setting up user by adding their personal and auth information as part of the - * invite flow - * @param req - * @param res - * @returns - */ -export const completeAccountInvite = async (req: Request, res: Response) => { - let user; - const { - email, - firstName, - lastName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - } = req.body; - - // get user - user = await User.findOne({ email }); - - if (!user || (user && user?.publicKey)) { - // case 1: user doesn't exist. - // case 2: user has already completed account - return res.status(403).send({ - error: "Failed to complete account for complete user", - }); - } - - const membershipOrg = await MembershipOrg.findOne({ - inviteEmail: email, - status: INVITED, - }); - - if (!membershipOrg) throw new Error("Failed to find invitations for email"); - - // complete setting up user's account - user = await completeAccount({ - userId: user._id.toString(), - firstName, - lastName, - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - }); - - if (!user) - throw new Error("Failed to complete account for non-existent user"); - - // update organization membership statuses that are - // invited to completed with user attached - const membershipsToUpdate = await MembershipOrg.find({ - inviteEmail: email, - status: INVITED, - }); - - membershipsToUpdate.forEach(async (membership) => { - await updateSubscriptionOrgQuantity({ - organizationId: membership.organization.toString(), - }); - }); - - await MembershipOrg.updateMany( - { - inviteEmail: email, - status: INVITED, - }, - { - user, - status: ACCEPTED, - } - ); - - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "", - }); - - const token = tokens.token; - - // store (refresh) token in httpOnly cookie - res.cookie("jid", tokens.refreshToken, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: await getHttpsEnabled(), - }); - - return res.status(200).send({ - message: "Successfully set up account", - user, - token, - }); -}; diff --git a/backend-mongo/src/controllers/v2/tagController.ts b/backend-mongo/src/controllers/v2/tagController.ts deleted file mode 100644 index c803b0e18..000000000 --- a/backend-mongo/src/controllers/v2/tagController.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { ForbiddenError } from "@casl/ability"; -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { Secret, Tag } from "../../models"; -import { BadRequestError } from "../../utils/errors"; -import { validateRequest } from "../../helpers/validation"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import * as reqValidator from "../../validation/tags"; - -export const createWorkspaceTag = async (req: Request, res: Response) => { - const { - body: { name, slug }, - params: { workspaceId } - } = await validateRequest(reqValidator.CreateWorkspaceTagsV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Tags - ); - - const tagToCreate = { - name, - workspace: new Types.ObjectId(workspaceId), - slug, - user: new Types.ObjectId(req.user._id) - }; - - const createdTag = await new Tag(tagToCreate).save(); - - res.json(createdTag); -}; - -export const deleteWorkspaceTag = async (req: Request, res: Response) => { - const { - params: { tagId } - } = await validateRequest(reqValidator.DeleteWorkspaceTagsV2, req); - - const tagFromDB = await Tag.findById(tagId); - if (!tagFromDB) { - throw BadRequestError(); - } - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: tagFromDB.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Tags - ); - - const result = await Tag.findByIdAndDelete(tagId); - - // remove the tag from secrets - await Secret.updateMany({ tags: { $in: [tagId] } }, { $pull: { tags: tagId } }); - - res.json(result); -}; - -export const getWorkspaceTags = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceTagsV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Tags - ); - - const workspaceTags = await Tag.find({ - workspace: new Types.ObjectId(workspaceId) - }); - - return res.json({ - workspaceTags - }); -}; diff --git a/backend-mongo/src/controllers/v2/usersController.ts b/backend-mongo/src/controllers/v2/usersController.ts deleted file mode 100644 index 3998956f7..000000000 --- a/backend-mongo/src/controllers/v2/usersController.ts +++ /dev/null @@ -1,314 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import crypto from "crypto"; -import bcrypt from "bcrypt"; -import { APIKeyData, AuthMethod, MembershipOrg, TokenVersion, User } from "../../models"; -import { getSaltRounds } from "../../config"; -import { validateRequest } from "../../helpers/validation"; -import { deleteUser } from "../../helpers/user"; -import * as reqValidator from "../../validation"; - -/** - * Update the current user's MFA-enabled status [isMfaEnabled]. - * Note: Infisical currently only supports email-based 2FA only; this will expand to - * include SMS and authenticator app modes of authentication in the future. - * @param req - * @param res - * @returns - */ -export const updateMyMfaEnabled = async (req: Request, res: Response) => { - const { - body: { isMfaEnabled } - } = await validateRequest(reqValidator.UpdateMyMfaEnabledV2, req); - - req.user.isMfaEnabled = isMfaEnabled; - - if (isMfaEnabled) { - // TODO: adapt this route/controller - // to work for different forms of MFA - req.user.mfaMethods = ["email"]; - } else { - req.user.mfaMethods = []; - } - - await req.user.save(); - - const user = req.user; - - return res.status(200).send({ - user - }); -}; - -/** - * Update name of the current user to [firstName, lastName]. - * @param req - * @param res - * @returns - */ -export const updateName = async (req: Request, res: Response) => { - const { - body: { lastName, firstName } - } = await validateRequest(reqValidator.UpdateNameV2, req); - - const user = await User.findByIdAndUpdate( - req.user._id.toString(), - { - firstName, - lastName: lastName ?? "" - }, - { - new: true - } - ); - - return res.status(200).send({ - user - }); -}; - -/** - * Update auth method of the current user to [authMethods] - * @param req - * @param res - * @returns - */ -export const updateAuthMethods = async (req: Request, res: Response) => { - const { - body: { authMethods } - } = await validateRequest(reqValidator.UpdateAuthMethodsV2, req); - - const hasSamlEnabled = req.user.authMethods.some((authMethod: AuthMethod) => - [AuthMethod.OKTA_SAML, AuthMethod.AZURE_SAML, AuthMethod.JUMPCLOUD_SAML].includes(authMethod) - ); - - if (hasSamlEnabled) { - return res.status(400).send({ - message: "Failed to update user authentication method because SAML SSO is enforced" - }); - } - - const user = await User.findByIdAndUpdate( - req.user._id.toString(), - { - authMethods - }, - { - new: true - } - ); - - return res.status(200).send({ - user - }); -}; - -/** - * Return organizations that the current user is part of. - * @param req - * @param res - */ -export const getMyOrganizations = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return organizations that current user is part of' - #swagger.description = 'Return organizations that current user is part of' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "organizations": { - "type": "array", - "items": { - $ref: "#/components/schemas/Organization" - }, - "description": "Organizations that user is part of" - } - } - } - } - } - } - */ - const organizations = ( - await MembershipOrg.find({ - user: req.user._id - }).populate("organization") - ).map((m) => m.organization); - - return res.status(200).send({ - organizations - }); -}; - -/** - * Return API keys belonging to current user. - * @param req - * @param res - * @returns - */ -export const getMyAPIKeys = async (req: Request, res: Response) => { - const apiKeyData = await APIKeyData.find({ - user: req.user._id - }); - - return res.status(200).send(apiKeyData); -}; - -/** - * Create new API key for current user. - * @param req - * @param res - * @returns - */ -export const createAPIKey = async (req: Request, res: Response) => { - const { - body: { name, expiresIn } - } = await validateRequest(reqValidator.CreateApiKeyV2, req); - - const secret = crypto.randomBytes(16).toString("hex"); - const secretHash = await bcrypt.hash(secret, await getSaltRounds()); - - const expiresAt = new Date(); - expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); - - let apiKeyData = await new APIKeyData({ - name, - lastUsed: new Date(), - expiresAt, - user: req.user._id, - secretHash - }).save(); - - // return api key data without sensitive data - apiKeyData = (await APIKeyData.findById(apiKeyData._id)) as any; - - if (!apiKeyData) throw new Error("Failed to find API key data"); - - const apiKey = `ak.${apiKeyData._id.toString()}.${secret}`; - - return res.status(200).send({ - apiKey, - apiKeyData - }); -}; - -/** - * Delete API key with id [apiKeyDataId] belonging to current user - * @param req - * @param res - */ -export const deleteAPIKey = async (req: Request, res: Response) => { - const { - params: { apiKeyDataId } - } = await validateRequest(reqValidator.DeleteApiKeyV2, req); - - const apiKeyData = await APIKeyData.findOneAndDelete({ - _id: new Types.ObjectId(apiKeyDataId), - user: req.user._id - }); - - return res.status(200).send({ - apiKeyData - }); -}; - -/** - * Return active sessions (TokenVersion) belonging to user - * @param req - * @param res - * @returns - */ -export const getMySessions = async (req: Request, res: Response) => { - const tokenVersions = await TokenVersion.find({ - user: req.user._id - }); - - return res.status(200).send(tokenVersions); -}; - -/** - * Revoke all active sessions belong to user - * @param req - * @param res - * @returns - */ -export const deleteMySessions = async (req: Request, res: Response) => { - await TokenVersion.updateMany( - { - user: req.user._id - }, - { - $inc: { - refreshVersion: 1, - accessVersion: 1 - } - } - ); - - return res.status(200).send({ - message: "Successfully revoked all sessions" - }); -}; - -/** - * Return the current user. - * @param req - * @param res - * @returns - */ - export const getMe = async (req: Request, res: Response) => { - /* - #swagger.summary = "Retrieve the current user on the request" - #swagger.description = "Retrieve the current user on the request" - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "user": { - "type": "object", - $ref: "#/components/schemas/CurrentUser", - "description": "Current user on request" - } - } - } - } - } - } - */ - const user = await User.findById(req.user._id).select( - "+salt +publicKey +encryptedPrivateKey +iv +tag +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag" - ); - - return res.status(200).send({ - user - }); -}; - -/** - * Delete the current user. - * @param req - * @param res - */ -export const deleteMe = async (req: Request, res: Response) => { - const user = await deleteUser({ - userId: req.user._id - }); - - return res.status(200).send({ - user - }); -} \ No newline at end of file diff --git a/backend-mongo/src/controllers/v2/workspaceController.ts b/backend-mongo/src/controllers/v2/workspaceController.ts deleted file mode 100644 index dca217a1b..000000000 --- a/backend-mongo/src/controllers/v2/workspaceController.ts +++ /dev/null @@ -1,883 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { - IIdentity, - IdentityMembership, - IdentityMembershipOrg, - Key, - Membership, - ServiceTokenData, - Workspace -} from "../../models"; -import { IRole, Role } from "../../ee/models"; -import { - pullSecrets as pull, - v2PushSecrets as push, - reformatPullSecrets -} from "../../helpers/secret"; -import { pushKeys } from "../../helpers/key"; -import { EventService, TelemetryService } from "../../services"; -import { eventPushSecrets } from "../../events"; -import { EEAuditLogService } from "../../ee/services"; -import { EventType } from "../../ee/models"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions, - getWorkspaceRolePermissions, - isAtLeastAsPrivilegedWorkspace -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; -import { BadRequestError, ForbiddenRequestError, ResourceNotFoundError } from "../../utils/errors"; -import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables"; - -interface V2PushSecret { - type: string; // personal or shared - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretKeyHash: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretValueHash: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - secretCommentHash?: string; -} - -/** - * Upload (encrypted) secrets to workspace with id [workspaceId] - * for environment [environment] - * @param req - * @param res - * @returns - */ -export const pushWorkspaceSecrets = async (req: Request, res: Response) => { - // upload (encrypted) secrets to workspace with id [workspaceId] - const postHogClient = await TelemetryService.getPostHogClient(); - let { secrets }: { secrets: V2PushSecret[] } = req.body; - const { keys, environment, channel } = req.body; - const { workspaceId } = req.params; - - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error("Failed to validate environment"); - } - - // sanitize secrets - secrets = secrets.filter( - (s: V2PushSecret) => s.secretKeyCiphertext !== "" && s.secretValueCiphertext !== "" - ); - - await push({ - userId: req.user._id, - workspaceId, - environment, - secrets, - channel: channel ? channel : "cli", - ipAddress: req.realIP - }); - - await pushKeys({ - userId: req.user._id, - workspaceId, - keys - }); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets pushed", - distinctId: req.user.email, - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : "cli" - } - }); - } - - // trigger event - push secrets - EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath: "/" - }) - }); - - return res.status(200).send({ - message: "Successfully uploaded workspace secrets" - }); -}; - -/** - * Return (encrypted) secrets for workspace with id [workspaceId] - * for environment [environment] - * @param req - * @param res - * @returns - */ -export const pullSecrets = async (req: Request, res: Response) => { - let secrets; - const postHogClient = await TelemetryService.getPostHogClient(); - const environment: string = req.query.environment as string; - const channel: string = req.query.channel as string; - const { workspaceId } = req.params; - - let userId; - if (req.user) { - userId = req.user._id.toString(); - } else if (req.serviceTokenData) { - userId = req.serviceTokenData.user.toString(); - } - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error("Failed to validate environment"); - } - - secrets = await pull({ - userId, - workspaceId, - environment, - channel: channel ? channel : "cli", - ipAddress: req.realIP - }); - - if (channel !== "cli") { - secrets = reformatPullSecrets({ secrets }); - } - - if (postHogClient) { - // capture secrets pushed event in production - postHogClient.capture({ - distinctId: req.user.email, - event: "secrets pulled", - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : "cli" - } - }); - } - - return res.status(200).send({ - secrets - }); -}; - -export const getWorkspaceKey = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return encrypted project key' - #swagger.description = 'Return encrypted project key' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project", - "required": true, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "array", - "items": { - $ref: "#/components/schemas/ProjectKey" - }, - "description": "Encrypted project key for the given project" - } - } - } - } - */ - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceKeyV2, req); - - const key = await Key.findOne({ - workspace: workspaceId, - receiver: req.user._id - }).populate("sender", "+publicKey"); - - if (!key) throw new Error(`getWorkspaceKey: Failed to find workspace key [workspaceId=${workspaceId}] [receiver=${req.user._id}]`); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.GET_WORKSPACE_KEY, - metadata: { - keyId: key._id.toString() - } - }, - { - workspaceId: new Types.ObjectId(workspaceId) - } - ); - - return res.status(200).json(key); -}; - -export const getWorkspaceServiceTokenData = async (req: Request, res: Response) => { - const { workspaceId } = req.params; - - const serviceTokenData = await ServiceTokenData.find({ - workspace: workspaceId - }).select("+encryptedKey +iv +tag"); - - return res.status(200).send({ - serviceTokenData - }); -}; - -/** - * Return memberships for workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ -export const getWorkspaceMemberships = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return project user memberships' - #swagger.description = 'Return project user memberships' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project", - "required": true, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "memberships": { - "type": "array", - "items": { - $ref: "#/components/schemas/Membership" - }, - "description": "Memberships of project" - } - } - } - } - } - } - */ - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceMembershipsV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Member - ); - - const memberships = await Membership.find({ - workspace: workspaceId - }).populate("user", "+publicKey"); - - return res.status(200).send({ - memberships - }); -}; - -/** - * Update role of membership with id [membershipId] to role [role] - * @param req - * @param res - * @returns - */ -export const updateWorkspaceMembership = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update project user membership' - #swagger.description = 'Update project user membership' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project", - "required": true, - "type": "string" - } - - #swagger.parameters['membershipId'] = { - "description": "ID of project membership to update", - "required": true, - "type": "string" - } - - #swagger.requestBody = { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "Role to update to for project membership", - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "membership": { - $ref: "#/components/schemas/Membership", - "description": "Updated membership" - } - } - } - } - } - } - */ - const { - params: { workspaceId, membershipId }, - body: { role } - } = await validateRequest(reqValidator.UpdateWorkspaceMembershipsV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Member - ); - - const membership = await Membership.findByIdAndUpdate( - membershipId, - { - role - }, - { - new: true - } - ); - - return res.status(200).send({ - membership - }); -}; - -/** - * Delete workspace membership with id [membershipId] - * @param req - * @param res - * @returns - */ -export const deleteWorkspaceMembership = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete project user membership' - #swagger.description = 'Delete project user membership' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project", - "required": true, - "type": "string" - } - - #swagger.parameters['membershipId'] = { - "description": "ID of project membership to delete", - "required": true, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "membership": { - $ref: "#/components/schemas/Membership", - "description": "Deleted membership" - } - } - } - } - } - } - */ - const { - params: { workspaceId, membershipId } - } = await validateRequest(reqValidator.DeleteWorkspaceMembershipsV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Member - ); - - const membership = await Membership.findByIdAndDelete(membershipId); - - if (!membership) throw new Error("Failed to delete workspace membership"); - - await Key.deleteMany({ - receiver: membership.user, - workspace: membership.workspace - }); - - return res.status(200).send({ - membership - }); -}; - -/** - * Change autoCapitilzation Rule of workspace - * @param req - * @param res - * @returns - */ -export const toggleAutoCapitalization = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - body: { autoCapitalization } - } = await validateRequest(reqValidator.ToggleAutoCapitalizationV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Settings - ); - - const workspace = await Workspace.findOneAndUpdate( - { - _id: workspaceId - }, - { - autoCapitalization - }, - { - new: true - } - ); - - return res.status(200).send({ - message: "Successfully changed autoCapitalization setting", - workspace - }); -}; - -/** - * Add identity with id [identityId] to workspace - * with id [workspaceId] - * @param req - * @param res - */ -export const addIdentityToWorkspace = async (req: Request, res: Response) => { - const { - params: { workspaceId, identityId }, - body: { - role - } - } = await validateRequest(reqValidator.AddIdentityToWorkspaceV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.Identity - ); - - let identityMembership = await IdentityMembership.findOne({ - identity: new Types.ObjectId(identityId), - workspace: new Types.ObjectId(workspaceId) - }); - - if (identityMembership) throw BadRequestError({ - message: `Identity with id ${identityId} already exists in project with id ${workspaceId}` - }); - - - const workspace = await Workspace.findById(workspaceId); - if (!workspace) throw ResourceNotFoundError(); - - const identityMembershipOrg = await IdentityMembershipOrg.findOne({ - identity: new Types.ObjectId(identityId), - organization: workspace.organization - }); - - if (!identityMembershipOrg) throw ResourceNotFoundError({ - message: `Failed to find identity with id ${identityId}` - }); - - if (!identityMembershipOrg.organization.equals(workspace.organization)) throw BadRequestError({ - message: "Failed to add identity to project in another organization" - }); - - const rolePermission = await getWorkspaceRolePermissions(role, workspaceId); - const isAsPrivilegedAsIntendedRole = isAtLeastAsPrivilegedWorkspace(permission, rolePermission); - - if (!isAsPrivilegedAsIntendedRole) throw ForbiddenRequestError({ - message: "Failed to add identity to project with more privileged role" - }); - - let customRole; - if (role) { - const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role); - if (isCustomRole) { - customRole = await Role.findOne({ - slug: role, - isOrgRole: false, - workspace: new Types.ObjectId(workspaceId) - }); - - if (!customRole) throw BadRequestError({ message: "Role not found" }); - } - } - - identityMembership = await new IdentityMembership({ - identity: identityMembershipOrg.identity, - workspace: new Types.ObjectId(workspaceId), - role: customRole ? CUSTOM : role, - customRole - }).save(); - - return res.status(200).send({ - identityMembership - }); -} - -/** - * Update role of identity with id [identityId] in workspace - * with id [workspaceId] to [role] - * @param req - * @param res - */ - export const updateIdentityWorkspaceRole = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update project identity membership' - #swagger.description = 'Update project identity membership' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project", - "required": true, - "type": "string" - } - - #swagger.parameters['identityId'] = { - "description": "ID of identity whose membership to update in project", - "required": true, - "type": "string" - } - - #swagger.requestBody = { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "Role to update to for identity project membership", - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityMembership": { - $ref: "#/components/schemas/IdentityMembership", - "description": "Updated identity membership" - } - } - } - } - } - } - */ - const { - params: { workspaceId, identityId }, - body: { - role - } - } = await validateRequest(reqValidator.UpdateIdentityWorkspaceRoleV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Identity - ); - - let identityMembership = await IdentityMembership - .findOne({ - identity: new Types.ObjectId(identityId), - workspace: new Types.ObjectId(workspaceId) - }) - .populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembership) throw BadRequestError({ - message: `Identity with id ${identityId} does not exist in project with id ${workspaceId}` - }); - - const identityRolePermission = await getWorkspaceRolePermissions( - identityMembership?.customRole?.slug ?? identityMembership.role, - identityMembership.workspace.toString() - ); - const isAsPrivilegedAsIdentity = isAtLeastAsPrivilegedWorkspace(permission, identityRolePermission); - if (!isAsPrivilegedAsIdentity) throw ForbiddenRequestError({ - message: "Failed to update role of more privileged identity" - }); - - const rolePermission = await getWorkspaceRolePermissions(role, workspaceId); - const isAsPrivilegedAsIntendedRole = isAtLeastAsPrivilegedWorkspace(permission, rolePermission); - - if (!isAsPrivilegedAsIntendedRole) throw ForbiddenRequestError({ - message: "Failed to update identity to a more privileged role" - }); - - let customRole; - if (role) { - const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role); - if (isCustomRole) { - customRole = await Role.findOne({ - slug: role, - isOrgRole: false, - workspace: new Types.ObjectId(workspaceId) - }); - - if (!customRole) throw BadRequestError({ message: "Role not found" }); - } - } - - identityMembership = await IdentityMembership.findOneAndUpdate( - { - identity: identityMembership.identity._id, - workspace: new Types.ObjectId(workspaceId), - }, - { - role: customRole ? CUSTOM : role, - customRole - }, - { - new: true - } - ); - - return res.status(200).send({ - identityMembership - }); -} - -/** - * Delete identity with id [identityId] from workspace - * with id [workspaceId] - * @param req - * @param res - */ - export const deleteIdentityFromWorkspace = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete project identity membership' - #swagger.description = 'Delete project identity membership' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project", - "required": true, - "type": "string" - } - - #swagger.parameters['identityId'] = { - "description": "ID of identity whose membership to delete in project", - "required": true, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityMembership": { - $ref: "#/components/schemas/IdentityMembership", - "description": "Deleted identity membership" - } - } - } - } - } - } - */ - const { - params: { workspaceId, identityId } - } = await validateRequest(reqValidator.DeleteIdentityFromWorkspaceV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.Identity - ); - - const identityMembership = await IdentityMembership - .findOne({ - identity: new Types.ObjectId(identityId), - workspace: new Types.ObjectId(workspaceId) - }) - .populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembership) throw ResourceNotFoundError({ - message: `Identity with id ${identityId} does not exist in project with id ${workspaceId}` - }); - - const identityRolePermission = await getWorkspaceRolePermissions( - identityMembership?.customRole?.slug ?? identityMembership.role, - identityMembership.workspace.toString() - ); - const isAsPrivilegedAsIdentity = isAtLeastAsPrivilegedWorkspace(permission, identityRolePermission); - if (!isAsPrivilegedAsIdentity) throw ForbiddenRequestError({ - message: "Failed to remove more privileged identity from project" - }); - - await IdentityMembership.findByIdAndDelete(identityMembership._id); - - return res.status(200).send({ - identityMembership - }); -} - -/** - * Return list of identity memberships for workspace with id [workspaceId] - * @param req - * @param res - * @returns - */ - export const getWorkspaceIdentityMemberships = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return project identity memberships' - #swagger.description = 'Return project identity memberships' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identityMemberships": { - "type": "array", - "items": { - $ref: "#/components/schemas/IdentityMembership" - }, - "description": "Identity memberships of project" - } - } - } - } - } - } - */ - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceIdentityMembersV2, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.Identity - ); - - const identityMemberships = await IdentityMembership.find({ - workspace: new Types.ObjectId(workspaceId) - }).populate("identity customRole"); - - return res.status(200).send({ - identityMemberships - }); -} \ No newline at end of file diff --git a/backend-mongo/src/controllers/v3/authController.ts b/backend-mongo/src/controllers/v3/authController.ts deleted file mode 100644 index 4e3576c3b..000000000 --- a/backend-mongo/src/controllers/v3/authController.ts +++ /dev/null @@ -1,224 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -import { Request, Response } from "express"; -import jwt from "jsonwebtoken"; -import * as bigintConversion from "bigint-conversion"; -const jsrp = require("jsrp"); -import { LoginSRPDetail, User } from "../../models"; -import { createToken, issueAuthTokens, validateProviderAuthToken } from "../../helpers/auth"; -import { checkUserDevice } from "../../helpers/user"; -import { sendMail } from "../../helpers/nodemailer"; -import { TokenService } from "../../services"; -import { BadRequestError, InternalServerError } from "../../utils/errors"; -import { AuthTokenType, TOKEN_EMAIL_MFA } from "../../variables"; -import { getAuthSecret, getHttpsEnabled, getJwtMfaLifetime } from "../../config"; -import { AuthMethod } from "../../models/user"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/auth"; - -declare module "jsonwebtoken" { - export interface ProviderAuthJwtPayload extends jwt.JwtPayload { - userId: string; - email: string; - authProvider: AuthMethod; - isUserCompleted: boolean; - } -} - -/** - * Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol - * @param req - * @param res - * @returns - */ -export const login1 = async (req: Request, res: Response) => { - const { - body: { email, clientPublicKey, providerAuthToken } - } = await validateRequest(reqValidator.Login1V3, req); - - const user = await User.findOne({ - email - }).select("+salt +verifier"); - - if (!user) throw new Error("Failed to find user"); - - if (!user.authMethods.includes(AuthMethod.EMAIL)) { - await validateProviderAuthToken({ - email, - providerAuthToken - }); - } - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier - }, - async () => { - // generate server-side public key - const serverPublicKey = server.getPublicKey(); - await LoginSRPDetail.findOneAndReplace( - { - email: email - }, - { - email, - userId: user.id, - clientPublicKey: clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt) - }, - { upsert: true, returnNewDocument: false } - ); - - return res.status(200).send({ - serverPublicKey, - salt: user.salt - }); - } - ); -}; - -/** - * Log in user step 2: complete step 2 of SRP protocol and return token and their (encrypted) - * private key - * @param req - * @param res - * @returns - */ -export const login2 = async (req: Request, res: Response) => { - if (!req.headers["user-agent"]) - throw InternalServerError({ message: "User-Agent header is required" }); - - const { - body: { email, providerAuthToken, clientProof } - } = await validateRequest(reqValidator.Login2V3, req); - - const user = await User.findOne({ - email - }).select( - "+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices" - ); - - if (!user) throw new Error("Failed to find user"); - - if (!user.authMethods.includes(AuthMethod.EMAIL)) { - await validateProviderAuthToken({ - email, - providerAuthToken - }); - } - - const loginSRPDetail = await LoginSRPDetail.findOneAndDelete({ email: email }); - - if (!loginSRPDetail) { - return BadRequestError(Error("Failed to find login details for SRP")); - } - - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetail.serverBInt - }, - async () => { - server.setClientPublicKey(loginSRPDetail.clientPublicKey); - - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - if (user.isMfaEnabled) { - // case: user has MFA enabled - - // generate temporary MFA token - const token = createToken({ - payload: { - authTokenType: AuthTokenType.MFA_TOKEN, - userId: user._id.toString() - }, - expiresIn: await getJwtMfaLifetime(), - secret: await getAuthSecret() - }); - - const code = await TokenService.createToken({ - type: TOKEN_EMAIL_MFA, - email - }); - - // send MFA code [code] to [email] - await sendMail({ - template: "emailMfa.handlebars", - subjectLine: "Infisical MFA code", - recipients: [user.email], - substitutions: { - code - } - }); - - return res.status(200).send({ - mfaEnabled: true, - token - }); - } - - await checkUserDevice({ - user, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - // store (refresh) token in httpOnly cookie - res.cookie("jid", tokens.refreshToken, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: await getHttpsEnabled() - }); - - // case: user does not have MFA enablgged - // return (access) token in response - - interface ResponseData { - mfaEnabled: boolean; - encryptionVersion: any; - protectedKey?: string; - protectedKeyIV?: string; - protectedKeyTag?: string; - token: string; - publicKey?: string; - encryptedPrivateKey?: string; - iv?: string; - tag?: string; - } - - const response: ResponseData = { - mfaEnabled: false, - encryptionVersion: user.encryptionVersion, - token: tokens.token, - publicKey: user.publicKey, - encryptedPrivateKey: user.encryptedPrivateKey, - iv: user.iv, - tag: user.tag - }; - - if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) { - response.protectedKey = user.protectedKey; - response.protectedKeyIV = user.protectedKeyIV; - response.protectedKeyTag = user.protectedKeyTag; - } - - return res.status(200).send(response); - } - - return res.status(400).send({ - message: "Failed to authenticate. Try again?" - }); - } - ); -}; diff --git a/backend-mongo/src/controllers/v3/index.ts b/backend-mongo/src/controllers/v3/index.ts deleted file mode 100644 index b52e0aa41..000000000 --- a/backend-mongo/src/controllers/v3/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as usersController from "./usersController"; -import * as secretsController from "./secretsController"; -import * as workspacesController from "./workspacesController"; -import * as authController from "./authController"; -import * as signupController from "./signupController"; - -export { - usersController, - authController, - secretsController, - signupController, - workspacesController -} diff --git a/backend-mongo/src/controllers/v3/secretsController.ts b/backend-mongo/src/controllers/v3/secretsController.ts deleted file mode 100644 index b9edc431c..000000000 --- a/backend-mongo/src/controllers/v3/secretsController.ts +++ /dev/null @@ -1,1461 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { EventService, SecretService } from "../../services"; -import { eventPushSecrets } from "../../events"; -import { BotService } from "../../services"; -import { containsGlobPatterns, repackageSecretToRaw } from "../../helpers/secrets"; -import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; -import { getAllImportedSecrets } from "../../services/SecretImportService"; -import { Folder, IServiceTokenData, Membership, ServiceTokenData, User } from "../../models"; -import { getFolderByPath } from "../../services/FolderService"; -import { BadRequestError } from "../../utils/errors"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/secrets"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { ForbiddenError, subject } from "@casl/ability"; -import { validateServiceTokenDataClientForWorkspace } from "../../validation"; -import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from "../../variables"; -import { ActorType } from "../../ee/models"; -import { UnauthorizedRequestError } from "../../utils/errors"; -import { AuthData } from "../../interfaces/middleware"; -import { - generateSecretApprovalRequest, - getSecretPolicyOfBoard -} from "../../ee/services/SecretApprovalService"; -import { CommitType } from "../../ee/models/secretApprovalRequest"; -import { logger } from "../../utils/logging"; -import { createReminder, deleteReminder } from "../../helpers/reminder"; - -const checkSecretsPermission = async ({ - authData, - workspaceId, - environment, - secretPath, - secretAction -}: { - authData: AuthData; - workspaceId: string; - environment: string; - secretPath: string; - secretAction: ProjectPermissionActions; // CRUD -}): Promise<{ - authVerifier: (env: string, secPath: string) => boolean; -}> => { - let STV2RequiredPermissions = []; - - switch (secretAction) { - case ProjectPermissionActions.Create: - STV2RequiredPermissions = [PERMISSION_WRITE_SECRETS]; - break; - case ProjectPermissionActions.Read: - STV2RequiredPermissions = [PERMISSION_READ_SECRETS]; - break; - case ProjectPermissionActions.Edit: - STV2RequiredPermissions = [PERMISSION_WRITE_SECRETS]; - break; - case ProjectPermissionActions.Delete: - STV2RequiredPermissions = [PERMISSION_WRITE_SECRETS]; - break; - } - - switch (authData.actor.type) { - case ActorType.USER: { - const { permission } = await getAuthDataProjectPermissions({ - authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - secretAction, - subject(ProjectPermissionSub.Secrets, { environment, secretPath }) - ); - return { - authVerifier: (env: string, secPath: string) => - permission.can( - secretAction, - subject(ProjectPermissionSub.Secrets, { - environment: env, - secretPath: secPath - }) - ) - }; - } - case ActorType.SERVICE: { - await validateServiceTokenDataClientForWorkspace({ - serviceTokenData: authData.authPayload as IServiceTokenData, - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath, - requiredPermissions: STV2RequiredPermissions - }); - return { authVerifier: () => true }; - } - case ActorType.IDENTITY: { - const { permission } = await getAuthDataProjectPermissions({ - authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - secretAction, - subject(ProjectPermissionSub.Secrets, { environment, secretPath }) - ); - return { - authVerifier: (env: string, secPath: string) => - permission.can( - secretAction, - subject(ProjectPermissionSub.Secrets, { - environment: env, - secretPath: secPath - }) - ) - }; - } - default: { - throw UnauthorizedRequestError(); - } - } -}; - -/** - * Return secrets for workspace with id [workspaceId] and environment - * [environment] in plaintext - * @param req - * @param res - */ -export const getSecretsRaw = async (req: Request, res: Response) => { - /* - #swagger.summary = 'List secrets' - #swagger.description = 'List secrets' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of workspace where to get secrets from", - "required": true, - "type": "string", - "in": "query" - } - - #swagger.parameters['environment'] = { - "description": "Slug of environment where to get secrets from", - "required": true, - "type": "string", - "in": "query" - } - - #swagger.parameters['secretPath'] = { - "description": "Path where to update secret like / or /foo/bar. Default is /", - "required": false, - "type": "string", - "in": "query" - } - - #swagger.parameters['include_imports'] = { - "description": "Whether or not to include imported secrets. Default is false", - "required": false, - "type": "boolean", - "in": "query" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - $ref: '#/definitions/RawSecret' - }, - "description": "List of secrets" - } - } - } - } - } - } - */ - const validatedData = await validateRequest(reqValidator.GetSecretsRawV3, req); - let { - query: { secretPath, environment, workspaceId } - } = validatedData; - const { - query: { include_imports: includeImports } - } = validatedData; - - logger.info( - `getSecretsRaw: fetch raw secrets [environment=${environment}] [workspaceId=${workspaceId}] [secretPath=${secretPath}] [includeImports=${includeImports}]` - ); - - if (req.authData.authPayload instanceof ServiceTokenData) { - // if the service token has single scope, it will get all secrets for that scope by default - const serviceTokenDetails: IServiceTokenData = req?.serviceTokenData; - if ( - serviceTokenDetails && - serviceTokenDetails.scopes.length == 1 && - !containsGlobPatterns(serviceTokenDetails.scopes[0].secretPath) - ) { - const scope = serviceTokenDetails.scopes[0]; - secretPath = scope.secretPath; - environment = scope.environment; - workspaceId = serviceTokenDetails.workspace.toString(); - } - } - - if (!environment || !workspaceId) - throw BadRequestError({ message: "Missing environment or workspace id" }); - - const { authVerifier: permissionCheckFn } = await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Read - }); - - const secrets = await SecretService.getSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath, - authData: req.authData - }); - - const key = await BotService.getWorkspaceKeyWithBot({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - if (includeImports) { - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - let folderId = "root"; - // if folder exist get it and replace folderid with new one - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath as string); - if (!folder) { - throw BadRequestError({ message: "Folder not found" }); - } - folderId = folder.id; - } - const importedSecrets = await getAllImportedSecrets( - workspaceId, - environment, - folderId, - permissionCheckFn - ); - return res.status(200).send({ - secrets: secrets.map((secret) => - repackageSecretToRaw({ - secret, - key - }) - ), - imports: importedSecrets.map((el) => ({ - ...el, - secrets: el.secrets.map((secret) => repackageSecretToRaw({ secret, key })) - })) - }); - } - - return res.status(200).send({ - secrets: secrets.map((secret) => { - const rep = repackageSecretToRaw({ - secret, - key - }); - return rep; - }) - }); -}; - -/** - * Return secret with name [secretName] in plaintext - * @param req - * @param res - */ -export const getSecretByNameRaw = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Get secret' - #swagger.description = 'Get secret' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['secretName'] = { - "description": "Name of secret to get", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.parameters['workspaceId'] = { - "description": "ID of workspace where to get secret", - "required": true, - "type": "string", - "in": "query" - } - - #swagger.parameters['environment'] = { - "description": "Slug of environment where to get secret", - "required": true, - "type": "string", - "in": "query" - } - - #swagger.parameters['secretPath'] = { - "description": "Path where to update secret like / or /foo/bar. Default is /", - "required": false, - "type": "string", - "in": "query" - } - - #swagger.parameters['type'] = { - "description": "Type of secret to get; either shared or personal. Default is shared.", - "required": true, - "type": "string", - "in": "query" - } - - #swagger.parameters['include_imports'] = { - "description": "Whether or not to include imported secrets. Default is false", - "required": false, - "type": "boolean", - "in": "query" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secret": { - $ref: '#/definitions/RawSecret' - } - } - } - } - } - } - */ - const { - query: { secretPath, environment, workspaceId, type, include_imports, version }, - params: { secretName } - } = await validateRequest(reqValidator.GetSecretByNameRawV3, req); - - logger.info( - `getSecretByNameRaw: fetch raw secret by name [environment=${environment}] [workspaceId=${workspaceId}] [secretPath=${secretPath}] [type=${type}] [include_imports=${include_imports}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Read - }); - - const secret = await SecretService.getSecret({ - secretName, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - secretPath, - authData: req.authData, - include_imports, - version - }); - - const key = await BotService.getWorkspaceKeyWithBot({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - return res.status(200).send({ - secret: repackageSecretToRaw({ - secret, - key - }) - }); -}; - -/** - * Create secret with name [secretName] in plaintext - * @param req - * @param res - */ -export const createSecretRaw = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Create secret' - #swagger.description = 'Create secret' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['secretName'] = { - "description": "Name of secret to create", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of the workspace where to create secret", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to create secret", - "example": "dev" - }, - "secretPath": { - "type": "string", - "description": "Path where to create secret. Default is /", - "example": "/foo/bar" - }, - "secretValue": { - "type": "string", - "description": "Value of secret to create", - "example": "Some value" - }, - "secretComment": { - "type": "string", - "description": "Comment for secret to create", - "example": "Some comment" - }, - "type": { - "type": "string", - "description": "Type of secret to create; either shared or personal. Default is shared.", - "example": "shared" - }, - "skipMultilineEncoding": { - "type": "boolean", - "description": "Convert multi line secrets into one line by wrapping", - "example": "true" - }, - }, - "required": ["workspaceId", "environment", "secretValue"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - $ref: '#/definitions/RawSecret' - } - } - } - } - */ - const { - params: { secretName }, - body: { - workspaceId, - environment, - secretPath, - type, - secretValue, - secretComment, - skipMultilineEncoding - } - } = await validateRequest(reqValidator.CreateSecretRawV3, req); - - logger.info( - `createSecretRaw: create a secret raw by name and value [environment=${environment}] [workspaceId=${workspaceId}] [secretPath=${secretPath}] [type=${type}] [skipMultilineEncoding=${skipMultilineEncoding}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Create - }); - - const key = await BotService.getWorkspaceKeyWithBot({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8({ - plaintext: secretName, - key - }); - - const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8({ - plaintext: secretValue, - key - }); - - const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8({ - plaintext: secretComment, - key - }); - - const secret = await SecretService.createSecret({ - secretName, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - authData: req.authData, - secretKeyCiphertext: secretKeyEncrypted.ciphertext, - secretKeyIV: secretKeyEncrypted.iv, - secretKeyTag: secretKeyEncrypted.tag, - secretValueCiphertext: secretValueEncrypted.ciphertext, - secretValueIV: secretValueEncrypted.iv, - secretValueTag: secretValueEncrypted.tag, - secretPath, - secretCommentCiphertext: secretCommentEncrypted.ciphertext, - secretCommentIV: secretCommentEncrypted.iv, - secretCommentTag: secretCommentEncrypted.tag, - skipMultilineEncoding - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - const secretWithoutBlindIndex = secret.toObject(); - delete secretWithoutBlindIndex.secretBlindIndex; - - return res.status(200).send({ - secret: repackageSecretToRaw({ - secret: secretWithoutBlindIndex, - key - }) - }); -}; - -/** - * Update secret with name [secretName] - * @param req - * @param res - */ -export const updateSecretByNameRaw = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update secret' - #swagger.description = 'Update secret' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['secretName'] = { - "description": "Name of secret to update", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of the workspace where to update secret", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of environment where to update secret", - "example": "dev" - }, - "secretPath": { - "type": "string", - "description": "Path where to update secret like / or /foo/bar. Default is /", - "example": "/foo/bar" - }, - "secretValue": { - "type": "string", - "description": "Value of secret to update to", - "example": "Some value" - }, - "type": { - "type": "string", - "description": "Type of secret to update; either shared or personal. Default is shared.", - "example": "shared" - }, - "skipMultilineEncoding": { - "type": "boolean", - "description": "Convert multi line secrets into one line by wrapping", - "example": "true" - }, - }, - "required": ["workspaceId", "environment", "secretValue"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - $ref: '#/definitions/RawSecret' - } - } - } - } - */ - const { - params: { secretName }, - body: { workspaceId, environment, secretValue, secretPath, type, skipMultilineEncoding } - } = await validateRequest(reqValidator.UpdateSecretByNameRawV3, req); - - logger.info( - `updateSecretByNameRaw: update raw secret by name [environment=${environment}] [workspaceId=${workspaceId}] [secretPath=${secretPath}] [type=${type}] [skipMultilineEncoding=${skipMultilineEncoding}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Edit - }); - - const key = await BotService.getWorkspaceKeyWithBot({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8({ - plaintext: secretValue, - key - }); - - const secret = await SecretService.updateSecret({ - secretName, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - authData: req.authData, - secretValueCiphertext: secretValueEncrypted.ciphertext, - secretValueIV: secretValueEncrypted.iv, - secretValueTag: secretValueEncrypted.tag, - secretPath, - skipMultilineEncoding - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - return res.status(200).send({ - secret: repackageSecretToRaw({ - secret, - key - }) - }); -}; - -/** - * Delete secret with name [secretName] - * @param req - * @param res - */ -export const deleteSecretByNameRaw = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete secret' - #swagger.description = 'Delete secret' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['secretName'] = { - "description": "Name of secret to delete", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "workspaceId": { - "type": "string", - "description": "ID of workspace where to delete secret", - "example": "someWorkspaceId" - }, - "environment": { - "type": "string", - "description": "Slug of Environment where to delete secret", - "example": "dev" - }, - "secretPath": { - "type": "string", - "description": "Path where to delete secret. Default is /", - "example": "/foo/bar" - }, - "type": { - "type": "string", - "description": "Type of secret to delete; either shared or personal. Default is shared", - "example": "shared" - } - }, - "required": ["workspaceId", "environment"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "secret": { - $ref: '#/definitions/RawSecret' - } - }, - "description": "The deleted secret" - } - } - } - } - */ - const { - params: { secretName }, - body: { environment, secretPath, type, workspaceId } - } = await validateRequest(reqValidator.DeleteSecretByNameRawV3, req); - - logger.info( - `deleteSecretByNameRaw: delete a secret by name [environment=${environment}] [workspaceId=${workspaceId}] [secretPath=${secretPath}] [type=${type}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Delete - }); - - const { secret } = await SecretService.deleteSecret({ - secretName, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - authData: req.authData, - secretPath - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - const key = await BotService.getWorkspaceKeyWithBot({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - return res.status(200).send({ - secret: repackageSecretToRaw({ - secret, - key - }) - }); -}; - -/** - * Get secrets for workspace with id [workspaceId] and environment - * [environment] - * @param req - * @param res - */ -export const getSecrets = async (req: Request, res: Response) => { - const validatedData = await validateRequest(reqValidator.GetSecretsV3, req); - const { - query: { environment, workspaceId, include_imports: includeImports } - } = validatedData; - - const { - query: { secretPath } - } = validatedData; - - logger.info( - `getSecrets: fetch encrypted secrets [environment=${environment}] [workspaceId=${workspaceId}] [includeImports=${includeImports}]` - ); - - const { authVerifier: permissionCheckFn } = await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Read - }); - - const secrets = await SecretService.getSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath, - authData: req.authData - }); - - if (includeImports) { - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - let folderId = "root"; - // if folder exist get it and replace folderid with new one - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath as string); - if (!folder) { - throw BadRequestError({ message: "Folder not found" }); - } - folderId = folder.id; - } - const importedSecrets = await getAllImportedSecrets( - workspaceId, - environment, - folderId, - permissionCheckFn - ); - return res.status(200).send({ - secrets, - imports: importedSecrets - }); - } - - return res.status(200).send({ - secrets - }); -}; - -/** - * Return secret with name [secretName] - * @param req - * @param res - */ -export const getSecretByName = async (req: Request, res: Response) => { - const { - query: { secretPath, environment, workspaceId, type, include_imports, version }, - params: { secretName } - } = await validateRequest(reqValidator.GetSecretByNameV3, req); - - logger.info( - `getSecretByName: get a single secret by name [environment=${environment}] [workspaceId=${workspaceId}] [include_imports=${include_imports}] [type=${type}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Read - }); - - const secret = await SecretService.getSecret({ - secretName, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - secretPath, - authData: req.authData, - include_imports, - version - }); - - return res.status(200).send({ - secret - }); -}; - -/** - * Create secret with name [secretName] - * @param req - * @param res - */ -export const createSecret = async (req: Request, res: Response) => { - const { - body: { - workspaceId, - secretPath, - environment, - metadata, - type, - secretKeyIV, - secretKeyTag, - secretValueIV, - secretValueTag, - secretCommentIV, - secretCommentTag, - secretKeyCiphertext, - secretValueCiphertext, - secretCommentCiphertext, - skipMultilineEncoding - }, - params: { secretName } - } = await validateRequest(reqValidator.CreateSecretV3, req); - - logger.info( - `createSecret: create an encrypted secret [environment=${environment}] [workspaceId=${workspaceId}] [skipMultilineEncoding=${skipMultilineEncoding}] [type=${type}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Create - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (membership && type !== "personal") { - const secretApprovalPolicy = await getSecretPolicyOfBoard( - workspaceId, - environment, - secretPath - ); - if (secretApprovalPolicy) { - const secretApprovalRequest = await generateSecretApprovalRequest({ - workspaceId, - environment, - secretPath, - policy: secretApprovalPolicy, - commiterMembershipId: membership._id.toString(), - authData: req.authData, - data: { - [CommitType.CREATE]: [ - { - secretName, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentIV, - secretCommentTag, - secretCommentCiphertext, - skipMultilineEncoding, - secretKeyTag, - secretKeyCiphertext, - secretKeyIV - } - ] - } - }); - return res.send({ approval: secretApprovalRequest }); - } - } - } - - const secret = await SecretService.createSecret({ - secretName, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - authData: req.authData, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretPath, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - metadata, - skipMultilineEncoding - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - const secretWithoutBlindIndex = secret.toObject(); - delete secretWithoutBlindIndex.secretBlindIndex; - - return res.status(200).send({ - secret: secretWithoutBlindIndex - }); -}; - -/** - * Update secret with name [secretName] - * @param req - * @param res - */ -export const updateSecretByName = async (req: Request, res: Response) => { - const { - body: { - secretValueCiphertext, - secretValueTag, - secretValueIV, - secretId, - type, - environment, - secretPath, - workspaceId, - tags, - secretCommentIV, - secretCommentTag, - secretCommentCiphertext, - secretName: newSecretName, - secretKeyIV, - secretKeyTag, - secretKeyCiphertext, - skipMultilineEncoding, - secretReminderRepeatDays, - secretReminderNote - }, - params: { secretName } - } = await validateRequest(reqValidator.UpdateSecretByNameV3, req); - - logger.info( - `updateSecretByName: update a encrypted secret by name [environment=${environment}] [workspaceId=${workspaceId}] [skipMultilineEncoding=${skipMultilineEncoding}] [type=${type}]` - ); - - if (newSecretName && (!secretKeyIV || !secretKeyTag || !secretKeyCiphertext)) { - throw BadRequestError({ message: "Missing encrypted key" }); - } - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Edit - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (membership && type !== "personal") { - const secretApprovalPolicy = await getSecretPolicyOfBoard( - workspaceId, - environment, - secretPath - ); - if (secretApprovalPolicy) { - const secretApprovalRequest = await generateSecretApprovalRequest({ - workspaceId, - environment, - secretPath, - policy: secretApprovalPolicy, - commiterMembershipId: membership._id.toString(), - authData: req.authData, - data: { - [CommitType.UPDATE]: [ - { - secretName, - newSecretName, - secretValueCiphertext, - secretValueIV, - secretValueTag, - tags, - secretCommentIV, - secretCommentTag, - secretCommentCiphertext, - skipMultilineEncoding, - secretKeyTag, - secretKeyCiphertext, - secretKeyIV - } - ] - } - }); - return res.send({ approval: secretApprovalRequest }); - } - } - } - - if (type !== "personal") { - const existingSecret = await SecretService.getSecret({ - secretName, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - secretPath, - authData: req.authData - }); - - if (secretReminderRepeatDays !== undefined) { - if ( - (secretReminderRepeatDays && - existingSecret.secretReminderRepeatDays !== secretReminderRepeatDays) || - (secretReminderNote && existingSecret.secretReminderNote !== secretReminderNote) - ) { - await createReminder(existingSecret, { - _id: existingSecret._id, - secretReminderRepeatDays, - secretReminderNote, - workspace: existingSecret.workspace - }); - } else if ( - secretReminderRepeatDays === null && - secretReminderNote === null && - existingSecret.secretReminderRepeatDays - ) { - await deleteReminder({ - _id: existingSecret._id, - secretReminderRepeatDays: existingSecret.secretReminderRepeatDays - }); - } - } - } - - const secret = await SecretService.updateSecret({ - secretName, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - secretId, - authData: req.authData, - newSecretName, - secretValueCiphertext, - secretValueIV, - secretReminderRepeatDays, - secretReminderNote, - secretValueTag, - secretPath, - tags, - secretCommentIV, - secretCommentTag, - secretCommentCiphertext, - skipMultilineEncoding, - secretKeyTag, - secretKeyCiphertext, - secretKeyIV - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - return res.status(200).send({ - secret - }); -}; - -/** - * Delete secret with name [secretName] - * @param req - * @param res - */ -export const deleteSecretByName = async (req: Request, res: Response) => { - const { - body: { type, environment, secretPath, workspaceId, secretId }, - params: { secretName } - } = await validateRequest(reqValidator.DeleteSecretByNameV3, req); - - logger.info( - `deleteSecretByName: delete a encrypted secret by name [environment=${environment}] [workspaceId=${workspaceId}] [type=${type}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Delete - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (membership && type !== "personal") { - const secretApprovalPolicy = await getSecretPolicyOfBoard( - workspaceId, - environment, - secretPath - ); - if (secretApprovalPolicy) { - const secretApprovalRequest = await generateSecretApprovalRequest({ - workspaceId, - environment, - secretPath, - authData: req.authData, - policy: secretApprovalPolicy, - commiterMembershipId: membership._id.toString(), - data: { - [CommitType.DELETE]: [ - { - secretName - } - ] - } - }); - return res.send({ approval: secretApprovalRequest }); - } - } - } - - const { secret } = await SecretService.deleteSecret({ - secretName, - secretId, - workspaceId: new Types.ObjectId(workspaceId), - environment, - type, - authData: req.authData, - secretPath - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - return res.status(200).send({ - secret - }); -}; - -export const createSecretByNameBatch = async (req: Request, res: Response) => { - const { - body: { secrets, secretPath, environment, workspaceId } - } = await validateRequest(reqValidator.CreateSecretByNameBatchV3, req); - - logger.info( - `createSecretByNameBatch: create a list of secrets by their names [environment=${environment}] [workspaceId=${workspaceId}] [secretsLength=${secrets?.length}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Create - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (membership) { - const secretApprovalPolicy = await getSecretPolicyOfBoard( - workspaceId, - environment, - secretPath - ); - if (secretApprovalPolicy) { - const secretApprovalRequest = await generateSecretApprovalRequest({ - workspaceId, - environment, - secretPath, - authData: req.authData, - policy: secretApprovalPolicy, - commiterMembershipId: membership._id.toString(), - data: { - [CommitType.CREATE]: secrets.filter(({ type }) => type === "shared") - } - }); - return res.send({ approval: secretApprovalRequest }); - } - } - } - - const createdSecrets = await SecretService.createSecretBatch({ - secretPath, - environment, - workspaceId: new Types.ObjectId(workspaceId), - secrets, - authData: req.authData - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - return res.status(200).send({ - secrets: createdSecrets - }); -}; - -export const updateSecretByNameBatch = async (req: Request, res: Response) => { - const { - body: { secrets, secretPath, environment, workspaceId } - } = await validateRequest(reqValidator.UpdateSecretByNameBatchV3, req); - - logger.info( - `updateSecretByNameBatch: update a list of secrets by their names [environment=${environment}] [workspaceId=${workspaceId}] [secretsLength=${secrets?.length}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Edit - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (membership) { - const secretApprovalPolicy = await getSecretPolicyOfBoard( - workspaceId, - environment, - secretPath - ); - if (secretApprovalPolicy) { - const secretApprovalRequest = await generateSecretApprovalRequest({ - workspaceId, - environment, - secretPath, - policy: secretApprovalPolicy, - commiterMembershipId: membership._id.toString(), - data: { - [CommitType.UPDATE]: secrets.filter(({ type }) => type === "shared") - }, - authData: req.authData - }); - return res.send({ approval: secretApprovalRequest }); - } - } - } - - const updatedSecrets = await SecretService.updateSecretBatch({ - secretPath, - environment, - workspaceId: new Types.ObjectId(workspaceId), - secrets, - authData: req.authData - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - return res.status(200).send({ - secrets: updatedSecrets - }); -}; - -export const deleteSecretByNameBatch = async (req: Request, res: Response) => { - const { - body: { secrets, secretPath, environment, workspaceId } - } = await validateRequest(reqValidator.DeleteSecretByNameBatchV3, req); - - logger.info( - `deleteSecretByNameBatch: delete a list of secrets by their names [environment=${environment}] [workspaceId=${workspaceId}] [secretsLength=${secrets?.length}]` - ); - - await checkSecretsPermission({ - authData: req.authData, - workspaceId, - environment, - secretPath, - secretAction: ProjectPermissionActions.Delete - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (membership) { - const secretApprovalPolicy = await getSecretPolicyOfBoard( - workspaceId, - environment, - secretPath - ); - if (secretApprovalPolicy) { - const secretApprovalRequest = await generateSecretApprovalRequest({ - workspaceId, - environment, - secretPath, - policy: secretApprovalPolicy, - commiterMembershipId: membership._id.toString(), - data: { - [CommitType.DELETE]: secrets.filter(({ type }) => type === "shared") - }, - authData: req.authData - }); - return res.send({ approval: secretApprovalRequest }); - } - } - } - - const deletedSecrets = await SecretService.deleteSecretBatch({ - secretPath, - environment, - workspaceId: new Types.ObjectId(workspaceId), - secrets, - authData: req.authData - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - secretPath - }) - }); - - return res.status(200).send({ - secrets: deletedSecrets - }); -}; diff --git a/backend-mongo/src/controllers/v3/signupController.ts b/backend-mongo/src/controllers/v3/signupController.ts deleted file mode 100644 index d16fbe9ca..000000000 --- a/backend-mongo/src/controllers/v3/signupController.ts +++ /dev/null @@ -1,193 +0,0 @@ -import jwt from "jsonwebtoken"; -import { Request, Response } from "express"; -import * as Sentry from "@sentry/node"; -import { MembershipOrg, User } from "../../models"; -import { completeAccount } from "../../helpers/user"; -import { initializeDefaultOrg } from "../../helpers/signup"; -import { issueAuthTokens, validateProviderAuthToken } from "../../helpers/auth"; -import { ACCEPTED, AuthTokenType, INVITED } from "../../variables"; -import { standardRequest } from "../../config/request"; -import { getAuthSecret, getHttpsEnabled, getLoopsApiKey } from "../../config"; -import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors"; -import { TelemetryService } from "../../services"; -import { AuthMethod } from "../../models"; -import { validateRequest } from "../../helpers/validation"; -import * as reqValidator from "../../validation/auth"; - -/** - * Complete setting up user by adding their personal and auth information as part of the - * signup flow - * @param req - * @param res - * @returns - */ -export const completeAccountSignup = async (req: Request, res: Response) => { - let user, token; - try { - const { - body: { - email, - publicKey, - salt, - lastName, - verifier, - firstName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - organizationName, - providerAuthToken, - attributionSource, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag - } - } = await validateRequest(reqValidator.CompletedAccountSignupV3, req); - - user = await User.findOne({ email }); - - if (!user || (user && user?.publicKey)) { - // case 1: user doesn't exist. - // case 2: user has already completed account - return res.status(403).send({ - error: "Failed to complete account for complete user" - }); - } - - if (providerAuthToken) { - await validateProviderAuthToken({ - email, - providerAuthToken - }); - } else { - const [AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE] = <[string, string]>( - req.headers["authorization"]?.split(" ", 2) - ) ?? [null, null]; - if (AUTH_TOKEN_TYPE === null) { - throw BadRequestError({ message: "Missing Authorization Header in the request header." }); - } - if (AUTH_TOKEN_TYPE.toLowerCase() !== "bearer") { - throw BadRequestError({ - message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.` - }); - } - if (AUTH_TOKEN_VALUE === null) { - throw BadRequestError({ - message: "Missing Authorization Body in the request header" - }); - } - - const decodedToken = ( - jwt.verify(AUTH_TOKEN_VALUE, await getAuthSecret()) - ); - - if (decodedToken.authTokenType !== AuthTokenType.SIGNUP_TOKEN) throw UnauthorizedRequestError(); - if (decodedToken.userId !== user.id) throw UnauthorizedRequestError(); - } - - // complete setting up user's account - user = await completeAccount({ - userId: user._id.toString(), - firstName, - lastName, - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - }); - - if (!user) throw new Error("Failed to complete account for non-existent user"); // ensure user is non-null - - const hasSamlEnabled = user.authMethods.some((authMethod: AuthMethod) => - [AuthMethod.OKTA_SAML, AuthMethod.AZURE_SAML, AuthMethod.JUMPCLOUD_SAML].includes(authMethod) - ); - - if (!hasSamlEnabled) { - // TODO: modify this part - // initialize default organization and workspace - await initializeDefaultOrg({ - organizationName, - user - }); - } - - // update organization membership statuses that are - // invited to completed with user attached - await MembershipOrg.updateMany( - { - inviteEmail: email, - status: INVITED - }, - { - user, - status: ACCEPTED - } - ); - - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id, - ip: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - token = tokens.token; - - // sending a welcome email to new users - if (await getLoopsApiKey()) { - await standardRequest.post( - "https://app.loops.so/api/v1/events/send", - { - email: email, - eventName: "Sign Up", - firstName: firstName, - lastName: lastName - }, - { - headers: { - Accept: "application/json", - Authorization: "Bearer " + (await getLoopsApiKey()) - } - } - ); - } - - // store (refresh) token in httpOnly cookie - res.cookie("jid", tokens.refreshToken, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: await getHttpsEnabled() - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - if (postHogClient) { - postHogClient.capture({ - event: "User Signed Up", - distinctId: email, - properties: { - email, - ...(attributionSource ? { attributionSource } : {}) - } - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to complete account setup" - }); - } - - return res.status(200).send({ - message: "Successfully set up account", - user, - token - }); -}; diff --git a/backend-mongo/src/controllers/v3/usersController.ts b/backend-mongo/src/controllers/v3/usersController.ts deleted file mode 100644 index e94173540..000000000 --- a/backend-mongo/src/controllers/v3/usersController.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Request, Response } from "express"; -import { APIKeyDataV2 } from "../../models"; - -/** - * Return API keys belonging to current user. - * @param req - * @param res - * @returns - */ -export const getMyAPIKeys = async (req: Request, res: Response) => { - const apiKeyData = await APIKeyDataV2.find({ - user: req.user._id - }); - - return res.status(200).send({ - apiKeyData - }); -} \ No newline at end of file diff --git a/backend-mongo/src/controllers/v3/workspacesController.ts b/backend-mongo/src/controllers/v3/workspacesController.ts deleted file mode 100644 index 32f04074a..000000000 --- a/backend-mongo/src/controllers/v3/workspacesController.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { validateRequest } from "../../helpers/validation"; -import { Membership, Secret, User } from "../../models"; -import { SecretService } from "../../services"; -import { getAuthDataProjectPermissions } from "../../ee/services/ProjectRoleService"; -import { UnauthorizedRequestError } from "../../utils/errors"; -import * as reqValidator from "../../validation/workspace"; - -/** - * Return whether or not all secrets in workspace with id [workspaceId] - * are blind-indexed - * @param req - * @param res - * @returns - */ -export const getWorkspaceBlindIndexStatus = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceBlinkIndexStatusV3, req); - - await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (!membership) throw UnauthorizedRequestError(); - - if (membership.role !== "admin") - throw UnauthorizedRequestError({ message: "User must be an admin" }); - } - - const secretsWithoutBlindIndex = await Secret.countDocuments({ - workspace: new Types.ObjectId(workspaceId), - secretBlindIndex: { - $exists: false - } - }); - - return res.status(200).send(secretsWithoutBlindIndex === 0); -}; - -/** - * Get all secrets for workspace with id [workspaceId] - */ -export const getWorkspaceSecrets = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.GetWorkspaceSecretsV3, req); - - await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (!membership) throw UnauthorizedRequestError(); - - if (membership.role !== "admin") - throw UnauthorizedRequestError({ message: "User must be an admin" }); - } - - const secrets = await Secret.find({ - workspace: new Types.ObjectId(workspaceId) - }); - - return res.status(200).send({ - secrets - }); -}; - -/** - * Update blind indices for secrets in workspace with id [workspaceId] - * @param req - * @param res - */ -export const nameWorkspaceSecrets = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - body: { secretsToUpdate } - } = await validateRequest(reqValidator.NameWorkspaceSecretsV3, req); - - await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - if (req.authData.authPayload instanceof User) { - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (!membership) throw UnauthorizedRequestError(); - - if (membership.role !== "admin") - throw UnauthorizedRequestError({ message: "User must be an admin" }); - } - - // get secret blind index salt - const salt = await SecretService.getSecretBlindIndexSalt({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - // update secret blind indices - const operations = await Promise.all( - secretsToUpdate.map(async (secretToUpdate) => { - const secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt({ - secretName: secretToUpdate.secretName, - salt - }); - - return { - updateOne: { - filter: { - _id: new Types.ObjectId(secretToUpdate._id) - }, - update: { - secretBlindIndex - } - } - }; - }) - ); - - await Secret.bulkWrite(operations); - - return res.status(200).send({ - message: "Successfully named workspace secrets" - }); -}; diff --git a/backend-mongo/src/data/disposable_emails.txt b/backend-mongo/src/data/disposable_emails.txt deleted file mode 100644 index 70e24a460..000000000 --- a/backend-mongo/src/data/disposable_emails.txt +++ /dev/null @@ -1,3519 +0,0 @@ -0-mail.com -027168.com -0815.ru -0815.ry -0815.su -0845.ru -0box.eu -0clickemail.com -0n0ff.net -0nelce.com -0v.ro -0w.ro -0wnd.net -0wnd.org -0x207.info -1-8.biz -1-tm.com -10-minute-mail.com -1000rebates.stream -100likers.com -105kg.ru -10dk.email -10mail.com -10mail.org -10minut.com.pl -10minut.xyz -10minutemail.be -10minutemail.cf -10minutemail.co.uk -10minutemail.co.za -10minutemail.com -10minutemail.de -10minutemail.ga -10minutemail.gq -10minutemail.ml -10minutemail.net -10minutemail.nl -10minutemail.pro -10minutemail.us -10minutemailbox.com -10minutemails.in -10minutenemail.de -10minutesmail.com -10minutesmail.fr -10minutmail.pl -10x9.com -11163.com -123-m.com -12hosting.net -12houremail.com -12minutemail.com -12minutemail.net -12storage.com -140unichars.com -147.cl -14n.co.uk -15qm.com -1blackmoon.com -1ce.us -1chuan.com -1clck2.com -1fsdfdsfsdf.tk -1mail.ml -1pad.de -1s.fr -1secmail.com -1secmail.net -1secmail.org -1st-forms.com -1to1mail.org -1usemail.com -1webmail.info -1zhuan.com -2012-2016.ru -20email.eu -20email.it -20mail.eu -20mail.in -20mail.it -20minutemail.com -20minutemail.it -20mm.eu -2120001.net -21cn.com -247web.net -24hinbox.com -24hourmail.com -24hourmail.net -2anom.com -2chmail.net -2ether.net -2fdgdfgdfgdf.tk -2odem.com -2prong.com -2wc.info -300book.info -30mail.ir -30minutemail.com -30wave.com -3202.com -36ru.com -3d-painting.com -3l6.com -3mail.ga -3trtretgfrfe.tk -4-n.us -4057.com -418.dk -42o.org -4gfdsgfdgfd.tk -4k5.net -4mail.cf -4mail.ga -4nextmail.com -4nmv.ru -4tb.host -4warding.com -4warding.net -4warding.org -50set.ru -55hosting.net -5ghgfhfghfgh.tk -5gramos.com -5july.org -5mail.cf -5mail.ga -5minutemail.net -5oz.ru -5tb.in -5x25.com -5ymail.com -60minutemail.com -672643.net -675hosting.com -675hosting.net -675hosting.org -6hjgjhgkilkj.tk -6ip.us -6mail.cf -6mail.ga -6mail.ml -6paq.com -6somok.ru -6url.com -75hosting.com -75hosting.net -75hosting.org -7days-printing.com -7mail.ga -7mail.ml -7tags.com -80665.com -8127ep.com -8mail.cf -8mail.ga -8mail.ml -99.com -99cows.com -99experts.com -9mail.cf -9me.site -9mot.ru -9ox.net -9q.ro -a-bc.net -a45.in -a7996.com -aa5zy64.com -abacuswe.us -abakiss.com -abcmail.email -abilitywe.us -abovewe.us -absolutewe.us -abundantwe.us -abusemail.de -abuser.eu -abyssmail.com -ac20mail.in -academiccommunity.com -academywe.us -acceleratewe.us -accentwe.us -acceptwe.us -acclaimwe.us -accordwe.us -accreditedwe.us -acentri.com -achievementwe.us -achievewe.us -acornwe.us -acrossgracealley.com -acrylicwe.us -activatewe.us -activitywe.us -acucre.com -acuitywe.us -acumenwe.us -adaptivewe.us -adaptwe.us -add3000.pp.ua -addictingtrailers.com -adeptwe.us -adfskj.com -adios.email -adiq.eu -aditus.info -admiralwe.us -ado888.biz -adobeccepdm.com -adoniswe.us -adpugh.org -adroh.com -adsd.org -adubiz.info -advantagewe.us -advantimo.com -adventurewe.us -adventwe.us -advisorwe.us -advocatewe.us -adwaterandstir.com -aegde.com -aegia.net -aegiscorp.net -aegiswe.us -aelo.es -aeonpsi.com -afarek.com -affiliate-nebenjob.info -affiliatedwe.us -affilikingz.de -affinitywe.us -affluentwe.us -affordablewe.us -afia.pro -afrobacon.com -afterhourswe.us -agedmail.com -agendawe.us -agger.ro -agilewe.us -agorawe.us -agtx.net -aheadwe.us -ahem.email -ahk.jp -ahmedkhlef.com -air2token.com -airmailbox.website -airsi.de -ajaxapp.net -akapost.com -akerd.com -akgq701.com -akmail.in -al-qaeda.us -albionwe.us -alchemywe.us -alfaceti.com -aliaswe.us -alienware13.com -aligamel.com -alisongamel.com -alivance.com -alivewe.us -all-cats.ru -allaccesswe.us -allamericanwe.us -allaroundwe.us -alldirectbuy.com -allegiancewe.us -allegrowe.us -allemojikeyboard.com -allgoodwe.us -alliancewe.us -allinonewe.us -allofthem.net -alloutwe.us -allowed.org -alloywe.us -allprowe.us -allseasonswe.us -allstarwe.us -allthegoodnamesaretaken.org -allurewe.us -almondwe.us -alph.wtf -alpha-web.net -alphaomegawe.us -alpinewe.us -altairwe.us -altitudewe.us -altuswe.us -ama-trade.de -ama-trans.de -amadeuswe.us -amail.club -amail.com -amail1.com -amail4.me -amazon-aws.org -amberwe.us -ambiancewe.us -ambitiouswe.us -amelabs.com -americanawe.us -americasbestwe.us -americaswe.us -amicuswe.us -amilegit.com -amiri.net -amiriindustries.com -amplewe.us -amplifiedwe.us -amplifywe.us -ampsylike.com -analogwe.us -analysiswe.us -analyticalwe.us -analyticswe.us -analyticwe.us -anappfor.com -anappthat.com -andreihusanu.ro -andthen.us -animesos.com -anit.ro -ano-mail.net -anon-mail.de -anonbox.net -anonmail.top -anonmails.de -anonymail.dk -anonymbox.com -anonymized.org -anonymousness.com -anotherdomaincyka.tk -ansibleemail.com -anthony-junkmail.com -antireg.com -antireg.ru -antispam.de -antispam24.de -antispammail.de -anyalias.com -aoeuhtns.com -apfelkorps.de -aphlog.com -apkmd.com -appc.se -appinventor.nl -appixie.com -apps.dj -appzily.com -arduino.hk -ariaz.jetzt -armyspy.com -aron.us -arroisijewellery.com -art-en-ligne.pro -artman-conception.com -arur01.tk -arurgitu.gq -arvato-community.de -aschenbrandt.net -asdasd.nl -asdasd.ru -ashleyandrew.com -ask-mail.com -asorent.com -ass.pp.ua -astonut.tk -astroempires.info -asu.mx -asu.su -at.hm -at0mik.org -atnextmail.com -attnetwork.com -augmentationtechnology.com -ausgefallen.info -auti.st -autorobotica.com -autosouvenir39.ru -autotwollow.com -autowb.com -aver.com -averdov.com -avia-tonic.fr -avls.pt -awatum.de -awdrt.org -awiki.org -awsoo.com -axiz.org -axon7zte.com -axsup.net -ayakamail.cf -azazazatashkent.tk -azcomputerworks.com -azmeil.tk -b1of96u.com -b2bx.net -b2cmail.de -badgerland.eu -badoop.com -badpotato.tk -balaket.com -banit.club -banit.me -bank-opros1.ru -bareed.ws -barryogorman.com -bartdevos.be -basscode.org -bauwerke-online.com -bazaaboom.com -bbbbyyzz.info -bbhost.us -bbitf.com -bbitj.com -bbitq.com -bcaoo.com -bcast.ws -bcb.ro -bccto.me -bdmuzic.pw -beaconmessenger.com -bearsarefuzzy.com -beddly.com -beefmilk.com -belamail.org -belljonestax.com -beluckygame.com -benipaula.org -bepureme.com -beribase.ru -beribaza.ru -berirabotay.ru -best-john-boats.com -bestchoiceusedcar.com -bestlistbase.com -bestoption25.club -bestparadize.com -bestsoundeffects.com -besttempmail.com -betr.co -bgtmail.com -bgx.ro -bheps.com -bidourlnks.com -big1.us -bigprofessor.so -bigstring.com -bigwhoop.co.za -bij.pl -binka.me -binkmail.com -binnary.com -bio-muesli.info -bio-muesli.net -bione.co -bitwhites.top -bitymails.us -blackgoldagency.ru -blackmarket.to -bladesmail.net -blip.ch -blnkt.net -block521.com -blogmyway.org -blogos.net -blogspam.ro -blondemorkin.com -bluedumpling.info -bluewerks.com -bnote.com -boatmail.us -bobmail.info -bobmurchison.com -bofthew.com -bonobo.email -boofx.com -bookthemmore.com -bootybay.de -borged.com -borged.net -borged.org -bot.nu -boun.cr -bouncr.com -boxformail.in -boximail.com -boxmail.lol -boxomail.live -boxtemp.com.br -bptfp.net -brand-app.biz -brandallday.net -brasx.org -breakthru.com -brefmail.com -brennendesreich.de -briggsmarcus.com -broadbandninja.com -bsnow.net -bspamfree.org -bspooky.com -bst-72.com -btb-notes.com -btc.email -btcmail.pw -btcmod.com -btizet.pl -buccalmassage.ru -budaya-tionghoa.com -budayationghoa.com -buffemail.com -bugfoo.com -bugmenever.com -bugmenot.com -bukhariansiddur.com -bulrushpress.com -bum.net -bumpymail.com -bunchofidiots.com -bund.us -bundes-li.ga -bunsenhoneydew.com -burnthespam.info -burstmail.info -businessbackend.com -businesssuccessislifesuccess.com -buspad.org -bussitussi.com -buymoreplays.com -buyordie.info -buyusdomain.com -buyusedlibrarybooks.org -buzzcluby.com -byebyemail.com -byespm.com -byom.de -c51vsgq.com -cachedot.net -californiafitnessdeals.com -cam4you.cc -camping-grill.info -candymail.de -cane.pw -capitalistdilemma.com -car101.pro -carbtc.net -cars2.club -carsencyclopedia.com -cartelera.org -caseedu.tk -cashflow35.com -casualdx.com -cavi.mx -cbair.com -cbes.net -cc.liamria -ccmail.uk -cdfaq.com -cdpa.cc -ceed.se -cek.pm -cellurl.com -centermail.com -centermail.net -cetpass.com -cfo2go.ro -chacuo.net -chaichuang.com -chalupaurybnicku.cz -chammy.info -chasefreedomactivate.com -chatich.com -cheaphub.net -cheatmail.de -chenbot.email -chibakenma.ml -chickenkiller.com -chielo.com -childsavetrust.org -chilkat.com -chinamkm.com -chithinh.com -chitthi.in -choco.la -chogmail.com -choicemail1.com -chong-mail.com -chong-mail.net -chong-mail.org -chumpstakingdumps.com -cigar-auctions.com -civikli.com -civx.org -ckaazaza.tk -ckiso.com -cl-cl.org -cl0ne.net -claimab.com -clandest.in -classesmail.com -clearwatermail.info -click-email.com -clickdeal.co -clipmail.eu -clixser.com -clonemoi.tk -cloud-mail.top -cloudns.cx -clout.wiki -clrmail.com -cmail.club -cmail.com -cmail.net -cmail.org -cnamed.com -cndps.com -cnew.ir -cnmsg.net -cnsds.de -co.cc -cobarekyo1.ml -cocoro.uk -cocovpn.com -codeandscotch.com -codivide.com -coffeetimer24.com -coieo.com -coin-host.net -coinlink.club -coldemail.info -compareshippingrates.org -completegolfswing.com -comwest.de -conf.work -consumerriot.com -contbay.com -cooh-2.site -coolandwacky.us -coolimpool.org -coreclip.com -cosmorph.com -courrieltemporaire.com -coza.ro -crankhole.com -crapmail.org -crastination.de -crazespaces.pw -crazymailing.com -cream.pink -crepeau12.com -cringemonster.com -cross-law.ga -cross-law.gq -crossmailjet.com -crossroadsmail.com -crunchcompass.com -crusthost.com -cs.email -csh.ro -cszbl.com -ctmailing.us -ctos.ch -cu.cc -cubiclink.com -cuendita.com -cuirushi.org -cuoly.com -cupbest.com -curlhph.tk -curryworld.de -cust.in -cutout.club -cutradition.com -cuvox.de -cyber-innovation.club -cyber-phone.eu -cylab.org -d1yun.com -d3p.dk -daabox.com -dab.ro -dacoolest.com -daemsteam.com -daibond.info -daily-email.com -daintly.com -damai.webcam -dammexe.net -damnthespam.com -dandikmail.com -darkharvestfilms.com -daryxfox.net -dasdasdascyka.tk -dash-pads.com -dataarca.com -datarca.com -datazo.ca -datenschutz.ru -datum2.com -davidkoh.net -davidlcreative.com -dawin.com -daymail.life -daymailonline.com -dayrep.com -dbunker.com -dcctb.com -dcemail.com -ddcrew.com -de-a.org -dea-21olympic.com -deadaddress.com -deadchildren.org -deadfake.cf -deadfake.ga -deadfake.ml -deadfake.tk -deadspam.com -deagot.com -dealja.com -dealrek.com -deekayen.us -defomail.com -degradedfun.net -deinbox.com -delayload.com -delayload.net -delikkt.de -delivrmail.com -demen.ml -dengekibunko.ga -dengekibunko.gq -dengekibunko.ml -der-kombi.de -derkombi.de -derluxuswagen.de -desoz.com -despam.it -despammed.com -dev-null.cf -dev-null.ga -dev-null.gq -dev-null.ml -developermail.com -devnullmail.com -deyom.com -dharmatel.net -dhm.ro -dhy.cc -dialogus.com -diapaulpainting.com -dicopto.com -digdig.org -digital-message.com -digitalesbusiness.info -digitalmail.info -digitalmariachis.com -digitalsanctuary.com -dildosfromspace.com -dim-coin.com -dingbone.com -diolang.com -directmail24.net -disaq.com -disbox.net -disbox.org -discard.cf -discard.email -discard.ga -discard.gq -discard.ml -discard.tk -discardmail.com -discardmail.de -discos4.com -disign-concept.eu -disign-revelation.com -dispo.in -dispomail.eu -disposable-e.ml -disposable-email.ml -disposable.cf -disposable.ga -disposable.ml -disposable.site -disposableaddress.com -disposableemailaddresses.com -disposableinbox.com -disposablemails.com -dispose.it -disposeamail.com -disposemail.com -disposemymail.com -dispostable.com -divad.ga -divermail.com -divismail.ru -diwaq.com -dlemail.ru -dmarc.ro -dndent.com -dnses.ro -doanart.com -dob.jp -dodgeit.com -dodgemail.de -dodgit.com -dodgit.org -dodsi.com -doiea.com -dolphinnet.net -domforfb1.tk -domforfb18.tk -domforfb19.tk -domforfb2.tk -domforfb23.tk -domforfb27.tk -domforfb29.tk -domforfb3.tk -domforfb4.tk -domforfb5.tk -domforfb6.tk -domforfb7.tk -domforfb8.tk -domforfb9.tk -domozmail.com -donemail.ru -dongqing365.com -dontreg.com -dontsendmespam.de -doojazz.com -doquier.tk -dotman.de -dotmsg.com -dotslashrage.com -doublemail.de -douchelounge.com -dozvon-spb.ru -dp76.com -dr69.site -drdrb.com -drdrb.net -dred.ru -drevo.si -drivetagdev.com -drmail.in -droolingfanboy.de -dropcake.de -dropjar.com -droplar.com -dropmail.me -dropsin.net -dsgvo.ru -dsiay.com -dspwebservices.com -duam.net -duck2.club -dudmail.com -duk33.com -dukedish.com -dump-email.info -dumpandjunk.com -dumpmail.de -dumpyemail.com -durandinterstellar.com -duskmail.com -dwse.edu.pl -dyceroprojects.com -dz17.net -e-mail.com -e-mail.org -e-marketstore.ru -e-tomarigi.com -e3z.de -e4ward.com -eanok.com -easy-trash-mail.com -easynetwork.info -easytrashmail.com -eatmea2z.club -eay.jp -ebbob.com -ebeschlussbuch.de -ecallheandi.com -ecolo-online.fr -edgex.ru -edinburgh-airporthotels.com -edv.to -ee1.pl -ee2.pl -eeedv.de -eelmail.com -efxs.ca -egzones.com -einmalmail.de -einrot.com -einrot.de -eintagsmail.de -elearningjournal.org -electro.mn -elitevipatlantamodels.com -elki-mkzn.ru -email-fake.cf -email-fake.com -email-fake.ga -email-fake.gq -email-fake.ml -email-fake.tk -email-jetable.fr -email-lab.com -email-temp.com -email.edu.pl -email.net -email1.pro -email60.com -emailage.cf -emailage.ga -emailage.gq -emailage.ml -emailage.tk -emailate.com -emailcu.icu -emaildienst.de -emaildrop.io -emailfake.com -emailfake.ml -emailfreedom.ml -emailgenerator.de -emailgo.de -emailias.com -emailigo.de -emailinfive.com -emailisvalid.com -emaillime.com -emailmiser.com -emailna.co -emailnax.com -emailo.pro -emailondeck.com -emailportal.info -emailproxsy.com -emailresort.com -emails.ga -emailsecurer.com -emailsensei.com -emailsingularity.net -emailspam.cf -emailspam.ga -emailspam.gq -emailspam.ml -emailspam.tk -emailsy.info -emailtech.info -emailtemporanea.com -emailtemporanea.net -emailtemporar.ro -emailtemporario.com.br -emailthe.net -emailtmp.com -emailto.de -emailure.net -emailwarden.com -emailxfer.com -emailz.cf -emailz.ga -emailz.gq -emailz.ml -emeil.in -emeil.ir -emeraldwebmail.com -emil.com -emkei.cf -emkei.ga -emkei.gq -emkei.ml -emkei.tk -eml.pp.ua -emlhub.com -emlpro.com -emltmp.com -empireanime.ga -emstjzh.com -emz.net -enayu.com -enterto.com -envy17.com -eoffice.top -eoopy.com -epb.ro -ephemail.net -ephemeral.email -eposta.buzz -eposta.work -eqiluxspam.ga -ereplyzy.com -ericjohnson.ml -ero-tube.org -esadverse.com -esbano-ru.ru -esc.la -escapehatchapp.com -esemay.com -esgeneri.com -esiix.com -esprity.com -estate-invest.fr -eth2btc.info -ether123.net -ethereum1.top -ethersports.org -ethersportz.info -etotvibor.ru -etranquil.com -etranquil.net -etranquil.org -euaqa.com -evanfox.info -eveav.com -evilcomputer.com -evopo.com -evyush.com -exdonuts.com -existiert.net -exitstageleft.net -explodemail.com -express.net.ua -extracurricularsociety.com -extremail.ru -eyepaste.com -ez.lv -ezehe.com -ezfill.com -ezstest.com -f4k.es -f5.si -facebook-email.cf -facebook-email.ga -facebook-email.ml -facebookmail.gq -facebookmail.ml -fackme.gq -fadingemail.com -faecesmail.me -fag.wf -failbone.com -faithkills.com -fake-box.com -fake-email.pp.ua -fake-mail.cf -fake-mail.ga -fake-mail.ml -fakedemail.com -fakeinbox.cf -fakeinbox.com -fakeinbox.ga -fakeinbox.info -fakeinbox.ml -fakeinbox.tk -fakeinformation.com -fakemail.fr -fakemail.io -fakemailgenerator.com -fakemailz.com -fallinhay.com -fammix.com -fanclub.pm -fangoh.com -fansworldwide.de -fantasymail.de -farrse.co.uk -fast-email.info -fast-mail.fr -fastacura.com -fastchevy.com -fastchrysler.com -fasternet.biz -fastkawasaki.com -fastmazda.com -fastmitsubishi.com -fastnissan.com -fastsubaru.com -fastsuzuki.com -fasttoyota.com -fastyamaha.com -fatflap.com -fbma.tk -fddns.ml -fdfdsfds.com -femailtor.com -fer-gabon.org -fermaxxi.ru -fettometern.com -fexbox.org -fexbox.ru -fexpost.com -fextemp.com -ficken.de -fictionsite.com -fightallspam.com -figjs.com -figshot.com -figurescoin.com -fiifke.de -filbert4u.com -filberts4u.com -film-blog.biz -filzmail.com -findemail.info -findu.pl -finews.biz -fir.hk -firemailbox.club -fitnesrezink.ru -fivemail.de -fixmail.tk -fizmail.com -fleckens.hu -flemail.ru -flowu.com -flu.cc -fluidsoft.us -flurred.com -fly-ts.de -flyinggeek.net -flyspam.com -foobarbot.net -footard.com -foreastate.com -forecastertests.com -foreskin.cf -foreskin.ga -foreskin.gq -foreskin.ml -foreskin.tk -forgetmail.com -fornow.eu -forspam.net -forward.cat -fosil.pro -foxja.com -foxtrotter.info -fr.cr -fr.nf -fr33mail.info -fragolina2.tk -frapmail.com -frappina.tk -free-email.cf -free-email.ga -free-temp.net -freebabysittercam.com -freeblackbootytube.com -freecat.net -freedom4you.info -freedompop.us -freefattymovies.com -freehotmail.net -freeinbox.email -freelance-france.eu -freeletter.me -freemail.ms -freemails.cf -freemails.ga -freemails.ml -freemeil.ga -freemeil.gq -freemeil.ml -freeml.net -freeplumpervideos.com -freerubli.ru -freeschoolgirlvids.com -freesistercam.com -freeteenbums.com -freundin.ru -friendlymail.co.uk -front14.org -frwdmail.com -ftp.sh -ftpinc.ca -fuckedupload.com -fuckingduh.com -fuckme69.club -fucknloveme.top -fuckxxme.top -fudgerub.com -fuirio.com -fukaru.com -fukurou.ch -fullangle.org -fulvie.com -fun64.com -funnycodesnippets.com -funnymail.de -furzauflunge.de -futuramind.com -fuwamofu.com -fuwari.be -fux0ringduh.com -fxnxs.com -fyii.de -g14l71lb.com -g1xmail.top -g2xmail.top -g3xmail.top -g4hdrop.us -gafy.net -gage.ga -galaxy.tv -gally.jp -gamail.top -gamegregious.com -gamgling.com -garasikita.pw -garbagecollector.org -garbagemail.org -gardenscape.ca -garizo.com -garliclife.com -garrymccooey.com -gav0.com -gawab.com -gbcmail.win -gbmail.top -gcmail.top -gdmail.top -gedmail.win -geekforex.com -geew.ru -gehensiemirnichtaufdensack.de -geldwaschmaschine.de -gelitik.in -genderfuck.net -geronra.com -geschent.biz -get-mail.cf -get-mail.ga -get-mail.ml -get-mail.tk -get.pp.ua -get1mail.com -get2mail.fr -getairmail.cf -getairmail.com -getairmail.ga -getairmail.gq -getairmail.ml -getairmail.tk -geteit.com -getfun.men -getmails.eu -getnada.com -getnowtoday.cf -getonemail.com -getonemail.net -getover.de -getsimpleemail.com -gett.icu -gexik.com -ggmal.ml -ghosttexter.de -giacmosuaviet.info -giaiphapmuasam.com -giantmail.de -gifto12.com -ginzi.be -ginzi.co.uk -ginzi.es -ginzi.net -ginzy.co.uk -ginzy.eu -girlmail.win -girlsindetention.com -girlsundertheinfluence.com -gishpuppy.com -giveh2o.info -givememail.club -givmail.com -glitch.sx -globaltouron.com -glubex.com -glucosegrin.com -gmal.com -gmatch.org -gmial.com -gmx1mail.top -gmxmail.top -gmxmail.win -gnctr-calgary.com -go2usa.info -go2vpn.net -goemailgo.com -golemico.com -gomail.in -goonby.com -goplaygame.ru -gorillaswithdirtyarmpits.com -goround.info -gosuslugi-spravka.ru -gothere.biz -gotmail.com -gotmail.net -gotmail.org -gowikibooks.com -gowikicampus.com -gowikicars.com -gowikifilms.com -gowikigames.com -gowikimusic.com -gowikinetwork.com -gowikitravel.com -gowikitv.com -grandmamail.com -grandmasmail.com -great-host.in -greencafe24.com -greendike.com -greenhousemail.com -greensloth.com -greggamel.com -greggamel.net -gregorsky.zone -gregorygamel.com -gregorygamel.net -grish.de -griuc.schule -grn.cc -groupbuff.com -grr.la -grugrug.ru -gruz-m.ru -gs-arc.org -gsredcross.org -gsrv.co.uk -gsxstring.ga -gudanglowongan.com -guerillamail.biz -guerillamail.com -guerillamail.de -guerillamail.info -guerillamail.net -guerillamail.org -guerillamailblock.com -guerrillamail.biz -guerrillamail.com -guerrillamail.de -guerrillamail.info -guerrillamail.net -guerrillamail.org -guerrillamailblock.com -gufum.com -gustr.com -gxemail.men -gynzi.co.uk -gynzi.es -gynzy.at -gynzy.es -gynzy.eu -gynzy.gr -gynzy.info -gynzy.lt -gynzy.mobi -gynzy.pl -gynzy.ro -gynzy.sk -gzb.ro -h8s.org -habitue.net -hacccc.com -hackersquad.tk -hackthatbit.ch -hahawrong.com -haida-edu.cn -hairs24.ru -haltospam.com -hamham.uk -hangxomcuatoilatotoro.ml -happydomik.ru -harakirimail.com -haribu.com -hartbot.de -hasanmail.ml -hat-geld.de -hatespam.org -hawrong.com -haydoo.com -hazelnut4u.com -hazelnuts4u.com -hazmatshipping.org -hccmail.win -headstrong.de -heathenhammer.com -heathenhero.com -hecat.es -heisei.be -hellodream.mobi -helloricky.com -helpinghandtaxcenter.org -helpjobs.ru -heros3.com -herp.in -herpderp.nl -hezll.com -hi5.si -hiddentragedy.com -hidebox.org -hidebusiness.xyz -hidemail.de -hidemail.pro -hidemail.us -hidzz.com -highbros.org -hiltonvr.com -himail.online -hmail.us -hmamail.com -hmh.ro -hoanggiaanh.com -hoanglong.tech -hochsitze.com -hola.org -holl.ga -honeys.be -honor-8.com -hopemail.biz -hornyalwary.top -host1s.com -hostcalls.com -hostguru.top -hostingmail.me -hostlaba.com -hot-mail.cf -hot-mail.ga -hot-mail.gq -hot-mail.ml -hot-mail.tk -hotmai.com -hotmailproduct.com -hotmial.com -hotpop.com -hotprice.co -hotsoup.be -housat.com -hpc.tw -hs.vc -ht.cx -huangniu8.com -hukkmu.tk -hulapla.de -humaility.com -hungpackage.com -hushmail.cf -huskion.net -hvastudiesucces.nl -hwsye.net -i2pmail.org -i6.cloudns.cc -iaoss.com -ibnuh.bz -icantbelieveineedtoexplainthisshit.com -icemail.club -ichigo.me -icx.in -icx.ro -idx4.com -idxue.com -ieatspam.eu -ieatspam.info -ieh-mail.de -iencm.com -iffymedia.com -ige.es -igg.biz -ignoremail.com -ihateyoualot.info -ihazspam.ca -iheartspam.org -ikbenspamvrij.nl -illistnoise.com -ilovespam.com -imail1.net -imails.info -imailt.com -imgof.com -imgv.de -immo-gerance.info -imstations.com -imul.info -in-ulm.de -in2reach.com -inactivemachine.com -inbax.tk -inbound.plus -inbox.si -inbox2.info -inboxalias.com -inboxbear.com -inboxclean.com -inboxclean.org -inboxdesign.me -inboxed.im -inboxed.pw -inboxkitten.com -inboxproxy.com -inboxstore.me -inclusiveprogress.com -incognitomail.com -incognitomail.net -incognitomail.org -incq.com -ind.st -indieclad.com -indirect.ws -indomaed.pw -indomina.cf -indoserver.stream -indosukses.press -ineec.net -infocom.zp.ua -inggo.org -inkomail.com -inmynetwork.tk -inoutmail.de -inoutmail.eu -inoutmail.info -inoutmail.net -inpwa.com -insanumingeniumhomebrew.com -insorg-mail.info -instaddr.ch -instance-email.com -instant-mail.de -instantblingmail.info -instantemailaddress.com -instantmail.fr -internet-v-stavropole.ru -internetoftags.com -interstats.org -intersteller.com -intopwa.com -intopwa.net -intopwa.org -investore.co -iozak.com -ip4.pp.ua -ip6.li -ip6.pp.ua -ipoo.org -ippandansei.tk -ipsur.org -irabops.com -irc.so -irish2me.com -irishspringrealty.com -iroid.com -ironiebehindert.de -irssi.tv -is.af -isdaq.com -ishop2k.com -isosq.com -istii.ro -isukrainestillacountry.com -it7.ovh -italy-mail.com -itcompu.com -itfast.net -itunesgiftcodegenerator.com -iubridge.com -iuemail.men -iwi.net -ixaks.com -ixx.io -j-p.us -jafps.com -jajxz.com -janproz.com -jaqis.com -jdmadventures.com -jdz.ro -je-recycle.info -jellow.ml -jellyrolls.com -jeoce.com -jet-renovation.fr -jetable.com -jetable.net -jetable.org -jetable.pp.ua -jiooq.com -jmail.ovh -jmail.ro -jnxjn.com -jobbikszimpatizans.hu -jobbrett.com -jobposts.net -jobs-to-be-done.net -joelpet.com -joetestalot.com -jopho.com -joseihorumon.info -josse.ltd -jourrapide.com -jpco.org -jsrsolutions.com -jumonji.tk -jungkamushukum.com -junk.to -junk1e.com -junkmail.ga -junkmail.gq -just-email.com -justemail.ml -juyouxi.com -jwork.ru -kademen.com -kadokawa.cf -kadokawa.ga -kadokawa.gq -kadokawa.ml -kadokawa.tk -kaengu.ru -kagi.be -kakadua.net -kalapi.org -kamen-market.ru -kamsg.com -kaovo.com -kappala.info -kara-turk.net -karatraman.ml -kariplan.com -karta-kykyruza.ru -kartvelo.com -kasmail.com -kaspop.com -katztube.com -kazelink.ml -kbox.li -kcrw.de -keepmymail.com -keinhirn.de -keipino.de -kekita.com -kellychibale-researchgroup-uct.com -kemptvillebaseball.com -kennedy808.com -kiani.com -killmail.com -killmail.net -kimsdisk.com -kingsq.ga -kino-100.ru -kiois.com -kismail.ru -kisstwink.com -kitnastar.com -kjkszpjcompany.com -kkmail.be -kksm.be -klassmaster.com -klassmaster.net -klick-tipp.us -klipschx12.com -kloap.com -kludgemush.com -klzlk.com -kmail.li -kmhow.com -knol-power.nl -kobrandly.com -kommunity.biz -kon42.com -konultant-jurist.ru -kook.ml -kopagas.com -kopaka.net -korona-nedvizhimosti.ru -koshu.ru -kosmetik-obatkuat.com -kostenlosemailadresse.de -koszmail.pl -kpay.be -kpooa.com -kpost.be -krd.ag -krsw.tk -kruay.com -krypton.tk -ksmtrck.tk -kuhrap.com -kulmeo.com -kulturbetrieb.info -kurzepost.de -kutakbisajauhjauh.gq -kvhrr.com -kvhrs.com -kvhrw.com -kwift.net -kwilco.net -kyal.pl -kyois.com -kzccv.com -l-c-a.us -l33r.eu -l6factors.com -labetteraverouge.at -labworld.org -lacedmail.com -lackmail.net -lackmail.ru -lacto.info -lags.us -lain.ch -lak.pp.ua -lakelivingstonrealestate.com -lakqs.com -lamasticots.com -landmail.co -laoeq.com -larisia.com -larland.com -last-chance.pro -lastmail.co -lastmail.com -lawlita.com -lazyinbox.com -lazyinbox.us -ldaho.biz -ldop.com -ldtp.com -le-tim.ru -lee.mx -leeching.net -leetmail.co -legalrc.loan -lellno.gq -lenovog4.com -lerbhe.com -letmeinonthis.com -letthemeatspam.com -lez.se -lgxscreen.com -lhsdv.com -liamcyrus.com -lifebyfood.com -lifetimefriends.info -lifetotech.com -ligsb.com -lillemap.net -lilo.me -lindenbaumjapan.com -link2mail.net -linkedintuts2016.pw -linshiyouxiang.net -linuxmail.so -litedrop.com -liveradio.tk -lkgn.se -llogin.ru -loadby.us -loan101.pro -loaoa.com -loapq.com -locanto1.club -locantofuck.top -locantowsite.club -locomodev.net -login-email.cf -login-email.ga -login-email.ml -login-email.tk -logular.com -loh.pp.ua -loin.in -lolfreak.net -lolmail.biz -lookugly.com -lordsofts.com -lortemail.dk -losemymail.com -lovemeet.faith -lovemeleaveme.com -lpfmgmtltd.com -lr7.us -lr78.com -lroid.com -lru.me -ls-server.ru -lsyx24.com -luckymail.org -lukecarriere.com -lukemail.info -lukop.dk -luv2.us -lyfestylecreditsolutions.com -lyft.live -lyricspad.net -lzoaq.com -m21.cc -m4ilweb.info -maboard.com -mac-24.com -macr2.com -macromaid.com -macromice.info -magamail.com -maggotymeat.ga -magicbox.ro -magim.be -magspam.net -maidlow.info -mail-card.net -mail-easy.fr -mail-filter.com -mail-help.net -mail-hosting.co -mail-hub.info -mail-now.top -mail-owl.com -mail-share.com -mail-temporaire.com -mail-temporaire.fr -mail-tester.com -mail.by -mail.wtf -mail0.ga -mail1.top -mail114.net -mail1a.de -mail1web.org -mail21.cc -mail22.club -mail2rss.org -mail333.com -mail4trash.com -mail666.ru -mail7.io -mail707.com -mail72.com -mailapp.top -mailback.com -mailbidon.com -mailbiz.biz -mailblocks.com -mailbox.in.ua -mailbox52.ga -mailbox80.biz -mailbox82.biz -mailbox87.de -mailbox92.biz -mailboxy.fun -mailbucket.org -mailcat.biz -mailcatch.com -mailchop.com -mailcker.com -maildax.me -mailde.de -mailde.info -maildrop.cc -maildrop.cf -maildrop.ga -maildrop.gq -maildrop.ml -maildu.de -maildx.com -maileater.com -mailed.in -mailed.ro -maileimer.de -maileme101.com -mailexpire.com -mailf5.com -mailfa.tk -mailfall.com -mailfirst.icu -mailforspam.com -mailfree.ga -mailfree.gq -mailfree.ml -mailfreeonline.com -mailfs.com -mailguard.me -mailgutter.com -mailhazard.com -mailhazard.us -mailhex.com -mailhub.pro -mailhz.me -mailimate.com -mailin8r.com -mailinatar.com -mailinater.com -mailinator.co.uk -mailinator.com -mailinator.gq -mailinator.info -mailinator.net -mailinator.org -mailinator.us -mailinator0.com -mailinator1.com -mailinator2.com -mailinator2.net -mailinator3.com -mailinator4.com -mailinator5.com -mailinator6.com -mailinator7.com -mailinator8.com -mailinator9.com -mailincubator.com -mailismagic.com -mailita.tk -mailjunk.cf -mailjunk.ga -mailjunk.gq -mailjunk.ml -mailjunk.tk -mailmate.com -mailme.gq -mailme.ir -mailme.lv -mailme24.com -mailmetrash.com -mailmoat.com -mailmoth.com -mailms.com -mailna.biz -mailna.co -mailna.in -mailna.me -mailnator.com -mailnesia.com -mailnull.com -mailonaut.com -mailorc.com -mailorg.org -mailosaur.net -mailox.fun -mailpick.biz -mailpluss.com -mailpooch.com -mailpoof.com -mailpress.gq -mailproxsy.com -mailquack.com -mailrock.biz -mailsac.com -mailscrap.com -mailseal.de -mailshell.com -mailshiv.com -mailsiphon.com -mailslapping.com -mailslite.com -mailsucker.net -mailt.net -mailt.top -mailtechx.com -mailtemp.info -mailtemporaire.com -mailtemporaire.fr -mailto.plus -mailtome.de -mailtothis.com -mailtraps.com -mailtrash.net -mailtrix.net -mailtv.net -mailtv.tv -mailuniverse.co.uk -mailzi.ru -mailzilla.com -mailzilla.org -mainerfolg.info -makemenaughty.club -makemetheking.com -malahov.de -malayalamdtp.com -mama3.org -mamulenok.ru -mandraghen.cf -manifestgenerator.com -mannawo.com -mansiondev.com -manybrain.com -mark-compressoren.ru -marketlink.info -markmurfin.com -mask03.ru -masonline.info -maswae.world -matamuasu.ga -matchpol.net -matra.site -max-mail.org -mbox.re -mbx.cc -mcache.net -mciek.com -mdhc.tk -meantinc.com -mebelnu.info -mechanicalresumes.com -medkabinet-uzi.ru -meepsheep.eu -meidecn.com -meinspamschutz.de -meltedbrownies.com -meltmail.com -memsg.site -mentonit.net -mepost.pw -merry.pink -messagebeamer.de -messwiththebestdielikethe.rest -metadownload.org -metaintern.net -metalunits.com -mezimages.net -mfsa.info -mfsa.ru -mhzayt.online -miaferrari.com -miauj.com -midcoastcustoms.com -midcoastcustoms.net -midcoastsolutions.com -midcoastsolutions.net -midiharmonica.com -midlertidig.com -midlertidig.net -midlertidig.org -mierdamail.com -migmail.net -migmail.pl -migumail.com -mihep.com -mijnhva.nl -ministry-of-silly-walks.de -minsmail.com -mintemail.com -mirai.re -misterpinball.de -miucce.com -mji.ro -mjj.edu.ge -mjukglass.nu -mkpfilm.com -ml8.ca -mm.my -mm5.se -mnode.me -moakt.cc -moakt.co -moakt.com -moakt.ws -mobileninja.co.uk -mobilevpn.top -moburl.com -mockmyid.com -moeri.org -mofu.be -mohmal.com -mohmal.im -mohmal.in -mohmal.tech -moimoi.re -molms.com -momentics.ru -monachat.tk -monadi.ml -moneypipe.net -monumentmail.com -moonwake.com -moot.es -moreawesomethanyou.com -moreorcs.com -morriesworld.ml -morsin.com -moruzza.com -motique.de -mountainregionallibrary.net -mox.pp.ua -moy-elektrik.ru -moza.pl -mozej.com -mp-j.ga -mr24.co -mrvpm.net -mrvpt.com -msgos.com -mspeciosa.com -msrc.ml -mswork.ru -msxd.com -mt2009.com -mt2014.com -mt2015.com -mtmdev.com -muathegame.com -muchomail.com -mucincanon.com -muehlacker.tk -muell.icu -muell.monster -muell.xyz -muellemail.com -muellmail.com -munoubengoshi.gq -musiccode.me -mutant.me -mvrht.com -mvrht.net -mwarner.org -mxclip.com -mxfuel.com -my-pomsies.ru -my-teddyy.ru -my10minutemail.com -mybitti.de -mycleaninbox.net -mycorneroftheinter.net -myde.ml -mydefipet.live -mydemo.equipment -myecho.es -myemailboxy.com -mygeoweb.info -myindohome.services -myinterserver.ml -mykickassideas.com -mymail-in.net -mymail90.com -mymailoasis.com -mynetstore.de -myopang.com -mypacks.net -mypartyclip.de -myphantomemail.com -mysamp.de -myspaceinc.com -myspaceinc.net -myspaceinc.org -myspacepimpedup.com -myspamless.com -mystvpn.com -mysugartime.ru -mytemp.email -mytempemail.com -mytempmail.com -mytrashmail.com -mywarnernet.net -mywrld.site -mywrld.top -myzx.com -mzico.com -n1nja.org -na-cat.com -nabuma.com -nada.email -nada.ltd -nagi.be -nakedtruth.biz -nanonym.ch -naslazhdai.ru -nationalgardeningclub.com -nawmin.info -nbzmr.com -negated.com -neko2.net -nekochan.fr -neomailbox.com -neotlozhniy-zaim.ru -nepwk.com -nervmich.net -nervtmich.net -net1mail.com -netcom.ws -netmails.com -netmails.net -netricity.nl -netris.net -netviewer-france.com -netzidiot.de -nevermail.de -newbpotato.tk -newfilm24.ru -newideasfornewpeople.info -newmail.top -next.ovh -nextmail.info -nextstopvalhalla.com -nezdiro.org -nezid.com -nezumi.be -nezzart.com -nfast.net -nguyenusedcars.com -nh3.ro -nice-4u.com -nicknassar.com -nincsmail.com -nincsmail.hu -niseko.be -niwl.net -nm7.cc -nmail.cf -nnh.com -nnot.net -nnoway.ru -no-spam.ws -no-ux.com -noblepioneer.com -nobugmail.com -nobulk.com -nobuma.com -noclickemail.com -nodezine.com -nogmailspam.info -noicd.com -nokiamail.com -nolemail.ga -nomail.cf -nomail.ga -nomail.pw -nomail2me.com -nomorespamemails.com -nonspam.eu -nonspammer.de -nonze.ro -noref.in -norseforce.com -norwegischlernen.info -nospam4.us -nospamfor.us -nospamthanks.info -nothingtoseehere.ca -notif.me -notmailinator.com -notrnailinator.com -notsharingmy.info -now.im -nowhere.org -nowmymail.com -nowmymail.net -nproxi.com -nthrl.com -ntlhelp.net -nubescontrol.com -nullbox.info -nurfuerspam.de -nut.cc -nutpa.net -nuts2trade.com -nvhrw.com -nwldx.com -nwytg.com -nwytg.net -ny7.me -nypato.com -nyrmusic.com -o2stk.org -o7i.net -oalsp.com -obfusko.com -objectmail.com -obobbo.com -oborudovanieizturcii.ru -obxpestcontrol.com -octovie.com -odaymail.com -odem.com -odnorazovoe.ru -oepia.com -oerpub.org -offshore-proxies.net -ohaaa.de -ohi.tw -oida.icu -oing.cf -okclprojects.com -okinawa.li -okrent.us -okzk.com -olimp-case.ru -olypmall.ru -omail.pro -omnievents.org -omtecha.com -one-mail.top -one-time.email -one2mail.info -onekisspresave.com -onemail.host -oneoffemail.com -oneoffmail.com -onetm.jp -onewaymail.com -onlatedotcom.info -online.ms -onlineidea.info -onqin.com -ontyne.biz -oohioo.com -oolus.com -oonies-shoprus.ru -oopi.org -oosln.com -opayq.com -openavz.com -opendns.ro -opentrash.com -opmmedia.ga -opp24.com -optimaweb.me -opwebw.com -oranek.com -ordinaryamerican.net -oreidresume.com -orgmbx.cc -oroki.de -oshietechan.link -otherinbox.com -ourklips.com -ourpreviewdomain.com -outlawspam.com -outmail.win -ovomail.co -ovpn.to -owleyes.ch -owlpic.com -ownsyou.de -oxopoha.com -ozyl.de -p-banlis.ru -p33.org -p71ce1m.com -pa9e.com -pachilly.com -packiu.com -pagamenti.tk -paharpurmim.ga -pakadebu.ga -pamaweb.com -pancakemail.com -papierkorb.me -paplease.com -para2019.ru -parlimentpetitioner.tk -pastebitch.com -patonce.com -pavilionx2.com -payperex2.com -payspun.com -pe.hu -pecinan.com -pecinan.net -pecinan.org -penisgoes.in -penoto.tk -pepbot.com -peterdethier.com -petloca.com -petrzilka.net -pewpewpewpew.pw -pfui.ru -phone-elkey.ru -photo-impact.eu -photomark.net -pi.vu -piaa.me -pig.pp.ua -pii.at -piki.si -pimpedupmyspace.com -pinehill-seattle.org -pingir.com -pipemail.space -pisls.com -pitaniezdorovie.ru -pivo-bar.ru -pixiil.com -pjjkp.com -placebomail10.com -pleasenoham.org -plexfirm.com -plexolan.de -plhk.ru -ploae.com -plw.me -poehali-otdihat.ru -pojok.ml -pokemail.net -pokiemobile.com -polarkingxx.ml -politikerclub.de -polyfaust.net -pooae.com -poofy.org -pookmail.com -poopiebutt.club -popcornfarm7.com -popcornfly.com -popesodomy.com -popgx.com -porjoton.com -porsh.net -posdz.com -posta.store -postacin.com -postonline.me -poutineyourface.com -powered.name -powerencry.com -powlearn.com -pp7rvv.com -ppetw.com -pptrvv.com -pqoia.com -pratikmail.com -pratikmail.net -pratikmail.org -prazdnik-37.ru -predatorrat.cf -predatorrat.ga -predatorrat.gq -predatorrat.ml -predatorrat.tk -premium-mail.fr -primabananen.net -prin.be -privacy.net -privatdemail.net -privy-mail.com -privy-mail.de -privymail.de -pro-tag.org -pro5g.com -procrackers.com -profast.top -projectcl.com -promailt.com -proprietativalcea.ro -propscore.com -protempmail.com -proxymail.eu -proxyparking.com -prtnx.com -prtshr.com -prtz.eu -psh.me -psles.com -psnator.com -psoxs.com -puglieisi.com -puji.pro -punkass.com -puppetmail.de -purcell.email -purelogistics.org -put2.net -puttanamaiala.tk -putthisinyourspamdatabase.com -pwrby.com -qasti.com -qbfree.us -qc.to -qibl.at -qiott.com -qipmail.net -qiq.us -qisdo.com -qisoa.com -qmrbe.com -qoika.com -qopow.com -qq.my -qsl.ro -qtum-ico.com -quadrafit.com -quick-mail.cc -quickemail.info -quickinbox.com -quickmail.nl -quicksend.ch -ququb.com -qvy.me -qwickmail.com -r4nd0m.de -ra3.us -rabin.ca -rabiot.reisen -rackabzar.com -raetp9.com -rainbowly.ml -raketenmann.de -rancidhome.net -randomail.io -randomail.net -rapt.be -raqid.com -rax.la -raxtest.com -razemail.com -razuz.com -rbb.org -rcasd.com -rcpt.at -rdklcrv.xyz -re-gister.com -reality-concept.club -reallymymail.com -realtyalerts.ca -rebates.stream -receiveee.com -recipeforfailure.com -recode.me -reconmail.com -recyclemail.dk -redfeathercrow.com -reftoken.net -regbypass.com -regspaces.tk -reimondo.com -rejectmail.com -rejo.technology -reliable-mail.com -remail.cf -remail.ga -remarkable.rocks -remote.li -reptilegenetics.com -resgedvgfed.tk -revolvingdoorhoax.org -rfc822.org -rhyta.com -richfinances.pw -riddermark.de -rifkian.ga -rippb.com -risingsuntouch.com -riski.cf -rklips.com -rkomo.com -rm2rf.com -rma.ec -rmqkr.net -rnailinator.com -ro.lt -robertspcrepair.com -robot-mail.com -rollindo.agency -ronnierage.net -rootfest.net -rosebearmylove.ru -rotaniliam.com -rover.info -rowe-solutions.com -royal.net -royaldoodles.org -royalmarket.life -royandk.com -rppkn.com -rsvhr.com -rtrtr.com -rtskiya.xyz -rudymail.ml -rumgel.com -runi.ca -rupayamail.com -ruru.be -rustydoor.com -rvb.ro -ryteto.me -s0ny.net -s33db0x.com -sabrestlouis.com -sackboii.com -saeoil.com -safaat.cf -safermail.info -safersignup.de -safetymail.info -safetypost.de -saharanightstempe.com -salmeow.tk -samsclass.info -sandcars.net -sandelf.de -sandwhichvideo.com -sanfinder.com -sanim.net -sanstr.com -sast.ro -satisfyme.club -satukosong.com -sausen.com -saynotospams.com -scatmail.com -scay.net -schachrol.com -schafmail.de -schmeissweg.tk -schrott-email.de -scrsot.com -sd3.in -sdvft.com -sdvgeft.com -sdvrecft.com -secmail.pw -secretemail.de -secure-mail.biz -secure-mail.cc -secured-link.net -securehost.com.es -seekapps.com -seekjobs4u.com -sejaa.lv -selfdestructingmail.com -selfdestructingmail.org -send22u.info -sendfree.org -sendingspecialflyers.com -sendnow.win -sendspamhere.com -senseless-entertainment.com -server.ms -services391.com -sexforswingers.com -sexical.com -sexyalwasmi.top -shadap.org -shalar.net -sharedmailbox.org -sharklasers.com -sheryli.com -shhmail.com -shhuut.org -shieldedmail.com -shieldemail.com -shiftmail.com -shipfromto.com -shiphazmat.org -shipping-regulations.com -shippingterms.org -shitaway.tk -shitmail.de -shitmail.me -shitmail.org -shmeriously.com -shopxda.com -shortmail.net -shotmail.ru -showslow.de -shrib.com -shut.name -shut.ws -siberpay.com -sidelka-mytischi.ru -siftportal.ru -sify.com -sika3.com -sikux.com -siliwangi.ga -silvercoin.life -sim-simka.ru -simaenaga.com -simpleitsecurity.info -sin.cl -sinaite.net -sinema.ml -sinfiltro.cl -singlespride.com -sinnlos-mail.de -sino.tw -siteposter.net -sizzlemctwizzle.com -sjuaq.com -skeefmail.com -skrx.tk -sky-inbox.com -sky-ts.de -skyrt.de -slapsfromlastnight.com -slaskpost.se -slave-auctions.net -slippery.email -slipry.net -slopsbox.com -slothmail.net -slushmail.com -sluteen.com -sly.io -smallker.tk -smapfree24.com -smapfree24.de -smapfree24.eu -smapfree24.info -smapfree24.org -smartnator.com -smarttalent.pw -smashmail.de -smellfear.com -smellrear.com -smellypotato.tk -smtp99.com -smwg.info -snakemail.com -snapwet.com -sneakmail.de -snece.com -social-mailer.tk -socialfurry.org -sofia.re -sofimail.com -sofort-mail.de -sofortmail.de -sofrge.com -softkey-office.ru -softpls.asia -sogetthis.com -sohai.ml -sohus.cn -soioa.com -soisz.com -solar-impact.pro -solvemail.info -solventtrap.wiki -songsign.com -sonshi.cf -soodmail.com -soodomail.com -soodonims.com -soombo.com -soon.it -spacebazzar.ru -spam-be-gone.com -spam.care -spam.la -spam.org.es -spam.su -spam4.me -spamail.de -spamarrest.com -spamavert.com -spambob.com -spambob.net -spambob.org -spambog.com -spambog.de -spambog.net -spambog.ru -spambooger.com -spambox.info -spambox.me -spambox.org -spambox.us -spamcero.com -spamcon.org -spamcorptastic.com -spamcowboy.com -spamcowboy.net -spamcowboy.org -spamday.com -spamdecoy.net -spamex.com -spamfighter.cf -spamfighter.ga -spamfighter.gq -spamfighter.ml -spamfighter.tk -spamfree.eu -spamfree24.com -spamfree24.de -spamfree24.eu -spamfree24.info -spamfree24.net -spamfree24.org -spamgoes.in -spamherelots.com -spamhereplease.com -spamhole.com -spamify.com -spaminator.de -spamkill.info -spaml.com -spaml.de -spamlot.net -spammer.fail -spammotel.com -spammy.host -spamobox.com -spamoff.de -spamsalad.in -spamslicer.com -spamsphere.com -spamspot.com -spamstack.net -spamthis.co.uk -spamthis.network -spamthisplease.com -spamtrail.com -spamtrap.ro -spamtroll.net -spamwc.cf -spamwc.ga -spamwc.gq -spamwc.ml -speedgaus.net -sperma.cf -spikio.com -spindl-e.com -spoofmail.de -spr.io -spritzzone.de -spruzme.com -spybox.de -spymail.com -squizzy.de -squizzy.net -sroff.com -sry.li -ssoia.com -stanfordujjain.com -starlight-breaker.net -starpower.space -startfu.com -startkeys.com -statdvr.com -stathost.net -statiix.com -stayhome.li -steam-area.ru -steambot.net -stexsy.com -stinkefinger.net -stop-my-spam.cf -stop-my-spam.com -stop-my-spam.ga -stop-my-spam.ml -stop-my-spam.pp.ua -stop-my-spam.tk -stopspam.app -storiqax.top -storj99.com -storj99.top -streetwisemail.com -stromox.com -stuckmail.com -stuffmail.de -stumpfwerk.com -stylist-volos.ru -submic.com -suburbanthug.com -suckmyd.com -sueshaw.com -suexamplesb.com -suioe.com -super-auswahl.de -supergreatmail.com -supermailer.jp -superplatyna.com -superrito.com -supersave.net -superstachel.de -superyp.com -suremail.info -sute.jp -svip520.cn -svk.jp -svxr.org -sweetpotato.ml -sweetxxx.de -swift-mail.net -swift10minutemail.com -syinxun.com -sylvannet.com -symphonyresume.com -syosetu.gq -syujob.accountants -szerz.com -tafmail.com -tafoi.gr -taglead.com -tagmymedia.com -tagyourself.com -talkinator.com -tanukis.org -tapchicuoihoi.com -taphear.com -tapi.re -tarzanmail.cf -tastrg.com -taukah.com -tb-on-line.net -tcwlm.com -tcwlx.com -tdtda.com -tech69.com -techblast.ch -techemail.com -techgroup.me -technoproxy.ru -teerest.com -teewars.org -tefl.ro -telecomix.pl -teleg.eu -teleworm.com -teleworm.us -tellos.xyz -teml.net -temp-link.net -temp-mail.com -temp-mail.de -temp-mail.org -temp-mail.pp.ua -temp-mail.ru -temp-mails.com -tempail.com -tempalias.com -tempe-mail.com -tempemail.biz -tempemail.co.za -tempemail.com -tempemail.net -tempinbox.co.uk -tempinbox.com -tempmail.cn -tempmail.co -tempmail.de -tempmail.eu -tempmail.it -tempmail.pp.ua -tempmail.us -tempmail.ws -tempmail2.com -tempmaildemo.com -tempmailer.com -tempmailer.de -tempmailer.net -tempmailo.com -tempomail.fr -tempomail.org -temporarily.de -temporarioemail.com.br -temporary-mail.net -temporaryemail.net -temporaryemail.us -temporaryforwarding.com -temporaryinbox.com -temporarymailaddress.com -tempr.email -tempsky.com -tempthe.net -tempymail.com -tensi.org -ternaklele.ga -testore.co -testudine.com -thanksnospam.info -thankyou2010.com -thatim.info -thc.st -theaviors.com -thebearshark.com -thecarinformation.com -thechildrensfocus.com -thecity.biz -thecloudindex.com -thediamants.org -thedirhq.info -theeyeoftruth.com -thejoker5.com -thelightningmail.net -thelimestones.com -thembones.com.au -themegreview.com -themostemail.com -thereddoors.online -theroyalweb.club -thescrappermovie.com -theteastory.info -thex.ro -thichanthit.com -thietbivanphong.asia -thisisnotmyrealemail.com -thismail.net -thisurl.website -thnikka.com -thoas.ru -thraml.com -thrma.com -throam.com -thrott.com -throwam.com -throwawayemailaddress.com -throwawaymail.com -throwawaymail.pp.ua -throya.com -thrubay.com -thunderbolt.science -thunkinator.org -thxmate.com -tiapz.com -tic.ec -tilien.com -timgiarevn.com -timkassouf.com -tinoza.org -tinyurl24.com -tipsb.com -tittbit.in -tiv.cc -tizi.com -tkitc.de -tlpn.org -tmail.com -tmail.ws -tmailinator.com -tmails.net -tmmbt.net -tmpbox.net -tmpemails.com -tmpeml.com -tmpeml.info -tmpjr.me -tmpmail.net -tmpmail.org -tmpx.sa.com -toddsbighug.com -tofeat.com -toiea.com -tokem.co -tokenmail.de -tonaeto.com -tonne.to -tonymanso.com -toomail.biz -toon.ml -top-shop-tovar.ru -top101.de -top1mail.ru -top1post.ru -topinrock.cf -topmail2.com -topmail2.net -topofertasdehoy.com -topranklist.de -toprumours.com -tormail.org -toss.pw -tosunkaya.com -totallynotfake.net -totalvista.com -totesmail.com -totoan.info -tourcc.com -tp-qa-mail.com -tpwlb.com -tqoai.com -tqosi.com -tradermail.info -tranceversal.com -trash-amil.com -trash-mail.at -trash-mail.cf -trash-mail.com -trash-mail.de -trash-mail.ga -trash-mail.gq -trash-mail.ml -trash-mail.tk -trash-me.com -trash2009.com -trash2010.com -trash2011.com -trashcanmail.com -trashdevil.com -trashdevil.de -trashemail.de -trashemails.de -trashinbox.com -trashmail.at -trashmail.com -trashmail.de -trashmail.gq -trashmail.io -trashmail.me -trashmail.net -trashmail.org -trashmail.ws -trashmailer.com -trashmailgenerator.de -trashmails.com -trashymail.com -trashymail.net -trasz.com -trayna.com -trbvm.com -trbvn.com -trbvo.com -trend-maker.ru -trgfu.com -trgovinanaveliko.info -trialmail.de -trickmail.net -trillianpro.com -triots.com -trixtrux1.ru -trollproject.com -tropicalbass.info -trungtamtoeic.com -truthfinderlogin.com -tryalert.com -tryninja.io -tryzoe.com -ttirv.org -ttszuo.xyz -tualias.com -tuofs.com -turoid.com -turual.com -turuma.com -tutuapp.bid -tvchd.com -tverya.com -twinmail.de -twkly.ml -twocowmail.net -twoweirdtricks.com -twzhhq.online -txen.de -txtadvertise.com -tyhe.ro -tyldd.com -tympe.net -uacro.com -uber-mail.com -ubismail.net -ubm.md -ucche.us -ucupdong.ml -uemail99.com -ufacturing.com -uggsrock.com -uguuchantele.com -uhe2.com -uhhu.ru -uiu.us -ujijima1129.gq -uk.to -ultra.fyi -ultrada.ru -uma3.be -umail.net -undo.it -unicodeworld.com -unids.com -unimark.org -unit7lahaina.com -unmail.ru -uooos.com -upliftnow.com -uplipht.com -uploadnolimit.com -upozowac.info -urfunktion.se -urhen.com -uroid.com -us.af -us.to -usa.cc -usako.net -usbc.be -used-product.fr -ushijima1129.cf -ushijima1129.ga -ushijima1129.gq -ushijima1129.ml -ushijima1129.tk -utiket.us -uu.gl -uu2.ovh -uuf.me -uwork4.us -uyhip.com -vaasfc4.tk -vaati.org -valemail.net -valhalladev.com -vankin.de -vctel.com -vda.ro -vddaz.com -vdig.com -veanlo.com -vemomail.win -venompen.com -veo.kr -ver0.cf -ver0.ga -ver0.gq -ver0.ml -ver0.tk -vercelli.cf -vercelli.ga -vercelli.gq -vercelli.ml -verdejo.com -vermutlich.net -veryday.ch -veryday.eu -veryday.info -veryrealemail.com -vesa.pw -vevs.de -vfemail.net -via.tokyo.jp -vickaentb.tk -victime.ninja -victoriantwins.com -vidchart.com -viditag.com -viewcastmedia.com -viewcastmedia.net -viewcastmedia.org -vikingsonly.com -vinernet.com -vintomaper.com -vipepe.com -vipmail.name -vipmail.pw -vipxm.net -viralplays.com -virtualemail.info -visal007.tk -visal168.cf -visal168.ga -visal168.gq -visal168.ml -visal168.tk -vixletdev.com -vixtricks.com -vkcode.ru -vmailing.info -vmani.com -vmpanda.com -vnedu.me -voidbay.com -volaj.com -voltaer.com -vomoto.com -vorga.org -votiputox.org -voxelcore.com -vpn.st -vps30.com -vps911.net -vradportal.com -vremonte24-store.ru -vrmtr.com -vsimcard.com -vssms.com -vtxmail.us -vubby.com -vuiy.pw -vusra.com -vztc.com -w-asertun.ru -w3internet.co.uk -wakingupesther.com -walala.org -walkmail.net -walkmail.ru -wallm.com -wanko.be -watch-harry-potter.com -watchever.biz -watchfull.net -watchironman3onlinefreefullmovie.com -wazabi.club -wbdev.tech -wbml.net -web-contact.info -web-ideal.fr -web-inc.net -web-mail.pp.ua -web2mailco.com -webcontact-france.eu -webemail.me -webhook.site -webm4il.info -webmail24.top -webtrip.ch -webuser.in -wee.my -wef.gr -weg-werf-email.de -wegwerf-email-addressen.de -wegwerf-email-adressen.de -wegwerf-email.at -wegwerf-email.de -wegwerf-email.net -wegwerf-emails.de -wegwerfadresse.de -wegwerfemail.com -wegwerfemail.de -wegwerfemail.info -wegwerfemail.net -wegwerfemail.org -wegwerfemailadresse.com -wegwerfmail.de -wegwerfmail.info -wegwerfmail.net -wegwerfmail.org -wegwerpmailadres.nl -wegwrfmail.de -wegwrfmail.net -wegwrfmail.org -wekawa.com -welikecookies.com -wellsfargocomcardholders.com -wemel.top -wetrainbayarea.com -wetrainbayarea.org -wfgdfhj.tk -wg0.com -wh4f.org -whatiaas.com -whatifanalytics.com -whatpaas.com -whatsaas.com -whiffles.org -whopy.com -whyspam.me -wibblesmith.com -wickmail.net -widaryanto.info -widget.gg -wierie.tk -wifimaple.com -wifioak.com -wikidocuslava.ru -wilemail.com -willhackforfood.biz -willselfdestruct.com -wimsg.com -winemaven.info -wins.com.br -wlist.ro -wmail.cf -wmail.club -wokcy.com -wolfmail.ml -wolfsmail.tk -wollan.info -worldspace.link -wpdork.com -wpg.im -wralawfirm.com -writeme.us -wronghead.com -ws.gy -wsym.de -wudet.men -wuespdj.xyz -wupics.com -wuuvo.com -wuzup.net -wuzupmail.net -wwjmp.com -wwwnew.eu -wxnw.net -x24.com -xagloo.co -xagloo.com -xbaby69.top -xcode.ro -xcodes.net -xcompress.com -xcoxc.com -xcpy.com -xemaps.com -xemne.com -xents.com -xjoi.com -xkx.me -xl.cx -xmail.com -xmailer.be -xmaily.com -xn--9kq967o.com -xn--d-bga.net -xojxe.com -xost.us -xoxox.cc -xperiae5.com -xrap.de -xrho.com -xvx.us -xwaretech.com -xwaretech.info -xwaretech.net -xww.ro -xxhamsterxx.ga -xxi2.com -xxlocanto.us -xxolocanto.us -xxqx3802.com -xy9ce.tk -xyzfree.net -xzsok.com -yabai-oppai.tk -yahmail.top -yahooproduct.net -yamail.win -yanet.me -yannmail.win -yapped.net -yaqp.com -yarnpedia.ga -ycare.de -ycn.ro -ye.vc -yedi.org -yeezus.ru -yep.it -yermail.net -yhg.biz -ynmrealty.com -yodx.ro -yogamaven.com -yoggm.com -yomail.info -yoo.ro -yopmail.com -yopmail.fr -yopmail.gq -yopmail.net -yopmail.pp.ua -yordanmail.cf -you-spam.com -yougotgoated.com -youmail.ga -youmailr.com -youneedmore.info -youpymail.com -yourdomain.com -youremail.cf -yourewronghereswhy.com -yourlms.biz -yourspamgoesto.space -yourtube.ml -yroid.com -yspend.com -ytpayy.com -yugasandrika.com -yui.it -yuoia.com -yuurok.com -yxzx.net -yyolf.net -z-o-e-v-a.ru -z0d.eu -z1p.biz -z86.ru -zain.site -zainmax.net -zaktouni.fr -zarabotokdoma11.ru -zasod.com -zaym-zaym.ru -zcrcd.com -zdenka.net -ze.tc -zebins.com -zebins.eu -zehnminuten.de -zehnminutenmail.de -zepp.dk -zetmail.com -zfymail.com -zhaoqian.ninja -zhaoyuanedu.cn -zhcne.com -zhewei88.com -zhorachu.com -zik.dj -zipcad.com -zipo1.gq -zippymail.info -zipsendtest.com -zoaxe.com -zoemail.com -zoemail.net -zoemail.org -zoetropes.org -zombie-hive.com -zomg.info -zsero.com -zumpul.com -zv68.com -zxcv.com -zxcvbnm.com -zymuying.com -zzi.us -zzrgg.com -zzz.com \ No newline at end of file diff --git a/backend-mongo/src/ee/LICENSE b/backend-mongo/src/ee/LICENSE deleted file mode 100644 index a1c37bb93..000000000 --- a/backend-mongo/src/ee/LICENSE +++ /dev/null @@ -1,36 +0,0 @@ -The Infisical Enterprise license (the “Enterprise License”) -Copyright (c) 2022 Infisical Inc - -With regard to the Infisical Software: - -This software and associated documentation files (the "Software") may only be -used in production, if you (and any entity that you represent) have agreed to, -and are in compliance with, the Infisical Subscription Terms of Service, available -at https://infisical.com/terms (the “Enterprise Terms”), or other -agreement governing the use of the Software, as agreed by you and Infisical, -and otherwise have a valid Infisical Enterprise License for the -correct number of user seats. Subject to the foregoing sentence, you are free to -modify this Software and publish patches to the Software. You agree that Infisical -and/or its licensors (as applicable) retain all right, title and interest in and -to all such modifications and/or patches, and all such modifications and/or -patches may only be used, copied, modified, displayed, distributed, or otherwise -exploited with a valid Infiscial Enterprise subscription for the correct -number of user seats. Notwithstanding the foregoing, you may copy and modify -the Software for development and testing purposes, without requiring a -subscription. You agree that Infisical and/or its licensors (as applicable) retain -all right, title and interest in and to all such modifications. You are not -granted any other rights beyond what is expressly stated herein. Subject to the -foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, -and/or sell the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -For all third party components incorporated into the Infisical Software, those -components are licensed under the original license provided by the owner of the -applicable component. diff --git a/backend-mongo/src/ee/controllers/v1/cloudProductsController.ts b/backend-mongo/src/ee/controllers/v1/cloudProductsController.ts deleted file mode 100644 index 0cc6ab372..000000000 --- a/backend-mongo/src/ee/controllers/v1/cloudProductsController.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Request, Response } from "express"; -import { EELicenseService } from "../../services"; -import { getLicenseServerUrl } from "../../../config"; -import { licenseServerKeyRequest } from "../../../config/request"; -import { validateRequest } from "../../../helpers/validation"; -import * as reqValidator from "../../../validation/cloudProducts"; - -/** - * Return available cloud product information. - * Note: Nicely formatted to easily construct a table from - * @param req - * @param res - * @returns - */ -export const getCloudProducts = async (req: Request, res: Response) => { - const { - query: { "billing-cycle": billingCycle } - } = await validateRequest(reqValidator.GetCloudProductsV1, req); - - if (EELicenseService.instanceType === "cloud") { - const { data } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}` - ); - - return res.status(200).send(data); - } - - return res.status(200).send({ - head: [], - rows: [] - }); -}; diff --git a/backend-mongo/src/ee/controllers/v1/identitiesController.ts b/backend-mongo/src/ee/controllers/v1/identitiesController.ts deleted file mode 100644 index 179beeda3..000000000 --- a/backend-mongo/src/ee/controllers/v1/identitiesController.ts +++ /dev/null @@ -1,460 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { - IIdentity, - Identity, - IdentityAccessToken, - IdentityMembership, - IdentityMembershipOrg, - IdentityUniversalAuth, - IdentityUniversalAuthClientSecret, - Organization -} from "../../../models"; -import { - EventType, - IRole, - Role -} from "../../models"; -import { validateRequest } from "../../../helpers/validation"; -import * as reqValidator from "../../../validation/identities"; -import { - getAuthDataOrgPermissions, - getOrgRolePermissions, - isAtLeastAsPrivilegedOrg -} from "../../services/RoleService"; -import { - BadRequestError, - ForbiddenRequestError, - ResourceNotFoundError, -} from "../../../utils/errors"; -import { ADMIN, CUSTOM, MEMBER, NO_ACCESS } from "../../../variables"; -import { - OrgPermissionActions, - OrgPermissionSubjects -} from "../../services/RoleService"; -import { EEAuditLogService } from "../../services"; -import { ForbiddenError } from "@casl/ability"; - -/** - * Create identity - * @param req - * @param res - * @returns - */ -export const createIdentity = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Create identity' - #swagger.description = 'Create identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of entity to create", - "example": "development" - }, - "organizationId": { - "type": "string", - "description": "ID of organization where to create identity", - "example": "dev-environment" - }, - "role": { - "type": "string", - "description": "Role to assume for organization membership", - "example": "no-access" - } - }, - "required": ["name", "organizationId", "role"] - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identity": { - $ref: '#/definitions/Identity' - } - }, - "description": "Details of the created identity" - } - } - } - } - */ - const { - body: { - name, - organizationId, - role - } - } = await validateRequest(reqValidator.CreateIdentityV1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Identity - ); - - const rolePermission = await getOrgRolePermissions(role, organizationId); - const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, rolePermission); - - if (!hasRequiredPrivileges) throw ForbiddenRequestError({ - message: "Failed to create a more privileged identity" - }); - - const organization = await Organization.findById(organizationId); - if (!organization) throw BadRequestError({ message: `Organization with id ${organizationId} not found` }); - - const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role); - - let customRole; - if (isCustomRole) { - customRole = await Role.findOne({ - slug: role, - isOrgRole: true, - organization: new Types.ObjectId(organizationId) - }); - - if (!customRole) throw BadRequestError({ message: "Role not found" }); - } - - const identity = await new Identity({ - name - }).save(); - - await new IdentityMembershipOrg({ - identity: identity._id, - organization: new Types.ObjectId(organizationId), - role: isCustomRole ? CUSTOM : role, - customRole - }).save(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.CREATE_IDENTITY, - metadata: { - identityId: identity._id.toString(), - name - } - }, - { - organizationId: new Types.ObjectId(organizationId) - } - ); - - return res.status(200).send({ - identity - }); -} - -/** - * Update identity with id [identityId] - * @param req - * @param res - * @returns - */ - export const updateIdentity = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Update identity' - #swagger.description = 'Update identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['identityId'] = { - "description": "ID of identity to update", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.requestBody = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of entity to update to", - "example": "development" - }, - "role": { - "type": "string", - "description": "Role to update to for organization membership", - "example": "no-access" - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identity": { - $ref: '#/definitions/Identity' - } - }, - "description": "Details of the updated identity" - } - } - } - } - */ - const { - params: { identityId }, - body: { - name, - role - } - } = await validateRequest(reqValidator.UpdateIdentityV1, req); - - const identityMembershipOrg = await IdentityMembershipOrg - .findOne({ - identity: new Types.ObjectId(identityId) - }) - .populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembershipOrg) throw ResourceNotFoundError({ - message: `Failed to find identity with id ${identityId}` - }); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: identityMembershipOrg.organization - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.Identity - ); - - const identityRolePermission = await getOrgRolePermissions( - identityMembershipOrg?.customRole?.slug ?? identityMembershipOrg.role, - identityMembershipOrg.organization.toString() - ); - const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, identityRolePermission); - if (!hasRequiredPrivileges) throw ForbiddenRequestError({ - message: "Failed to update more privileged identity" - }); - - if (role) { - const rolePermission = await getOrgRolePermissions(role, identityMembershipOrg.organization.toString()); - const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, rolePermission); - - if (!hasRequiredPrivileges) throw ForbiddenRequestError({ - message: "Failed to update identity to a more privileged role" - }); - } - - let customRole; - if (role) { - const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role); - if (isCustomRole) { - customRole = await Role.findOne({ - slug: role, - isOrgRole: true, - organization: identityMembershipOrg.organization - }); - - if (!customRole) throw BadRequestError({ message: "Role not found" }); - } - } - - const identity = await Identity.findByIdAndUpdate( - identityId, - { - name, - }, - { - new: true - } - ); - - if (!identity) throw BadRequestError({ - message: `Failed to update identity with id ${identityId}` - }); - - await IdentityMembershipOrg.findOneAndUpdate( - { - identity: identity._id - }, - { - role: customRole ? CUSTOM : role, - ...(customRole ? { - customRole - } : {}), - ...(role && !customRole ? { // non-custom role - $unset: { - customRole: 1 - } - } : {}) - }, - { - new: true - } - ); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_IDENTITY, - metadata: { - identityId: identity._id.toString(), - name: identity.name, - } - }, - { - organizationId: identityMembershipOrg.organization - } - ); - - return res.status(200).send({ - identity - }); -} - -/** - * Delete identity with id [identityId] - * @param req - * @param res - * @returns - */ - export const deleteIdentity = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Delete identity' - #swagger.description = 'Delete identity' - - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['identityId'] = { - "description": "ID of identity", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.responses[200] = { - content: { - "application/json": { - "schema": { - "type": "object", - "properties": { - "identity": { - $ref: '#/definitions/Identity' - } - }, - "description": "Details of the deleted identity" - } - } - } - } - */ - const { - params: { identityId } - } = await validateRequest(reqValidator.DeleteIdentityV1, req); - - const identityMembershipOrg = await IdentityMembershipOrg - .findOne({ - identity: new Types.ObjectId(identityId) - }) - .populate<{ - identity: IIdentity, - customRole: IRole - }>("identity customRole"); - - if (!identityMembershipOrg) throw ResourceNotFoundError({ - message: `Failed to find identity with id ${identityId}` - }); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: identityMembershipOrg.organization - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Delete, - OrgPermissionSubjects.Identity - ); - - const identityRolePermission = await getOrgRolePermissions( - identityMembershipOrg?.customRole?.slug ?? identityMembershipOrg.role, - identityMembershipOrg.organization.toString() - ); - const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, identityRolePermission); - if (!hasRequiredPrivileges) throw ForbiddenRequestError({ - message: "Failed to delete more privileged identity" - }); - - const identity = await Identity.findByIdAndDelete(identityMembershipOrg.identity); - if (!identity) throw ResourceNotFoundError({ - message: `Identity with id ${identityId} not found` - }); - - await IdentityMembershipOrg.findByIdAndDelete(identityMembershipOrg._id); - - await IdentityMembership.deleteMany({ - identity: identityMembershipOrg.identity - }); - - await IdentityUniversalAuth.deleteMany({ - identity: identityMembershipOrg.identity - }); - - await IdentityUniversalAuthClientSecret.deleteMany({ - identity: identityMembershipOrg.identity - }); - - await IdentityAccessToken.deleteMany({ - identity: identityMembershipOrg.identity - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_IDENTITY, - metadata: { - identityId: identity._id.toString() - } - }, - { - organizationId: identityMembershipOrg.organization - } - ); - - return res.status(200).send({ - identity - }); -} - - - - - diff --git a/backend-mongo/src/ee/controllers/v1/index.ts b/backend-mongo/src/ee/controllers/v1/index.ts deleted file mode 100644 index 0d17e5a06..000000000 --- a/backend-mongo/src/ee/controllers/v1/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as identitiesController from "./identitiesController"; -import * as secretController from "./secretController"; -import * as secretSnapshotController from "./secretSnapshotController"; -import * as organizationsController from "./organizationsController"; -import * as ssoController from "./ssoController"; -import * as usersController from "./usersController"; -import * as workspaceController from "./workspaceController"; -import * as membershipController from "./membershipController"; -import * as cloudProductsController from "./cloudProductsController"; -import * as roleController from "./roleController"; -import * as secretApprovalPolicyController from "./secretApprovalPolicyController"; -import * as secretApprovalRequestController from "./secretApprovalRequestsController"; -import * as secretRotationProviderController from "./secretRotationProviderController"; -import * as secretRotationController from "./secretRotationController"; - -export { - identitiesController, - secretController, - secretSnapshotController, - organizationsController, - ssoController, - usersController, - workspaceController, - membershipController, - cloudProductsController, - roleController, - secretApprovalPolicyController, - secretApprovalRequestController, - secretRotationProviderController, - secretRotationController -}; diff --git a/backend-mongo/src/ee/controllers/v1/membershipController.ts b/backend-mongo/src/ee/controllers/v1/membershipController.ts deleted file mode 100644 index 4d2321a45..000000000 --- a/backend-mongo/src/ee/controllers/v1/membershipController.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Request, Response } from "express"; -import { IUser, Membership, Workspace } from "../../../models"; -import { EventType } from "../../../ee/models"; -import { IMembershipPermission } from "../../../models/membership"; -import { BadRequestError, UnauthorizedRequestError } from "../../../utils/errors"; -import { ADMIN, MEMBER } from "../../../variables/organization"; -import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from "../../../variables"; -import _ from "lodash"; -import { EEAuditLogService } from "../../services"; - -export const denyMembershipPermissions = async (req: Request, res: Response) => { - const { membershipId } = req.params; - const { permissions } = req.body; - const sanitizedMembershipPermissions: IMembershipPermission[] = permissions.map((permission: IMembershipPermission) => { - if (!permission.ability || !permission.environmentSlug || ![PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS].includes(permission.ability)) { - throw BadRequestError({ message: "One or more required fields are missing from the request or have incorrect type" }) - } - - return { - environmentSlug: permission.environmentSlug, - ability: permission.ability - } - }) - - const sanitizedMembershipPermissionsUnique = _.uniqWith(sanitizedMembershipPermissions, _.isEqual) - - const membershipToModify = await Membership.findById(membershipId) - if (!membershipToModify) { - throw BadRequestError({ message: "Unable to locate resource" }) - } - - // check if the user making the request is a admin of this project - if (![ADMIN, MEMBER].includes(membershipToModify.role)) { - throw UnauthorizedRequestError() - } - - // check if the requested slugs are indeed a part of this related workspace - const relatedWorkspace = await Workspace.findById(membershipToModify.workspace) - if (!relatedWorkspace) { - throw BadRequestError({ message: "Something went wrong when locating the related workspace" }) - } - - const uniqueEnvironmentSlugs = new Set(_.uniq(_.map(relatedWorkspace.environments, "slug"))); - - sanitizedMembershipPermissionsUnique.forEach(permission => { - if (!uniqueEnvironmentSlugs.has(permission.environmentSlug)) { - throw BadRequestError({ message: "Unknown environment slug reference" }) - } - }) - - // update the permissions - const updatedMembershipWithPermissions = await Membership.findByIdAndUpdate( - { _id: membershipToModify._id }, - { $set: { deniedPermissions: sanitizedMembershipPermissionsUnique } }, - { new: true } - ).populate<{ user: IUser }>("user"); - - if (!updatedMembershipWithPermissions) { - throw BadRequestError({ message: "The resource has been removed before it can be modified" }) - } - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS, - metadata: { - userId: updatedMembershipWithPermissions.user._id.toString(), - email: updatedMembershipWithPermissions.user.email, - deniedPermissions: updatedMembershipWithPermissions.deniedPermissions.map(({ - environmentSlug, - ability - }) => ({ - environmentSlug, - ability - })) - } - }, - { - workspaceId: updatedMembershipWithPermissions.workspace - } - ); - - res.send({ - permissionsDenied: updatedMembershipWithPermissions.deniedPermissions, - }) -} diff --git a/backend-mongo/src/ee/controllers/v1/organizationsController.ts b/backend-mongo/src/ee/controllers/v1/organizationsController.ts deleted file mode 100644 index 2f0d5ec39..000000000 --- a/backend-mongo/src/ee/controllers/v1/organizationsController.ts +++ /dev/null @@ -1,550 +0,0 @@ -import { Types } from "mongoose"; -import { Request, Response } from "express"; -import { getLicenseServerUrl } from "../../../config"; -import { licenseServerKeyRequest } from "../../../config/request"; -import { EELicenseService } from "../../services"; -import { validateRequest } from "../../../helpers/validation"; -import * as reqValidator from "../../../validation/organization"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions, -} from "../../services/RoleService"; -import { ForbiddenError } from "@casl/ability"; -import { Organization } from "../../../models"; -import { OrganizationNotFoundError } from "../../../utils/errors"; - -export const getOrganizationPlansTable = async (req: Request, res: Response) => { - const { - query: { billingCycle }, - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgPlansTablev1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const { data } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}` - ); - - return res.status(200).send(data); -}; - -/** - * Return the organization current plan's feature set - */ -export const getOrganizationPlan = async (req: Request, res: Response) => { - const { - query: { workspaceId }, - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgPlanv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const plan = await EELicenseService.getPlan( - new Types.ObjectId(organizationId), - new Types.ObjectId(workspaceId) - ); - - return res.status(200).send({ - plan - }); -}; - -/** - * Return checkout url for pro trial - * @param req - * @param res - * @returns - */ -export const startOrganizationTrial = async (req: Request, res: Response) => { - const { - params: { organizationId }, - body: { success_url } - } = await validateRequest(reqValidator.StartOrgTrailv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Billing - ); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { - data: { url } - } = await licenseServerKeyRequest.post( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/session/trial`, - { - success_url - } - ); - - EELicenseService.delPlan(new Types.ObjectId(organizationId)); - - return res.status(200).send({ - url - }); -}; - -/** - * Return the organization's current plan's billing info - * @param req - * @param res - * @returns - */ -export const getOrganizationPlanBillingInfo = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgPlanBillingInfov1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { data } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/cloud-plan/billing` - ); - - return res.status(200).send(data); -}; - -/** - * Return the organization's current plan's feature table - * @param req - * @param res - * @returns - */ -export const getOrganizationPlanTable = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgPlanTablev1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { data } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/cloud-plan/table` - ); - - return res.status(200).send(data); -}; - -export const getOrganizationBillingDetails = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgBillingDetailsv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { data } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details` - ); - - return res.status(200).send(data); -}; - -export const updateOrganizationBillingDetails = async (req: Request, res: Response) => { - const { - params: { organizationId }, - body: { name, email } - } = await validateRequest(reqValidator.UpdateOrgBillingDetailsv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { data } = await licenseServerKeyRequest.patch( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details`, - { - ...(name ? { name } : {}), - ...(email ? { email } : {}) - } - ); - - return res.status(200).send(data); -}; - -/** - * Return the organization's payment methods on file - */ -export const getOrganizationPmtMethods = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgPmtMethodsv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { - data: { pmtMethods } - } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/payment-methods` - ); - - return res.status(200).send(pmtMethods); -}; - -/** - * Return URL to add payment method for organization - */ -export const addOrganizationPmtMethod = async (req: Request, res: Response) => { - const { - params: { organizationId }, - body: { success_url, cancel_url } - } = await validateRequest(reqValidator.CreateOrgPmtMethodv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { - data: { url } - } = await licenseServerKeyRequest.post( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/payment-methods`, - { - success_url, - cancel_url - } - ); - - return res.status(200).send({ - url - }); -}; - -/** - * Delete payment method with id [pmtMethodId] for organization - * @param req - * @param res - * @returns - */ -export const deleteOrganizationPmtMethod = async (req: Request, res: Response) => { - const { - params: { organizationId, pmtMethodId } - } = await validateRequest(reqValidator.DelOrgPmtMethodv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Delete, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { data } = await licenseServerKeyRequest.delete( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/payment-methods/${pmtMethodId}` - ); - - return res.status(200).send(data); -}; - -/** - * Return the organization's tax ids on file - */ -export const getOrganizationTaxIds = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgTaxIdsv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { - data: { tax_ids } - } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/tax-ids` - ); - - return res.status(200).send(tax_ids); -}; - -/** - * Add tax id to organization - */ -export const addOrganizationTaxId = async (req: Request, res: Response) => { - const { - params: { organizationId }, - body: { type, value } - } = await validateRequest(reqValidator.CreateOrgTaxId, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { data } = await licenseServerKeyRequest.post( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/tax-ids`, - { - type, - value - } - ); - - return res.status(200).send(data); -}; - -/** - * Delete tax id with id [taxId] from organization tax ids on file - * @param req - * @param res - * @returns - */ -export const deleteOrganizationTaxId = async (req: Request, res: Response) => { - const { - params: { organizationId, taxId } - } = await validateRequest(reqValidator.DelOrgTaxIdv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Delete, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { data } = await licenseServerKeyRequest.delete( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/billing-details/tax-ids/${taxId}` - ); - - return res.status(200).send(data); -}; - -/** - * Return organization's invoices on file - * @param req - * @param res - * @returns - */ -export const getOrganizationInvoices = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgInvoicesv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { - data: { invoices } - } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/invoices` - ); - - return res.status(200).send(invoices); -}; - -/** - * Return organization's licenses on file - * @param req - * @param res - * @returns - */ -export const getOrganizationLicenses = async (req: Request, res: Response) => { - const { - params: { organizationId } - } = await validateRequest(reqValidator.GetOrgLicencesv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Billing - ); - - const organization = await Organization.findById(organizationId); - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - const { - data: { licenses } - } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${ - organization.customerId - }/licenses` - ); - - return res.status(200).send(licenses); -}; diff --git a/backend-mongo/src/ee/controllers/v1/roleController.ts b/backend-mongo/src/ee/controllers/v1/roleController.ts deleted file mode 100644 index a4b3035e6..000000000 --- a/backend-mongo/src/ee/controllers/v1/roleController.ts +++ /dev/null @@ -1,290 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { Membership, User } from "../../../models"; -import { - CreateRoleSchema, - DeleteRoleSchema, - GetRoleSchema, - GetUserPermission, - GetUserProjectPermission, - UpdateRoleSchema -} from "../../validation/role"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - adminProjectPermissions, - getAuthDataProjectPermissions, - memberProjectPermissions, - noAccessProjectPermissions, - viewerProjectPermission -} from "../../services/ProjectRoleService"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - adminPermissions, - getAuthDataOrgPermissions, - getUserOrgPermissions, - memberPermissions, - noAccessPermissions -} from "../../services/RoleService"; -import { BadRequestError } from "../../../utils/errors"; -import { Role } from "../../models"; -import { validateRequest } from "../../../helpers/validation"; -import { packRules } from "@casl/ability/extra"; - -export const createRole = async (req: Request, res: Response) => { - const { - body: { workspaceId, name, description, slug, permissions, orgId } - } = await validateRequest(CreateRoleSchema, req); - - const isOrgRole = !workspaceId; // if workspaceid is provided then its a workspace rule - if (isOrgRole) { - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(orgId) - }); - - if (permission.cannot(OrgPermissionActions.Create, OrgPermissionSubjects.Role)) { - throw BadRequestError({ message: "user doesn't have the permission." }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - if (permission.cannot(ProjectPermissionActions.Create, ProjectPermissionSub.Role)) { - throw BadRequestError({ message: "User doesn't have the permission." }); - } - } - - const existingRole = await Role.findOne({ organization: orgId, workspace: workspaceId, slug }); - if (existingRole) { - throw BadRequestError({ message: "Role already exist" }); - } - - const role = new Role({ - organization: orgId, - workspace: workspaceId, - isOrgRole, - name, - slug, - permissions, - description - }); - await role.save(); - - res.status(200).json({ - message: "Successfully created role", - data: { - role - } - }); -}; - -export const updateRole = async (req: Request, res: Response) => { - const { - params: { id }, - body: { name, description, slug, permissions, workspaceId, orgId } - } = await validateRequest(UpdateRoleSchema, req); - const isOrgRole = !workspaceId; // if workspaceid is provided then its a workspace rule - - if (isOrgRole) { - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(orgId) - }); - if (permission.cannot(OrgPermissionActions.Edit, OrgPermissionSubjects.Role)) { - throw BadRequestError({ message: "User doesn't have the org permission." }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - if (permission.cannot(ProjectPermissionActions.Edit, ProjectPermissionSub.Role)) { - throw BadRequestError({ message: "User doesn't have the workspace permission." }); - } - } - - if (slug) { - const existingRole = await Role.findOne({ - organization: orgId, - slug, - isOrgRole, - workspace: workspaceId - }); - if (existingRole && existingRole.id !== id) { - throw BadRequestError({ message: "Role already exist" }); - } - } - - const role = await Role.findByIdAndUpdate( - id, - { name, description, slug, permissions }, - { returnDocument: "after" } - ); - - if (!role) { - throw BadRequestError({ message: "Role not found" }); - } - res.status(200).json({ - message: "Successfully updated role", - data: { - role - } - }); -}; - -export const deleteRole = async (req: Request, res: Response) => { - const { - params: { id } - } = await validateRequest(DeleteRoleSchema, req); - - const role = await Role.findById(id); - if (!role) { - throw BadRequestError({ message: "Role not found" }); - } - - const isOrgRole = !role.workspace; - if (isOrgRole) { - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: role.organization - }); - if (permission.cannot(OrgPermissionActions.Delete, OrgPermissionSubjects.Role)) { - throw BadRequestError({ message: "User doesn't have the org permission." }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: role.workspace - }); - - if (permission.cannot(ProjectPermissionActions.Delete, ProjectPermissionSub.Role)) { - throw BadRequestError({ message: "User doesn't have the workspace permission." }); - } - } - - await Role.findByIdAndDelete(role.id); - - res.status(200).json({ - message: "Successfully deleted role", - data: { - role - } - }); -}; - -export const getRoles = async (req: Request, res: Response) => { - const { - query: { workspaceId, orgId } - } = await validateRequest(GetRoleSchema, req); - - const isOrgRole = !workspaceId; - if (isOrgRole) { - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(orgId) - }); - if (permission.cannot(OrgPermissionActions.Read, OrgPermissionSubjects.Role)) { - throw BadRequestError({ message: "User doesn't have the org permission." }); - } - } else { - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - if (permission.cannot(ProjectPermissionActions.Read, ProjectPermissionSub.Role)) { - throw BadRequestError({ message: "User doesn't have the workspace permission." }); - } - } - - const customRoles = await Role.find({ organization: orgId, isOrgRole, workspace: workspaceId }); - // as this is shared between org and workspace switch the rule set based on it - const roles = [ - { - _id: "admin", - name: "Admin", - slug: "admin", - description: "Complete administration access over the organization", - permissions: isOrgRole ? adminPermissions.rules : adminProjectPermissions.rules - }, - { - _id: "no-access", - name: "No Access", - slug: "no-access", - description: "No access to any resources in the organization", - permissions: isOrgRole ? noAccessPermissions.rules : noAccessProjectPermissions.rules - }, - { - _id: "member", - name: isOrgRole ? "Member" : "Developer", - slug: "member", - description: "Non-administrative role in an organization", - permissions: isOrgRole ? memberPermissions.rules : memberProjectPermissions.rules - }, - // viewer role only for project level - ...(isOrgRole - ? [] - : [ - { - _id: "viewer", - name: "Viewer", - slug: "viewer", - description: "Non-administrative role in an organization", - permissions: viewerProjectPermission.rules - } - ]), - ...customRoles - ]; - - res.status(200).json({ - message: "Successfully fetched role list", - data: { - roles - } - }); -}; - -export const getUserPermissions = async (req: Request, res: Response) => { - const { - params: { orgId } - } = await validateRequest(GetUserPermission, req); - - const { permission, membership } = await getUserOrgPermissions(req.user._id, orgId); - - res.status(200).json({ - data: { - permissions: packRules(permission.rules), - membership - } - }); -}; - -export const getUserWorkspacePermissions = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(GetUserProjectPermission, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - let membership; - if (req.authData.authPayload instanceof User) { - membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }) - } - - res.status(200).json({ - data: { - permissions: packRules(permission.rules), - membership - } - }); -}; diff --git a/backend-mongo/src/ee/controllers/v1/secretApprovalPolicyController.ts b/backend-mongo/src/ee/controllers/v1/secretApprovalPolicyController.ts deleted file mode 100644 index 11f1ed557..000000000 --- a/backend-mongo/src/ee/controllers/v1/secretApprovalPolicyController.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { Types } from "mongoose"; -import { ForbiddenError, subject } from "@casl/ability"; -import { Request, Response } from "express"; -import { nanoid } from "nanoid"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../services/ProjectRoleService"; -import { validateRequest } from "../../../helpers/validation"; -import { SecretApprovalPolicy } from "../../models/secretApprovalPolicy"; -import { getSecretPolicyOfBoard } from "../../services/SecretApprovalService"; -import { BadRequestError } from "../../../utils/errors"; -import * as reqValidator from "../../validation/secretApproval"; - -const ERR_SECRET_APPROVAL_NOT_FOUND = BadRequestError({ message: "secret approval not found" }); - -export const createSecretApprovalPolicy = async (req: Request, res: Response) => { - const { - body: { approvals, secretPath, approvers, environment, workspaceId, name } - } = await validateRequest(reqValidator.CreateSecretApprovalRule, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.SecretApproval - ); - - const secretApproval = new SecretApprovalPolicy({ - workspace: workspaceId, - name: name ?? `${environment}-${nanoid(3)}`, - secretPath, - environment, - approvals, - approvers - }); - await secretApproval.save(); - - return res.send({ - approval: secretApproval - }); -}; - -export const updateSecretApprovalPolicy = async (req: Request, res: Response) => { - const { - body: { approvals, approvers, secretPath, name }, - params: { id } - } = await validateRequest(reqValidator.UpdateSecretApprovalRule, req); - - const secretApproval = await SecretApprovalPolicy.findById(id); - if (!secretApproval) throw ERR_SECRET_APPROVAL_NOT_FOUND; - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: secretApproval.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.SecretApproval - ); - - const updatedDoc = await SecretApprovalPolicy.findByIdAndUpdate(id, { - approvals, - approvers, - name: (name || secretApproval?.name) ?? `${secretApproval.environment}-${nanoid(3)}`, - ...(secretPath === null ? { $unset: { secretPath: 1 } } : { secretPath }) - }); - - return res.send({ - approval: updatedDoc - }); -}; - -export const deleteSecretApprovalPolicy = async (req: Request, res: Response) => { - const { - params: { id } - } = await validateRequest(reqValidator.DeleteSecretApprovalRule, req); - - const secretApproval = await SecretApprovalPolicy.findById(id); - if (!secretApproval) throw ERR_SECRET_APPROVAL_NOT_FOUND; - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: secretApproval.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.SecretApproval - ); - - const deletedDoc = await SecretApprovalPolicy.findByIdAndDelete(id); - - return res.send({ - approval: deletedDoc - }); -}; - -export const getSecretApprovalPolicy = async (req: Request, res: Response) => { - const { - query: { workspaceId } - } = await validateRequest(reqValidator.GetSecretApprovalRuleList, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.SecretApproval - ); - - const doc = await SecretApprovalPolicy.find({ workspace: workspaceId }); - - return res.send({ - approvals: doc - }); -}; - -export const getSecretApprovalPolicyOfBoard = async (req: Request, res: Response) => { - const { - query: { workspaceId, environment, secretPath } - } = await validateRequest(reqValidator.GetSecretApprovalPolicyOfABoard, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - subject(ProjectPermissionSub.Secrets, { secretPath, environment }) - ); - - const secretApprovalPolicy = await getSecretPolicyOfBoard(workspaceId, environment, secretPath); - return res.send({ policy: secretApprovalPolicy }); -}; diff --git a/backend-mongo/src/ee/controllers/v1/secretApprovalRequestsController.ts b/backend-mongo/src/ee/controllers/v1/secretApprovalRequestsController.ts deleted file mode 100644 index 93096e536..000000000 --- a/backend-mongo/src/ee/controllers/v1/secretApprovalRequestsController.ts +++ /dev/null @@ -1,366 +0,0 @@ -import { Request, Response } from "express"; -import { validateRequest } from "../../../helpers/validation"; -import { Folder, Membership, User } from "../../../models"; -import { ApprovalStatus, SecretApprovalRequest } from "../../models/secretApprovalRequest"; -import * as reqValidator from "../../validation/secretApprovalRequest"; -import { getFolderWithPathFromId } from "../../../services/FolderService"; -import { BadRequestError, UnauthorizedRequestError } from "../../../utils/errors"; -import { ISecretApprovalPolicy, SecretApprovalPolicy } from "../../models/secretApprovalPolicy"; -import { performSecretApprovalRequestMerge } from "../../services/SecretApprovalService"; -import { Types } from "mongoose"; -import { EEAuditLogService } from "../../services"; -import { EventType } from "../../models"; - -export const getSecretApprovalRequestCount = async (req: Request, res: Response) => { - const { - query: { workspaceId } - } = await validateRequest(reqValidator.getSecretApprovalRequestCount, req); - - if (!(req.authData.authPayload instanceof User)) return; - - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (!membership) throw UnauthorizedRequestError(); - - const approvalRequestCount = await SecretApprovalRequest.aggregate([ - { - $match: { - workspace: new Types.ObjectId(workspaceId) - } - }, - { - $lookup: { - from: SecretApprovalPolicy.collection.name, - localField: "policy", - foreignField: "_id", - as: "policy" - } - }, - { $unwind: "$policy" }, - ...(membership.role !== "admin" - ? [ - { - $match: { - $or: [ - { committer: new Types.ObjectId(membership.id) }, - { "policy.approvers": new Types.ObjectId(membership.id) } - ] - } - } - ] - : []), - { - $group: { - _id: "$status", - count: { $sum: 1 } - } - } - ]); - const openRequests = approvalRequestCount.find(({ _id }) => _id === "open"); - const closedRequests = approvalRequestCount.find(({ _id }) => _id === "close"); - - return res.send({ - approvals: { open: openRequests?.count || 0, closed: closedRequests?.count || 0 } - }); -}; - -export const getSecretApprovalRequests = async (req: Request, res: Response) => { - const { - query: { status, committer, workspaceId, environment, limit, offset } - } = await validateRequest(reqValidator.getSecretApprovalRequests, req); - - if (!(req.authData.authPayload instanceof User)) return; - - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: new Types.ObjectId(workspaceId) - }); - - if (!membership) throw UnauthorizedRequestError(); - - const query = { - workspace: new Types.ObjectId(workspaceId), - environment, - committer: committer ? new Types.ObjectId(committer) : undefined, - status - }; - // to strip of undefined in query we use es6 spread to ignore those fields - Object.entries(query).forEach( - ([key, value]) => value === undefined && delete query[key as keyof typeof query] - ); - const approvalRequests = await SecretApprovalRequest.aggregate([ - { - $match: query - }, - { $sort: { createdAt: -1 } }, - { - $lookup: { - from: SecretApprovalPolicy.collection.name, - localField: "policy", - foreignField: "_id", - as: "policy" - } - }, - { $unwind: "$policy" }, - ...(membership.role !== "admin" - ? [ - { - $match: { - $or: [ - { committer: new Types.ObjectId(membership.id) }, - { "policy.approvers": new Types.ObjectId(membership.id) } - ] - } - } - ] - : []), - { $skip: offset }, - { $limit: limit } - ]); - if (!approvalRequests.length) return res.send({ approvals: [] }); - - const unqiueEnvs = environment ?? { - $in: [...new Set(approvalRequests.map(({ environment }) => environment))] - }; - const approvalRootFolders = await Folder.find({ - workspace: workspaceId, - environment: unqiueEnvs - }).lean(); - - const formatedApprovals = approvalRequests.map((el) => { - let secretPath = "/"; - const folders = approvalRootFolders.find(({ environment }) => environment === el.environment); - if (folders) { - secretPath = getFolderWithPathFromId(folders?.nodes, el.folderId)?.folderPath || "/"; - } - return { ...el, secretPath }; - }); - - return res.send({ - approvals: formatedApprovals - }); -}; - -export const getSecretApprovalRequestDetails = async (req: Request, res: Response) => { - const { - params: { id } - } = await validateRequest(reqValidator.getSecretApprovalRequestDetails, req); - const secretApprovalRequest = await SecretApprovalRequest.findById(id) - .populate<{ policy: ISecretApprovalPolicy }>("policy") - .populate({ - path: "commits.secretVersion", - populate: { - path: "tags" - } - }) - .populate("commits.secret", "version") - .populate("commits.newVersion.tags") - .lean(); - if (!secretApprovalRequest) - throw BadRequestError({ message: "Secret approval request not found" }); - - if (!(req.authData.authPayload instanceof User)) return; - - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: secretApprovalRequest.workspace - }); - - if (!membership) throw UnauthorizedRequestError(); - - // allow to fetch only if its admin or is the committer or approver - if ( - membership.role !== "admin" && - !secretApprovalRequest.committer.equals(membership.id) && - !secretApprovalRequest.policy.approvers.find( - (approverId) => approverId.toString() === membership._id.toString() - ) - ) { - throw UnauthorizedRequestError({ message: "User has no access" }); - } - - let secretPath = "/"; - const approvalRootFolders = await Folder.findOne({ - workspace: secretApprovalRequest.workspace, - environment: secretApprovalRequest.environment - }).lean(); - if (approvalRootFolders) { - secretPath = - getFolderWithPathFromId(approvalRootFolders?.nodes, secretApprovalRequest.folderId) - ?.folderPath || "/"; - } - - return res.send({ - approval: { ...secretApprovalRequest, secretPath } - }); -}; - -export const updateSecretApprovalReviewStatus = async (req: Request, res: Response) => { - const { - body: { status }, - params: { id } - } = await validateRequest(reqValidator.updateSecretApprovalReviewStatus, req); - const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{ - policy: ISecretApprovalPolicy; - }>("policy"); - if (!secretApprovalRequest) - throw BadRequestError({ message: "Secret approval request not found" }); - - if (!(req.authData.authPayload instanceof User)) return; - - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: secretApprovalRequest.workspace - }); - - if (!membership) throw UnauthorizedRequestError(); - - if ( - membership.role !== "admin" && - secretApprovalRequest.committer !== membership.id && - !secretApprovalRequest.policy.approvers.find((approverId) => approverId.equals(membership.id)) - ) { - throw UnauthorizedRequestError({ message: "User has no access" }); - } - - const reviewerPos = secretApprovalRequest.reviewers.findIndex( - ({ member }) => member.toString() === membership._id.toString() - ); - if (reviewerPos !== -1) { - secretApprovalRequest.reviewers[reviewerPos].status = status; - } else { - secretApprovalRequest.reviewers.push({ member: membership._id, status }); - } - await secretApprovalRequest.save(); - - return res.send({ status }); -}; - -export const mergeSecretApprovalRequest = async (req: Request, res: Response) => { - const { - params: { id } - } = await validateRequest(reqValidator.mergeSecretApprovalRequest, req); - - const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{ - policy: ISecretApprovalPolicy; - }>("policy"); - - if (!secretApprovalRequest) - throw BadRequestError({ message: "Secret approval request not found" }); - - if (!(req.authData.authPayload instanceof User)) return; - - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: secretApprovalRequest.workspace - }); - - if (!membership) throw UnauthorizedRequestError(); - - if ( - membership.role !== "admin" && - secretApprovalRequest.committer !== membership.id && - !secretApprovalRequest.policy.approvers.find((approverId) => approverId.equals(membership.id)) - ) { - throw UnauthorizedRequestError({ message: "User has no access" }); - } - - const reviewers = secretApprovalRequest.reviewers.reduce>( - (prev, curr) => ({ ...prev, [curr.member.toString()]: curr.status }), - {} - ); - const hasMinApproval = - secretApprovalRequest.policy.approvals <= - secretApprovalRequest.policy.approvers.filter( - (approverId) => reviewers[approverId.toString()] === ApprovalStatus.APPROVED - ).length; - - if (!hasMinApproval) throw BadRequestError({ message: "Doesn't have minimum approvals needed" }); - - const approval = await performSecretApprovalRequestMerge( - id, - req.authData, - membership._id.toString() - ); - return res.send({ approval }); -}; - -export const updateSecretApprovalRequestStatus = async (req: Request, res: Response) => { - const { - body: { status }, - params: { id } - } = await validateRequest(reqValidator.updateSecretApprovalRequestStatus, req); - - const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{ - policy: ISecretApprovalPolicy; - }>("policy"); - - if (!secretApprovalRequest) - throw BadRequestError({ message: "Secret approval request not found" }); - - if (!(req.authData.authPayload instanceof User)) return; - - const membership = await Membership.findOne({ - user: req.authData.authPayload._id, - workspace: secretApprovalRequest.workspace - }); - - if (!membership) throw UnauthorizedRequestError(); - - if ( - membership.role !== "admin" && - secretApprovalRequest.committer !== membership.id && - !secretApprovalRequest.policy.approvers.find((approverId) => approverId.equals(membership._id)) - ) { - throw UnauthorizedRequestError({ message: "User has no access" }); - } - - if (secretApprovalRequest.hasMerged) - throw BadRequestError({ message: "Approval request has been merged" }); - if (secretApprovalRequest.status === "close" && status === "close") - throw BadRequestError({ message: "Approval request is already closed" }); - if (secretApprovalRequest.status === "open" && status === "open") - throw BadRequestError({ message: "Approval request is already open" }); - - const updatedRequest = await SecretApprovalRequest.findByIdAndUpdate( - id, - { status, statusChangeBy: membership._id }, - { new: true } - ); - - if (status === "close") { - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.SECRET_APPROVAL_CLOSED, - metadata: { - closedBy: membership._id.toString(), - secretApprovalRequestId: id, - secretApprovalRequestSlug: secretApprovalRequest.slug - } - }, - { - workspaceId: secretApprovalRequest.workspace - } - ); - } else { - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.SECRET_APPROVAL_REOPENED, - metadata: { - reopenedBy: membership._id.toString(), - secretApprovalRequestId: id, - secretApprovalRequestSlug: secretApprovalRequest.slug - } - }, - { - workspaceId: secretApprovalRequest.workspace - } - ); - } - return res.send({ approval: updatedRequest }); -}; diff --git a/backend-mongo/src/ee/controllers/v1/secretController.ts b/backend-mongo/src/ee/controllers/v1/secretController.ts deleted file mode 100644 index ec6018929..000000000 --- a/backend-mongo/src/ee/controllers/v1/secretController.ts +++ /dev/null @@ -1,269 +0,0 @@ -import { ForbiddenError, subject } from "@casl/ability"; -import { Request, Response } from "express"; -import { validateRequest } from "../../../helpers/validation"; -import { Folder, Secret } from "../../../models"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../services/ProjectRoleService"; -import { BadRequestError } from "../../../utils/errors"; -import * as reqValidator from "../../../validation"; -import { SecretVersion } from "../../models"; -import { EESecretService } from "../../services"; -import { getFolderWithPathFromId } from "../../../services/FolderService"; - -/** - * Return secret versions for secret with id [secretId] - * @param req - * @param res - */ -export const getSecretVersions = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return secret versions' - #swagger.description = 'Return secret versions' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.parameters['secretId'] = { - "description": "ID of secret", - "required": true, - "type": "string" - } - - #swagger.parameters['offset'] = { - "description": "Number of versions to skip", - "required": false, - "type": "string" - } - - #swagger.parameters['limit'] = { - "description": "Maximum number of versions to return", - "required": false, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - schema: { - "type": "object", - "properties": { - "secretVersions": { - "type": "array", - "items": { - $ref: "#/components/schemas/SecretVersion" - }, - "description": "Secret versions" - } - } - } - } - } - } - */ - const { - params: { secretId }, - query: { offset, limit } - } = await validateRequest(reqValidator.GetSecretVersionsV1, req); - - const secret = await Secret.findById(secretId); - if (!secret) { - throw BadRequestError({ message: "Failed to find secret" }); - } - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: secret.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.SecretRollback - ); - - const secretVersions = await SecretVersion.find({ - secret: secretId - }) - .sort({ createdAt: -1 }) - .skip(offset) - .limit(limit); - - return res.status(200).send({ - secretVersions - }); -}; - -/** - * Roll back secret with id [secretId] to version [version] - * @param req - * @param res - * @returns - */ -export const rollbackSecretVersion = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Roll back secret to a version.' - #swagger.description = 'Roll back secret to a version.' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.parameters['secretId'] = { - "description": "ID of secret", - "required": true, - "type": "string" - } - - #swagger.requestBody = { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "version": { - "type": "integer", - "description": "Version of secret to roll back to" - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - schema: { - "type": "object", - "properties": { - "secret": { - "type": "object", - $ref: "#/components/schemas/Secret", - "description": "Secret rolled back to" - } - } - } - } - } - } - */ - - const { - params: { secretId }, - body: { version } - } = await validateRequest(reqValidator.RollbackSecretVersionV1, req); - - const toBeUpdatedSec = await Secret.findById(secretId); - if (!toBeUpdatedSec) { - throw BadRequestError({ message: "Failed to find secret" }); - } - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: toBeUpdatedSec.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.SecretRollback - ); - - // validate secret version - const oldSecretVersion = await SecretVersion.findOne({ - secret: secretId, - version - }).select("+secretBlindIndex"); - - if (!oldSecretVersion) throw new Error("Failed to find secret version"); - - const { - workspace, - type, - user, - environment, - secretBlindIndex, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - algorithm, - folder, - keyEncoding - } = oldSecretVersion; - - let secretPath = "/"; - const folders = await Folder.findOne({ workspace, environment }); - if (folders) - secretPath = getFolderWithPathFromId(folders.nodes, folder || "root")?.folderPath || "/"; - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - subject(ProjectPermissionSub.Secrets, { environment: toBeUpdatedSec.environment, secretPath }) - ); - - // update secret - const secret = await Secret.findByIdAndUpdate( - secretId, - { - $inc: { - version: 1 - }, - workspace, - type, - user, - environment, - ...(secretBlindIndex ? { secretBlindIndex } : {}), - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - folderId: folder, - algorithm, - keyEncoding - }, - { - new: true - } - ); - - if (!secret) throw new Error("Failed to find and update secret"); - - // add new secret version - await new SecretVersion({ - secret: secretId, - version: secret.version, - workspace, - type, - user, - environment, - isDeleted: false, - ...(secretBlindIndex ? { secretBlindIndex } : {}), - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - folder, - algorithm, - keyEncoding - }).save(); - - // take secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: secret.workspace, - environment, - folderId: folder - }); - - return res.status(200).send({ - secret - }); -}; diff --git a/backend-mongo/src/ee/controllers/v1/secretRotationController.ts b/backend-mongo/src/ee/controllers/v1/secretRotationController.ts deleted file mode 100644 index f2f80ffe6..000000000 --- a/backend-mongo/src/ee/controllers/v1/secretRotationController.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { validateRequest } from "../../../helpers/validation"; -import * as reqValidator from "../../validation/secretRotation"; -import * as secretRotationService from "../../secretRotation/service"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; - -export const createSecretRotation = async (req: Request, res: Response) => { - const { - body: { - provider, - customProvider, - interval, - outputs, - secretPath, - environment, - workspaceId, - inputs - } - } = await validateRequest(reqValidator.createSecretRotationV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.SecretRotation - ); - - const secretRotation = await secretRotationService.createSecretRotation({ - workspaceId, - inputs, - environment, - secretPath, - outputs, - interval, - customProvider, - provider - }); - - return res.send({ secretRotation }); -}; - -export const restartSecretRotations = async (req: Request, res: Response) => { - const { - body: { id } - } = await validateRequest(reqValidator.restartSecretRotationV1, req); - - const doc = await secretRotationService.getSecretRotationById({ id }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: doc.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.SecretRotation - ); - - const secretRotation = await secretRotationService.restartSecretRotation({ id }); - return res.send({ secretRotation }); -}; - -export const deleteSecretRotations = async (req: Request, res: Response) => { - const { - params: { id } - } = await validateRequest(reqValidator.removeSecretRotationV1, req); - - const doc = await secretRotationService.getSecretRotationById({ id }); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: doc.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.SecretRotation - ); - - const secretRotations = await secretRotationService.deleteSecretRotation({ id }); - return res.send({ secretRotations }); -}; - -export const getSecretRotations = async (req: Request, res: Response) => { - const { - query: { workspaceId } - } = await validateRequest(reqValidator.getSecretRotationV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.SecretRotation - ); - - const secretRotations = await secretRotationService.getSecretRotationOfWorkspace(workspaceId); - return res.send({ secretRotations }); -}; diff --git a/backend-mongo/src/ee/controllers/v1/secretRotationProviderController.ts b/backend-mongo/src/ee/controllers/v1/secretRotationProviderController.ts deleted file mode 100644 index 5e66c40b2..000000000 --- a/backend-mongo/src/ee/controllers/v1/secretRotationProviderController.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { validateRequest } from "../../../helpers/validation"; -import * as reqValidator from "../../validation/secretRotationProvider"; -import * as secretRotationProviderService from "../../secretRotation/service"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; - -export const getProviderTemplates = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(reqValidator.getSecretRotationProvidersV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.SecretRotation - ); - - const rotationProviderList = await secretRotationProviderService.getProviderTemplate({ - workspaceId - }); - - return res.send(rotationProviderList); -}; diff --git a/backend-mongo/src/ee/controllers/v1/secretSnapshotController.ts b/backend-mongo/src/ee/controllers/v1/secretSnapshotController.ts deleted file mode 100644 index 34a1a6ef2..000000000 --- a/backend-mongo/src/ee/controllers/v1/secretSnapshotController.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { ForbiddenError } from "@casl/ability"; -import { Request, Response } from "express"; -import { validateRequest } from "../../../helpers/validation"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../services/ProjectRoleService"; -import * as reqValidator from "../../../validation/secretSnapshot"; -import { ISecretVersion, SecretSnapshot, TFolderRootVersionSchema } from "../../models"; - -/** - * Return secret snapshot with id [secretSnapshotId] - * @param req - * @param res - * @returns - */ -export const getSecretSnapshot = async (req: Request, res: Response) => { - const { - params: { secretSnapshotId } - } = await validateRequest(reqValidator.GetSecretSnapshotV1, req); - - const secretSnapshot = await SecretSnapshot.findById(secretSnapshotId) - .lean() - .populate<{ secretVersions: ISecretVersion[] }>({ - path: "secretVersions", - populate: { - path: "tags", - model: "Tag" - } - }) - .populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion"); - - if (!secretSnapshot) throw new Error("Failed to find secret snapshot"); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: secretSnapshot.workspace - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.SecretRollback - ); - - const folderId = secretSnapshot.folderId; - // to show only the folder required secrets - secretSnapshot.secretVersions = secretSnapshot.secretVersions.filter( - ({ folder }) => folder === folderId - ); - - secretSnapshot.folderVersion = secretSnapshot?.folderVersion?.nodes?.children?.map( - ({ id, name }) => ({ - id, - name - }) - ) as any; - - return res.status(200).send({ - secretSnapshot - }); -}; diff --git a/backend-mongo/src/ee/controllers/v1/ssoController.ts b/backend-mongo/src/ee/controllers/v1/ssoController.ts deleted file mode 100644 index 29ed9c18e..000000000 --- a/backend-mongo/src/ee/controllers/v1/ssoController.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { BotOrgService } from "../../../services"; -import { SSOConfig } from "../../models"; -import { AuthMethod, MembershipOrg, User } from "../../../models"; -import { getSSOConfigHelper } from "../../helpers/organizations"; -import { client } from "../../../config"; -import { ResourceNotFoundError } from "../../../utils/errors"; -import { getSiteURL } from "../../../config"; -import { EELicenseService } from "../../services"; -import * as reqValidator from "../../../validation/sso"; -import { validateRequest } from "../../../helpers/validation"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions -} from "../../services/RoleService"; -import { ForbiddenError } from "@casl/ability"; - -/** - * Redirect user to appropriate SSO endpoint after successful authentication - * to finish inputting their master key for logging in or signing up - * @param req - * @param res - * @returns - */ -export const redirectSSO = async (req: Request, res: Response) => { - if (req.isUserCompleted) { - return res.redirect( - `${await getSiteURL()}/login/sso?token=${encodeURIComponent(req.providerAuthToken)}` - ); - } - - return res.redirect( - `${await getSiteURL()}/signup/sso?token=${encodeURIComponent(req.providerAuthToken)}` - ); -}; - -/** - * Return organization SAML SSO configuration - * @param req - * @param res - * @returns - */ -export const getSSOConfig = async (req: Request, res: Response) => { - const { - query: { organizationId } - } = await validateRequest(reqValidator.GetSsoConfigv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Read, - OrgPermissionSubjects.Sso - ); - - const data = await getSSOConfigHelper({ - organizationId: new Types.ObjectId(organizationId) - }); - - return res.status(200).send(data); -}; - -/** - * Update organization SAML SSO configuration - * @param req - * @param res - * @returns - */ -export const updateSSOConfig = async (req: Request, res: Response) => { - const { - body: { organizationId, authProvider, isActive, entryPoint, issuer, cert } - } = await validateRequest(reqValidator.UpdateSsoConfigv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Edit, - OrgPermissionSubjects.Sso - ); - - const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId)); - - if (!plan.samlSSO) - return res.status(400).send({ - message: - "Failed to update SAML SSO configuration due to plan restriction. Upgrade plan to update SSO configuration." - }); - - interface PatchUpdate { - authProvider?: string; - isActive?: boolean; - encryptedEntryPoint?: string; - entryPointIV?: string; - entryPointTag?: string; - encryptedIssuer?: string; - issuerIV?: string; - issuerTag?: string; - encryptedCert?: string; - certIV?: string; - certTag?: string; - } - - const update: PatchUpdate = {}; - - if (authProvider) { - update.authProvider = authProvider; - } - - if (isActive !== undefined) { - update.isActive = isActive; - } - - const key = await BotOrgService.getSymmetricKey(new Types.ObjectId(organizationId)); - - if (entryPoint) { - const { - ciphertext: encryptedEntryPoint, - iv: entryPointIV, - tag: entryPointTag - } = client.encryptSymmetric(entryPoint, key); - - update.encryptedEntryPoint = encryptedEntryPoint; - update.entryPointIV = entryPointIV; - update.entryPointTag = entryPointTag; - } - - if (issuer) { - const { - ciphertext: encryptedIssuer, - iv: issuerIV, - tag: issuerTag - } = client.encryptSymmetric(issuer, key); - - update.encryptedIssuer = encryptedIssuer; - update.issuerIV = issuerIV; - update.issuerTag = issuerTag; - } - - if (cert) { - const { - ciphertext: encryptedCert, - iv: certIV, - tag: certTag - } = client.encryptSymmetric(cert, key); - - update.encryptedCert = encryptedCert; - update.certIV = certIV; - update.certTag = certTag; - } - - const ssoConfig = await SSOConfig.findOneAndUpdate( - { - organization: new Types.ObjectId(organizationId) - }, - update, - { - new: true - } - ); - - if (!ssoConfig) - throw ResourceNotFoundError({ - message: "Failed to find SSO config to update" - }); - - if (update.isActive !== undefined) { - const membershipOrgs = await MembershipOrg.find({ - organization: new Types.ObjectId(organizationId) - }).select("user"); - - if (update.isActive) { - await User.updateMany( - { - _id: { - $in: membershipOrgs.map((membershipOrg) => membershipOrg.user) - } - }, - { - authMethods: [ssoConfig.authProvider] - } - ); - } else { - await User.updateMany( - { - _id: { - $in: membershipOrgs.map((membershipOrg) => membershipOrg.user) - } - }, - { - authMethods: [AuthMethod.EMAIL] - } - ); - } - } - - return res.status(200).send(ssoConfig); -}; - -/** - * Create organization SAML SSO configuration - * @param req - * @param res - * @returns - */ -export const createSSOConfig = async (req: Request, res: Response) => { - const { - body: { organizationId, authProvider, isActive, entryPoint, issuer, cert } - } = await validateRequest(reqValidator.CreateSsoConfigv1, req); - - const { permission } = await getAuthDataOrgPermissions({ - authData: req.authData, - organizationId: new Types.ObjectId(organizationId) - }); - ForbiddenError.from(permission).throwUnlessCan( - OrgPermissionActions.Create, - OrgPermissionSubjects.Sso - ); - - const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId)); - - if (!plan.samlSSO) - return res.status(400).send({ - message: - "Failed to create SAML SSO configuration due to plan restriction. Upgrade plan to add SSO configuration." - }); - - const key = await BotOrgService.getSymmetricKey(new Types.ObjectId(organizationId)); - - const { - ciphertext: encryptedEntryPoint, - iv: entryPointIV, - tag: entryPointTag - } = client.encryptSymmetric(entryPoint, key); - - const { - ciphertext: encryptedIssuer, - iv: issuerIV, - tag: issuerTag - } = client.encryptSymmetric(issuer, key); - - const { - ciphertext: encryptedCert, - iv: certIV, - tag: certTag - } = client.encryptSymmetric(cert, key); - - const ssoConfig = await new SSOConfig({ - organization: new Types.ObjectId(organizationId), - authProvider, - isActive, - encryptedEntryPoint, - entryPointIV, - entryPointTag, - encryptedIssuer, - issuerIV, - issuerTag, - encryptedCert, - certIV, - certTag - }).save(); - - return res.status(200).send(ssoConfig); -}; diff --git a/backend-mongo/src/ee/controllers/v1/usersController.ts b/backend-mongo/src/ee/controllers/v1/usersController.ts deleted file mode 100644 index a492404f5..000000000 --- a/backend-mongo/src/ee/controllers/v1/usersController.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Request, Response } from "express"; - -/** - * Return the ip address of the current user - * @param req - * @param res - * @returns - */ -export const getMyIp = (req: Request, res: Response) => { - return res.status(200).send({ - ip: req.authData.ipAddress - }); -} \ No newline at end of file diff --git a/backend-mongo/src/ee/controllers/v1/workspaceController.ts b/backend-mongo/src/ee/controllers/v1/workspaceController.ts deleted file mode 100644 index 70d612792..000000000 --- a/backend-mongo/src/ee/controllers/v1/workspaceController.ts +++ /dev/null @@ -1,1079 +0,0 @@ -import { Request, Response } from "express"; -import { PipelineStage, Types } from "mongoose"; -import { - Folder, - Identity, - IdentityMembership, - Membership, - Secret, - ServiceTokenData, - TFolderSchema, - User, - Workspace -} from "../../../models"; -import { - ActorType, - AuditLog, - EventType, - FolderVersion, - IPType, - ISecretVersion, - IdentityActor, - SecretSnapshot, - SecretVersion, - ServiceActor, - TFolderRootVersionSchema, - TrustedIP, - UserActor -} from "../../models"; -import { EESecretService } from "../../services"; -import { getLatestSecretVersionIds } from "../../helpers/secretVersion"; -import { getFolderByPath, searchByFolderId } from "../../../services/FolderService"; -import { EEAuditLogService, EELicenseService } from "../../services"; -import { extractIPDetails, isValidIpOrCidr } from "../../../utils/ip"; -import { validateRequest } from "../../../helpers/validation"; -import { - AddWorkspaceTrustedIpV1, - DeleteWorkspaceTrustedIpV1, - GetWorkspaceAuditLogActorFilterOptsV1, - GetWorkspaceAuditLogsV1, - GetWorkspaceSecretSnapshotsCountV1, - GetWorkspaceSecretSnapshotsV1, - GetWorkspaceTrustedIpsV1, - RollbackWorkspaceSecretSnapshotV1, - UpdateWorkspaceTrustedIpV1 -} from "../../../validation"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - getAuthDataProjectPermissions -} from "../../services/ProjectRoleService"; -import { ForbiddenError } from "@casl/ability"; -import { BadRequestError } from "../../../utils/errors"; - -/** - * Return secret snapshots for workspace with id [workspaceId] - * @param req - * @param res - */ -export const getWorkspaceSecretSnapshots = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return project secret snapshot ids' - #swagger.description = 'Return project secret snapshots ids' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project where to get secret snapshots for", - "required": true, - "type": "string" - } - - #swagger.parameters['environment'] = { - "description": "Slug of environment where to get secret snapshots for", - "required": true, - "type": "string", - "in": "query" - } - - #swagger.parameters['directory'] = { - "description": "Path where to get secret snapshots for like / or /foo/bar. Default is /", - "required": false, - "type": "string", - "in": "query" - } - - #swagger.parameters['offset'] = { - "description": "Number of secret snapshots to skip", - "required": false, - "type": "string" - } - - #swagger.parameters['limit'] = { - "description": "Maximum number of secret snapshots to return", - "required": false, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - schema: { - "type": "object", - "properties": { - "secretSnapshots": { - "type": "array", - "items": { - $ref: "#/components/schemas/SecretSnapshot" - }, - "description": "Project secret snapshots" - } - } - } - } - } - } - */ - const { - params: { workspaceId }, - query: { environment, directory, offset, limit } - } = await validateRequest(GetWorkspaceSecretSnapshotsV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.SecretRollback - ); - - let folderId = "root"; - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - if (!folders && directory !== "/") throw BadRequestError({ message: "Folder not found" }); - - if (folders) { - const folder = getFolderByPath(folders?.nodes, directory); - if (!folder) throw BadRequestError({ message: "Invalid folder id" }); - folderId = folder.id; - } - - const secretSnapshots = await SecretSnapshot.find({ - workspace: workspaceId, - environment, - folderId - }) - .sort({ createdAt: -1 }) - .skip(offset) - .limit(limit); - - return res.status(200).send({ - secretSnapshots - }); -}; - -/** - * Return count of secret snapshots for workspace with id [workspaceId] - * @param req - * @param res - */ -export const getWorkspaceSecretSnapshotsCount = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - query: { environment, directory } - } = await validateRequest(GetWorkspaceSecretSnapshotsCountV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.SecretRollback - ); - - let folderId = "root"; - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - if (!folders && directory !== "/") throw BadRequestError({ message: "Folder not found" }); - - if (folders) { - const folder = getFolderByPath(folders?.nodes, directory); - if (!folder) throw BadRequestError({ message: "Invalid folder id" }); - folderId = folder.id; - } - - const count = await SecretSnapshot.countDocuments({ - workspace: workspaceId, - environment, - folderId - }); - - return res.status(200).send({ - count - }); -}; - -/** - * Rollback secret snapshot with id [secretSnapshotId] to version [version] - * @param req - * @param res - * @returns - */ -export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Roll back project secrets to those captured in a secret snapshot version.' - #swagger.description = 'Roll back project secrets to those captured in a secret snapshot version.' - - #swagger.security = [{ - "apiKeyAuth": [], - "bearerAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of project where to roll back", - "required": true, - "type": "string" - } - - #swagger.requestBody = { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "environment": { - "type": "string", - "description": "Slug of environment where to roll back" - }, - "directory": { - "type": "string", - "description": "Path where to roll back for like / or /foo/bar. Default is /" - }, - "version": { - "type": "integer", - "description": "Version of secret snapshot to roll back to", - } - } - } - } - } - } - - #swagger.responses[200] = { - content: { - "application/json": { - schema: { - "type": "object", - "properties": { - "secrets": { - "type": "array", - "items": { - $ref: "#/components/schemas/Secret" - }, - "description": "Secrets rolled back to" - } - } - } - } - } - } - */ - - const { - params: { workspaceId }, - body: { directory, environment, version } - } = await validateRequest(RollbackWorkspaceSecretSnapshotV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.SecretRollback - ); - - let folderId = "root"; - const folders = await Folder.findOne({ workspace: workspaceId, environment }); - if (!folders && directory !== "/") throw BadRequestError({ message: "Folder not found" }); - - if (folders) { - const folder = getFolderByPath(folders?.nodes, directory); - if (!folder) throw BadRequestError({ message: "Invalid folder id" }); - folderId = folder.id; - } - - // validate secret snapshot - const secretSnapshot = await SecretSnapshot.findOne({ - workspace: workspaceId, - version, - environment, - folderId: folderId - }) - .populate<{ secretVersions: ISecretVersion[] }>({ - path: "secretVersions", - select: "+secretBlindIndex" - }) - .populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion"); - - if (!secretSnapshot) throw new Error("Failed to find secret snapshot"); - - const snapshotFolderTree = secretSnapshot.folderVersion; - const latestFolderTree = await Folder.findOne({ - workspace: workspaceId, - environment - }); - - const latestFolderVersion = await FolderVersion.findOne({ - environment, - workspace: workspaceId, - "nodes.id": folderId - }).sort({ "nodes.version": -1 }); - - const oldSecretVersionsObj: Record = {}; - const secretIds: Types.ObjectId[] = []; - const folderIds: string[] = [folderId]; - - secretSnapshot.secretVersions.forEach((snapSecVer) => { - oldSecretVersionsObj[snapSecVer.secret.toString()] = snapSecVer; - secretIds.push(snapSecVer.secret); - }); - - // the parent node from current latest one - // this will be modified according to the snapshot and latest snapshots - const newFolderTree = latestFolderTree && searchByFolderId(latestFolderTree.nodes, folderId); - - if (newFolderTree) { - newFolderTree.children = snapshotFolderTree?.nodes?.children || []; - const queue = [newFolderTree]; - // a bfs algorithm in which we take the latest snapshots of all the folders in a level - while (queue.length) { - const groupByFolderId: Record = {}; - // the original queue is popped out completely to get what ever in a level - // subqueue is filled with all the children thus next level folders - // subQueue will then be transfered to the oriinal queue - const subQueue: TFolderSchema[] = []; - // get everything inside a level - while (queue.length) { - const folder = queue.pop() as TFolderSchema; - folder.children.forEach((el) => { - folderIds.push(el.id); // push ids and data into queu - subQueue.push(el); - // to modify the original tree very fast we keep a reference object - // key with folder id and pointing to the various nodes - groupByFolderId[el.id] = el; - }); - } - // get latest snapshots of all the folder - const matchWsFoldersPipeline = { - $match: { - workspace: new Types.ObjectId(workspaceId), - environment, - folderId: { - $in: Object.keys(groupByFolderId) - } - } - }; - const sortByFolderIdAndVersion: PipelineStage = { - $sort: { folderId: 1, version: -1 } - }; - const pickLatestVersionOfEachFolder = { - $group: { - _id: "$folderId", - latestVersion: { $first: "$version" }, - doc: { - $first: "$$ROOT" - } - } - }; - const populateSecVersion = { - $lookup: { - from: SecretVersion.collection.name, - localField: "doc.secretVersions", - foreignField: "_id", - as: "doc.secretVersions" - } - }; - const populateFolderVersion = { - $lookup: { - from: FolderVersion.collection.name, - localField: "doc.folderVersion", - foreignField: "_id", - as: "doc.folderVersion" - } - }; - const unwindFolderVerField = { - $unwind: { - path: "$doc.folderVersion", - preserveNullAndEmptyArrays: true - } - }; - const latestSnapshotsByFolders: Array<{ doc: typeof secretSnapshot }> = - await SecretSnapshot.aggregate([ - matchWsFoldersPipeline, - sortByFolderIdAndVersion, - pickLatestVersionOfEachFolder, - populateSecVersion, - populateFolderVersion, - unwindFolderVerField - ]); - - // recursive snapshotting each level - latestSnapshotsByFolders.forEach((snap) => { - // mutate the folder tree to update the nodes to the latest version tree - // we are reconstructing the folder tree by latest snapshots here - if (groupByFolderId[snap.doc.folderId]) { - groupByFolderId[snap.doc.folderId].children = - snap.doc?.folderVersion?.nodes?.children || []; - } - - // push all children of next level snapshots - if (snap.doc.folderVersion?.nodes?.children) { - queue.push(...snap.doc.folderVersion.nodes.children); - } - - snap.doc.secretVersions.forEach((snapSecVer) => { - // record all the secrets - oldSecretVersionsObj[snapSecVer.secret.toString()] = snapSecVer; - secretIds.push(snapSecVer.secret); - }); - }); - - queue.push(...subQueue); - } - } - - // TODO: fix any - const latestSecretVersionIds = await getLatestSecretVersionIds({ - secretIds - }); - - // TODO: fix any - const latestSecretVersions: any = ( - await SecretVersion.find( - { - _id: { - $in: latestSecretVersionIds.map((s) => s.versionId) - } - }, - "secret version" - ) - ).reduce( - (accumulator, s) => ({ - ...accumulator, - [`${s.secret.toString()}`]: s - }), - {} - ); - - const secDelQuery: Record = { - workspace: workspaceId, - environment - // undefined means root thus collect all secrets - }; - if (folderId !== "root" && folderIds.length) secDelQuery.folder = { $in: folderIds }; - - // delete existing secrets - await Secret.deleteMany(secDelQuery); - await Folder.deleteOne({ - workspace: workspaceId, - environment - }); - - // add secrets - const secrets = await Secret.insertMany( - Object.keys(oldSecretVersionsObj).map((sv) => { - const { - secret: secretId, - workspace, - type, - user, - environment, - secretBlindIndex, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - createdAt, - algorithm, - keyEncoding, - folder: secFolderId - } = oldSecretVersionsObj[sv]; - - return { - _id: secretId, - version: latestSecretVersions[secretId.toString()].version + 1, - workspace, - type, - user, - environment, - secretBlindIndex: secretBlindIndex ?? undefined, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext: "", - secretCommentIV: "", - secretCommentTag: "", - createdAt, - algorithm, - keyEncoding, - folder: secFolderId - }; - }) - ); - - // add secret versions - const secretV = await SecretVersion.insertMany( - secrets.map( - ({ - _id, - version, - workspace, - type, - user, - environment, - secretBlindIndex, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - algorithm, - keyEncoding, - folder: secFolderId - }) => ({ - _id: new Types.ObjectId(), - secret: _id, - version, - workspace, - type, - user, - environment, - isDeleted: false, - secretBlindIndex: secretBlindIndex ?? undefined, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - algorithm, - keyEncoding, - folder: secFolderId - }) - ) - ); - - if (newFolderTree && latestFolderTree) { - // save the updated folder tree to the present one - newFolderTree.version = (latestFolderVersion?.nodes?.version || 0) + 1; - latestFolderTree._id = new Types.ObjectId(); - latestFolderTree.isNew = true; - await latestFolderTree.save(); - - // create new folder version - const newFolderVersion = new FolderVersion({ - workspace: workspaceId, - environment, - nodes: newFolderTree - }); - await newFolderVersion.save(); - } - - // update secret versions of restored secrets as not deleted - await SecretVersion.updateMany( - { - secret: { - $in: Object.keys(oldSecretVersionsObj).map((sv) => oldSecretVersionsObj[sv].secret) - } - }, - { - isDeleted: false - } - ); - - // take secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - folderId - }); - - return res.status(200).send({ - secrets - }); -}; - -/** - * Return audit logs for workspace with id [workspaceId] - * @param req - * @param res - */ -export const getWorkspaceAuditLogs = async (req: Request, res: Response) => { - /* - #swagger.summary = 'Return audit logs' - #swagger.description = 'Return audit logs' - - #swagger.security = [{ - "apiKeyAuth": [] - }] - - #swagger.parameters['workspaceId'] = { - "description": "ID of the workspace where to get folders from", - "required": true, - "type": "string", - "in": "path" - } - - #swagger.parameters['offset'] = { - "description": "Number of logs to skip before starting to return logs for pagination", - "required": false, - "type": "string" - } - - #swagger.parameters['limit'] = { - "description": "Maximum number of logs to return for pagination", - "required": false, - "type": "string" - } - - #swagger.parameters['startDate'] = { - "description": "Filter logs from this date in ISO-8601 format", - "required": false, - "type": "string" - } - - #swagger.parameters['endDate'] = { - "description": "Filter logs till this date in ISO-8601 format", - "required": false, - "type": "string" - } - - #swagger.parameters['eventType'] = { - "description": "Filter by type of event such as get-secrets, get-secret, create-secret, update-secret, delete-secret, etc.", - "required": false, - "type": "string", - } - - #swagger.parameters['userAgentType'] = { - "description": "Filter by type of user agent such as web, cli, k8-operator, or other", - "required": false, - "type": "string", - } - - #swagger.parameters['actor'] = { - "description": "Filter by actor such as user or service", - "required": false, - "type": "string" - } - - #swagger.responses[200] = { - content: { - "application/json": { - schema: { - "type": "object", - "properties": { - "auditLogs": { - "type": "array", - "items": { - $ref: "#/components/schemas/AuditLog", - }, - "description": "List of audit log" - }, - } - } - } - } - } - */ - const { - query: { limit, offset, endDate, eventType, startDate, userAgentType, actor }, - params: { workspaceId } - } = await validateRequest(GetWorkspaceAuditLogsV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.AuditLogs - ); - - let actorMetadataQuery = ""; - if (actor) { - switch (actor?.split("-", 2)[0]) { - case ActorType.USER: - actorMetadataQuery = "actor.metadata.userId"; - break; - case ActorType.SERVICE: - actorMetadataQuery = "actor.metadata.serviceId"; - break; - case ActorType.IDENTITY: - actorMetadataQuery = "actor.metadata.identityId"; - break; - } - } - - const query = { - workspace: new Types.ObjectId(workspaceId), - ...(eventType - ? { - "event.type": eventType - } - : {}), - ...(userAgentType - ? { - userAgentType - } - : {}), - ...(actor - ? { - "actor.type": actor.substring(0, actor.lastIndexOf("-")), - ...({ - [actorMetadataQuery]: actor.substring(actor.lastIndexOf("-") + 1) - }) - } - : {}), - ...(startDate || endDate - ? { - createdAt: { - ...(startDate && { $gte: new Date(startDate) }), - ...(endDate && { $lte: new Date(endDate) }) - } - } - : {}) - }; - - const auditLogs = await AuditLog.find(query).sort({ createdAt: -1 }).skip(offset).limit(limit); - - return res.status(200).send({ - auditLogs - }); -}; - -/** - * Return audit log actor filter options for workspace with id [workspaceId] - * @param req - * @param res - */ -export const getWorkspaceAuditLogActorFilterOpts = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(GetWorkspaceAuditLogActorFilterOptsV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.AuditLogs - ); - - const userIds = await Membership.distinct("user", { - workspace: new Types.ObjectId(workspaceId) - }); - - const userActors: UserActor[] = ( - await User.find({ - _id: { - $in: userIds - } - }).select("email") - ).map((user) => ({ - type: ActorType.USER, - metadata: { - userId: user._id.toString(), - email: user.email - } - })); - - const serviceActors: ServiceActor[] = ( - await ServiceTokenData.find({ - workspace: new Types.ObjectId(workspaceId) - }).select("name") - ).map((serviceTokenData) => ({ - type: ActorType.SERVICE, - metadata: { - serviceId: serviceTokenData._id.toString(), - name: serviceTokenData.name - } - })); - - const identityIds = await IdentityMembership.distinct("identity", { - workspace: new Types.ObjectId(workspaceId) - }); - - const identityActors: IdentityActor[] = ( - await Identity.find({ - _id: { - $in: identityIds - } - }) - ).map((identity) => ({ - type: ActorType.IDENTITY, - metadata: { - identityId: identity._id.toString(), - name: identity.name - } - })); - - const actors = [...userActors, ...serviceActors, ...identityActors]; - - return res.status(200).send({ - actors - }); -}; - -/** - * Return trusted ips for workspace with id [workspaceId] - * @param req - * @param res - */ -export const getWorkspaceTrustedIps = async (req: Request, res: Response) => { - const { - params: { workspaceId } - } = await validateRequest(GetWorkspaceTrustedIpsV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Read, - ProjectPermissionSub.IpAllowList - ); - - const trustedIps = await TrustedIP.find({ - workspace: new Types.ObjectId(workspaceId) - }); - - return res.status(200).send({ - trustedIps - }); -}; - -/** - * Add a trusted ip to workspace with id [workspaceId] - * @param req - * @param res - */ -export const addWorkspaceTrustedIp = async (req: Request, res: Response) => { - const { - params: { workspaceId }, - body: { comment, isActive, ipAddress: ip } - } = await validateRequest(AddWorkspaceTrustedIpV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Create, - ProjectPermissionSub.IpAllowList - ); - - const workspace = await Workspace.findById(workspaceId); - if (!workspace) throw BadRequestError({ message: "Workspace not found" }); - - const plan = await EELicenseService.getPlan(workspace.organization); - - if (!plan.ipAllowlisting) - return res.status(400).send({ - message: - "Failed to add IP access range due to plan restriction. Upgrade plan to add IP access range." - }); - - const isValidIPOrCidr = isValidIpOrCidr(ip); - - if (!isValidIPOrCidr) - return res.status(400).send({ - message: "The IP is not a valid IPv4, IPv6, or CIDR block" - }); - - const { ipAddress, type, prefix } = extractIPDetails(ip); - - const trustedIp = await new TrustedIP({ - workspace: new Types.ObjectId(workspaceId), - ipAddress, - type, - prefix, - isActive, - comment - }).save(); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.ADD_TRUSTED_IP, - metadata: { - trustedIpId: trustedIp._id.toString(), - ipAddress: trustedIp.ipAddress, - prefix: trustedIp.prefix - } - }, - { - workspaceId: trustedIp.workspace - } - ); - - return res.status(200).send({ - trustedIp - }); -}; - -/** - * Update trusted ip with id [trustedIpId] workspace with id [workspaceId] - * @param req - * @param res - */ -export const updateWorkspaceTrustedIp = async (req: Request, res: Response) => { - const { - params: { workspaceId, trustedIpId }, - body: { ipAddress: ip, comment } - } = await validateRequest(UpdateWorkspaceTrustedIpV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Edit, - ProjectPermissionSub.IpAllowList - ); - - const workspace = await Workspace.findById(workspaceId); - if (!workspace) throw BadRequestError({ message: "Workspace not found" }); - - const plan = await EELicenseService.getPlan(workspace.organization); - - if (!plan.ipAllowlisting) - return res.status(400).send({ - message: - "Failed to update IP access range due to plan restriction. Upgrade plan to update IP access range." - }); - - const isValidIPOrCidr = isValidIpOrCidr(ip); - - if (!isValidIPOrCidr) - return res.status(400).send({ - message: "The IP is not a valid IPv4, IPv6, or CIDR block" - }); - - const { ipAddress, type, prefix } = extractIPDetails(ip); - - const updateObject: { - ipAddress: string; - type: IPType; - comment: string; - prefix?: number; - $unset?: { - prefix: number; - }; - } = { - ipAddress, - type, - comment - }; - - if (prefix !== undefined) { - updateObject.prefix = prefix; - } else { - updateObject.$unset = { prefix: 1 }; - } - - const trustedIp = await TrustedIP.findOneAndUpdate( - { - _id: new Types.ObjectId(trustedIpId), - workspace: new Types.ObjectId(workspaceId) - }, - updateObject, - { - new: true - } - ); - - if (!trustedIp) - return res.status(400).send({ - message: "Failed to update trusted IP" - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.UPDATE_TRUSTED_IP, - metadata: { - trustedIpId: trustedIp._id.toString(), - ipAddress: trustedIp.ipAddress, - prefix: trustedIp.prefix - } - }, - { - workspaceId: trustedIp.workspace - } - ); - - return res.status(200).send({ - trustedIp - }); -}; - -/** - * Delete IP access range from workspace with id [workspaceId] - * @param req - * @param res - */ -export const deleteWorkspaceTrustedIp = async (req: Request, res: Response) => { - const { - params: { workspaceId, trustedIpId } - } = await validateRequest(DeleteWorkspaceTrustedIpV1, req); - - const { permission } = await getAuthDataProjectPermissions({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId) - }); - - ForbiddenError.from(permission).throwUnlessCan( - ProjectPermissionActions.Delete, - ProjectPermissionSub.IpAllowList - ); - - const workspace = await Workspace.findById(workspaceId); - if (!workspace) throw BadRequestError({ message: "Workspace not found" }); - - const plan = await EELicenseService.getPlan(workspace.organization); - - if (!plan.ipAllowlisting) - return res.status(400).send({ - message: - "Failed to delete IP access range due to plan restriction. Upgrade plan to delete IP access range." - }); - - const trustedIp = await TrustedIP.findOneAndDelete({ - _id: new Types.ObjectId(trustedIpId), - workspace: new Types.ObjectId(workspaceId) - }); - - if (!trustedIp) - return res.status(400).send({ - message: "Failed to delete trusted IP" - }); - - await EEAuditLogService.createAuditLog( - req.authData, - { - type: EventType.DELETE_TRUSTED_IP, - metadata: { - trustedIpId: trustedIp._id.toString(), - ipAddress: trustedIp.ipAddress, - prefix: trustedIp.prefix - } - }, - { - workspaceId: trustedIp.workspace - } - ); - - return res.status(200).send({ - trustedIp - }); -}; diff --git a/backend-mongo/src/ee/controllers/v3/apiKeyDataController.ts b/backend-mongo/src/ee/controllers/v3/apiKeyDataController.ts deleted file mode 100644 index 1fe7d6d3b..000000000 --- a/backend-mongo/src/ee/controllers/v3/apiKeyDataController.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Request, Response } from "express"; -import { Types } from "mongoose"; -import { APIKeyDataV2 } from "../../../models/apiKeyDataV2"; -import { validateRequest } from "../../../helpers/validation"; -import { BadRequestError } from "../../../utils/errors"; -import * as reqValidator from "../../../validation"; -import { createToken } from "../../../helpers"; -import { AuthTokenType } from "../../../variables"; -import { getAuthSecret } from "../../../config"; - -/** - * Create API key data v2 - * @param req - * @param res - */ -export const createAPIKeyData = async (req: Request, res: Response) => { - const { - body: { - name - } - } = await validateRequest(reqValidator.CreateAPIKeyV3, req); - - const apiKeyData = await new APIKeyDataV2({ - name, - user: req.user._id, - usageCount: 0, - }).save(); - - const apiKey = createToken({ - payload: { - authTokenType: AuthTokenType.API_KEY, - apiKeyDataId: apiKeyData._id.toString(), - userId: req.user._id.toString() - }, - secret: await getAuthSecret() - }); - - return res.status(200).send({ - apiKeyData, - apiKey - }); -} - -/** - * Update API key data v2 with id [apiKeyDataId] - * @param req - * @param res - */ - export const updateAPIKeyData = async (req: Request, res: Response) => { - const { - params: { apiKeyDataId }, - body: { - name, - } - } = await validateRequest(reqValidator.UpdateAPIKeyV3, req); - - const apiKeyData = await APIKeyDataV2.findOneAndUpdate( - { - _id: new Types.ObjectId(apiKeyDataId), - user: req.user._id - }, - { - name - }, - { - new: true - } - ); - - if (!apiKeyData) throw BadRequestError({ - message: "Failed to update API key" - }); - - return res.status(200).send({ - apiKeyData - }); -} - -/** - * Delete API key data v2 with id [apiKeyDataId] - * @param req - * @param res - */ - export const deleteAPIKeyData = async (req: Request, res: Response) => { - const { - params: { apiKeyDataId } - } = await validateRequest(reqValidator.DeleteAPIKeyV3, req); - - const apiKeyData = await APIKeyDataV2.findOneAndDelete({ - _id: new Types.ObjectId(apiKeyDataId), - user: req.user._id - }); - - if (!apiKeyData) throw BadRequestError({ - message: "Failed to delete API key" - }); - - return res.status(200).send({ - apiKeyData - }); -} \ No newline at end of file diff --git a/backend-mongo/src/ee/controllers/v3/index.ts b/backend-mongo/src/ee/controllers/v3/index.ts deleted file mode 100644 index 2a8f130dd..000000000 --- a/backend-mongo/src/ee/controllers/v3/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import * as apiKeyDataController from "./apiKeyDataController"; - -export { - apiKeyDataController -} \ No newline at end of file diff --git a/backend-mongo/src/ee/helpers/checkMembershipPermissions.ts b/backend-mongo/src/ee/helpers/checkMembershipPermissions.ts deleted file mode 100644 index 4f6ddc771..000000000 --- a/backend-mongo/src/ee/helpers/checkMembershipPermissions.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Types } from "mongoose"; -import _ from "lodash"; -import { Membership } from "../../models"; -import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from "../../variables"; - -export const userHasWorkspaceAccess = async (userId: Types.ObjectId, workspaceId: Types.ObjectId, environment: string, action: any) => { - const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId }) - if (!membershipForWorkspace) { - return false - } - - const deniedMembershipPermissions = membershipForWorkspace.deniedPermissions; - const isDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: action }); - - if (isDisallowed) { - return false - } - - return true -} - -export const userHasWriteOnlyAbility = async (userId: Types.ObjectId, workspaceId: Types.ObjectId, environment: string) => { - const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId }) - if (!membershipForWorkspace) { - return false - } - - const deniedMembershipPermissions = membershipForWorkspace.deniedPermissions; - const isWriteDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: PERMISSION_WRITE_SECRETS }); - const isReadDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: PERMISSION_READ_SECRETS }); - - // case: you have write only if read is blocked and write is not - if (isReadDisallowed && !isWriteDisallowed) { - return true - } - - return false -} - -export const userHasNoAbility = async (userId: Types.ObjectId, workspaceId: Types.ObjectId, environment: string) => { - const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId }) - if (!membershipForWorkspace) { - return true - } - - const deniedMembershipPermissions = membershipForWorkspace.deniedPermissions; - const isWriteDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: PERMISSION_WRITE_SECRETS }); - const isReadBlocked = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: PERMISSION_READ_SECRETS }); - - if (isReadBlocked && isWriteDisallowed) { - return true - } - - return false -} \ No newline at end of file diff --git a/backend-mongo/src/ee/helpers/organizations.ts b/backend-mongo/src/ee/helpers/organizations.ts deleted file mode 100644 index f9f125b39..000000000 --- a/backend-mongo/src/ee/helpers/organizations.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Types } from "mongoose"; -import { - SSOConfig -} from "../models"; -import { - BotOrgService -} from "../../services"; -import { client } from "../../config"; -import { ValidationError } from "../../utils/errors"; - -export const getSSOConfigHelper = async ({ - organizationId, - ssoConfigId -}: { - organizationId?: Types.ObjectId; - ssoConfigId?: Types.ObjectId; -}) => { - - if (!organizationId && !ssoConfigId) throw ValidationError({ - message: "Getting SSO data requires either id of organization or SSO data" - }); - - const ssoConfig = await SSOConfig.findOne({ - ...(organizationId ? { organization: organizationId } : {}), - ...(ssoConfigId ? { _id: ssoConfigId } : {}) - }); - - if (!ssoConfig) throw new Error("Failed to find organization SSO data"); - - const key = await BotOrgService.getSymmetricKey( - ssoConfig.organization - ); - - const entryPoint = client.decryptSymmetric( - ssoConfig.encryptedEntryPoint, - key, - ssoConfig.entryPointIV, - ssoConfig.entryPointTag - ); - - const issuer = client.decryptSymmetric( - ssoConfig.encryptedIssuer, - key, - ssoConfig.issuerIV, - ssoConfig.issuerTag - ); - - const cert = client.decryptSymmetric( - ssoConfig.encryptedCert, - key, - ssoConfig.certIV, - ssoConfig.certTag - ); - - return ({ - _id: ssoConfig._id, - organization: ssoConfig.organization, - authProvider: ssoConfig.authProvider, - isActive: ssoConfig.isActive, - entryPoint, - issuer, - cert - }); -} \ No newline at end of file diff --git a/backend-mongo/src/ee/helpers/secret.ts b/backend-mongo/src/ee/helpers/secret.ts deleted file mode 100644 index 54b26f56e..000000000 --- a/backend-mongo/src/ee/helpers/secret.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { Types } from "mongoose"; -import { Secret } from "../../models"; -import { - FolderVersion, - ISecretVersion, - SecretSnapshot, - SecretVersion, -} from "../models"; - -/** - * Save a secret snapshot that is a copy of the current state of secrets in workspace with id - * [workspaceId] under a new snapshot with incremented version under the - * secretsnapshots collection. - * @param {Object} obj - * @param {String} obj.workspaceId - * @returns {SecretSnapshot} secretSnapshot - new secret snapshot - */ -const takeSecretSnapshotHelper = async ({ - workspaceId, - environment, - folderId = "root", -}: { - workspaceId: Types.ObjectId; - environment: string; - folderId?: string; -}) => { - // get all folder ids - const secretIds = ( - await Secret.find( - { - workspace: workspaceId, - environment, - folder: folderId, - }, - "_id" - ).lean() - ).map((s) => s._id); - - const latestSecretVersions = ( - await SecretVersion.aggregate([ - { - $match: { - environment, - workspace: new Types.ObjectId(workspaceId), - secret: { - $in: secretIds, - }, - }, - }, - { - $group: { - _id: "$secret", - version: { $max: "$version" }, - versionId: { $max: "$_id" }, // secret version id - }, - }, - { - $sort: { version: -1 }, - }, - ]).exec() - ).map((s) => s.versionId); - const latestFolderVersion = await FolderVersion.findOne({ - environment, - workspace: workspaceId, - "nodes.id": folderId, - }).sort({ "nodes.version": -1 }); - - const latestSecretSnapshot = await SecretSnapshot.findOne({ - workspace: workspaceId, - }).sort({ version: -1 }); - - const secretSnapshot = await new SecretSnapshot({ - workspace: workspaceId, - environment, - version: latestSecretSnapshot ? latestSecretSnapshot.version + 1 : 1, - secretVersions: latestSecretVersions, - folderId, - folderVersion: latestFolderVersion, - }).save(); - - return secretSnapshot; -}; - -/** - * Add secret versions [secretVersions] to the SecretVersion collection. - * @param {Object} obj - * @param {Object[]} obj.secretVersions - * @returns {SecretVersion[]} newSecretVersions - new secret versions - */ -const addSecretVersionsHelper = async ({ - secretVersions, -}: { - secretVersions: ISecretVersion[]; -}) => { - const newSecretVersions = await SecretVersion.insertMany(secretVersions); - - return newSecretVersions; -}; - -const markDeletedSecretVersionsHelper = async ({ - secretIds, -}: { - secretIds: Types.ObjectId[]; -}) => { - await SecretVersion.updateMany( - { - secret: { $in: secretIds }, - }, - { - isDeleted: true, - }, - { - new: true, - } - ); -}; - -export { - takeSecretSnapshotHelper, - addSecretVersionsHelper, - markDeletedSecretVersionsHelper, -}; diff --git a/backend-mongo/src/ee/helpers/secretVersion.ts b/backend-mongo/src/ee/helpers/secretVersion.ts deleted file mode 100644 index 4b173f9ef..000000000 --- a/backend-mongo/src/ee/helpers/secretVersion.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Types } from "mongoose"; -import { SecretVersion } from "../models"; - -/** - * Return latest secret versions for secrets with ids [secretIds] - * @param {Object} obj - * @param {Object} obj.secretIds = ids of secrets to get latest versions for - * @returns - */ -const getLatestSecretVersionIds = async ({ - secretIds, -}: { - secretIds: Types.ObjectId[]; -}) => { - const latestSecretVersionIds = await SecretVersion.aggregate([ - { - $match: { - secret: { - $in: secretIds, - }, - }, - }, - { - $group: { - _id: "$secret", - version: { $max: "$version" }, - versionId: { $max: "$_id" }, // id of latest secret version - }, - }, - { - $sort: { version: -1 }, - }, - ]).exec(); - - return latestSecretVersionIds; -}; - -/** - * Return latest [n] secret versions for secrets with ids [secretIds] - * @param {Object} obj - * @param {Object} obj.secretIds = ids of secrets to get latest versions for - * @param {Number} obj.n - number of latest secret versions to return for each secret - * @returns - */ -const getLatestNSecretSecretVersionIds = async ({ - secretIds, - n, -}: { - secretIds: Types.ObjectId[]; - n: number; -}) => { - // TODO: optimize query - const latestNSecretVersions = await SecretVersion.aggregate([ - { - $match: { - secret: { - $in: secretIds, - }, - }, - }, - { - $sort: { version: -1 }, - }, - { - $group: { - _id: "$secret", - versions: { $push: "$$ROOT" }, - }, - }, - { - $project: { - _id: 0, - secret: "$_id", - versions: { $slice: ["$versions", n] }, - }, - }, - ]); - - return latestNSecretVersions; -}; - -export { getLatestSecretVersionIds, getLatestNSecretSecretVersionIds }; diff --git a/backend-mongo/src/ee/models/auditLog/auditLog.ts b/backend-mongo/src/ee/models/auditLog/auditLog.ts deleted file mode 100644 index 824e2f89f..000000000 --- a/backend-mongo/src/ee/models/auditLog/auditLog.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { ActorType, EventType, UserAgentType } from "./enums"; -import { Actor, Event } from "./types"; - -export interface IAuditLog { - actor: Actor; - organization: Types.ObjectId; - workspace: Types.ObjectId; - ipAddress: string; - event: Event; - userAgent: string; - userAgentType: UserAgentType; - expiresAt?: Date; -} - -const auditLogSchema = new Schema( - { - actor: { - type: { - type: String, - enum: ActorType, - required: true - }, - metadata: { - type: Schema.Types.Mixed - } - }, - organization: { - type: Schema.Types.ObjectId, - required: false - }, - workspace: { - type: Schema.Types.ObjectId, - required: false, - index: true - }, - ipAddress: { - type: String, - required: true - }, - event: { - type: { - type: String, - enum: EventType, - required: true - }, - metadata: { - type: Schema.Types.Mixed - } - }, - userAgent: { - type: String, - required: true - }, - userAgentType: { - type: String, - enum: UserAgentType, - required: true - }, - expiresAt: { - type: Date, - expires: 0 - } - }, - { - timestamps: true - } -); - -export const AuditLog = model("AuditLog", auditLogSchema); diff --git a/backend-mongo/src/ee/models/auditLog/enums.ts b/backend-mongo/src/ee/models/auditLog/enums.ts deleted file mode 100644 index ad0051bbc..000000000 --- a/backend-mongo/src/ee/models/auditLog/enums.ts +++ /dev/null @@ -1,69 +0,0 @@ -export enum ActorType { // would extend to AWS, Azure, ... - USER = "user", // userIdentity - SERVICE = "service", - IDENTITY = "identity" -} - -export enum UserAgentType { - WEB = "web", - CLI = "cli", - K8_OPERATOR = "k8-operator", - TERRAFORM = "terraform", - OTHER = "other", - PYTHON_SDK = "InfisicalPythonSDK", - NODE_SDK = "InfisicalNodeSDK" -} - -export enum EventType { - GET_SECRETS = "get-secrets", - GET_SECRET = "get-secret", - REVEAL_SECRET = "reveal-secret", - CREATE_SECRET = "create-secret", - CREATE_SECRETS = "create-secrets", - UPDATE_SECRET = "update-secret", - UPDATE_SECRETS = "update-secrets", - DELETE_SECRET = "delete-secret", - DELETE_SECRETS = "delete-secrets", - GET_WORKSPACE_KEY = "get-workspace-key", - AUTHORIZE_INTEGRATION = "authorize-integration", - UNAUTHORIZE_INTEGRATION = "unauthorize-integration", - CREATE_INTEGRATION = "create-integration", - DELETE_INTEGRATION = "delete-integration", - ADD_TRUSTED_IP = "add-trusted-ip", - UPDATE_TRUSTED_IP = "update-trusted-ip", - DELETE_TRUSTED_IP = "delete-trusted-ip", - CREATE_SERVICE_TOKEN = "create-service-token", // v2 - DELETE_SERVICE_TOKEN = "delete-service-token", // v2 - CREATE_IDENTITY = "create-identity", - UPDATE_IDENTITY = "update-identity", - DELETE_IDENTITY = "delete-identity", - LOGIN_IDENTITY_UNIVERSAL_AUTH = "login-identity-universal-auth", - ADD_IDENTITY_UNIVERSAL_AUTH = "add-identity-universal-auth", - UPDATE_IDENTITY_UNIVERSAL_AUTH = "update-identity-universal-auth", - GET_IDENTITY_UNIVERSAL_AUTH = "get-identity-universal-auth", - CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "create-identity-universal-auth-client-secret", - REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "revoke-identity-universal-auth-client-secret", - GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS = "get-identity-universal-auth-client-secret", - CREATE_ENVIRONMENT = "create-environment", - UPDATE_ENVIRONMENT = "update-environment", - DELETE_ENVIRONMENT = "delete-environment", - ADD_WORKSPACE_MEMBER = "add-workspace-member", - ADD_BATCH_WORKSPACE_MEMBER = "add-workspace-members", - REMOVE_WORKSPACE_MEMBER = "remove-workspace-member", - CREATE_FOLDER = "create-folder", - UPDATE_FOLDER = "update-folder", - DELETE_FOLDER = "delete-folder", - CREATE_WEBHOOK = "create-webhook", - UPDATE_WEBHOOK_STATUS = "update-webhook-status", - DELETE_WEBHOOK = "delete-webhook", - GET_SECRET_IMPORTS = "get-secret-imports", - CREATE_SECRET_IMPORT = "create-secret-import", - UPDATE_SECRET_IMPORT = "update-secret-import", - DELETE_SECRET_IMPORT = "delete-secret-import", - UPDATE_USER_WORKSPACE_ROLE = "update-user-workspace-role", - UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS = "update-user-workspace-denied-permissions", - SECRET_APPROVAL_MERGED = "secret-approval-merged", - SECRET_APPROVAL_REQUEST = "secret-approval-request", - SECRET_APPROVAL_CLOSED = "secret-approval-closed", - SECRET_APPROVAL_REOPENED = "secret-approval-reopened" -} diff --git a/backend-mongo/src/ee/models/auditLog/index.ts b/backend-mongo/src/ee/models/auditLog/index.ts deleted file mode 100644 index 37b86b5d1..000000000 --- a/backend-mongo/src/ee/models/auditLog/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./auditLog"; -export * from "./enums"; -export * from "./types"; \ No newline at end of file diff --git a/backend-mongo/src/ee/models/auditLog/types.ts b/backend-mongo/src/ee/models/auditLog/types.ts deleted file mode 100644 index a4e470414..000000000 --- a/backend-mongo/src/ee/models/auditLog/types.ts +++ /dev/null @@ -1,585 +0,0 @@ -import { ActorType, EventType } from "./enums"; -import { IIdentityTrustedIp } from "../../../models"; - -interface UserActorMetadata { - userId: string; - email: string; -} - -interface ServiceActorMetadata { - serviceId: string; - name: string; -} - -interface IdentityActorMetadata { - identityId: string; - name: string; -} - -export interface UserActor { - type: ActorType.USER; - metadata: UserActorMetadata; -} - -export interface ServiceActor { - type: ActorType.SERVICE; - metadata: ServiceActorMetadata; -} - -export interface IdentityActor { - type: ActorType.IDENTITY; - metadata: IdentityActorMetadata; -} - -export type Actor = UserActor | ServiceActor | IdentityActor; - -interface GetSecretsEvent { - type: EventType.GET_SECRETS; - metadata: { - environment: string; - secretPath: string; - numberOfSecrets: number; - }; -} - -interface GetSecretEvent { - type: EventType.GET_SECRET; - metadata: { - environment: string; - secretPath: string; - secretId: string; - secretKey: string; - secretVersion: number; - }; -} - -interface CreateSecretEvent { - type: EventType.CREATE_SECRET; - metadata: { - environment: string; - secretPath: string; - secretId: string; - secretKey: string; - secretVersion: number; - }; -} - -interface CreateSecretBatchEvent { - type: EventType.CREATE_SECRETS; - metadata: { - environment: string; - secretPath: string; - secrets: Array<{ secretId: string; secretKey: string; secretVersion: number }>; - }; -} - -interface UpdateSecretEvent { - type: EventType.UPDATE_SECRET; - metadata: { - environment: string; - secretPath: string; - secretId: string; - secretKey: string; - secretVersion: number; - }; -} - -interface UpdateSecretBatchEvent { - type: EventType.UPDATE_SECRETS; - metadata: { - environment: string; - secretPath: string; - secrets: Array<{ secretId: string; secretKey: string; secretVersion: number }>; - }; -} - -interface DeleteSecretEvent { - type: EventType.DELETE_SECRET; - metadata: { - environment: string; - secretPath: string; - secretId: string; - secretKey: string; - secretVersion: number; - }; -} - -interface DeleteSecretBatchEvent { - type: EventType.DELETE_SECRETS; - metadata: { - environment: string; - secretPath: string; - secrets: Array<{ secretId: string; secretKey: string; secretVersion: number }>; - }; -} - -interface GetWorkspaceKeyEvent { - type: EventType.GET_WORKSPACE_KEY; - metadata: { - keyId: string; - }; -} - -interface AuthorizeIntegrationEvent { - type: EventType.AUTHORIZE_INTEGRATION; - metadata: { - integration: string; - }; -} - -interface UnauthorizeIntegrationEvent { - type: EventType.UNAUTHORIZE_INTEGRATION; - metadata: { - integration: string; - }; -} - -interface CreateIntegrationEvent { - type: EventType.CREATE_INTEGRATION; - metadata: { - integrationId: string; - integration: string; // TODO: fix type - environment: string; - secretPath: string; - url?: string; - app?: string; - appId?: string; - targetEnvironment?: string; - targetEnvironmentId?: string; - targetService?: string; - targetServiceId?: string; - path?: string; - region?: string; - }; -} - -interface DeleteIntegrationEvent { - type: EventType.DELETE_INTEGRATION; - metadata: { - integrationId: string; - integration: string; // TODO: fix type - environment: string; - secretPath: string; - url?: string; - app?: string; - appId?: string; - targetEnvironment?: string; - targetEnvironmentId?: string; - targetService?: string; - targetServiceId?: string; - path?: string; - region?: string; - }; -} - -interface AddTrustedIPEvent { - type: EventType.ADD_TRUSTED_IP; - metadata: { - trustedIpId: string; - ipAddress: string; - prefix?: number; - }; -} - -interface UpdateTrustedIPEvent { - type: EventType.UPDATE_TRUSTED_IP; - metadata: { - trustedIpId: string; - ipAddress: string; - prefix?: number; - }; -} - -interface DeleteTrustedIPEvent { - type: EventType.DELETE_TRUSTED_IP; - metadata: { - trustedIpId: string; - ipAddress: string; - prefix?: number; - }; -} - -interface CreateServiceTokenEvent { - type: EventType.CREATE_SERVICE_TOKEN; - metadata: { - name: string; - scopes: Array<{ - environment: string; - secretPath: string; - }>; - }; -} - -interface DeleteServiceTokenEvent { - type: EventType.DELETE_SERVICE_TOKEN; - metadata: { - name: string; - scopes: Array<{ - environment: string; - secretPath: string; - }>; - }; -} - -interface CreateIdentityEvent { // note: currently not logging org-role - type: EventType.CREATE_IDENTITY; - metadata: { - identityId: string; - name: string; - }; -} - -interface UpdateIdentityEvent { - type: EventType.UPDATE_IDENTITY; - metadata: { - identityId: string; - name?: string; - }; -} - -interface DeleteIdentityEvent { - type: EventType.DELETE_IDENTITY; - metadata: { - identityId: string; - }; -} - -interface LoginIdentityUniversalAuthEvent { - type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH ; - metadata: { - identityId: string; - identityUniversalAuthId: string; - clientSecretId: string; - identityAccessTokenId: string; - }; -} - -interface AddIdentityUniversalAuthEvent { - type: EventType.ADD_IDENTITY_UNIVERSAL_AUTH; - metadata: { - identityId: string; - clientSecretTrustedIps: Array; - accessTokenTTL: number; - accessTokenMaxTTL: number; - accessTokenNumUsesLimit: number; - accessTokenTrustedIps: Array; - }; -} - -interface UpdateIdentityUniversalAuthEvent { - type: EventType.UPDATE_IDENTITY_UNIVERSAL_AUTH; - metadata: { - identityId: string; - clientSecretTrustedIps?: Array; - accessTokenTTL?: number; - accessTokenMaxTTL?: number; - accessTokenNumUsesLimit?: number; - accessTokenTrustedIps?: Array; - }; -} - -interface GetIdentityUniversalAuthEvent { - type: EventType.GET_IDENTITY_UNIVERSAL_AUTH; - metadata: { - identityId: string; - }; -} - -interface CreateIdentityUniversalAuthClientSecretEvent { - type: EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ; - metadata: { - identityId: string; - clientSecretId: string; - }; -} - -interface GetIdentityUniversalAuthClientSecretsEvent { - type: EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS; - metadata: { - identityId: string; - }; -} - - -interface RevokeIdentityUniversalAuthClientSecretEvent { - type: EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ; - metadata: { - identityId: string; - clientSecretId: string; - }; -} - -interface CreateEnvironmentEvent { - type: EventType.CREATE_ENVIRONMENT; - metadata: { - name: string; - slug: string; - }; -} - -interface UpdateEnvironmentEvent { - type: EventType.UPDATE_ENVIRONMENT; - metadata: { - oldName: string; - newName: string; - oldSlug: string; - newSlug: string; - }; -} - -interface DeleteEnvironmentEvent { - type: EventType.DELETE_ENVIRONMENT; - metadata: { - name: string; - slug: string; - }; -} - -interface AddWorkspaceMemberEvent { - type: EventType.ADD_WORKSPACE_MEMBER; - metadata: { - userId: string; - email: string; - }; -} - -interface AddBatchWorkspaceMemberEvent { - type: EventType.ADD_BATCH_WORKSPACE_MEMBER; - metadata: Array<{ - userId: string; - email: string; - }>; -} - -interface RemoveWorkspaceMemberEvent { - type: EventType.REMOVE_WORKSPACE_MEMBER; - metadata: { - userId: string; - email: string; - }; -} - -interface CreateFolderEvent { - type: EventType.CREATE_FOLDER; - metadata: { - environment: string; - folderId: string; - folderName: string; - folderPath: string; - }; -} - -interface UpdateFolderEvent { - type: EventType.UPDATE_FOLDER; - metadata: { - environment: string; - folderId: string; - oldFolderName: string; - newFolderName: string; - folderPath: string; - }; -} - -interface DeleteFolderEvent { - type: EventType.DELETE_FOLDER; - metadata: { - environment: string; - folderId: string; - folderName: string; - folderPath: string; - }; -} - -interface CreateWebhookEvent { - type: EventType.CREATE_WEBHOOK; - metadata: { - webhookId: string; - environment: string; - secretPath: string; - webhookUrl: string; - isDisabled: boolean; - }; -} - -interface UpdateWebhookStatusEvent { - type: EventType.UPDATE_WEBHOOK_STATUS; - metadata: { - webhookId: string; - environment: string; - secretPath: string; - webhookUrl: string; - isDisabled: boolean; - }; -} - -interface DeleteWebhookEvent { - type: EventType.DELETE_WEBHOOK; - metadata: { - webhookId: string; - environment: string; - secretPath: string; - webhookUrl: string; - isDisabled: boolean; - }; -} - -interface GetSecretImportsEvent { - type: EventType.GET_SECRET_IMPORTS; - metadata: { - environment: string; - secretImportId: string; - folderId: string; - numberOfImports: number; - }; -} - -interface CreateSecretImportEvent { - type: EventType.CREATE_SECRET_IMPORT; - metadata: { - secretImportId: string; - folderId: string; - importFromEnvironment: string; - importFromSecretPath: string; - importToEnvironment: string; - importToSecretPath: string; - }; -} - -interface UpdateSecretImportEvent { - type: EventType.UPDATE_SECRET_IMPORT; - metadata: { - secretImportId: string; - folderId: string; - importToEnvironment: string; - importToSecretPath: string; - orderBefore: { - environment: string; - secretPath: string; - }[]; - orderAfter: { - environment: string; - secretPath: string; - }[]; - }; -} - -interface DeleteSecretImportEvent { - type: EventType.DELETE_SECRET_IMPORT; - metadata: { - secretImportId: string; - folderId: string; - importFromEnvironment: string; - importFromSecretPath: string; - importToEnvironment: string; - importToSecretPath: string; - }; -} - -interface UpdateUserRole { - type: EventType.UPDATE_USER_WORKSPACE_ROLE; - metadata: { - userId: string; - email: string; - oldRole: string; - newRole: string; - }; -} - -interface UpdateUserDeniedPermissions { - type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS; - metadata: { - userId: string; - email: string; - deniedPermissions: { - environmentSlug: string; - ability: string; - }[]; - }; -} -interface SecretApprovalMerge { - type: EventType.SECRET_APPROVAL_MERGED; - metadata: { - mergedBy: string; - secretApprovalRequestSlug: string; - secretApprovalRequestId: string; - }; -} - -interface SecretApprovalClosed { - type: EventType.SECRET_APPROVAL_CLOSED; - metadata: { - closedBy: string; - secretApprovalRequestSlug: string; - secretApprovalRequestId: string; - }; -} - -interface SecretApprovalReopened { - type: EventType.SECRET_APPROVAL_REOPENED; - metadata: { - reopenedBy: string; - secretApprovalRequestSlug: string; - secretApprovalRequestId: string; - }; -} - -interface SecretApprovalRequest { - type: EventType.SECRET_APPROVAL_REQUEST; - metadata: { - committedBy: string; - secretApprovalRequestSlug: string; - secretApprovalRequestId: string; - }; -} - -export type Event = - | GetSecretsEvent - | GetSecretEvent - | CreateSecretEvent - | CreateSecretBatchEvent - | UpdateSecretEvent - | UpdateSecretBatchEvent - | DeleteSecretEvent - | DeleteSecretBatchEvent - | GetWorkspaceKeyEvent - | AuthorizeIntegrationEvent - | UnauthorizeIntegrationEvent - | CreateIntegrationEvent - | DeleteIntegrationEvent - | AddTrustedIPEvent - | UpdateTrustedIPEvent - | DeleteTrustedIPEvent - | CreateServiceTokenEvent - | DeleteServiceTokenEvent - | CreateIdentityEvent - | UpdateIdentityEvent - | DeleteIdentityEvent - | LoginIdentityUniversalAuthEvent - | AddIdentityUniversalAuthEvent - | UpdateIdentityUniversalAuthEvent - | GetIdentityUniversalAuthEvent - | CreateIdentityUniversalAuthClientSecretEvent - | GetIdentityUniversalAuthClientSecretsEvent - | RevokeIdentityUniversalAuthClientSecretEvent - | CreateEnvironmentEvent - | UpdateEnvironmentEvent - | DeleteEnvironmentEvent - | AddWorkspaceMemberEvent - | AddBatchWorkspaceMemberEvent - | RemoveWorkspaceMemberEvent - | CreateFolderEvent - | UpdateFolderEvent - | DeleteFolderEvent - | CreateWebhookEvent - | UpdateWebhookStatusEvent - | DeleteWebhookEvent - | GetSecretImportsEvent - | CreateSecretImportEvent - | UpdateSecretImportEvent - | DeleteSecretImportEvent - | UpdateUserRole - | UpdateUserDeniedPermissions - | SecretApprovalMerge - | SecretApprovalClosed - | SecretApprovalRequest - | SecretApprovalReopened; diff --git a/backend-mongo/src/ee/models/folderVersion.ts b/backend-mongo/src/ee/models/folderVersion.ts deleted file mode 100644 index dbcebcb92..000000000 --- a/backend-mongo/src/ee/models/folderVersion.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export type TFolderRootVersionSchema = { - _id: Types.ObjectId; - workspace: Types.ObjectId; - environment: string; - nodes: TFolderVersionSchema; -}; - -export type TFolderVersionSchema = { - id: string; - name: string; - version: number; - children: TFolderVersionSchema[]; -}; - -const folderVersionSchema = new Schema({ - id: { - required: true, - type: String, - default: "root", - }, - name: { - required: true, - type: String, - default: "root", - }, - version: { - required: true, - type: Number, - default: 1, - }, -}); - -folderVersionSchema.add({ children: [folderVersionSchema] }); - -const folderRootVersionSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - }, - environment: { - type: String, - required: true, - }, - nodes: folderVersionSchema, - }, - { - timestamps: true, - } -); - -export const FolderVersion = model( - "FolderVersion", - folderRootVersionSchema -); \ No newline at end of file diff --git a/backend-mongo/src/ee/models/gitAppInstallationSession.ts b/backend-mongo/src/ee/models/gitAppInstallationSession.ts deleted file mode 100644 index 0cdf8df3c..000000000 --- a/backend-mongo/src/ee/models/gitAppInstallationSession.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -type GitAppInstallationSession = { - id: string; - sessionId: string; - organization: Types.ObjectId; - user: Types.ObjectId; -} - -const gitAppInstallationSession = new Schema({ - id: { - required: true, - type: String, - }, - sessionId: { - type: String, - required: true, - unique: true - }, - organization: { - type: Schema.Types.ObjectId, - required: true, - unique: true - }, - user: { - type: Schema.Types.ObjectId, - ref: "User" - } -}); - - -export const GitAppInstallationSession = model("git_app_installation_session", gitAppInstallationSession); \ No newline at end of file diff --git a/backend-mongo/src/ee/models/gitAppOrganizationInstallation.ts b/backend-mongo/src/ee/models/gitAppOrganizationInstallation.ts deleted file mode 100644 index 4ce55b0cb..000000000 --- a/backend-mongo/src/ee/models/gitAppOrganizationInstallation.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Schema, model } from "mongoose"; - -type Installation = { - installationId: string - organizationId: string - user: Schema.Types.ObjectId -}; - - -const gitAppOrganizationInstallation = new Schema({ - installationId: { - type: String, - required: true, - unique: true - }, - organizationId: { - type: String, - required: true, - unique: true - }, - user: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - } -}); - - -export const GitAppOrganizationInstallation = model("git_app_organization_installation", gitAppOrganizationInstallation); \ No newline at end of file diff --git a/backend-mongo/src/ee/models/gitRisks.ts b/backend-mongo/src/ee/models/gitRisks.ts deleted file mode 100644 index 8d3f59208..000000000 --- a/backend-mongo/src/ee/models/gitRisks.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { Schema, model } from "mongoose"; - -export const STATUS_RESOLVED_FALSE_POSITIVE = "RESOLVED_FALSE_POSITIVE"; -export const STATUS_RESOLVED_REVOKED = "RESOLVED_REVOKED"; -export const STATUS_RESOLVED_NOT_REVOKED = "RESOLVED_NOT_REVOKED"; -export const STATUS_UNRESOLVED = "UNRESOLVED"; - -export type IGitRisks = { - id: string; - description: string; - startLine: string; - endLine: string; - startColumn: string; - endColumn: string; - match: string; - secret: string; - file: string; - symlinkFile: string; - commit: string; - entropy: string; - author: string; - email: string; - date: string; - message: string; - tags: string[]; - ruleID: string; - fingerprint: string; - fingerPrintWithoutCommitId: string - - isFalsePositive: boolean; // New field for marking risks as false positives - isResolved: boolean; // New field for marking risks as resolved - riskOwner: string | null; // New field for setting a risk owner (nullable string) - installationId: string, - repositoryId: string, - repositoryLink: string - repositoryFullName: string - status: string - pusher: { - name: string, - email: string - }, - organization: Schema.Types.ObjectId, -} - -const gitRisks = new Schema({ - id: { - type: String, - }, - description: { - type: String, - }, - startLine: { - type: String, - }, - endLine: { - type: String, - }, - startColumn: { - type: String, - }, - endColumn: { - type: String, - }, - file: { - type: String, - }, - symlinkFile: { - type: String, - }, - commit: { - type: String, - }, - entropy: { - type: String, - }, - author: { - type: String, - }, - email: { - type: String, - }, - date: { - type: String, - }, - message: { - type: String, - }, - tags: { - type: [String], - }, - ruleID: { - type: String, - }, - fingerprint: { - type: String, - unique: true - }, - fingerPrintWithoutCommitId: { - type: String, - }, - isFalsePositive: { - type: Boolean, - default: false - }, - isResolved: { - type: Boolean, - default: false - }, - riskOwner: { - type: String, - default: null - }, - installationId: { - type: String, - require: true - }, - repositoryId: { - type: String - }, - repositoryLink: { - type: String - }, - repositoryFullName: { - type: String - }, - pusher: { - name: { - type: String - }, - email: { - type: String - }, - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization", - }, - status: { - type: String, - enum: [ - STATUS_RESOLVED_FALSE_POSITIVE, - STATUS_RESOLVED_REVOKED, - STATUS_RESOLVED_NOT_REVOKED, - STATUS_UNRESOLVED - ], - default: STATUS_UNRESOLVED - } -}, { timestamps: true }); - -export const GitRisks = model("GitRisks", gitRisks); \ No newline at end of file diff --git a/backend-mongo/src/ee/models/index.ts b/backend-mongo/src/ee/models/index.ts deleted file mode 100644 index b2a9556ac..000000000 --- a/backend-mongo/src/ee/models/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from "./secretSnapshot"; -export * from "./secretVersion"; -export * from "./folderVersion"; -export * from "./role"; -export * from "./ssoConfig"; -export * from "./trustedIp"; -export * from "./auditLog"; -export * from "./gitRisks"; -export * from "./gitAppOrganizationInstallation"; -export * from "./gitAppInstallationSession"; -export * from "./secretApprovalPolicy"; -export * from "./secretApprovalRequest"; diff --git a/backend-mongo/src/ee/models/role.ts b/backend-mongo/src/ee/models/role.ts deleted file mode 100644 index d3de1d3ae..000000000 --- a/backend-mongo/src/ee/models/role.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IRole { - _id: Types.ObjectId; - name: string; - description: string; - slug: string; - permissions: Array; - workspace: Types.ObjectId; - organization: Types.ObjectId; - isOrgRole: boolean; -} - -const roleSchema = new Schema( - { - name: { - type: String, - required: true - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization", - required: true - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace" - }, - isOrgRole: { - type: Boolean, - required: true, - select: false - }, - description: { - type: String - }, - slug: { - type: String, - required: true - }, - permissions: { - type: Array, - required: true - } - }, - { - timestamps: true - } -); - -roleSchema.index({ organization: 1, workspace: 1 }); - -export const Role = model("Role", roleSchema); \ No newline at end of file diff --git a/backend-mongo/src/ee/models/secretApprovalPolicy.ts b/backend-mongo/src/ee/models/secretApprovalPolicy.ts deleted file mode 100644 index 376b541c7..000000000 --- a/backend-mongo/src/ee/models/secretApprovalPolicy.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface ISecretApprovalPolicy { - _id: Types.ObjectId; - workspace: Types.ObjectId; - name: string; - environment: string; - secretPath?: string; - approvers: Types.ObjectId[]; - approvals: number; -} - -const secretApprovalPolicySchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - approvers: [ - { - // user associated with the personal secret - type: Schema.Types.ObjectId, - ref: "Membership" - } - ], - name: { - type: String - }, - environment: { - type: String, - required: true - }, - secretPath: { - type: String, - required: false - }, - approvals: { - type: Number, - default: 1 - } - }, - { - timestamps: true - } -); - -export const SecretApprovalPolicy = model( - "SecretApprovalPolicy", - secretApprovalPolicySchema -); diff --git a/backend-mongo/src/ee/models/secretApprovalRequest.ts b/backend-mongo/src/ee/models/secretApprovalRequest.ts deleted file mode 100644 index 24e8af39a..000000000 --- a/backend-mongo/src/ee/models/secretApprovalRequest.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { customAlphabet } from "nanoid"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8 -} from "../../variables"; - -export enum ApprovalStatus { - PENDING = "pending", - APPROVED = "approved", - REJECTED = "rejected" -} - -export enum CommitType { - DELETE = "delete", - UPDATE = "update", - CREATE = "create" -} - -const SLUG_ALPHABETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -const nanoId = customAlphabet(SLUG_ALPHABETS, 10); - -export interface ISecretApprovalSecChange { - _id: Types.ObjectId; - version: number; - secretBlindIndex?: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentIV?: string; - secretCommentTag?: string; - secretCommentCiphertext?: string; - skipMultilineEncoding?: boolean; - algorithm?: "aes-256-gcm"; - keyEncoding?: "utf8" | "base64"; - tags?: string[]; -} - -export type ISecretCommits = Array< - | { - newVersion: ISecretApprovalSecChange; - op: CommitType.CREATE; - } - | { - // secret is recorded to get the latest version, we can keep ref to secret for pulling change as it will also get changed - // on merge - secretVersion: J; - secret: T; - newVersion: Partial> & { _id: Types.ObjectId }; - op: CommitType.UPDATE; - } - | { - secret: T; - secretVersion: J; - op: CommitType.DELETE; - } ->; -export interface ISecretApprovalRequest { - _id: Types.ObjectId; - committer: Types.ObjectId; - slug: string; - statusChangeBy: Types.ObjectId; - reviewers: { - member: Types.ObjectId; - status: ApprovalStatus; - }[]; - workspace: Types.ObjectId; - environment: string; - folderId: string; - hasMerged: boolean; - status: "open" | "close"; - policy: Types.ObjectId; - commits: ISecretCommits; - conflicts: Array<{ secretId: string; op: CommitType }>; -} - -const secretApprovalSecretChangeSchema = new Schema({ - version: { - type: Number, - default: 1, - required: true - }, - secretBlindIndex: { - type: String, - select: false - }, - secretKeyCiphertext: { - type: String, - required: true - }, - secretKeyIV: { - type: String, // symmetric - required: true - }, - secretKeyTag: { - type: String, // symmetric - required: true - }, - secretValueCiphertext: { - type: String, - required: true - }, - secretValueIV: { - type: String, // symmetric - required: true - }, - secretValueTag: { - type: String, // symmetric - required: true - }, - skipMultilineEncoding: { - type: Boolean, - required: false - }, - algorithm: { - // the encryption algorithm used - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true, - default: ALGORITHM_AES_256_GCM - }, - keyEncoding: { - type: String, - enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64], - required: true, - default: ENCODING_SCHEME_UTF8 - }, - tags: { - ref: "Tag", - type: [Schema.Types.ObjectId], - default: [] - } -}); - -const secretApprovalRequestSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - environment: { - type: String, - required: true - }, - folderId: { - type: String, - required: true, - default: "root" - }, - slug: { - type: String, - default: () => nanoId() - }, - reviewers: { - type: [ - { - member: { - // user associated with the personal secret - type: Schema.Types.ObjectId, - ref: "Membership" - }, - status: { type: String, enum: ApprovalStatus, default: ApprovalStatus.PENDING } - } - ], - default: [] - }, - policy: { type: Schema.Types.ObjectId, ref: "SecretApprovalPolicy" }, - hasMerged: { type: Boolean, default: false }, - status: { type: String, enum: ["close", "open"], default: "open" }, - committer: { type: Schema.Types.ObjectId, ref: "Membership" }, - statusChangeBy: { type: Schema.Types.ObjectId, ref: "Membership" }, - commits: [ - { - secret: { type: Types.ObjectId, ref: "Secret" }, - newVersion: secretApprovalSecretChangeSchema, - secretVersion: { type: Types.ObjectId, ref: "SecretVersion" }, - op: { type: String, enum: [CommitType], required: true } - } - ], - conflicts: { - type: [ - { - secretId: { type: String, required: true }, - op: { type: String, enum: [CommitType], required: true } - } - ], - default: [] - } - }, - { - timestamps: true - } -); - -export const SecretApprovalRequest = model( - "SecretApprovalRequest", - secretApprovalRequestSchema -); diff --git a/backend-mongo/src/ee/models/secretSnapshot.ts b/backend-mongo/src/ee/models/secretSnapshot.ts deleted file mode 100644 index 71d1b27e6..000000000 --- a/backend-mongo/src/ee/models/secretSnapshot.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface ISecretSnapshot { - workspace: Types.ObjectId; - environment: string; - folderId: string | "root"; - version: number; - secretVersions: Types.ObjectId[]; - folderVersion: Types.ObjectId; -} - -const secretSnapshotSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - }, - environment: { - type: String, - required: true, - }, - folderId: { - type: String, - default: "root", - }, - version: { - type: Number, - default: 1, - required: true, - }, - secretVersions: [ - { - type: Schema.Types.ObjectId, - ref: "SecretVersion", - required: true, - }, - ], - folderVersion: { - type: Schema.Types.ObjectId, - ref: "FolderVersion", - }, - }, - { - timestamps: true, - } -); - -export const SecretSnapshot = model( - "SecretSnapshot", - secretSnapshotSchema -); \ No newline at end of file diff --git a/backend-mongo/src/ee/models/secretVersion.ts b/backend-mongo/src/ee/models/secretVersion.ts deleted file mode 100644 index 11ffa79ab..000000000 --- a/backend-mongo/src/ee/models/secretVersion.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, - SECRET_PERSONAL, - SECRET_SHARED -} from "../../variables"; - -export interface ISecretVersion { - _id: Types.ObjectId; - secret: Types.ObjectId; - version: number; - workspace: Types.ObjectId; // new - type: string; // new - user?: Types.ObjectId; // new - environment: string; // new - isDeleted: boolean; - secretBlindIndex?: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - skipMultilineEncoding?: boolean; - algorithm: "aes-256-gcm"; - keyEncoding: "utf8" | "base64"; - createdAt: string; - folder?: string; - tags?: string[]; -} - -const secretVersionSchema = new Schema( - { - secret: { - // could be deleted - type: Schema.Types.ObjectId, - ref: "Secret", - required: true - }, - version: { - type: Number, - default: 1, - required: true - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - type: { - type: String, - enum: [SECRET_SHARED, SECRET_PERSONAL], - required: true - }, - user: { - // user associated with the personal secret - type: Schema.Types.ObjectId, - ref: "User" - }, - environment: { - type: String, - required: true - }, - isDeleted: { - // consider removing field - type: Boolean, - default: false, - required: true - }, - secretBlindIndex: { - type: String, - select: false - }, - secretKeyCiphertext: { - type: String, - required: true - }, - secretKeyIV: { - type: String, // symmetric - required: true - }, - secretKeyTag: { - type: String, // symmetric - required: true - }, - secretValueCiphertext: { - type: String, - required: true - }, - secretValueIV: { - type: String, // symmetric - required: true - }, - secretValueTag: { - type: String, // symmetric - required: true - }, - skipMultilineEncoding: { - type: Boolean, - required: false - }, - algorithm: { - // the encryption algorithm used - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true, - default: ALGORITHM_AES_256_GCM - }, - keyEncoding: { - type: String, - enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64], - required: true, - default: ENCODING_SCHEME_UTF8 - }, - folder: { - type: String, - required: true - }, - tags: { - ref: "Tag", - type: [Schema.Types.ObjectId], - default: [] - } - }, - { - timestamps: true - } -); - -export const SecretVersion = model("SecretVersion", secretVersionSchema); diff --git a/backend-mongo/src/ee/models/ssoConfig.ts b/backend-mongo/src/ee/models/ssoConfig.ts deleted file mode 100644 index b591b8817..000000000 --- a/backend-mongo/src/ee/models/ssoConfig.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export enum AuthProvider { - OKTA_SAML = "okta-saml", - AZURE_SAML = "azure-saml", - JUMPCLOUD_SAML = "jumpcloud-saml" -} - -export interface ISSOConfig { - organization: Types.ObjectId; - authProvider: AuthProvider; - isActive: boolean; - encryptedEntryPoint: string; - entryPointIV: string; - entryPointTag: string; - encryptedIssuer: string; - issuerIV: string; - issuerTag: string; - encryptedCert: string; - certIV: string; - certTag: string; -} - -const ssoConfigSchema = new Schema( - { - organization: { - type: Schema.Types.ObjectId, - ref: "Organization" - }, - authProvider: { - type: String, - enum: AuthProvider, - required: true - }, - isActive: { - type: Boolean, - required: true - }, - encryptedEntryPoint: { - type: String - }, - entryPointIV: { - type: String - }, - entryPointTag: { - type: String - }, - encryptedIssuer: { - type: String - }, - issuerIV: { - type: String - }, - issuerTag: { - type: String - }, - encryptedCert: { - type: String - }, - certIV: { - type: String - }, - certTag: { - type: String - } - }, - { - timestamps: true - } -); - -export const SSOConfig = model("SSOConfig", ssoConfigSchema); \ No newline at end of file diff --git a/backend-mongo/src/ee/models/trustedIp.ts b/backend-mongo/src/ee/models/trustedIp.ts deleted file mode 100644 index 85616be11..000000000 --- a/backend-mongo/src/ee/models/trustedIp.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export enum IPType { - IPV4 = "ipv4", - IPV6 = "ipv6" -} - -export interface ITrustedIP { - _id: Types.ObjectId; - workspace: Types.ObjectId; - ipAddress: string; - type: "ipv4" | "ipv6", // either IPv4/IPv6 address or network IPv4/IPv6 address - isActive: boolean; - comment: string; - prefix?: number; // CIDR -} - -const trustedIpSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - ipAddress: { - type: String, - required: true - }, - type: { - type: String, - enum: [ - IPType.IPV4, - IPType.IPV6 - ], - required: true - }, - prefix: { - type: Number, - required: false - }, - isActive: { - type: Boolean, - required: true - }, - comment: { - type: String - } - }, - { - timestamps: true - } -); - -export const TrustedIP = model("TrustedIP", trustedIpSchema); \ No newline at end of file diff --git a/backend-mongo/src/ee/routes/v1/cloudProducts.ts b/backend-mongo/src/ee/routes/v1/cloudProducts.ts deleted file mode 100644 index 23912222b..000000000 --- a/backend-mongo/src/ee/routes/v1/cloudProducts.ts +++ /dev/null @@ -1,16 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth, validateRequest } from "../../../middleware"; -import { cloudProductsController } from "../../controllers/v1"; -import { AuthMode } from "../../../variables"; - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - validateRequest, - cloudProductsController.getCloudProducts -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/identities.ts b/backend-mongo/src/ee/routes/v1/identities.ts deleted file mode 100644 index c78a7d8c8..000000000 --- a/backend-mongo/src/ee/routes/v1/identities.ts +++ /dev/null @@ -1,31 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { AuthMode } from "../../../variables"; -import { identitiesController } from "../../controllers/v1"; - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - identitiesController.createIdentity -); - -router.patch( - "/:identityId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - identitiesController.updateIdentity -); - -router.delete( - "/:identityId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - identitiesController.deleteIdentity -); - -export default router; \ No newline at end of file diff --git a/backend-mongo/src/ee/routes/v1/index.ts b/backend-mongo/src/ee/routes/v1/index.ts deleted file mode 100644 index b22c61629..000000000 --- a/backend-mongo/src/ee/routes/v1/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -import identities from "./identities"; -import secret from "./secret"; -import secretSnapshot from "./secretSnapshot"; -import organizations from "./organizations"; -import sso from "./sso"; -import users from "./users"; -import workspace from "./workspace"; -import cloudProducts from "./cloudProducts"; -import secretScanning from "./secretScanning"; -import roles from "./role"; -import secretApprovalPolicy from "./secretApprovalPolicy"; -import secretApprovalRequest from "./secretApprovalRequest"; -import secretRotationProvider from "./secretRotationProvider"; -import secretRotation from "./secretRotation"; - -export { - identities, - secret, - secretSnapshot, - organizations, - sso, - users, - workspace, - cloudProducts, - secretScanning, - roles, - secretApprovalPolicy, - secretApprovalRequest, - secretRotationProvider, - secretRotation -}; diff --git a/backend-mongo/src/ee/routes/v1/organizations.ts b/backend-mongo/src/ee/routes/v1/organizations.ts deleted file mode 100644 index bbe5019b4..000000000 --- a/backend-mongo/src/ee/routes/v1/organizations.ts +++ /dev/null @@ -1,127 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { organizationsController } from "../../controllers/v1"; -import { AuthMode } from "../../../variables"; - -router.get( - "/:organizationId/plans/table", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationPlansTable -); - -router.get( - "/:organizationId/plan", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationPlan -); - -router.post( - "/:organizationId/session/trial", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.startOrganizationTrial -); - -router.get( - "/:organizationId/plan/billing", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationPlanBillingInfo -); - -router.get( - "/:organizationId/plan/table", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationPlanTable -); - -router.get( - "/:organizationId/billing-details", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationBillingDetails -); - -router.patch( - "/:organizationId/billing-details", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.updateOrganizationBillingDetails -); - -router.get( - "/:organizationId/billing-details/payment-methods", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationPmtMethods -); - -router.post( - "/:organizationId/billing-details/payment-methods", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.addOrganizationPmtMethod -); - -router.delete( - "/:organizationId/billing-details/payment-methods/:pmtMethodId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.deleteOrganizationPmtMethod -); - -router.get( - "/:organizationId/billing-details/tax-ids", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationTaxIds -); - -router.post( - "/:organizationId/billing-details/tax-ids", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.addOrganizationTaxId -); - -router.delete( - "/:organizationId/billing-details/tax-ids/:taxId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.deleteOrganizationTaxId -); - -router.get( - "/:organizationId/invoices", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationInvoices -); - -router.get( - "/:organizationId/licenses", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationLicenses -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/role.ts b/backend-mongo/src/ee/routes/v1/role.ts deleted file mode 100644 index 0794b6b19..000000000 --- a/backend-mongo/src/ee/routes/v1/role.ts +++ /dev/null @@ -1,33 +0,0 @@ -import express from "express"; -import { roleController } from "../../controllers/v1"; -import { requireAuth } from "../../../middleware"; -import { AuthMode } from "../../../variables"; - -const router = express.Router(); - -router.post("/", requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), roleController.createRole); - -router.patch("/:id", requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), roleController.updateRole); - -router.delete( - "/:id", - requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), - roleController.deleteRole -); - -router.get("/", requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), roleController.getRoles); - -// get a user permissions in an org -router.get( - "/organization/:orgId/permissions", - requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), - roleController.getUserPermissions -); - -router.get( - "/workspace/:workspaceId/permissions", - requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), - roleController.getUserWorkspacePermissions -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/secret.ts b/backend-mongo/src/ee/routes/v1/secret.ts deleted file mode 100644 index bdbdec965..000000000 --- a/backend-mongo/src/ee/routes/v1/secret.ts +++ /dev/null @@ -1,25 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { secretController } from "../../controllers/v1"; -import { - AuthMode -} from "../../../variables"; - -router.get( - "/:secretId/secret-versions", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - secretController.getSecretVersions -); - -router.post( - "/:secretId/secret-versions/rollback", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - secretController.rollbackSecretVersion -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/secretApprovalPolicy.ts b/backend-mongo/src/ee/routes/v1/secretApprovalPolicy.ts deleted file mode 100644 index c4b082286..000000000 --- a/backend-mongo/src/ee/routes/v1/secretApprovalPolicy.ts +++ /dev/null @@ -1,47 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { secretApprovalPolicyController } from "../../controllers/v1"; -import { AuthMode } from "../../../variables"; - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalPolicyController.getSecretApprovalPolicy -); - -router.get( - "/board", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalPolicyController.getSecretApprovalPolicyOfBoard -); - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalPolicyController.createSecretApprovalPolicy -); - -router.patch( - "/:id", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalPolicyController.updateSecretApprovalPolicy -); - -router.delete( - "/:id", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalPolicyController.deleteSecretApprovalPolicy -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/secretApprovalRequest.ts b/backend-mongo/src/ee/routes/v1/secretApprovalRequest.ts deleted file mode 100644 index e78c67c96..000000000 --- a/backend-mongo/src/ee/routes/v1/secretApprovalRequest.ts +++ /dev/null @@ -1,55 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { secretApprovalRequestController } from "../../controllers/v1"; -import { AuthMode } from "../../../variables"; - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalRequestController.getSecretApprovalRequests -); - -router.get( - "/count", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalRequestController.getSecretApprovalRequestCount -); - -router.get( - "/:id", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalRequestController.getSecretApprovalRequestDetails -); - -router.post( - "/:id/merge", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalRequestController.mergeSecretApprovalRequest -); - -router.post( - "/:id/review", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalRequestController.updateSecretApprovalReviewStatus -); - -router.post( - "/:id/status", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretApprovalRequestController.updateSecretApprovalRequestStatus -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/secretRotation.ts b/backend-mongo/src/ee/routes/v1/secretRotation.ts deleted file mode 100644 index a4da8a72f..000000000 --- a/backend-mongo/src/ee/routes/v1/secretRotation.ts +++ /dev/null @@ -1,41 +0,0 @@ -import express from "express"; - -import { AuthMode } from "../../../variables"; -import { requireAuth } from "../../../middleware"; -import { secretRotationController } from "../../controllers/v1"; - -const router = express.Router(); - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretRotationController.createSecretRotation -); - -router.post( - "/restart", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretRotationController.restartSecretRotations -); - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretRotationController.getSecretRotations -); - -router.delete( - "/:id", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretRotationController.deleteSecretRotations -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/secretRotationProvider.ts b/backend-mongo/src/ee/routes/v1/secretRotationProvider.ts deleted file mode 100644 index 16ab17184..000000000 --- a/backend-mongo/src/ee/routes/v1/secretRotationProvider.ts +++ /dev/null @@ -1,17 +0,0 @@ -import express from "express"; - -import { AuthMode } from "../../../variables"; -import { requireAuth } from "../../../middleware"; -import { secretRotationProviderController } from "../../controllers/v1"; - -const router = express.Router(); - -router.get( - "/:workspaceId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretRotationProviderController.getProviderTemplates -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/secretScanning.ts b/backend-mongo/src/ee/routes/v1/secretScanning.ts deleted file mode 100644 index 0afdf0545..000000000 --- a/backend-mongo/src/ee/routes/v1/secretScanning.ts +++ /dev/null @@ -1,53 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { - createInstallationSession, - getCurrentOrganizationInstallationStatus, - getRisksForOrganization, - linkInstallationToOrganization, - updateRisksStatus -} from "../../../controllers/v1/secretScanningController"; -import { AuthMode } from "../../../variables"; - -router.post( - "/create-installation-session/organization/:organizationId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - createInstallationSession -); - -router.post( - "/link-installation", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - linkInstallationToOrganization -); - -router.get( - "/installation-status/organization/:organizationId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - getCurrentOrganizationInstallationStatus -); - -router.get( - "/organization/:organizationId/risks", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - getRisksForOrganization -); - -router.post( - "/organization/:organizationId/risks/:riskId/status", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - updateRisksStatus -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/secretSnapshot.ts b/backend-mongo/src/ee/routes/v1/secretSnapshot.ts deleted file mode 100644 index f8c643e60..000000000 --- a/backend-mongo/src/ee/routes/v1/secretSnapshot.ts +++ /dev/null @@ -1,15 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { AuthMode } from "../../../variables"; -import { secretSnapshotController } from "../../controllers/v1"; - -router.get( - "/:secretSnapshotId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - secretSnapshotController.getSecretSnapshot -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/sso.ts b/backend-mongo/src/ee/routes/v1/sso.ts deleted file mode 100644 index 24f0d36a1..000000000 --- a/backend-mongo/src/ee/routes/v1/sso.ts +++ /dev/null @@ -1,60 +0,0 @@ -import express from "express"; -const router = express.Router(); -import passport from "passport"; -import { requireAuth } from "../../../middleware"; -import { ssoController } from "../../controllers/v1"; -import { authLimiter } from "../../../helpers/rateLimiter"; -import { AuthMode } from "../../../variables"; - -router.get( - "/redirect/saml2/:ssoIdentifier", - authLimiter, - (req, res, next) => { - const options = { - failureRedirect: "/", - additionalParams: { - RelayState: JSON.stringify({ - spInitiated: true, - callbackPort: req.query.callback_port ?? "" - }) - }, - }; - passport.authenticate("saml", options)(req, res, next); - } -); - -router.post( - "/saml2/:ssoIdentifier", - passport.authenticate("saml", { - failureRedirect: "/login/provider/error", - failureFlash: true, - session: false - }), - ssoController.redirectSSO -); - -router.get( - "/config", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - ssoController.getSSOConfig -); - -router.post( - "/config", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - ssoController.createSSOConfig -); - -router.patch( - "/config", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - ssoController.updateSSOConfig -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v1/users.ts b/backend-mongo/src/ee/routes/v1/users.ts deleted file mode 100644 index d5015401e..000000000 --- a/backend-mongo/src/ee/routes/v1/users.ts +++ /dev/null @@ -1,17 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { - requireAuth -} from "../../../middleware"; -import { AuthMode } from "../../../variables"; -import { usersController } from "../../controllers/v1"; - -router.get( - "/me/ip", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY], - }), - usersController.getMyIp -); - -export default router; \ No newline at end of file diff --git a/backend-mongo/src/ee/routes/v1/workspace.ts b/backend-mongo/src/ee/routes/v1/workspace.ts deleted file mode 100644 index ace4458cc..000000000 --- a/backend-mongo/src/ee/routes/v1/workspace.ts +++ /dev/null @@ -1,79 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { AuthMode } from "../../../variables"; -import { workspaceController } from "../../controllers/v1"; - -router.get( - "/:workspaceId/secret-snapshots", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.getWorkspaceSecretSnapshots -); - -router.get( - "/:workspaceId/secret-snapshots/count", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspaceSecretSnapshotsCount -); - -router.post( - "/:workspaceId/secret-snapshots/rollback", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.rollbackWorkspaceSecretSnapshot -); - -router.get( - "/:workspaceId/audit-logs", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.getWorkspaceAuditLogs -); - -router.get( - "/:workspaceId/audit-logs/filters/actors", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - workspaceController.getWorkspaceAuditLogActorFilterOpts -); - -router.get( - "/:workspaceId/trusted-ips", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspaceTrustedIps -); - -router.post( - "/:workspaceId/trusted-ips", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.addWorkspaceTrustedIp -); - -router.patch( - "/:workspaceId/trusted-ips/:trustedIpId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.updateWorkspaceTrustedIp -); - -router.delete( - "/:workspaceId/trusted-ips/:trustedIpId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.deleteWorkspaceTrustedIp -); - -export default router; diff --git a/backend-mongo/src/ee/routes/v3/apiKeyData.ts b/backend-mongo/src/ee/routes/v3/apiKeyData.ts deleted file mode 100644 index 6d069a719..000000000 --- a/backend-mongo/src/ee/routes/v3/apiKeyData.ts +++ /dev/null @@ -1,31 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../../middleware"; -import { AuthMode } from "../../../variables"; -import { apiKeyDataController } from "../../controllers/v3"; - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - apiKeyDataController.createAPIKeyData -); - -router.patch( - "/:apiKeyDataId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - apiKeyDataController.updateAPIKeyData -); - -router.delete( - "/:apiKeyDataId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - apiKeyDataController.deleteAPIKeyData -); - -export default router; \ No newline at end of file diff --git a/backend-mongo/src/ee/routes/v3/index.ts b/backend-mongo/src/ee/routes/v3/index.ts deleted file mode 100644 index c534640e3..000000000 --- a/backend-mongo/src/ee/routes/v3/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import apiKeyData from "./apiKeyData"; - -export { - apiKeyData -} \ No newline at end of file diff --git a/backend-mongo/src/ee/secretRotation/db.ts b/backend-mongo/src/ee/secretRotation/db.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/backend-mongo/src/ee/secretRotation/models.ts b/backend-mongo/src/ee/secretRotation/models.ts deleted file mode 100644 index 0ddde5d83..000000000 --- a/backend-mongo/src/ee/secretRotation/models.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Schema, model } from "mongoose"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8 -} from "../../variables"; -import { ISecretRotation } from "./types"; - -const secretRotationSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace" - }, - provider: { - type: String, - required: true - }, - customProvider: { - type: Schema.Types.ObjectId, - ref: "SecretRotationProvider" - }, - environment: { - type: String, - required: true - }, - secretPath: { - type: String, - required: true - }, - interval: { - type: Number, - required: true - }, - lastRotatedAt: { - type: String - }, - status: { - type: String, - enum: ["success", "failed"] - }, - statusMessage: { - type: String - }, - // encrypted data on input keys and secrets got - encryptedData: { - type: String, - select: false - }, - encryptedDataIV: { - type: String, - select: false - }, - encryptedDataTag: { - type: String, - select: false - }, - algorithm: { - // the encryption algorithm used - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true, - select: false, - default: ALGORITHM_AES_256_GCM - }, - keyEncoding: { - type: String, - enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64], - required: true, - select: false, - default: ENCODING_SCHEME_UTF8 - }, - outputs: [ - { - key: { - type: String, - required: true - }, - secret: { - type: Schema.Types.ObjectId, - ref: "Secret" - } - } - ] - }, - { - timestamps: true - } -); - -export const SecretRotation = model("SecretRotation", secretRotationSchema); diff --git a/backend-mongo/src/ee/secretRotation/queue/queue.ts b/backend-mongo/src/ee/secretRotation/queue/queue.ts deleted file mode 100644 index 0127bbd9c..000000000 --- a/backend-mongo/src/ee/secretRotation/queue/queue.ts +++ /dev/null @@ -1,288 +0,0 @@ -import Queue, { Job } from "bull"; -import { client, getEncryptionKey, getRootEncryptionKey } from "../../../config"; -import { BotService, EventService, TelemetryService } from "../../../services"; -import { SecretRotation } from "../models"; -import { rotationTemplates } from "../templates"; -import { - ISecretRotationData, - ISecretRotationEncData, - ISecretRotationProviderTemplate, - TProviderFunctionTypes -} from "../types"; -import { - decryptSymmetric128BitHexKeyUTF8, - encryptSymmetric128BitHexKeyUTF8 -} from "../../../utils/crypto"; -import { ISecret, Secret } from "../../../models"; -import { ENCODING_SCHEME_BASE64, ENCODING_SCHEME_UTF8, SECRET_SHARED } from "../../../variables"; -import { EESecretService } from "../../services"; -import { SecretVersion } from "../../models"; -import { eventPushSecrets } from "../../../events"; -import { logger } from "../../../utils/logging"; - -import { - secretRotationPreSetFn, - secretRotationRemoveFn, - secretRotationSetFn, - secretRotationTestFn -} from "./queue.utils"; - -const secretRotationQueue = new Queue("secret-rotation-service", process.env.REDIS_URL as string); - -secretRotationQueue.process(async (job: Job) => { - logger.info(`secretRotationQueue.process: [rotationDocument=${job.data.rotationDocId}]`); - const rotationStratDocId = job.data.rotationDocId; - const secretRotation = await SecretRotation.findById(rotationStratDocId) - .select("+encryptedData +encryptedDataTag +encryptedDataIV +keyEncoding") - .populate<{ - outputs: [ - { - key: string; - secret: ISecret; - } - ]; - }>("outputs.secret"); - - const infisicalRotationProvider = rotationTemplates.find( - ({ name }) => name === secretRotation?.provider - ); - - try { - if (!infisicalRotationProvider || !secretRotation) - throw new Error("Failed to find rotation strategy"); - - if (secretRotation.outputs.some(({ secret }) => !secret)) - throw new Error("Secrets not found in dashboard"); - - const workspaceId = secretRotation.workspace; - - // deep copy - const provider = JSON.parse( - JSON.stringify(infisicalRotationProvider) - ) as ISecretRotationProviderTemplate; - - // decrypt user provided inputs for secret rotation - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - let decryptedData = ""; - if (rootEncryptionKey && secretRotation.keyEncoding === ENCODING_SCHEME_BASE64) { - // case: encoding scheme is base64 - decryptedData = client.decryptSymmetric( - secretRotation.encryptedData, - rootEncryptionKey, - secretRotation.encryptedDataIV, - secretRotation.encryptedDataTag - ); - } else if (encryptionKey && secretRotation.keyEncoding === ENCODING_SCHEME_UTF8) { - // case: encoding scheme is utf8 - decryptedData = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secretRotation.encryptedData, - iv: secretRotation.encryptedDataIV, - tag: secretRotation.encryptedDataTag, - key: encryptionKey - }); - } - - const variables = JSON.parse(decryptedData) as ISecretRotationEncData; - - // rotation set cycle - const newCredential: ISecretRotationData = { - inputs: variables.inputs, - outputs: {}, - internal: {} - }; - // special glue code for database - if (provider.template.functions.set.type === TProviderFunctionTypes.DB) { - const lastCred = variables.creds.at(-1); - if (lastCred && variables.creds.length === 1) { - newCredential.internal.username = - lastCred.internal.username === variables.inputs.username1 - ? variables.inputs.username2 - : variables.inputs.username1; - } else { - newCredential.internal.username = lastCred - ? lastCred.internal.username - : variables.inputs.username1; - } - } - if (provider.template.functions.set?.pre) { - secretRotationPreSetFn(provider.template.functions.set.pre, newCredential); - } - await secretRotationSetFn(provider.template.functions.set, newCredential); - await secretRotationTestFn(provider.template.functions.test, newCredential); - - if (variables.creds.length === 2) { - const deleteCycleCred = variables.creds.pop(); - if (deleteCycleCred && provider.template.functions.remove) { - const deleteCycleVar = { inputs: variables.inputs, ...deleteCycleCred }; - await secretRotationRemoveFn(provider.template.functions.remove, deleteCycleVar); - } - } - variables.creds.unshift({ outputs: newCredential.outputs, internal: newCredential.internal }); - const { ciphertext, iv, tag } = client.encryptSymmetric( - JSON.stringify(variables), - rootEncryptionKey - ); - - // save the rotation state - await SecretRotation.findByIdAndUpdate(rotationStratDocId, { - encryptedData: ciphertext, - encryptedDataIV: iv, - encryptedDataTag: tag, - status: "success", - statusMessage: "Rotated successfully", - lastRotatedAt: new Date().toUTCString() - }); - - const key = await BotService.getWorkspaceKeyWithBot({ - workspaceId: secretRotation.workspace - }); - - const encryptedSecrets = secretRotation.outputs.map(({ key: outputKey, secret }) => ({ - secret, - value: encryptSymmetric128BitHexKeyUTF8({ - plaintext: - typeof newCredential.outputs[outputKey] === "object" - ? JSON.stringify(newCredential.outputs[outputKey]) - : String(newCredential.outputs[outputKey]), - key - }) - })); - - // now save the secret do a bulk update - // can't use the updateSecret function due to various parameter required issue - // REFACTOR(akhilmhdh): secret module should be lot more flexible. Ability to update bulk or individually by blindIndex, by id etc - await Secret.bulkWrite( - encryptedSecrets.map(({ secret, value }) => ({ - updateOne: { - filter: { - workspace: workspaceId, - environment: secretRotation.environment, - _id: secret._id, - type: SECRET_SHARED - }, - update: { - $inc: { - version: 1 - }, - secretValueCiphertext: value.ciphertext, - secretValueIV: value.iv, - secretValueTag: value.tag - } - } - })) - ); - - await EESecretService.addSecretVersions({ - secretVersions: encryptedSecrets.map(({ secret, value }) => { - const { - _id, - version, - workspace, - type, - folder, - secretBlindIndex, - secretKeyIV, - secretKeyTag, - secretKeyCiphertext, - skipMultilineEncoding, - environment, - algorithm, - keyEncoding - } = secret; - - return new SecretVersion({ - secret: _id, - version: version + 1, - workspace: workspace, - type, - folder, - environment, - isDeleted: false, - secretBlindIndex: secretBlindIndex, - secretKeyCiphertext: secretKeyCiphertext, - secretKeyIV: secretKeyIV, - secretKeyTag: secretKeyTag, - secretValueCiphertext: value.ciphertext, - secretValueIV: value.iv, - secretValueTag: value.tag, - algorithm, - keyEncoding, - skipMultilineEncoding - }); - }) - }); - - // akhilmhdh: @tony need to do something about this as its depend on authData which is not possibile in here - // await EEAuditLogService.createAuditLog( - // {actor:ActorType.Machine}, - // { - // type: EventType.UPDATE_SECRETS, - // metadata: { - // environment, - // secretPath, - // secrets: secretsToBeUpdated.map(({ _id, version, secretBlindIndex }) => ({ - // secretId: _id.toString(), - // secretKey: secretBlindIndexToKey[secretBlindIndex || ""], - // secretVersion: version + 1 - // })) - // } - // }, - // { - // workspaceId - // } - // ); - - const folderId = encryptedSecrets?.[0]?.secret?.folder; - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId, - environment: secretRotation.environment, - folderId - }); - - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: secretRotation.workspace, - environment: secretRotation.environment, - secretPath: secretRotation.secretPath - }) - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - if (postHogClient) { - postHogClient.capture({ - event: "secrets rotated", - properties: { - numberOfSecrets: encryptedSecrets.length, - environment: secretRotation.environment, - workspaceId, - folderId - } - }); - } - } catch (err) { - logger.error(err); - await SecretRotation.findByIdAndUpdate(rotationStratDocId, { - status: "failed", - statusMessage: (err as Error).message, - lastRotatedAt: new Date().toUTCString() - }); - } - - return Promise.resolve(); -}); - -const daysToMillisecond = (days: number) => days * 24 * 60 * 60 * 1000; -export const startSecretRotationQueue = async (rotationDocId: string, interval: number) => { - // when migration to bull mq just use the option immedite to trigger repeatable immediately - secretRotationQueue.add({ rotationDocId }, { jobId: rotationDocId, removeOnComplete: true }); - return secretRotationQueue.add( - { rotationDocId }, - { repeat: { every: daysToMillisecond(interval) }, jobId: rotationDocId } - ); -}; - -export const removeSecretRotationQueue = async (rotationDocId: string, interval: number) => { - return secretRotationQueue.removeRepeatable({ every: interval * 1000, jobId: rotationDocId }); -}; diff --git a/backend-mongo/src/ee/secretRotation/queue/queue.utils.ts b/backend-mongo/src/ee/secretRotation/queue/queue.utils.ts deleted file mode 100644 index c1ddbefc1..000000000 --- a/backend-mongo/src/ee/secretRotation/queue/queue.utils.ts +++ /dev/null @@ -1,179 +0,0 @@ -import axios from "axios"; -import jmespath from "jmespath"; -import { customAlphabet } from "nanoid"; -import { Client as PgClient } from "pg"; -import mysql from "mysql2"; -import { - ISecretRotationData, - TAssignOp, - TDbProviderClients, - TDbProviderFunction, - TDirectAssignOp, - THttpProviderFunction, - TProviderFunction, - TProviderFunctionTypes -} from "../types"; -const REGEX = /\${([^}]+)}/g; -const SLUG_ALPHABETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -const nanoId = customAlphabet(SLUG_ALPHABETS, 10); - -export const interpolate = (data: any, getValue: (key: string) => unknown) => { - if (!data) return; - - if (typeof data === "number") return data; - - if (typeof data === "string") { - return data.replace(REGEX, (_a, b) => getValue(b) as string); - } - - if (typeof data === "object" && Array.isArray(data)) { - data.forEach((el, index) => { - data[index] = interpolate(el, getValue); - }); - } - - if (typeof data === "object") { - if ((data as { ref: string })?.ref) return getValue((data as { ref: string }).ref); - const temp = data as Record; // for converting ts object to record type - Object.keys(temp).forEach((key) => { - temp[key as keyof typeof temp] = interpolate(data[key as keyof typeof temp], getValue); - }); - } - return data; -}; - -const getInterpolationValue = (variables: ISecretRotationData) => (key: string) => { - if (key.includes("|")) { - const [keyword, ...arg] = key.split("|").map((el) => el.trim()); - switch (keyword) { - case "random": { - return nanoId(parseInt(arg[0], 10)); - } - default: { - throw Error(`Interpolation key not found - ${key}`); - } - } - } - const [type, keyName] = key.split(".").map((el) => el.trim()); - return variables[type as keyof ISecretRotationData][keyName]; -}; - -export const secretRotationHttpFn = async ( - func: THttpProviderFunction, - variables: ISecretRotationData -) => { - // string interpolation - const headers = interpolate(func.header, getInterpolationValue(variables)); - const url = interpolate(func.url, getInterpolationValue(variables)); - const body = interpolate(func.body, getInterpolationValue(variables)); - // axios will automatically throw error if req status is not between 2xx range - return axios({ method: func.method, url, headers, data: body }); -}; - -export const secretRotationDbFn = async ( - func: TDbProviderFunction, - variables: ISecretRotationData -) => { - const { type, client, pre, ...dbConnection } = func; - const { username, password, host, database, port, query, ca } = interpolate( - dbConnection, - getInterpolationValue(variables) - ); - const ssl = ca ? { rejectUnauthorized: false, ca } : undefined; - if (host === "localhost" || host === "127.0.0.1") throw new Error("Invalid db host"); - if (client === TDbProviderClients.Pg) { - const pgClient = new PgClient({ user: username, password, host, database, port, ssl }); - await pgClient.connect(); - const res = await pgClient.query(query); - await pgClient.end(); - return res.rows[0]; - } else if (client === TDbProviderClients.Sql) { - const sqlClient = mysql.createPool({ - user: username, - password, - host, - database, - port, - connectionLimit: 1, - ssl - }); - const res = await new Promise((resolve, reject) => { - sqlClient.query(query, (err, data) => { - if (err) return reject(err); - resolve(data); - }); - }); - await new Promise((resolve, reject) => { - sqlClient.end(function (err) { - if (err) return reject(err); - return resolve({}); - }); - }); - return (res as any)?.[0]; - } -}; - -export const secretRotationPreSetFn = ( - op: Record, - variables: ISecretRotationData -) => { - const getValFn = getInterpolationValue(variables); - Object.entries(op || {}).forEach(([key, assignFn]) => { - const [type, keyName] = key.split(".") as [keyof ISecretRotationData, string]; - variables[type][keyName] = interpolate(assignFn.value, getValFn); - }); -}; - -export const secretRotationSetFn = async ( - func: TProviderFunction, - variables: ISecretRotationData -) => { - const getValFn = getInterpolationValue(variables); - // http setter - if (func.type === TProviderFunctionTypes.HTTP) { - const res = await secretRotationHttpFn(func, variables); - Object.entries(func.setter || {}).forEach(([key, assignFn]) => { - const [type, keyName] = key.split(".") as [keyof ISecretRotationData, string]; - if (assignFn.assign === TAssignOp.JmesPath) { - variables[type][keyName] = jmespath.search(res.data, assignFn.path); - } else if (assignFn.value) { - variables[type][keyName] = interpolate(assignFn.value, getValFn); - } - }); - // db setter - } else if (func.type === TProviderFunctionTypes.DB) { - const data = await secretRotationDbFn(func, variables); - Object.entries(func.setter || {}).forEach(([key, assignFn]) => { - const [type, keyName] = key.split(".") as [keyof ISecretRotationData, string]; - if (assignFn.assign === TAssignOp.JmesPath) { - if (typeof data === "object") { - variables[type][keyName] = jmespath.search(data, assignFn.path); - } - } else if (assignFn.value) { - variables[type][keyName] = interpolate(assignFn.value, getValFn); - } - }); - } -}; - -export const secretRotationTestFn = async ( - func: TProviderFunction, - variables: ISecretRotationData -) => { - if (func.type === TProviderFunctionTypes.HTTP) { - await secretRotationHttpFn(func, variables); - } else if (func.type === TProviderFunctionTypes.DB) { - await secretRotationDbFn(func, variables); - } -}; - -export const secretRotationRemoveFn = async ( - func: TProviderFunction, - variables: ISecretRotationData -) => { - if (!func) return; - if (func.type === TProviderFunctionTypes.HTTP) { - // string interpolation - return await secretRotationHttpFn(func, variables); - } -}; diff --git a/backend-mongo/src/ee/secretRotation/service.ts b/backend-mongo/src/ee/secretRotation/service.ts deleted file mode 100644 index 9e00f20e1..000000000 --- a/backend-mongo/src/ee/secretRotation/service.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { ISecretRotationEncData, TCreateSecretRotation, TGetProviderTemplates } from "./types"; -import { rotationTemplates } from "./templates"; -import { SecretRotation } from "./models"; -import { client, getEncryptionKey, getRootEncryptionKey } from "../../config"; -import { BadRequestError } from "../../utils/errors"; -import Ajv from "ajv"; -import { removeSecretRotationQueue, startSecretRotationQueue } from "./queue/queue"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8 -} from "../../variables"; -import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; - -const ajv = new Ajv({ strict: false }); - -export const getProviderTemplate = async ({ workspaceId }: TGetProviderTemplates) => { - return { - custom: [], - providers: rotationTemplates - }; -}; - -export const createSecretRotation = async ({ - workspaceId, - secretPath, - environment, - provider, - interval, - inputs, - outputs -}: TCreateSecretRotation) => { - const rotationTemplate = rotationTemplates.find(({ name }) => name === provider); - if (!rotationTemplate) throw BadRequestError({ message: "Provider not found" }); - - const formattedInputs: Record = {}; - Object.entries(inputs).forEach(([key, value]) => { - const type = rotationTemplate.template.inputs.properties[key].type; - if (type === "string") { - formattedInputs[key] = value; - return; - } - if (type === "integer") { - formattedInputs[key] = parseInt(value as string, 10); - return; - } - formattedInputs[key] = JSON.parse(value as string); - }); - // ensure input one follows the correct schema - const valid = ajv.validate(rotationTemplate.template.inputs, formattedInputs); - if (!valid) { - throw BadRequestError({ message: ajv.errors?.[0].message }); - } - - const encData: Partial = { - inputs: formattedInputs, - creds: [] - }; - - const secretRotation = new SecretRotation({ - workspace: workspaceId, - provider, - environment, - secretPath, - interval, - outputs: Object.entries(outputs).map(([key, secret]) => ({ key, secret })) - }); - - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - if (rootEncryptionKey) { - const { ciphertext, iv, tag } = client.encryptSymmetric( - JSON.stringify(encData), - rootEncryptionKey - ); - secretRotation.encryptedDataIV = iv; - secretRotation.encryptedDataTag = tag; - secretRotation.encryptedData = ciphertext; - secretRotation.algorithm = ALGORITHM_AES_256_GCM; - secretRotation.keyEncoding = ENCODING_SCHEME_BASE64; - } else if (encryptionKey) { - const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: JSON.stringify(encData), - key: encryptionKey - }); - secretRotation.encryptedDataIV = iv; - secretRotation.encryptedDataTag = tag; - secretRotation.encryptedData = ciphertext; - secretRotation.algorithm = ALGORITHM_AES_256_GCM; - secretRotation.keyEncoding = ENCODING_SCHEME_UTF8; - } - - await secretRotation.save(); - await startSecretRotationQueue(secretRotation._id.toString(), interval); - - return secretRotation; -}; - -export const deleteSecretRotation = async ({ id }: { id: string }) => { - const doc = await SecretRotation.findByIdAndRemove(id); - if (!doc) throw BadRequestError({ message: "Rotation not found" }); - - await removeSecretRotationQueue(doc._id.toString(), doc.interval); - return doc; -}; - -export const restartSecretRotation = async ({ id }: { id: string }) => { - const secretRotation = await SecretRotation.findById(id); - if (!secretRotation) throw BadRequestError({ message: "Rotation not found" }); - - await removeSecretRotationQueue(secretRotation._id.toString(), secretRotation.interval); - await startSecretRotationQueue(secretRotation._id.toString(), secretRotation.interval); - - return secretRotation; -}; - -export const getSecretRotationById = async ({ id }: { id: string }) => { - const doc = await SecretRotation.findById(id); - if (!doc) throw BadRequestError({ message: "Rotation not found" }); - return doc; -}; - -export const getSecretRotationOfWorkspace = async (workspaceId: string) => { - const secretRotations = await SecretRotation.find({ - workspace: workspaceId - }).populate("outputs.secret"); - - return secretRotations; -}; diff --git a/backend-mongo/src/ee/secretRotation/templates/index.ts b/backend-mongo/src/ee/secretRotation/templates/index.ts deleted file mode 100644 index 063d5149f..000000000 --- a/backend-mongo/src/ee/secretRotation/templates/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ISecretRotationProviderTemplate } from "../types"; -import { MYSQL_TEMPLATE } from "./mysql"; -import { POSTGRES_TEMPLATE } from "./postgres"; -import { SENDGRID_TEMPLATE } from "./sendgrid"; - -export const rotationTemplates: ISecretRotationProviderTemplate[] = [ - { - name: "sendgrid", - title: "Twilio Sendgrid", - image: "sendgrid.png", - description: "Rotate Twilio Sendgrid API keys", - template: SENDGRID_TEMPLATE - }, - { - name: "postgres", - title: "PostgreSQL", - image: "postgres.png", - description: "Rotate PostgreSQL/CockroachDB user credentials", - template: POSTGRES_TEMPLATE - }, - { - name: "mysql", - title: "MySQL", - image: "mysql.png", - description: "Rotate MySQL@7/MariaDB user credentials", - template: MYSQL_TEMPLATE - } -]; diff --git a/backend-mongo/src/ee/secretRotation/templates/mysql.ts b/backend-mongo/src/ee/secretRotation/templates/mysql.ts deleted file mode 100644 index ce44c753f..000000000 --- a/backend-mongo/src/ee/secretRotation/templates/mysql.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { TAssignOp, TDbProviderClients, TProviderFunctionTypes } from "../types"; - -export const MYSQL_TEMPLATE = { - inputs: { - type: "object" as const, - properties: { - admin_username: { type: "string" as const }, - admin_password: { type: "string" as const }, - host: { type: "string" as const }, - database: { type: "string" as const }, - port: { type: "integer" as const, default: "3306" }, - username1: { - type: "string", - default: "infisical-sql-user1", - desc: "This user must be created in your database" - }, - username2: { - type: "string", - default: "infisical-sql-user2", - desc: "This user must be created in your database" - }, - ca: { type: "string", desc: "SSL certificate for db auth(string)" } - }, - required: [ - "admin_username", - "admin_password", - "host", - "database", - "username1", - "username2", - "port" - ], - additionalProperties: false - }, - outputs: { - db_username: { type: "string" }, - db_password: { type: "string" } - }, - internal: { - rotated_password: { type: "string" }, - username: { type: "string" } - }, - functions: { - set: { - type: TProviderFunctionTypes.DB as const, - client: TDbProviderClients.Sql, - username: "${inputs.admin_username}", - password: "${inputs.admin_password}", - host: "${inputs.host}", - database: "${inputs.database}", - port: "${inputs.port}", - ca: "${inputs.ca}", - query: "ALTER USER ${internal.username} IDENTIFIED BY '${internal.rotated_password}'", - setter: { - "outputs.db_username": { - assign: TAssignOp.Direct as const, - value: "${internal.username}" - }, - "outputs.db_password": { - assign: TAssignOp.Direct as const, - value: "${internal.rotated_password}" - } - }, - pre: { - "internal.rotated_password": { - assign: TAssignOp.Direct as const, - value: "${random | 32}" - } - } - }, - test: { - type: TProviderFunctionTypes.DB as const, - client: TDbProviderClients.Sql, - username: "${internal.username}", - password: "${internal.rotated_password}", - host: "${inputs.host}", - database: "${inputs.database}", - port: "${inputs.port}", - ca: "${inputs.ca}", - query: "SELECT NOW()" - } - } -}; diff --git a/backend-mongo/src/ee/secretRotation/templates/postgres.ts b/backend-mongo/src/ee/secretRotation/templates/postgres.ts deleted file mode 100644 index 3b3153be1..000000000 --- a/backend-mongo/src/ee/secretRotation/templates/postgres.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { TAssignOp, TDbProviderClients, TProviderFunctionTypes } from "../types"; - -export const POSTGRES_TEMPLATE = { - inputs: { - type: "object" as const, - properties: { - admin_username: { type: "string" as const }, - admin_password: { type: "string" as const }, - host: { type: "string" as const }, - database: { type: "string" as const }, - port: { type: "integer" as const, default: "5432" }, - username1: { - type: "string", - default: "infisical-pg-user1", - desc: "This user must be created in your database" - }, - username2: { - type: "string", - default: "infisical-pg-user2", - desc: "This user must be created in your database" - }, - ca: { type: "string", desc: "SSL certificate for db auth(string)" } - }, - required: [ - "admin_username", - "admin_password", - "host", - "database", - "username1", - "username2", - "port" - ], - additionalProperties: false - }, - outputs: { - db_username: { type: "string" }, - db_password: { type: "string" } - }, - internal: { - rotated_password: { type: "string" }, - username: { type: "string" } - }, - functions: { - set: { - type: TProviderFunctionTypes.DB as const, - client: TDbProviderClients.Pg, - username: "${inputs.admin_username}", - password: "${inputs.admin_password}", - host: "${inputs.host}", - database: "${inputs.database}", - port: "${inputs.port}", - ca: "${inputs.ca}", - query: "ALTER USER ${internal.username} WITH PASSWORD '${internal.rotated_password}'", - setter: { - "outputs.db_username": { - assign: TAssignOp.Direct as const, - value: "${internal.username}" - }, - "outputs.db_password": { - assign: TAssignOp.Direct as const, - value: "${internal.rotated_password}" - } - }, - pre: { - "internal.rotated_password": { - assign: TAssignOp.Direct as const, - value: "${random | 32}" - } - } - }, - test: { - type: TProviderFunctionTypes.DB as const, - client: TDbProviderClients.Pg, - username: "${internal.username}", - password: "${internal.rotated_password}", - host: "${inputs.host}", - database: "${inputs.database}", - port: "${inputs.port}", - ca: "${inputs.ca}", - query: "SELECT NOW()" - } - } -}; diff --git a/backend-mongo/src/ee/secretRotation/templates/sendgrid.ts b/backend-mongo/src/ee/secretRotation/templates/sendgrid.ts deleted file mode 100644 index b600f3e0c..000000000 --- a/backend-mongo/src/ee/secretRotation/templates/sendgrid.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { TAssignOp, TProviderFunctionTypes } from "../types"; - -export const SENDGRID_TEMPLATE = { - inputs: { - type: "object" as const, - properties: { - admin_api_key: { type: "string" as const, desc: "Sendgrid admin api key to create new keys" }, - api_key_scopes: { - type: "array", - items: { type: "string" as const }, - desc: "Scopes for created tokens by rotation(Array)" - } - }, - required: ["admin_api_key", "api_key_scopes"], - additionalProperties: false - }, - outputs: { - api_key: { type: "string" } - }, - internal: { - api_key_id: { type: "string" } - }, - functions: { - set: { - type: TProviderFunctionTypes.HTTP as const, - url: "https://api.sendgrid.com/v3/api_keys", - method: "POST", - header: { - Authorization: "Bearer ${inputs.admin_api_key}" - }, - body: { - name: "infisical-${random | 16}", - scopes: { ref: "inputs.api_key_scopes" } - }, - setter: { - "outputs.api_key": { - assign: TAssignOp.JmesPath as const, - path: "api_key" - }, - "internal.api_key_id": { - assign: TAssignOp.JmesPath as const, - path: "api_key_id" - } - } - }, - remove: { - type: TProviderFunctionTypes.HTTP as const, - url: "https://api.sendgrid.com/v3/api_keys/${internal.api_key_id}", - header: { - Authorization: "Bearer ${inputs.admin_api_key}" - }, - method: "DELETE" - }, - test: { - type: TProviderFunctionTypes.HTTP as const, - url: "https://api.sendgrid.com/v3/api_keys/${internal.api_key_id}", - header: { - Authorization: "Bearer ${inputs.admin_api_key}" - }, - method: "GET" - } - } -}; diff --git a/backend-mongo/src/ee/secretRotation/types.ts b/backend-mongo/src/ee/secretRotation/types.ts deleted file mode 100644 index 36ad36798..000000000 --- a/backend-mongo/src/ee/secretRotation/types.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { Document, Types } from "mongoose"; - -export interface ISecretRotation extends Document { - _id: Types.ObjectId; - name: string; - interval: number; - provider: string; - customProvider: Types.ObjectId; - workspace: Types.ObjectId; - environment: string; - secretPath: string; - outputs: Array<{ - key: string; - secret: Types.ObjectId; - }>; - status?: "success" | "failed"; - lastRotatedAt?: string; - statusMessage?: string; - encryptedData: string; - encryptedDataIV: string; - encryptedDataTag: string; - algorithm: string; - keyEncoding: string; -} - -export type ISecretRotationEncData = { - inputs: Record; - creds: Array<{ - outputs: Record; - internal: Record; - }>; -}; - -export type ISecretRotationData = { - inputs: Record; - outputs: Record; - internal: Record; -}; - -export type ISecretRotationProviderTemplate = { - name: string; - title: string; - image?: string; - description?: string; - template: TProviderTemplate; -}; - -export enum TProviderFunctionTypes { - HTTP = "http", - DB = "database" -} - -export enum TDbProviderClients { - // postgres, cockroack db, amazon red shift - Pg = "pg", - // mysql and maria db - Sql = "sql" -} - -export enum TAssignOp { - Direct = "direct", - JmesPath = "jmesopath" -} - -export type TJmesPathAssignOp = { - assign: TAssignOp.JmesPath; - path: string; -}; - -export type TDirectAssignOp = { - assign: TAssignOp.Direct; - value: string; -}; - -export type TAssignFunction = TJmesPathAssignOp | TDirectAssignOp; - -export type THttpProviderFunction = { - type: TProviderFunctionTypes.HTTP; - url: string; - method: string; - header?: Record; - query?: Record; - body?: Record; - setter?: Record; - pre?: Record; -}; - -export type TDbProviderFunction = { - type: TProviderFunctionTypes.DB; - client: TDbProviderClients; - username: string; - password: string; - host: string; - database: string; - port: string; - query: string; - setter?: Record; - pre?: Record; -}; - -export type TProviderFunction = THttpProviderFunction | TDbProviderFunction; - -export type TProviderTemplate = { - inputs: { - type: "object"; - properties: Record; - required?: string[]; - }; - outputs: Record; - functions: { - set: TProviderFunction; - remove?: TProviderFunction; - test: TProviderFunction; - }; -}; - -// function type args -export type TGetProviderTemplates = { - workspaceId: string; -}; - -export type TCreateSecretRotation = { - provider: string; - customProvider?: string; - workspaceId: string; - secretPath: string; - environment: string; - interval: number; - inputs: Record; - outputs: Record; -}; diff --git a/backend-mongo/src/ee/services/EEAuditLogService.ts b/backend-mongo/src/ee/services/EEAuditLogService.ts deleted file mode 100644 index 9d220feee..000000000 --- a/backend-mongo/src/ee/services/EEAuditLogService.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Types } from "mongoose"; -import { AuditLog, Event } from "../models"; -import { AuthData } from "../../interfaces/middleware"; -import EELicenseService from "./EELicenseService"; -import { Workspace } from "../../models"; - -interface EventScope { - workspaceId?: Types.ObjectId; - organizationId?: Types.ObjectId; -} - -type ValidEventScope = - | Required> - | Required> - | Required - | Record; - -export default class EEAuditLogService { - static async createAuditLog(authData: AuthData, event: Event, eventScope: ValidEventScope = {}, shouldSave = true) { - - const MS_IN_DAY = 24 * 60 * 60 * 1000; - - let organizationId; - if ("organizationId" in eventScope) { - organizationId = eventScope.organizationId; - } - - let workspaceId; - if ("workspaceId" in eventScope) { - workspaceId = eventScope.workspaceId; - - if (!organizationId) { - organizationId = (await Workspace.findById(workspaceId).select("organization").lean())?.organization; - } - } - - let expiresAt; - if (organizationId) { - const ttl = (await EELicenseService.getPlan(organizationId)).auditLogsRetentionDays * MS_IN_DAY; - expiresAt = new Date(Date.now() + ttl); - } - - const auditLog = await new AuditLog({ - actor: authData.actor, - organization: organizationId, - workspace: workspaceId, - ipAddress: authData.ipAddress, - event, - userAgent: authData.userAgent, - userAgentType: authData.userAgentType, - expiresAt - }); - - if (shouldSave) { - await auditLog.save(); - } - - return auditLog; - } -} \ No newline at end of file diff --git a/backend-mongo/src/ee/services/EELicenseService.ts b/backend-mongo/src/ee/services/EELicenseService.ts deleted file mode 100644 index 6baea04dc..000000000 --- a/backend-mongo/src/ee/services/EELicenseService.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { Types } from "mongoose"; -import * as Sentry from "@sentry/node"; -import NodeCache from "node-cache"; -import { - getLicenseKey, - getLicenseServerKey, - getLicenseServerUrl, -} from "../../config"; -import { - licenseKeyRequest, - licenseServerKeyRequest, - refreshLicenseKeyToken, - refreshLicenseServerKeyToken, -} from "../../config/request"; -import { Organization } from "../../models"; -import { OrganizationNotFoundError } from "../../utils/errors"; - -interface FeatureSet { - _id: string | null; - slug: "starter" | "team" | "pro" | "enterprise" | null; - tier: number; - workspaceLimit: number | null; - workspacesUsed: number; - memberLimit: number | null; - membersUsed: number; - environmentLimit: number | null; - environmentsUsed: number; - secretVersioning: boolean; - pitRecovery: boolean; - ipAllowlisting: boolean; - rbac: boolean; - customRateLimits: boolean; - customAlerts: boolean; - auditLogs: boolean; - auditLogsRetentionDays: number; - samlSSO: boolean; - status: "incomplete" | "incomplete_expired" | "trialing" | "active" | "past_due" | "canceled" | "unpaid" | null; - trial_end: number | null; - has_used_trial: boolean; - secretApproval: boolean; - secretRotation: boolean; -} - -/** - * Class to handle license/plan configurations: - * - Infisical Cloud: Fetch and cache customer plans in [localFeatureSet] - * - Self-hosted regular: Use default global feature set - * - Self-hosted enterprise: Fetch and update global feature set - */ -class EELicenseService { - - private readonly _isLicenseValid: boolean; // TODO: deprecate - - public instanceType: "self-hosted" | "enterprise-self-hosted" | "cloud" = "self-hosted"; - - public globalFeatureSet: FeatureSet = { - _id: null, - slug: null, - tier: -1, - workspaceLimit: null, - workspacesUsed: 0, - memberLimit: null, - membersUsed: 0, - environmentLimit: null, - environmentsUsed: 0, - secretVersioning: true, - pitRecovery: false, - ipAllowlisting: false, - rbac: false, - customRateLimits: false, - customAlerts: false, - auditLogs: false, - auditLogsRetentionDays: 0, - samlSSO: false, - status: null, - trial_end: null, - has_used_trial: true, - secretApproval: false, - secretRotation: true, - } - - public localFeatureSet: NodeCache; - - constructor() { - this._isLicenseValid = true; - this.localFeatureSet = new NodeCache({ - stdTTL: 60, - }); - } - - public async getPlan(organizationId: Types.ObjectId, workspaceId?: Types.ObjectId): Promise { - try { - if (this.instanceType === "cloud") { - const cachedPlan = this.localFeatureSet.get(`${organizationId.toString()}-${workspaceId?.toString() ?? ""}`); - if (cachedPlan) { - return cachedPlan; - } - - const organization = await Organization.findById(organizationId); - if (!organization) throw OrganizationNotFoundError(); - - let url = `${await getLicenseServerUrl()}/api/license-server/v1/customers/${organization.customerId}/cloud-plan`; - - if (workspaceId) { - url += `?workspaceId=${workspaceId}`; - } - - const { data: { currentPlan } } = await licenseServerKeyRequest.get(url); - - // cache fetched plan for organization - this.localFeatureSet.set(`${organizationId.toString()}-${workspaceId?.toString() ?? ""}`, currentPlan); - - return currentPlan; - } - } catch (err) { - return this.globalFeatureSet; - } - - return this.globalFeatureSet; - } - - public async refreshPlan(organizationId: Types.ObjectId, workspaceId?: Types.ObjectId) { - if (this.instanceType === "cloud") { - this.localFeatureSet.del(`${organizationId.toString()}-${workspaceId?.toString() ?? ""}`); - await this.getPlan(organizationId, workspaceId); - } - } - - public async delPlan(organizationId: Types.ObjectId) { - if (this.instanceType === "cloud") { - this.localFeatureSet.del(`${organizationId.toString()}-`); - } - } - - public async initGlobalFeatureSet() { - const licenseServerKey = await getLicenseServerKey(); - const licenseKey = await getLicenseKey(); - - try { - if (licenseServerKey) { - // license server key is present -> validate it - const token = await refreshLicenseServerKeyToken() - - if (token) { - this.instanceType = "cloud"; - } - - return; - } - - if (licenseKey) { - // license key is present -> validate it - const token = await refreshLicenseKeyToken(); - - if (token) { - const { data: { currentPlan } } = await licenseKeyRequest.get( - `${await getLicenseServerUrl()}/api/license/v1/plan` - ); - - this.globalFeatureSet = currentPlan; - this.instanceType = "enterprise-self-hosted"; - } - } - } catch (err) { - // case: self-hosted free - Sentry.setUser(null); - Sentry.captureException(err); - } - } - - public get isLicenseValid(): boolean { - return this._isLicenseValid; - } -} - -export default new EELicenseService(); diff --git a/backend-mongo/src/ee/services/EESecretService.ts b/backend-mongo/src/ee/services/EESecretService.ts deleted file mode 100644 index 1e065b6cd..000000000 --- a/backend-mongo/src/ee/services/EESecretService.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Types } from "mongoose"; -import { ISecretVersion } from "../models"; -import { - addSecretVersionsHelper, - markDeletedSecretVersionsHelper, - takeSecretSnapshotHelper, -} from "../helpers/secret"; -import EELicenseService from "./EELicenseService"; - -/** - * Class to handle Enterprise Edition secret actions - */ -export default class EESecretService { - /** - * Save a secret snapshot that is a copy of the current state of secrets in workspace with id - * [workspaceId] under a new snapshot with incremented version under the - * SecretSnapshot collection. - * Requires a valid license key [licenseKey] - * @param {Object} obj - * @param {String} obj.workspaceId - * @returns {SecretSnapshot} secretSnapshot - new secret snpashot - */ - static async takeSecretSnapshot({ - workspaceId, - environment, - folderId, - }: { - workspaceId: Types.ObjectId; - environment: string; - folderId?: string; - }) { - if (!EELicenseService.isLicenseValid) return; - return await takeSecretSnapshotHelper({ - workspaceId, - environment, - folderId, - }); - } - - /** - * Add secret versions [secretVersions] to the SecretVersion collection. - * @param {Object} obj - * @param {Object[]} obj.secretVersions - * @returns {SecretVersion[]} newSecretVersions - new secret versions - */ - static async addSecretVersions({ - secretVersions, - }: { - secretVersions: ISecretVersion[]; - }) { - if (!EELicenseService.isLicenseValid) return; - return await addSecretVersionsHelper({ - secretVersions, - }); - } - - /** - * Mark secret versions associated with secrets with ids [secretIds] - * as deleted. - * @param {Object} obj - * @param {ObjectId[]} obj.secretIds - secret ids - */ - static async markDeletedSecretVersions({ - secretIds, - }: { - secretIds: Types.ObjectId[]; - }) { - if (!EELicenseService.isLicenseValid) return; - await markDeletedSecretVersionsHelper({ - secretIds, - }); - } -} diff --git a/backend-mongo/src/ee/services/GithubSecretScanning/GithubSecretScanningService.ts b/backend-mongo/src/ee/services/GithubSecretScanning/GithubSecretScanningService.ts deleted file mode 100644 index e0a45215c..000000000 --- a/backend-mongo/src/ee/services/GithubSecretScanning/GithubSecretScanningService.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Probot } from "probot"; -import { - GitAppOrganizationInstallation, - GitRisks -} from "../../models"; -import { scanGithubPushEventForSecretLeaks } from "../../../queues/secret-scanning/githubScanPushEvent"; -export default async (app: Probot) => { - app.on("installation.deleted", async (context) => { - const { payload } = context; - const { installation, repositories } = payload; - if (repositories) { - for (const repository of repositories) { - await GitRisks.deleteMany({ repositoryId: repository.id }) - } - await GitAppOrganizationInstallation.deleteOne({ installationId: installation.id }) - } - }) - - app.on("installation", async (context) => { - const { payload } = context; - payload.repositories - const { installation, repositories } = payload; - // TODO: start full repo scans - }) - - app.on("push", async (context) => { - const { payload } = context; - const { commits, repository, installation, pusher } = payload; - - if (!commits || !repository || !installation || !pusher) { - return - } - - const installationLinkToOrgExists = await GitAppOrganizationInstallation.findOne({ installationId: installation?.id }).lean() - if (!installationLinkToOrgExists) { - return - } - - scanGithubPushEventForSecretLeaks({ - commits: commits, - pusher: { name: pusher.name, email: pusher.email }, - repository: { fullName: repository.full_name, id: repository.id }, - organizationId: installationLinkToOrgExists.organizationId, - installationId: installation.id - }) - }); -}; diff --git a/backend-mongo/src/ee/services/GithubSecretScanning/helper.ts b/backend-mongo/src/ee/services/GithubSecretScanning/helper.ts deleted file mode 100644 index 3dc46d835..000000000 --- a/backend-mongo/src/ee/services/GithubSecretScanning/helper.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { exec } from "child_process"; -import { mkdir, readFile, rm, writeFile } from "fs"; -import { tmpdir } from "os"; -import { join } from "path" -import { SecretMatch } from "./types"; - -export async function scanFullRepoContentAndGetFindings(octokit: any, installationId: number, repositoryFullName: string): Promise { - const tempFolder = await createTempFolder(); - const findingsPath = join(tempFolder, "findings.json"); - const repoPath = join(tempFolder, "repo.git") - try { - const { data: { token }} = await octokit.apps.createInstallationAccessToken({installation_id: installationId}) - await cloneRepo(token, repositoryFullName, repoPath) - await runInfisicalScanOnRepo(repoPath, findingsPath); - const findingsData = await readFindingsFile(findingsPath); - return JSON.parse(findingsData); - } finally { - await deleteTempFolder(tempFolder); - } -} - -export async function scanContentAndGetFindings(textContent: string): Promise { - const tempFolder = await createTempFolder(); - const filePath = join(tempFolder, "content.txt"); - const findingsPath = join(tempFolder, "findings.json"); - - try { - await writeTextToFile(filePath, textContent); - await runInfisicalScan(filePath, findingsPath); - const findingsData = await readFindingsFile(findingsPath); - return JSON.parse(findingsData); - } finally { - await deleteTempFolder(tempFolder); - } -} - -export function createTempFolder(): Promise { - return new Promise((resolve, reject) => { - const tempDir = tmpdir() - const tempFolderName = Math.random().toString(36).substring(2); - const tempFolderPath = join(tempDir, tempFolderName); - - mkdir(tempFolderPath, (err: any) => { - if (err) { - reject(err); - } else { - resolve(tempFolderPath); - } - }); - }); -} - - - -export function writeTextToFile(filePath: string, content: string): Promise { - return new Promise((resolve, reject) => { - writeFile(filePath, content, (err) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); -} - -export async function cloneRepo(installationAcccessToken: string, repositoryFullName: string, repoPath: string): Promise { - const cloneUrl = `https://x-access-token:${installationAcccessToken}@github.com/${repositoryFullName}.git`; - const command = `git clone ${cloneUrl} ${repoPath} --bare` - return new Promise((resolve, reject) => { - exec(command, (error) => { - if (error) { - reject(error); - } else { - resolve(); - } - }); - }) -} - -export function runInfisicalScanOnRepo(repoPath: string, outputPath: string): Promise { - return new Promise((resolve, reject) => { - const command = `cd ${repoPath} && infisical scan --exit-code=77 -r "${outputPath}"`; - exec(command, (error) => { - if (error && error.code != 77) { - reject(error); - } else { - resolve(); - } - }); - }); -} - -export function runInfisicalScan(inputPath: string, outputPath: string): Promise { - return new Promise((resolve, reject) => { - const command = `cat "${inputPath}" | infisical scan --exit-code=77 --pipe -r "${outputPath}"`; - exec(command, (error) => { - if (error && error.code != 77) { - reject(error); - } else { - resolve(); - } - }); - }); -} - -export function readFindingsFile(filePath: string): Promise { - return new Promise((resolve, reject) => { - readFile(filePath, "utf8", (err, data) => { - if (err) { - reject(err); - } else { - resolve(data); - } - }); - }); -} - -export function deleteTempFolder(folderPath: string): Promise { - return new Promise((resolve, reject) => { - rm(folderPath, { recursive: true }, (err) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); -} - -export function convertKeysToLowercase(obj: T): T { - const convertedObj = {} as T; - - for (const key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - const lowercaseKey = key.charAt(0).toLowerCase() + key.slice(1); - convertedObj[lowercaseKey as keyof T] = obj[key]; - } - } - - return convertedObj; -} \ No newline at end of file diff --git a/backend-mongo/src/ee/services/GithubSecretScanning/types.ts b/backend-mongo/src/ee/services/GithubSecretScanning/types.ts deleted file mode 100644 index 7bedbbfc3..000000000 --- a/backend-mongo/src/ee/services/GithubSecretScanning/types.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type SecretMatch = { - Description: string; - StartLine: number; - EndLine: number; - StartColumn: number; - EndColumn: number; - Match: string; - Secret: string; - File: string; - SymlinkFile: string; - Commit: string; - Entropy: number; - Author: string; - Email: string; - Date: string; - Message: string; - Tags: string[]; - RuleID: string; - Fingerprint: string; - FingerPrintWithoutCommitId: string -}; \ No newline at end of file diff --git a/backend-mongo/src/ee/services/ProjectRoleService.ts b/backend-mongo/src/ee/services/ProjectRoleService.ts deleted file mode 100644 index 18511948b..000000000 --- a/backend-mongo/src/ee/services/ProjectRoleService.ts +++ /dev/null @@ -1,415 +0,0 @@ -import { Types } from "mongoose"; -import { - AbilityBuilder, - ForcedSubject, - MongoAbility, - RawRuleOf, - buildMongoQueryMatcher, - createMongoAbility -} from "@casl/ability"; -import { UnauthorizedRequestError } from "../../utils/errors"; -import { FieldCondition, FieldInstruction, JsInterpreter } from "@ucast/mongo2js"; -import picomatch from "picomatch"; -import { AuthData } from "../../interfaces/middleware"; -import { ActorType, IRole, Role } from "../models"; -import { - IIdentity, - IdentityMembership, - Membership, - ServiceTokenData -} from "../../models"; -import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables"; -import { BadRequestError } from "../../utils/errors"; - -const $glob: FieldInstruction = { - type: "field", - validate(instruction, value) { - if (typeof value !== "string") { - throw new Error(`"${instruction.name}" expects value to be a string`); - } - } -}; - -const glob: JsInterpreter> = (node, object, context) => { - const secretPath = context.get(object, node.field); - const permissionSecretGlobPath = node.value; - return picomatch.isMatch(secretPath, permissionSecretGlobPath, { strictSlashes: false }); -}; - -export const conditionsMatcher = buildMongoQueryMatcher({ $glob }, { glob }); - -export enum ProjectPermissionActions { - Read = "read", - Create = "create", - Edit = "edit", - Delete = "delete" -} - -export enum ProjectPermissionSub { - Role = "role", - Member = "member", - Settings = "settings", - Integrations = "integrations", - Webhooks = "webhooks", - ServiceTokens = "service-tokens", - Environments = "environments", - Tags = "tags", - AuditLogs = "audit-logs", - IpAllowList = "ip-allowlist", - Workspace = "workspace", - Secrets = "secrets", - SecretRollback = "secret-rollback", - SecretApproval = "secret-approval", - SecretRotation = "secret-rotation", - Identity = "identity" -} - -type SubjectFields = { - environment: string; - secretPath: string; -}; - -export type ProjectPermissionSet = - | [ - ProjectPermissionActions, - ProjectPermissionSub.Secrets | (ForcedSubject & SubjectFields) - ] - | [ProjectPermissionActions, ProjectPermissionSub.Role] - | [ProjectPermissionActions, ProjectPermissionSub.Tags] - | [ProjectPermissionActions, ProjectPermissionSub.Member] - | [ProjectPermissionActions, ProjectPermissionSub.Integrations] - | [ProjectPermissionActions, ProjectPermissionSub.Webhooks] - | [ProjectPermissionActions, ProjectPermissionSub.AuditLogs] - | [ProjectPermissionActions, ProjectPermissionSub.Environments] - | [ProjectPermissionActions, ProjectPermissionSub.IpAllowList] - | [ProjectPermissionActions, ProjectPermissionSub.Settings] - | [ProjectPermissionActions, ProjectPermissionSub.ServiceTokens] - | [ProjectPermissionActions, ProjectPermissionSub.SecretApproval] - | [ProjectPermissionActions, ProjectPermissionSub.SecretRotation] - | [ProjectPermissionActions, ProjectPermissionSub.Identity] - | [ProjectPermissionActions.Delete, ProjectPermissionSub.Workspace] - | [ProjectPermissionActions.Edit, ProjectPermissionSub.Workspace] - | [ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback] - | [ProjectPermissionActions.Create, ProjectPermissionSub.SecretRollback]; - -const buildAdminPermission = () => { - const { can, build } = new AbilityBuilder>(createMongoAbility); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Secrets); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Secrets); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Secrets); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); - can(ProjectPermissionActions.Create, ProjectPermissionSub.SecretApproval); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.SecretApproval); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); - can(ProjectPermissionActions.Create, ProjectPermissionSub.SecretRotation); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretRotation); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.SecretRotation); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); - can(ProjectPermissionActions.Create, ProjectPermissionSub.SecretRollback); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Member); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Member); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Member); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Role); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Role); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Role); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Role); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Identity); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Identity); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens); - can(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.ServiceTokens); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Settings); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Settings); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Environments); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Environments); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Tags); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Tags); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Tags); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); - can(ProjectPermissionActions.Create, ProjectPermissionSub.AuditLogs); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.AuditLogs); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.AuditLogs); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList); - can(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.IpAllowList); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.IpAllowList); - - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Workspace); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Workspace); - - return build({ conditionsMatcher }); -}; - -export const adminProjectPermissions = buildAdminPermission(); - -const buildMemberPermission = () => { - const { can, build } = new AbilityBuilder>(createMongoAbility); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Secrets); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Secrets); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Secrets); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); - can(ProjectPermissionActions.Create, ProjectPermissionSub.SecretRollback); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Member); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Member); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Identity); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Identity); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens); - can(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.ServiceTokens); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Settings); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Settings); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Environments); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Environments); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); - can(ProjectPermissionActions.Create, ProjectPermissionSub.Tags); - can(ProjectPermissionActions.Edit, ProjectPermissionSub.Tags); - can(ProjectPermissionActions.Delete, ProjectPermissionSub.Tags); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Role); - can(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); - can(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList); - - return build({ conditionsMatcher }); -}; - -export const memberProjectPermissions = buildMemberPermission(); - -const buildViewerPermission = () => { - const { can, build } = new AbilityBuilder>(createMongoAbility); - - can(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); - can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Member); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Role); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Identity); - can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); - can(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); - can(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList); - - return build({ conditionsMatcher }); -}; - -export const viewerProjectPermission = buildViewerPermission(); - -const buildNoAccessProjectPermission = () => { - const { build } = new AbilityBuilder>(createMongoAbility); - return build({ conditionsMatcher }); -} - -export const noAccessProjectPermissions = buildNoAccessProjectPermission(); - -/** - * Return permissions for user/service pertaining to workspace with id [workspaceId] - * - * Note: should not rely on this function for ST V2 authorization logic - * b/c ST V2 does not support role-based access control - */ -export const getAuthDataProjectPermissions = async ({ - authData, - workspaceId -}: { - authData: AuthData; - workspaceId: Types.ObjectId; -}) => { - let role: "admin" | "member" | "viewer" | "no-access" | "custom"; - let customRole; - - switch (authData.actor.type) { - case ActorType.USER: { - const membership = await Membership.findOne({ - user: authData.authPayload._id, - workspace: workspaceId - }) - .populate<{ - customRole: IRole & { permissions: RawRuleOf>[] }; - }>("customRole") - .exec(); - - if (!membership || (membership.role === "custom" && !membership.customRole)) { - throw UnauthorizedRequestError(); - } - - role = membership.role; - customRole = membership.customRole; - break; - } - case ActorType.SERVICE: { - const serviceTokenData = await ServiceTokenData.findById(authData.authPayload._id); - if (!serviceTokenData || !serviceTokenData.workspace.equals(workspaceId)) throw UnauthorizedRequestError(); - role = "viewer"; - break; - } - case ActorType.IDENTITY: { - const identityMembership = await IdentityMembership.findOne({ - identity: authData.authPayload._id, - workspace: workspaceId - }) - .populate<{ - customRole: IRole & { permissions: RawRuleOf>[] }; - identity: IIdentity - }>("customRole identity") - .exec(); - - if (!identityMembership || (identityMembership.role === "custom" && !identityMembership.customRole)) { - throw UnauthorizedRequestError(); - } - - role = identityMembership.role; - customRole = identityMembership.customRole; - - break; - } - default: - throw UnauthorizedRequestError(); - } - - switch (role) { - case ADMIN: - return { permission: adminProjectPermissions }; - case MEMBER: - return { permission: memberProjectPermissions }; - case VIEWER: - return { permission: viewerProjectPermission }; - case NO_ACCESS: - return { permission: noAccessProjectPermissions }; - case CUSTOM: { - if (!customRole) throw UnauthorizedRequestError(); - return { - permission: createMongoAbility( - customRole.permissions, - { conditionsMatcher } - ) - }; - } - default: - throw UnauthorizedRequestError(); - } -} - -export const getWorkspaceRolePermissions = async (role: string, workspaceId: string) => { - const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role); - if (isCustomRole) { - const workspaceRole = await Role.findOne({ - slug: role, - isOrgRole: false, - workspace: new Types.ObjectId(workspaceId) - }); - - if (!workspaceRole) throw BadRequestError({ message: "Role not found" }); - - return createMongoAbility(workspaceRole.permissions as RawRuleOf>[], { - conditionsMatcher - }); - } - - switch (role) { - case ADMIN: - return adminProjectPermissions; - case MEMBER: - return memberProjectPermissions; - case VIEWER: - return viewerProjectPermission; - case NO_ACCESS: - return noAccessProjectPermissions; - default: - throw BadRequestError({ message: "Role not found" }); - } -} - -/** - * Extracts and formats permissions from a CASL Ability object or a raw permission set. - * @param ability - * @returns - */ - const extractPermissions = (ability: any) => { - return ability.A.map((permission: any) => `${permission.action}_${permission.subject}`); -} - -/** - * Compares two sets of permissions to determine if the first set is at least as privileged as the second set. - * The function checks if all permissions in the second set are contained within the first set and if the first set has equal or more permissions. - * -*/ -export const isAtLeastAsPrivilegedWorkspace = (permissions1: MongoAbility | ProjectPermissionSet, permissions2: MongoAbility | ProjectPermissionSet) => { - - const set1 = new Set(extractPermissions(permissions1)); - const set2 = new Set(extractPermissions(permissions2)); - - for (const perm of set2) { - if (!set1.has(perm)) { - return false; - } - } - - return set1.size >= set2.size; -} \ No newline at end of file diff --git a/backend-mongo/src/ee/services/RoleService.ts b/backend-mongo/src/ee/services/RoleService.ts deleted file mode 100644 index 1822c1d71..000000000 --- a/backend-mongo/src/ee/services/RoleService.ts +++ /dev/null @@ -1,301 +0,0 @@ -import { Types } from "mongoose"; -import { AbilityBuilder, MongoAbility, RawRuleOf, createMongoAbility } from "@casl/ability"; -import { - IIdentity, - IdentityMembershipOrg, - MembershipOrg -} from "../../models"; -import { ActorType, IRole, Role } from "../models"; -import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors"; -import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS} from "../../variables"; -import { conditionsMatcher } from "./ProjectRoleService"; -import { AuthData } from "../../interfaces/middleware"; - -export enum OrgPermissionActions { - Read = "read", - Create = "create", - Edit = "edit", - Delete = "delete" -} - -export enum OrgPermissionSubjects { - Workspace = "workspace", - Role = "role", - Member = "member", - Settings = "settings", - IncidentAccount = "incident-contact", - Sso = "sso", - Billing = "billing", - SecretScanning = "secret-scanning", - Identity = "identity" -} - -export type OrgPermissionSet = - | [OrgPermissionActions.Read, OrgPermissionSubjects.Workspace] - | [OrgPermissionActions.Create, OrgPermissionSubjects.Workspace] - | [OrgPermissionActions, OrgPermissionSubjects.Role] - | [OrgPermissionActions, OrgPermissionSubjects.Member] - | [OrgPermissionActions, OrgPermissionSubjects.Settings] - | [OrgPermissionActions, OrgPermissionSubjects.IncidentAccount] - | [OrgPermissionActions, OrgPermissionSubjects.Sso] - | [OrgPermissionActions, OrgPermissionSubjects.SecretScanning] - | [OrgPermissionActions, OrgPermissionSubjects.Billing] - | [OrgPermissionActions, OrgPermissionSubjects.Identity]; - -const buildAdminPermission = () => { - const { can, build } = new AbilityBuilder>(createMongoAbility); - // ws permissions - can(OrgPermissionActions.Read, OrgPermissionSubjects.Workspace); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Workspace); - // role permission - can(OrgPermissionActions.Read, OrgPermissionSubjects.Role); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Role); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.Role); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.Role); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.Member); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Member); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.Member); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.Member); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning); - can(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.SecretScanning); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.Settings); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Settings); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.Settings); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount); - can(OrgPermissionActions.Create, OrgPermissionSubjects.IncidentAccount); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.IncidentAccount); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.IncidentAccount); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.Sso); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Sso); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.Sso); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Billing); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.Billing); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity); - - return build({ conditionsMatcher }); -}; - -export const adminPermissions = buildAdminPermission(); - -const buildMemberPermission = () => { - const { can, build } = new AbilityBuilder>(createMongoAbility); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.Workspace); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Workspace); - can(OrgPermissionActions.Read, OrgPermissionSubjects.Member); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Member); - can(OrgPermissionActions.Read, OrgPermissionSubjects.Role); - can(OrgPermissionActions.Read, OrgPermissionSubjects.Settings); - can(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); - can(OrgPermissionActions.Read, OrgPermissionSubjects.Sso); - can(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning); - can(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.SecretScanning); - - can(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); - can(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); - can(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); - can(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity); - - return build({ conditionsMatcher }); -}; - -export const memberPermissions = buildMemberPermission(); - -const buildNoAccessPermission = () => { - const { build } = new AbilityBuilder>(createMongoAbility); - return build({ conditionsMatcher }); -} - -export const noAccessPermissions = buildNoAccessPermission(); - -export const getUserOrgPermissions = async (userId: string, orgId: string) => { - // TODO(akhilmhdh): speed this up by pulling from cache later - - const membership = await MembershipOrg.findOne({ - user: userId, - organization: orgId, - status: ACCEPTED - }) - .populate<{ customRole: IRole & { permissions: RawRuleOf>[] } }>( - "customRole" - ) - .exec(); - - if (!membership || (membership.role === "custom" && !membership.customRole)) { - throw UnauthorizedRequestError({ message: "User doesn't belong to organization" }); - } - - if (membership.role === ADMIN) return { permission: adminPermissions, membership }; - - if (membership.role === MEMBER) return { permission: memberPermissions, membership }; - - if (membership.role === NO_ACCESS) return { permission: noAccessPermissions, membership } - - if (membership.role === CUSTOM) { - const permission = createMongoAbility(membership.customRole.permissions, { - conditionsMatcher - }); - return { permission, membership }; - } - - throw BadRequestError({ message: "User role not found" }); -}; - -/** - * Return permissions for user/service pertaining to organization with id [organizationId] - * - * Note: should not rely on this function for ST V2 authorization logic - * b/c ST V2 does not support role-based access control but also not organization-level resources - */ - export const getAuthDataOrgPermissions = async ({ - authData, - organizationId -}: { - authData: AuthData; - organizationId: Types.ObjectId; -}) => { - let role: "admin" | "member" | "no-access" | "custom"; - let customRole; - - switch (authData.actor.type) { - case ActorType.USER: { - const membershipOrg = await MembershipOrg.findOne({ - user: authData.authPayload._id, - organization: organizationId, - status: ACCEPTED - }) - .populate<{ customRole: IRole & { permissions: RawRuleOf>[] } }>( - "customRole" - ) - .exec(); - - if (!membershipOrg || (membershipOrg.role === "custom" && !membershipOrg.customRole)) { - throw UnauthorizedRequestError({ message: "User doesn't belong to organization" }); - } - - role = membershipOrg.role; - customRole = membershipOrg.customRole; - break; - } - case ActorType.SERVICE: { - throw UnauthorizedRequestError({ - message: "Failed to access organization-level resources with service token" - }); - } - case ActorType.IDENTITY: { - const identityMembershipOrg = await IdentityMembershipOrg.findOne({ - identity: authData.authPayload._id, - organization: organizationId - }) - .populate<{ - customRole: IRole & { permissions: RawRuleOf>[] }; - identity: IIdentity - }>("customRole identity") - .exec(); - - if (!identityMembershipOrg || (identityMembershipOrg.role === "custom" && !identityMembershipOrg.customRole)) { - throw UnauthorizedRequestError(); - } - - role = identityMembershipOrg.role; - customRole = identityMembershipOrg.customRole; - break; - } - default: - throw UnauthorizedRequestError(); - } - - switch (role) { - case ADMIN: - return { permission: adminPermissions }; - case MEMBER: - return { permission: memberPermissions }; - case NO_ACCESS: - return { permission: noAccessPermissions }; - case CUSTOM: { - if (!customRole) throw UnauthorizedRequestError(); - return { - permission: createMongoAbility( - customRole.permissions, - { conditionsMatcher } - ) - }; - } - } -} - -export const getOrgRolePermissions = async (role: string, orgId: string) => { - const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role); - if (isCustomRole) { - const orgRole = await Role.findOne({ - slug: role, - isOrgRole: true, - organization: new Types.ObjectId(orgId) - }); - - if (!orgRole) throw BadRequestError({ message: "Org Role not found" }); - - return createMongoAbility(orgRole.permissions as RawRuleOf>[], { - conditionsMatcher - }); - } - - switch (role) { - case ADMIN: - return adminPermissions; - case MEMBER: - return memberPermissions; - case NO_ACCESS: - return noAccessPermissions; - default: - throw BadRequestError({ message: "User org role not found" }); - } -} - -/** - * Extracts and formats permissions from a CASL Ability object or a raw permission set. - * @param ability - * @returns - */ -const extractPermissions = (ability: any) => { - return ability.A.map((permission: any) => `${permission.action}_${permission.subject}`); -} - -/** - * Compares two sets of permissions to determine if the first set is at least as privileged as the second set. - * The function checks if all permissions in the second set are contained within the first set and if the first set has equal or more permissions. - * -*/ -export const isAtLeastAsPrivilegedOrg = (permissions1: MongoAbility | OrgPermissionSet, permissions2: MongoAbility | OrgPermissionSet) => { - - const set1 = new Set(extractPermissions(permissions1)); - const set2 = new Set(extractPermissions(permissions2)); - - for (const perm of set2) { - if (!set1.has(perm)) { - return false; - } - } - - return set1.size >= set2.size; -} \ No newline at end of file diff --git a/backend-mongo/src/ee/services/SecretApprovalService.ts b/backend-mongo/src/ee/services/SecretApprovalService.ts deleted file mode 100644 index 58e2a9a20..000000000 --- a/backend-mongo/src/ee/services/SecretApprovalService.ts +++ /dev/null @@ -1,656 +0,0 @@ -import picomatch from "picomatch"; -import { Types } from "mongoose"; -import { - containsGlobPatterns, - generateSecretBlindIndexWithSaltHelper, - getSecretBlindIndexSaltHelper -} from "../../helpers/secrets"; -import { Folder, ISecret, Secret } from "../../models"; -import { ISecretApprovalPolicy, SecretApprovalPolicy } from "../models/secretApprovalPolicy"; -import { - CommitType, - ISecretApprovalRequest, - ISecretApprovalSecChange, - ISecretCommits, - SecretApprovalRequest -} from "../models/secretApprovalRequest"; -import { BadRequestError } from "../../utils/errors"; -import { getFolderByPath } from "../../services/FolderService"; -import { ALGORITHM_AES_256_GCM, ENCODING_SCHEME_UTF8, SECRET_SHARED } from "../../variables"; -import TelemetryService from "../../services/TelemetryService"; -import { EEAuditLogService, EESecretService } from "../services"; -import { EventType, SecretVersion } from "../models"; -import { AuthData } from "../../interfaces/middleware"; - -// if glob pattern score is 1, if not exist score is 0 and if its not both then its exact path meaning score 2 -const getPolicyScore = (policy: ISecretApprovalPolicy) => - policy.secretPath ? (containsGlobPatterns(policy.secretPath) ? 1 : 2) : 0; - -// this will fetch the policy that gets priority for an environment and secret path -export const getSecretPolicyOfBoard = async ( - workspaceId: string, - environment: string, - secretPath: string -) => { - const policies = await SecretApprovalPolicy.find({ workspace: workspaceId, environment }); - if (!policies) return; - // this will filter policies either without scoped to secret path or the one that matches with secret path - const policiesFilteredByPath = policies.filter( - ({ secretPath: policyPath }) => - !policyPath || picomatch.isMatch(secretPath, policyPath, { strictSlashes: false }) - ); - // now sort by priority. exact secret path gets first match followed by glob followed by just env scoped - // if that is tie get by first createdAt - const policiesByPriority = policiesFilteredByPath.sort( - (a, b) => getPolicyScore(b) - getPolicyScore(a) - ); - const finalPolicy = policiesByPriority.shift(); - return finalPolicy; -}; - -const getLatestSecretVersion = async (secretIds: Types.ObjectId[]) => { - const latestSecretVersions = await SecretVersion.aggregate([ - { - $match: { - secret: { - $in: secretIds - }, - type: SECRET_SHARED - } - }, - { - $sort: { version: -1 } - }, - { - $group: { - _id: "$secret", - version: { $max: "$version" }, - versionId: { $max: "$_id" }, // id of latest secret versionId - secret: { $first: "$$ROOT" } - } - } - ]).exec(); - // reduced with secret id and latest version as document - return latestSecretVersions.reduce( - (prev, curr) => ({ ...prev, [curr._id.toString()]: curr.secret }), - {} - ); -}; - -type TApprovalCreateSecret = Omit & { - secretName: string; -}; -type TApprovalUpdateSecret = Partial> & { - secretName: string; - newSecretName?: string; -}; - -type TGenerateSecretApprovalRequestArg = { - workspaceId: string; - environment: string; - secretPath: string; - policy: ISecretApprovalPolicy; - data: { - [CommitType.CREATE]?: TApprovalCreateSecret[]; - [CommitType.UPDATE]?: TApprovalUpdateSecret[]; - [CommitType.DELETE]?: { secretName: string }[]; - }; - commiterMembershipId: string; - authData: AuthData; -}; - -export const generateSecretApprovalRequest = async ({ - workspaceId, - environment, - secretPath, - policy, - data, - commiterMembershipId, - authData -}: TGenerateSecretApprovalRequestArg) => { - // calculate folder id from secret path - let folderId = "root"; - const rootFolder = await Folder.findOne({ workspace: workspaceId, environment }); - if (!rootFolder && secretPath !== "/") throw BadRequestError({ message: "Folder not found" }); - if (rootFolder) { - const folder = getFolderByPath(rootFolder.nodes, secretPath); - if (!folder) throw BadRequestError({ message: "Folder not found" }); - folderId = folder.id; - } - - // generate secret blindIndexes - const salt = await getSecretBlindIndexSaltHelper({ - workspaceId: new Types.ObjectId(workspaceId) - }); - const commits: ISecretApprovalRequest["commits"] = []; - - // ----- - // for created secret approval change - const createdSecret = data[CommitType.CREATE]; - if (createdSecret && createdSecret?.length) { - // validation checks whether secret exists for creation - const secretBlindIndexes = await Promise.all( - createdSecret.map(({ secretName }) => - generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }) - ) - ).then((blindIndexes) => - blindIndexes.reduce>((prev, curr, i) => { - prev[createdSecret[i].secretName] = curr; - return prev; - }, {}) - ); - // check created secret exists - const exists = await Secret.exists({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment - }) - .or( - createdSecret.map(({ secretName }) => ({ - secretBlindIndex: secretBlindIndexes[secretName], - type: SECRET_SHARED - })) - ) - .exec(); - if (exists) throw BadRequestError({ message: "Secrets already exist" }); - commits.push( - ...createdSecret.map((el) => ({ - op: CommitType.CREATE as const, - newVersion: { - ...el, - version: 0, - _id: new Types.ObjectId(), - secretBlindIndex: secretBlindIndexes[el.secretName] - } - })) - ); - } - - // ---- - // updated secrets approval change - const updatedSecret = data[CommitType.UPDATE]; - if (updatedSecret && updatedSecret?.length) { - // validation checks whether secret doesn't exists for update - const secretBlindIndexes = await Promise.all( - updatedSecret.map(({ secretName }) => - generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }) - ) - ).then((blindIndexes) => - blindIndexes.reduce>((prev, curr, i) => { - prev[updatedSecret[i].secretName] = curr; - return prev; - }, {}) - ); - // check update secret exists - const oldSecrets = await Secret.find({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment, - type: SECRET_SHARED, - secretBlindIndex: { - $in: updatedSecret.map(({ secretName }) => secretBlindIndexes[secretName]) - } - }) - .select("+secretBlindIndex") - .lean() - .exec(); - if (oldSecrets.length !== updatedSecret.length) - throw BadRequestError({ message: "Secrets already exist" }); - - // finally check updating blindindex exist - const nameUpdatedSecrets = updatedSecret.filter(({ newSecretName }) => Boolean(newSecretName)); - const newSecretBlindIndexes = await Promise.all( - nameUpdatedSecrets.map(({ newSecretName }) => - generateSecretBlindIndexWithSaltHelper({ - secretName: newSecretName as string, - salt - }) - ) - ).then((blindIndexes) => - blindIndexes.reduce>((prev, curr, i) => { - prev[nameUpdatedSecrets[i].secretName] = curr; - return prev; - }, {}) - ); - const doesAnySecretExistWithNewIndex = await Secret.find({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment, - secretBlindIndex: { $in: Object.values(newSecretBlindIndexes) } - }); - if (doesAnySecretExistWithNewIndex.length) - throw BadRequestError({ message: "Secret with new name already exist" }); - - const oldSecretsGroupById = oldSecrets.reduce>( - (prev, curr) => ({ ...prev, [curr?.secretBlindIndex || ""]: curr }), - {} - ); - const latestSecretVersions = await getLatestSecretVersion( - updatedSecret.map((el) => oldSecretsGroupById[secretBlindIndexes[el.secretName]]._id) - ); - - commits.push( - ...updatedSecret.map((el) => { - const secretId = oldSecretsGroupById[secretBlindIndexes[el.secretName]]._id; - return { - op: CommitType.UPDATE as const, - secret: secretId, - secretVersion: latestSecretVersions[secretId.toString()]._id, - newVersion: { - ...el, - secretBlindIndex: newSecretBlindIndexes?.[el.secretName], - _id: new Types.ObjectId(), - version: oldSecretsGroupById[secretBlindIndexes[el.secretName]].version || 1 - } - }; - }) - ); - } - - // ----- - // deleted secrets - const deletedSecrets = data[CommitType.DELETE]; - if (deletedSecrets && deletedSecrets.length) { - const secretBlindIndexes = await Promise.all( - deletedSecrets.map(({ secretName }) => - generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }) - ) - ).then((blindIndexes) => - blindIndexes.reduce>((prev, curr, i) => { - prev[deletedSecrets[i].secretName] = curr; - return prev; - }, {}) - ); - - const secretsToDelete = await Secret.find({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment, - type: SECRET_SHARED, - secretBlindIndex: { - $in: deletedSecrets.map(({ secretName }) => secretBlindIndexes[secretName]) - } - }) - .select({ secretBlindIndex: 1, _id: 1 }) - .lean() - .exec(); - if (secretsToDelete.length !== deletedSecrets.length) - throw BadRequestError({ message: "Deleted secrets not found" }); - - const oldSecretsGroupById = secretsToDelete.reduce>( - (prev, curr) => ({ ...prev, [curr?.secretBlindIndex || ""]: curr }), - {} - ); - const latestSecretVersions = await getLatestSecretVersion( - deletedSecrets.map((el) => oldSecretsGroupById[secretBlindIndexes[el.secretName]]._id) - ); - - commits.push( - ...deletedSecrets.map((el) => { - const secretId = oldSecretsGroupById[secretBlindIndexes[el.secretName]]._id; - return { - op: CommitType.DELETE as const, - secret: secretId, - secretVersion: latestSecretVersions[secretId.toString()] - }; - }) - ); - } - - const secretApprovalRequest = new SecretApprovalRequest({ - workspace: workspaceId, - environment, - folderId, - policy, - commits, - committer: commiterMembershipId - }); - await secretApprovalRequest.save(); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.SECRET_APPROVAL_REQUEST, - metadata: { - committedBy: commiterMembershipId, - secretApprovalRequestId: secretApprovalRequest._id.toString(), - secretApprovalRequestSlug: secretApprovalRequest.slug - } - }, - { - workspaceId: secretApprovalRequest.workspace - } - ); - - return secretApprovalRequest; -}; - -// validation for a merge conditions happen in another function in controller -export const performSecretApprovalRequestMerge = async ( - id: string, - authData: AuthData, - userMembershipId: string -) => { - const secretApprovalRequest = await SecretApprovalRequest.findById(id) - .populate<{ commits: ISecretCommits }>({ - path: "commits.secret", - select: "+secretBlindIndex", - populate: { - path: "tags" - } - }) - .select("+commits.newVersion.secretBlindIndex"); - if (!secretApprovalRequest) throw BadRequestError({ message: "Approval request not found" }); - - const workspaceId = secretApprovalRequest.workspace; - const environment = secretApprovalRequest.environment; - const folderId = secretApprovalRequest.folderId; - const postHogClient = await TelemetryService.getPostHogClient(); - const conflicts: Array<{ secretId: string; op: CommitType }> = []; - - const secretCreationCommits = secretApprovalRequest.commits.filter( - ({ op }) => op === CommitType.CREATE - ) as Array<{ op: CommitType.CREATE; newVersion: ISecretApprovalSecChange }>; - if (secretCreationCommits.length) { - // the created secrets already exist thus creation conflict ones - const conflictedSecrets = await Secret.find({ - workspace: workspaceId, - environment, - folder: folderId, - secretBlindIndex: { - $in: secretCreationCommits.map(({ newVersion }) => newVersion.secretBlindIndex) - } - }) - .select("+secretBlindIndex") - .lean(); - const conflictGroupByBlindIndex = conflictedSecrets.reduce>( - (prev, curr) => ({ ...prev, [curr.secretBlindIndex || ""]: true }), - {} - ); - const nonConflictSecrets = secretCreationCommits.filter( - ({ newVersion }) => !conflictGroupByBlindIndex[newVersion.secretBlindIndex || ""] - ); - secretCreationCommits - .filter(({ newVersion }) => conflictGroupByBlindIndex[newVersion.secretBlindIndex || ""]) - .forEach((el) => { - conflicts.push({ op: CommitType.CREATE, secretId: el.newVersion._id.toString() }); - }); - - // create secret - const newlyCreatedSecrets: ISecret[] = await Secret.insertMany( - nonConflictSecrets.map( - ({ - newVersion: { - secretKeyIV, - secretKeyTag, - secretValueIV, - secretValueTag, - secretCommentIV, - secretCommentTag, - secretKeyCiphertext, - secretValueCiphertext, - secretCommentCiphertext, - skipMultilineEncoding, - secretBlindIndex, - algorithm, - keyEncoding, - tags - } - }) => ({ - version: 1, - workspace: new Types.ObjectId(workspaceId), - environment, - type: SECRET_SHARED, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - folder: folderId, - algorithm: algorithm || ALGORITHM_AES_256_GCM, - keyEncoding: keyEncoding || ENCODING_SCHEME_UTF8, - tags, - skipMultilineEncoding, - secretBlindIndex - }) - ) - ); - - await EESecretService.addSecretVersions({ - secretVersions: newlyCreatedSecrets.map( - (secret) => - new SecretVersion({ - secret: secret._id, - version: secret.version, - workspace: secret.workspace, - type: secret.type, - folder: folderId, - tags: secret.tags, - skipMultilineEncoding: secret?.skipMultilineEncoding, - environment: secret.environment, - isDeleted: false, - secretBlindIndex: secret.secretBlindIndex, - secretKeyCiphertext: secret.secretKeyCiphertext, - secretKeyIV: secret.secretKeyIV, - secretKeyTag: secret.secretKeyTag, - secretValueCiphertext: secret.secretValueCiphertext, - secretValueIV: secret.secretValueIV, - secretValueTag: secret.secretValueTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }) - ) - }); - } - - const secretUpdationCommits = secretApprovalRequest.commits.filter( - ({ op }) => op === CommitType.UPDATE - ) as Array<{ - op: CommitType.UPDATE; - newVersion: Partial> & { _id: Types.ObjectId }; - secret: ISecret; - }>; - if (secretUpdationCommits.length) { - const conflictedByNewBlindIndex = await Secret.find({ - workspace: workspaceId, - environment, - folder: folderId, - secretBlindIndex: { - $in: secretUpdationCommits - .map(({ newVersion }) => newVersion?.secretBlindIndex) - .filter(Boolean) - } - }) - .select("+secretBlindIndex") - .lean(); - const conflictGroupByBlindIndex = conflictedByNewBlindIndex.reduce>( - (prev, curr) => (curr?.secretBlindIndex ? { ...prev, [curr.secretBlindIndex]: true } : prev), - {} - ); - secretUpdationCommits - .filter( - ({ newVersion, secret }) => - (newVersion.secretBlindIndex && conflictGroupByBlindIndex[newVersion.secretBlindIndex]) || - !secret - ) - .forEach((el) => { - conflicts.push({ op: CommitType.UPDATE, secretId: el.newVersion._id.toString() }); - }); - - const nonConflictSecrets = secretUpdationCommits.filter( - ({ newVersion, secret }) => - Boolean(secret) && - (newVersion?.secretBlindIndex - ? !conflictGroupByBlindIndex[newVersion.secretBlindIndex] - : true) - ); - await Secret.bulkWrite( - // id and version are stripped off - nonConflictSecrets.map( - ({ - newVersion: { - secretKeyIV, - secretKeyTag, - secretValueIV, - secretValueTag, - secretCommentIV, - secretCommentTag, - secretKeyCiphertext, - secretValueCiphertext, - secretCommentCiphertext, - skipMultilineEncoding, - secretBlindIndex, - tags - }, - secret - }) => ({ - updateOne: { - filter: { - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - secretBlindIndex: secret.secretBlindIndex, - type: SECRET_SHARED - }, - update: { - $inc: { - version: 1 - }, - secretKeyIV, - secretKeyTag, - secretValueIV, - secretValueTag, - secretCommentIV, - secretCommentTag, - secretKeyCiphertext, - secretValueCiphertext, - secretCommentCiphertext, - skipMultilineEncoding, - secretBlindIndex, - tags, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - } - } - }) - ) - ); - - await EESecretService.addSecretVersions({ - secretVersions: nonConflictSecrets.map(({ newVersion, secret }) => { - return new SecretVersion({ - secret: secret._id, - version: secret.version + 1, - workspace: workspaceId, - type: SECRET_SHARED, - folder: folderId, - environment, - isDeleted: false, - secretBlindIndex: newVersion?.secretBlindIndex ?? secret.secretBlindIndex, - secretKeyCiphertext: newVersion?.secretKeyCiphertext ?? secret.secretKeyCiphertext, - secretKeyIV: newVersion?.secretKeyIV ?? secret.secretKeyCiphertext, - secretKeyTag: newVersion?.secretKeyTag ?? secret.secretKeyTag, - secretValueCiphertext: newVersion?.secretValueCiphertext ?? secret.secretValueCiphertext, - secretValueIV: newVersion?.secretValueIV ?? secret.secretValueIV, - secretValueTag: newVersion?.secretValueTag ?? secret.secretValueTag, - tags: newVersion?.tags ?? secret.tags, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - skipMultilineEncoding: newVersion?.skipMultilineEncoding ?? secret.skipMultilineEncoding - }); - }) - }); - } - - const secretDeletionCommits = secretApprovalRequest.commits.filter( - ({ op }) => op === CommitType.DELETE - ) as Array<{ - op: CommitType.DELETE; - secret: ISecret; - }>; - if (secretDeletionCommits.length) { - await Secret.deleteMany({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment - }) - .or( - secretDeletionCommits.map(({ secret: { secretBlindIndex } }) => ({ - secretBlindIndex, - type: { $in: ["shared", "personal"] } - })) - ) - .exec(); - - await EESecretService.markDeletedSecretVersions({ - secretIds: secretDeletionCommits.map(({ secret }) => secret._id) - }); - } - - const updatedSecretApproval = await SecretApprovalRequest.findByIdAndUpdate( - id, - { - conflicts, - hasMerged: true, - status: "close", - statusChangeBy: userMembershipId - }, - { new: true } - ); - - if (postHogClient) { - if (postHogClient) { - postHogClient.capture({ - event: "secrets merged", - distinctId: await TelemetryService.getDistinctId({ - authData - }), - properties: { - numberOfSecrets: secretApprovalRequest.commits.length, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - } - - await EESecretService.takeSecretSnapshot({ - workspaceId, - environment, - folderId - }); - - // question to team where to keep secretKey - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.SECRET_APPROVAL_MERGED, - metadata: { - mergedBy: userMembershipId, - secretApprovalRequestId: id, - secretApprovalRequestSlug: secretApprovalRequest.slug - } - }, - { - workspaceId - } - ); - - return updatedSecretApproval; -}; diff --git a/backend-mongo/src/ee/services/index.ts b/backend-mongo/src/ee/services/index.ts deleted file mode 100644 index 4ec55e725..000000000 --- a/backend-mongo/src/ee/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import EELicenseService from "./EELicenseService"; -import EESecretService from "./EESecretService"; -import EEAuditLogService from "./EEAuditLogService"; -import GithubSecretScanningService from "./GithubSecretScanning/GithubSecretScanningService" - -export { - EELicenseService, - EESecretService, - EEAuditLogService, - GithubSecretScanningService -} \ No newline at end of file diff --git a/backend-mongo/src/ee/validation/role.ts b/backend-mongo/src/ee/validation/role.ts deleted file mode 100644 index e3ecafe59..000000000 --- a/backend-mongo/src/ee/validation/role.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { z } from "zod"; - -export const CreateRoleSchema = z.object({ - body: z.object({ - slug: z.string().trim(), - name: z.string().trim(), - description: z.string().trim().optional(), - workspaceId: z.string().trim().optional(), - orgId: z.string().trim(), - permissions: z - .object({ - subject: z.string().trim(), - action: z.string().trim(), - conditions: z - .record(z.union([z.string().trim(), z.number(), z.object({ $glob: z.string() })])) - .optional() - }) - .array() - }) -}); - -export const UpdateRoleSchema = z.object({ - params: z.object({ - id: z.string().trim() - }), - body: z.object({ - slug: z.string().trim().optional(), - name: z.string().trim().optional(), - description: z.string().trim().optional(), - workspaceId: z.string().trim().optional(), - orgId: z.string().trim(), - permissions: z - .object({ - subject: z.string().trim(), - action: z.string().trim(), - conditions: z - .record(z.union([z.string().trim(), z.number(), z.object({ $glob: z.string() })])) - .optional() - }) - .array() - .optional() - }) -}); - -export const DeleteRoleSchema = z.object({ - params: z.object({ - id: z.string().trim() - }) -}); - -export const GetRoleSchema = z.object({ - query: z.object({ - workspaceId: z.string().trim().optional(), - orgId: z.string().trim() - }) -}); - -export const GetUserPermission = z.object({ - params: z.object({ - orgId: z.string().trim() - }) -}); - -export const GetUserProjectPermission = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); diff --git a/backend-mongo/src/ee/validation/secretApproval.ts b/backend-mongo/src/ee/validation/secretApproval.ts deleted file mode 100644 index 999820e48..000000000 --- a/backend-mongo/src/ee/validation/secretApproval.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { z } from "zod"; - -export const GetSecretApprovalRuleList = z.object({ - query: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetSecretApprovalPolicyOfABoard = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim() - }) -}); - -export const CreateSecretApprovalRule = z.object({ - body: z - .object({ - workspaceId: z.string(), - name: z.string().optional(), - environment: z.string(), - secretPath: z.string().optional().nullable(), - approvers: z.string().array().min(1), - approvals: z.number().min(1).default(1) - }) - .refine((data) => data.approvals <= data.approvers.length, { - path: ["approvals"], - message: "The number of approvals should be lower than the number of approvers." - }) -}); - -export const UpdateSecretApprovalRule = z.object({ - params: z.object({ - id: z.string() - }), - body: z - .object({ - name: z.string().optional(), - approvers: z.string().array().min(1), - approvals: z.number().min(1).default(1), - secretPath: z.string().optional().nullable() - }) - .refine((data) => data.approvals <= data.approvers.length, { - path: ["approvals"], - message: "The number of approvals should be lower than the number of approvers." - }) -}); - -export const DeleteSecretApprovalRule = z.object({ - params: z.object({ - id: z.string() - }) -}); diff --git a/backend-mongo/src/ee/validation/secretApprovalRequest.ts b/backend-mongo/src/ee/validation/secretApprovalRequest.ts deleted file mode 100644 index 07aff586c..000000000 --- a/backend-mongo/src/ee/validation/secretApprovalRequest.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { z } from "zod"; -import { ApprovalStatus } from "../models/secretApprovalRequest"; - -export const getSecretApprovalRequests = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim().optional(), - committer: z.string().trim().optional(), - status: z.enum(["open", "close"]).optional(), - limit: z.coerce.number().default(20), - offset: z.coerce.number().default(0) - }) -}); - -export const getSecretApprovalRequestCount = z.object({ - query: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const getSecretApprovalRequestDetails = z.object({ - params: z.object({ - id: z.string().trim() - }) -}); - -export const updateSecretApprovalReviewStatus = z.object({ - body: z.object({ - status: z.enum([ApprovalStatus.APPROVED, ApprovalStatus.REJECTED]) - }), - params: z.object({ - id: z.string().trim() - }) -}); - -export const mergeSecretApprovalRequest = z.object({ - params: z.object({ - id: z.string().trim() - }) -}); - -export const updateSecretApprovalRequestStatus = z.object({ - params: z.object({ - id: z.string().trim() - }), - body: z.object({ - status: z.enum(["open", "close"]) - }) -}); diff --git a/backend-mongo/src/ee/validation/secretRotation.ts b/backend-mongo/src/ee/validation/secretRotation.ts deleted file mode 100644 index 616844aaf..000000000 --- a/backend-mongo/src/ee/validation/secretRotation.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { z } from "zod"; - -export const createSecretRotationV1 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - secretPath: z.string().trim(), - environment: z.string().trim(), - interval: z.number().min(1), - provider: z.string().trim(), - customProvider: z.string().trim().optional(), - inputs: z.record(z.unknown()), - outputs: z.record(z.string()) - }) -}); - -export const restartSecretRotationV1 = z.object({ - body: z.object({ - id: z.string().trim() - }) -}); - -export const getSecretRotationV1 = z.object({ - query: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const removeSecretRotationV1 = z.object({ - params: z.object({ - id: z.string().trim() - }) -}); diff --git a/backend-mongo/src/ee/validation/secretRotationProvider.ts b/backend-mongo/src/ee/validation/secretRotationProvider.ts deleted file mode 100644 index d322939bb..000000000 --- a/backend-mongo/src/ee/validation/secretRotationProvider.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { z } from "zod"; - -export const getSecretRotationProvidersV1 = z.object({ - params: z.object({ - workspaceId: z.string() - }) -}); diff --git a/backend-mongo/src/events/index.ts b/backend-mongo/src/events/index.ts deleted file mode 100644 index ac9ad176d..000000000 --- a/backend-mongo/src/events/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { eventPushSecrets } from "./secret"; -import { eventStartIntegration } from "./integration"; - -export { eventPushSecrets, eventStartIntegration }; diff --git a/backend-mongo/src/events/integration.ts b/backend-mongo/src/events/integration.ts deleted file mode 100644 index 746858e46..000000000 --- a/backend-mongo/src/events/integration.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Types } from "mongoose"; -import { EVENT_START_INTEGRATION } from "../variables"; - -/* - * Return event for starting integrations - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace to push secrets to - * @returns - */ -export const eventStartIntegration = ({ - workspaceId, - environment -}: { - workspaceId: Types.ObjectId; - environment: string; -}) => { - return { - name: EVENT_START_INTEGRATION, - workspaceId, - environment, - payload: {} - }; -}; diff --git a/backend-mongo/src/events/secret.ts b/backend-mongo/src/events/secret.ts deleted file mode 100644 index 894e3300d..000000000 --- a/backend-mongo/src/events/secret.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Types } from "mongoose"; -import { EVENT_PULL_SECRETS, EVENT_PUSH_SECRETS } from "../variables"; - -interface PushSecret { - ciphertextKey: string; - ivKey: string; - tagKey: string; - hashKey: string; - ciphertextValue: string; - ivValue: string; - tagValue: string; - hashValue: string; - type: "shared" | "personal"; -} - -/** - * Return event for pushing secrets - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace to push secrets to - * @returns - */ -const eventPushSecrets = ({ - workspaceId, - environment, - secretPath -}: { - workspaceId: Types.ObjectId; - environment: string; - secretPath: string; -}) => { - return { - name: EVENT_PUSH_SECRETS, - workspaceId, - environment, - secretPath, - payload: {} - }; -}; - -/** - * Return event for pulling secrets - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace to pull secrets from - * @returns - */ -const eventPullSecrets = ({ workspaceId }: { workspaceId: string }) => { - return { - name: EVENT_PULL_SECRETS, - workspaceId, - payload: {} - }; -}; - -export { eventPushSecrets }; diff --git a/backend-mongo/src/helpers/auth.ts b/backend-mongo/src/helpers/auth.ts deleted file mode 100644 index 14024bd03..000000000 --- a/backend-mongo/src/helpers/auth.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { Types } from "mongoose"; -import jwt from "jsonwebtoken"; -import { ITokenVersion, TokenVersion } from "../models"; -import { UnauthorizedRequestError } from "../utils/errors"; -import { - getAuthSecret, - getJwtAuthLifetime, - getJwtRefreshLifetime -} from "../config"; -import { AuthTokenType } from "../variables"; - -/** - * Return newly issued (JWT) auth and refresh tokens to user with id [userId] - * @param {Object} obj - * @param {String} obj.userId - id of user who we are issuing tokens for - * @return {Object} obj - * @return {String} obj.token - issued JWT token - * @return {String} obj.refreshToken - issued refresh token - */ -export const issueAuthTokens = async ({ - userId, - ip, - userAgent, -}: { - userId: Types.ObjectId; - ip: string; - userAgent: string; -}) => { - let tokenVersion: ITokenVersion | null; - - // continue with (session) token version matching existing ip and user agent - tokenVersion = await TokenVersion.findOne({ - user: userId, - ip, - userAgent, - }); - - if (!tokenVersion) { - // case: no existing ip and user agent exists - // -> create new (session) token version for ip and user agent - tokenVersion = await new TokenVersion({ - user: userId, - refreshVersion: 0, - accessVersion: 0, - ip, - userAgent, - lastUsed: new Date(), - }).save(); - } - - // issue tokens - const token = createToken({ - payload: { - authTokenType: AuthTokenType.ACCESS_TOKEN, - userId, - tokenVersionId: tokenVersion._id.toString(), - accessVersion: tokenVersion.accessVersion, - }, - expiresIn: await getJwtAuthLifetime(), - secret: await getAuthSecret(), - }); - - const refreshToken = createToken({ - payload: { - authTokenType: AuthTokenType.REFRESH_TOKEN, - userId, - tokenVersionId: tokenVersion._id.toString(), - refreshVersion: tokenVersion.refreshVersion, - }, - expiresIn: await getJwtRefreshLifetime(), - secret: await getAuthSecret(), - }); - - return { - token, - refreshToken, - }; -}; - -/** - * Remove JWT and refresh tokens for user with id [userId] - * @param {Object} obj - * @param {String} obj.userId - id of user whose tokens are cleared. - */ -export const clearTokens = async (tokenVersionId: Types.ObjectId): Promise => { - // increment refreshVersion on user by 1 - - await TokenVersion.findOneAndUpdate({ - _id: tokenVersionId, - }, { - $inc: { - refreshVersion: 1, - accessVersion: 1, - }, - }); -}; - -/** - * Return a new (JWT) token for user with id [userId] that expires in [expiresIn]; can be used to, for instance, generate - * bearer/auth, refresh, and temporary signup tokens - * @param {Object} obj - * @param {Object} obj.payload - payload of (JWT) token - * @param {String} obj.secret - (JWT) secret such as [AUTH_SECRET] - * @param {String} obj.expiresIn - string describing time span such as '10h' or '7d' - */ -export const createToken = ({ - payload, - expiresIn, - secret, -}: { - payload: any; - expiresIn?: string | number; - secret: string; -}) => { - return jwt.sign(payload, secret, { - ...( - (expiresIn !== undefined && expiresIn !== null) - ? { expiresIn } - : {} - ) - }); -}; - -export const validateProviderAuthToken = async ({ - email, - providerAuthToken, -}: { - email: string; - providerAuthToken?: string; -}) => { - - if (!providerAuthToken) { - throw new Error("Invalid authentication request."); - } - - const decodedToken = ( - jwt.verify(providerAuthToken, await getAuthSecret()) - ); - - if (decodedToken.authTokenType !== AuthTokenType.PROVIDER_TOKEN) throw UnauthorizedRequestError(); - - if (decodedToken.email !== email) { - throw new Error("Invalid authentication credentials.") - } -} diff --git a/backend-mongo/src/helpers/bot.ts b/backend-mongo/src/helpers/bot.ts deleted file mode 100644 index 63814434d..000000000 --- a/backend-mongo/src/helpers/bot.ts +++ /dev/null @@ -1,394 +0,0 @@ -import { Types } from "mongoose"; -import { Bot, BotKey, ISecret, IUser, Secret } from "../models"; -import { - decryptAsymmetric, - decryptSymmetric128BitHexKeyUTF8, - encryptSymmetric128BitHexKeyUTF8, - generateKeyPair -} from "../utils/crypto"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, - SECRET_SHARED -} from "../variables"; -import { client, getEncryptionKey, getRootEncryptionKey } from "../config"; -import { BotNotFoundError, InternalServerError } from "../utils/errors"; -import { Folder } from "../models"; -import { getFolderByPath } from "../services/FolderService"; -import { getAllImportedSecrets } from "../services/SecretImportService"; -import { expandSecrets } from "./secrets"; - -/** - * Create an inactive bot with name [name] for workspace with id [workspaceId] - * @param {Object} obj - * @param {String} obj.name - name of bot - * @param {String} obj.workspaceId - id of workspace that bot belongs to - */ -export const createBot = async ({ - name, - workspaceId -}: { - name: string; - workspaceId: Types.ObjectId; -}) => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - const { publicKey, privateKey } = generateKeyPair(); - - if (rootEncryptionKey) { - const { ciphertext, iv, tag } = client.encryptSymmetric(privateKey, rootEncryptionKey); - - return await new Bot({ - name, - workspace: workspaceId, - isActive: false, - publicKey, - encryptedPrivateKey: ciphertext, - iv, - tag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_BASE64 - }).save(); - } else if (encryptionKey) { - const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: privateKey, - key: await getEncryptionKey() - }); - - return await new Bot({ - name, - workspace: workspaceId, - isActive: false, - publicKey, - encryptedPrivateKey: ciphertext, - iv, - tag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }).save(); - } - - throw InternalServerError({ - message: "Failed to create new bot due to missing encryption key" - }); -}; - -/** - * Return whether or not workspace with id [workspaceId] is end-to-end encrypted - * @param {Types.ObjectId} workspaceId - id of workspace to check - */ -export const getIsWorkspaceE2EEHelper = async (workspaceId: Types.ObjectId) => { - const botKey = await BotKey.exists({ - workspace: workspaceId - }); - - return botKey ? false : true; -}; - -/** - * Return decrypted secrets for workspace with id [workspaceId] - * and [environment] using bot - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace - * @param {String} obj.environment - environment - */ -export const getSecretsBotHelper = async ({ - workspaceId, - environment, - secretPath -}: { - workspaceId: Types.ObjectId; - environment: string; - secretPath: string; -}) => { - const content: Record< - string, - { value: string; comment?: string; skipMultilineEncoding?: boolean } - > = {}; - const key = await getKey({ workspaceId: workspaceId }); - - let folderId = "root"; - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }); - - if (!folders && secretPath !== "/") { - throw InternalServerError({ message: "Folder not found" }); - } - - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) { - throw InternalServerError({ message: "Folder not found" }); - } - folderId = folder.id; - } - - const secrets = await Secret.find({ - workspace: workspaceId, - environment, - type: SECRET_SHARED, - folder: folderId - }); - - const importedSecrets = await getAllImportedSecrets( - workspaceId.toString(), - environment, - folderId, - () => true // integrations are setup to read all the ones - ); - - importedSecrets.forEach(({ secrets }) => { - secrets.forEach((secret) => { - const secretKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - key - }); - - const secretValue = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - key - }); - - content[secretKey] = { value: secretValue }; - - if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) { - const commentValue = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretCommentCiphertext, - iv: secret.secretCommentIV, - tag: secret.secretCommentTag, - key - }); - content[secretKey].comment = commentValue; - } - - content[secretKey].skipMultilineEncoding = secret.skipMultilineEncoding; - }); - }); - - secrets.forEach((secret: ISecret) => { - const secretKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - key - }); - - const secretValue = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - key - }); - - content[secretKey] = { value: secretValue }; - - if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) { - const commentValue = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretCommentCiphertext, - iv: secret.secretCommentIV, - tag: secret.secretCommentTag, - key - }); - content[secretKey].comment = commentValue; - } - - content[secretKey].skipMultilineEncoding = secret.skipMultilineEncoding; - }); - - await expandSecrets(workspaceId.toString(), key, content); - - return content; -}; - -/** - * Return bot's copy of the workspace key for workspace - * with id [workspaceId] - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace - * @returns {String} key - decrypted workspace key - */ -export const getKey = async ({ workspaceId }: { workspaceId: Types.ObjectId }) => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - const botKey = await BotKey.findOne({ - workspace: workspaceId - }).populate<{ sender: IUser }>("sender", "publicKey"); - - if (!botKey) throw BotNotFoundError({ message: `getKey: Failed to find bot key for [workspaceId=${workspaceId}]` }) - - const bot = await Bot.findOne({ - workspace: workspaceId - }).select("+encryptedPrivateKey +iv +tag +algorithm +keyEncoding"); - - if (!bot) throw new Error("Failed to find bot"); - if (!bot.isActive) throw new Error("Bot is not active"); - - if (rootEncryptionKey && bot.keyEncoding === ENCODING_SCHEME_BASE64) { - // case: encoding scheme is base64 - const privateKeyBot = client.decryptSymmetric( - bot.encryptedPrivateKey, - rootEncryptionKey, - bot.iv, - bot.tag - ); - - return decryptAsymmetric({ - ciphertext: botKey.encryptedKey, - nonce: botKey.nonce, - publicKey: botKey.sender.publicKey as string, - privateKey: privateKeyBot - }); - } else if (encryptionKey && bot.keyEncoding === ENCODING_SCHEME_UTF8) { - // case: encoding scheme is utf8 - const privateKeyBot = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: bot.encryptedPrivateKey, - iv: bot.iv, - tag: bot.tag, - key: encryptionKey - }); - - return decryptAsymmetric({ - ciphertext: botKey.encryptedKey, - nonce: botKey.nonce, - publicKey: botKey.sender.publicKey as string, - privateKey: privateKeyBot - }); - } - - throw InternalServerError({ - message: "Failed to obtain bot's copy of workspace key needed for bot operations" - }); -}; - -/** - * Return symmetrically encrypted [plaintext] using the - * key for workspace with id [workspaceId] - * @param {Object} obj1 - * @param {String} obj1.workspaceId - id of workspace - * @param {String} obj1.plaintext - plaintext to encrypt - */ -export const encryptSymmetricHelper = async ({ - workspaceId, - plaintext -}: { - workspaceId: Types.ObjectId; - plaintext: string; -}) => { - const key = await getKey({ workspaceId: workspaceId }); - const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ - plaintext, - key - }); - - return { - ciphertext, - iv, - tag - }; -}; -/** - * Return symmetrically decrypted [ciphertext] using the - * key for workspace with id [workspaceId] - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace - * @param {String} obj.ciphertext - ciphertext to decrypt - * @param {String} obj.iv - iv - * @param {String} obj.tag - tag - */ -export const decryptSymmetricHelper = async ({ - workspaceId, - ciphertext, - iv, - tag -}: { - workspaceId: Types.ObjectId; - ciphertext: string; - iv: string; - tag: string; -}) => { - const key = await getKey({ workspaceId: workspaceId }); - const plaintext = decryptSymmetric128BitHexKeyUTF8({ - ciphertext, - iv, - tag, - key - }); - - return plaintext; -}; - -/** - * Return decrypted comments for workspace secrets with id [workspaceId] - * and [envionment] using bot - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace - * @param {String} obj.environment - environment - */ -export const getSecretsCommentBotHelper = async ({ - workspaceId, - environment, - secretPath -}: { - workspaceId: Types.ObjectId; - environment: string; - secretPath: string; -}) => { - const content = {} as any; - const key = await getKey({ workspaceId: workspaceId }); - - let folderId = "root"; - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }); - - if (!folders && secretPath !== "/") { - throw InternalServerError({ message: "Folder not found" }); - } - - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) { - throw InternalServerError({ message: "Folder not found" }); - } - folderId = folder.id; - } - - const secrets = await Secret.find({ - workspace: workspaceId, - environment, - type: SECRET_SHARED, - folder: folderId - }); - - secrets.forEach((secret: ISecret) => { - if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) { - const secretKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - key - }); - - const commentValue = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretCommentCiphertext, - iv: secret.secretCommentIV, - tag: secret.secretCommentTag, - key - }); - - content[secretKey] = commentValue; - } - }); - - return content; -}; diff --git a/backend-mongo/src/helpers/botOrg.ts b/backend-mongo/src/helpers/botOrg.ts deleted file mode 100644 index 003cabbdc..000000000 --- a/backend-mongo/src/helpers/botOrg.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { Types } from "mongoose"; -import { client, getEncryptionKey, getRootEncryptionKey } from "../config"; -import { BotOrg } from "../models"; -import { decryptSymmetric128BitHexKeyUTF8 } from "../utils/crypto"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8 -} from "../variables"; -import { InternalServerError } from "../utils/errors"; -import { encryptSymmetric128BitHexKeyUTF8, generateKeyPair } from "../utils/crypto"; - -/** - * Create a bot with name [name] for organization with id [organizationId] - * @param {Object} obj - * @param {String} obj.name - name of bot - * @param {String} obj.organizationId - id of organization that bot belongs to - */ -export const createBotOrg = async ({ - name, - organizationId, -}: { - name: string; - organizationId: Types.ObjectId; -}) => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - const { publicKey, privateKey } = generateKeyPair(); - const key = client.createSymmetricKey(); - - if (rootEncryptionKey) { - const { - ciphertext: encryptedPrivateKey, - iv: privateKeyIV, - tag: privateKeyTag - } = client.encryptSymmetric(privateKey, rootEncryptionKey); - - const { - ciphertext: encryptedSymmetricKey, - iv: symmetricKeyIV, - tag: symmetricKeyTag - } = client.encryptSymmetric(key, rootEncryptionKey); - - return await new BotOrg({ - name, - organization: organizationId, - publicKey, - encryptedSymmetricKey, - symmetricKeyIV, - symmetricKeyTag, - symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, - symmetricKeyKeyEncoding: ENCODING_SCHEME_BASE64, - encryptedPrivateKey, - privateKeyIV, - privateKeyTag, - privateKeyAlgorithm: ALGORITHM_AES_256_GCM, - privateKeyKeyEncoding: ENCODING_SCHEME_BASE64 - }).save(); - } else if (encryptionKey) { - const { - ciphertext: encryptedPrivateKey, - iv: privateKeyIV, - tag: privateKeyTag - } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: privateKey, - key: encryptionKey - }); - - const { - ciphertext: encryptedSymmetricKey, - iv: symmetricKeyIV, - tag: symmetricKeyTag - } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: key, - key: encryptionKey - }); - - return await new BotOrg({ - name, - organization: organizationId, - publicKey, - encryptedSymmetricKey, - symmetricKeyIV, - symmetricKeyTag, - symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, - symmetricKeyKeyEncoding: ENCODING_SCHEME_UTF8, - encryptedPrivateKey, - privateKeyIV, - privateKeyTag, - privateKeyAlgorithm: ALGORITHM_AES_256_GCM, - privateKeyKeyEncoding: ENCODING_SCHEME_UTF8 - }).save(); - } - - throw InternalServerError({ - message: "Failed to create new organization bot due to missing encryption key", - }); -}; - -export const getSymmetricKeyHelper = async (organizationId: Types.ObjectId) => { - const rootEncryptionKey = await getRootEncryptionKey(); - const encryptionKey = await getEncryptionKey(); - - const botOrg = await BotOrg.findOne({ - organization: organizationId - }); - - if (!botOrg) throw new Error("Failed to find organization bot"); - - if (rootEncryptionKey && botOrg.symmetricKeyKeyEncoding == ENCODING_SCHEME_BASE64) { - const key = client.decryptSymmetric( - botOrg.encryptedSymmetricKey, - rootEncryptionKey, - botOrg.symmetricKeyIV, - botOrg.symmetricKeyTag - ); - - return key; - } else if (encryptionKey && botOrg.symmetricKeyKeyEncoding === ENCODING_SCHEME_UTF8) { - const key = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: botOrg.encryptedSymmetricKey, - iv: botOrg.symmetricKeyIV, - tag: botOrg.symmetricKeyTag, - key: encryptionKey - }); - - return key; - } - - throw InternalServerError({ - message: "Failed to match encryption key with organization bot symmetric key encoding" - }); -} \ No newline at end of file diff --git a/backend-mongo/src/helpers/database.ts b/backend-mongo/src/helpers/database.ts deleted file mode 100644 index dc6d2faa6..000000000 --- a/backend-mongo/src/helpers/database.ts +++ /dev/null @@ -1,40 +0,0 @@ -import mongoose from "mongoose"; -import { logger } from "../utils/logging"; - -/** - * Initialize database connection - * @param {Object} obj - * @param {String} obj.mongoURL - mongo connection string - * @returns - */ -export const initDatabaseHelper = async ({ - mongoURL, -}: { - mongoURL: string; -}) => { - try { - await mongoose.connect(mongoURL); - - // allow empty strings to pass the required validator - mongoose.Schema.Types.String.checkRequired(v => typeof v === "string"); - - logger.info("Database connection established"); - - } catch (err) { - logger.error(err, "Unable to establish database connection"); - } - - return mongoose.connection; -} - -/** - * Close database conection - */ -export const closeDatabaseHelper = async () => { - if (mongoose.connection && mongoose.connection.readyState === 1) { - await mongoose.connection.close(); - return "Database connection closed"; - } else { - return "Database connection already closed"; - } -}; \ No newline at end of file diff --git a/backend-mongo/src/helpers/event.ts b/backend-mongo/src/helpers/event.ts deleted file mode 100644 index 231ac9c2e..000000000 --- a/backend-mongo/src/helpers/event.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Types } from "mongoose"; -import { Bot } from "../models"; -import { EVENT_PUSH_SECRETS, EVENT_START_INTEGRATION } from "../variables"; -import { IntegrationService } from "../services"; -import { triggerWebhook } from "../services/WebhookService"; - -interface Event { - name: string; - workspaceId: Types.ObjectId; - environment?: string; - secretPath?: string; - payload: any; -} - -/** - * Handle event [event] - * @param {Object} obj - * @param {Event} obj.event - an event - * @param {String} obj.event.name - name of event - * @param {String} obj.event.workspaceId - id of workspace that event is part of - * @param {Object} obj.event.payload - payload of event (depends on event) - */ -export const handleEventHelper = async ({ event }: { event: Event }) => { - const { workspaceId, environment, secretPath } = event; - - // TODO: moduralize bot check into separate function - const bot = await Bot.findOne({ - workspace: workspaceId, - isActive: true - }); - - switch (event.name) { - case EVENT_PUSH_SECRETS: - if (bot) { - IntegrationService.syncIntegrations({ - workspaceId, - environment - }); - } - triggerWebhook(workspaceId.toString(), environment || "", secretPath || ""); - break; - case EVENT_START_INTEGRATION: - if (bot) { - IntegrationService.syncIntegrations({ - workspaceId, - environment - }); - } - break; - } -}; diff --git a/backend-mongo/src/helpers/index.ts b/backend-mongo/src/helpers/index.ts deleted file mode 100644 index f9a0009fc..000000000 --- a/backend-mongo/src/helpers/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -export * from "./auth"; -export * from "./bot"; -export * from "./database"; -export * from "./event"; -export * from "./integration"; -export * from "./key"; -export * from "./membership"; -export * from "./membershipOrg"; -export * from "./nodemailer"; -export * from "./organization"; -export * from "./rateLimiter"; -export * from "./secret"; -export * from "./secrets"; -export * from "./signup"; -export * from "./token"; -export * from "./user"; -export * from "./workspace"; \ No newline at end of file diff --git a/backend-mongo/src/helpers/integration.ts b/backend-mongo/src/helpers/integration.ts deleted file mode 100644 index 6b94d5916..000000000 --- a/backend-mongo/src/helpers/integration.ts +++ /dev/null @@ -1,330 +0,0 @@ -import { Types } from "mongoose"; -import { Bot, IIntegrationAuth, IntegrationAuth } from "../models"; -import { exchangeCode, exchangeRefresh } from "../integrations"; -import { BotService } from "../services"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_UTF8, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_NETLIFY, - INTEGRATION_VERCEL, -} from "../variables"; -import { InternalServerError, UnauthorizedRequestError } from "../utils/errors"; -import { IntegrationAuthMetadata } from "../models/integrationAuth/types"; - -interface Update { - workspace: string; - integration: string; - url?: string; - teamId?: string; - accountId?: string; - metadata?: IntegrationAuthMetadata -} - -/** - * Perform OAuth2 code-token exchange for workspace with id [workspaceId] and integration - * named [integration] - * - Store integration access and refresh tokens returned from the OAuth2 code-token exchange - * - Add placeholder inactive integration - * - Create bot sequence for integration - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace - * @param {String} obj.integration - name of integration - * @param {String} obj.code - code - * @returns {IntegrationAuth} integrationAuth - integration auth after OAuth2 code-token exchange - */ -export const handleOAuthExchangeHelper = async ({ - workspaceId, - integration, - code, - environment, - url -}: { - workspaceId: string; - integration: string; - code: string; - environment: string; - url?: string; -}) => { - const bot = await Bot.findOne({ - workspace: workspaceId, - isActive: true - }); - - if (!bot) throw new Error("Bot must be enabled for OAuth2 code-token exchange"); - - // exchange code for access and refresh tokens - const res = await exchangeCode({ - integration, - code, - url - }); - - const update: Update = { - workspace: workspaceId, - integration - }; - - if (res.url) { - update.url = res.url; - } - - switch (integration) { - case INTEGRATION_VERCEL: - update.teamId = res.teamId; - break; - case INTEGRATION_NETLIFY: - update.accountId = res.accountId; - break; - case INTEGRATION_GCP_SECRET_MANAGER: - update.metadata = { - authMethod: "oauth2" - } - break; - } - - const integrationAuth = await IntegrationAuth.findOneAndUpdate( - { - workspace: workspaceId, - integration - }, - update, - { - new: true, - upsert: true - } - ); - - if (res.refreshToken) { - // case: refresh token returned from exchange - // set integration auth refresh token - await setIntegrationAuthRefreshHelper({ - integrationAuthId: integrationAuth._id.toString(), - refreshToken: res.refreshToken - }); - } - - if (res.accessToken) { - // case: access token returned from exchange - // set integration auth access token - await setIntegrationAuthAccessHelper({ - integrationAuthId: integrationAuth._id.toString(), - accessToken: res.accessToken, - accessExpiresAt: res.accessExpiresAt - }); - } - - return integrationAuth; -}; - -/** - * Return decrypted refresh token using the bot's copy - * of the workspace key for workspace belonging to integration auth - * with id [integrationAuthId] - * @param {Object} obj - * @param {String} obj.integrationAuthId - id of integration auth - * @param {String} refreshToken - decrypted refresh token - */ -export const getIntegrationAuthRefreshHelper = async ({ - integrationAuthId -}: { - integrationAuthId: Types.ObjectId; -}) => { - const integrationAuth = await IntegrationAuth.findById(integrationAuthId).select( - "+refreshCiphertext +refreshIV +refreshTag" - ); - - if (!integrationAuth) - throw UnauthorizedRequestError({ - message: "Failed to locate Integration Authentication credentials" - }); - - const refreshToken = await BotService.decryptSymmetric({ - workspaceId: integrationAuth.workspace, - ciphertext: integrationAuth.refreshCiphertext as string, - iv: integrationAuth.refreshIV as string, - tag: integrationAuth.refreshTag as string - }); - - return refreshToken; -}; - -/** - * Return decrypted access token using the bot's copy - * of the workspace key for workspace belonging to integration auth - * with id [integrationAuthId] - * @param {Object} obj - * @param {String} obj.integrationAuthId - id of integration auth - * @returns {String} accessToken - decrypted access token - */ -export const getIntegrationAuthAccessHelper = async ({ - integrationAuthId -}: { - integrationAuthId: Types.ObjectId; -}) => { - let accessId; - let accessToken; - const integrationAuth = await IntegrationAuth.findById(integrationAuthId).select( - "workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt +refreshCiphertext +refreshIV +refreshTag +accessIdCiphertext +accessIdIV +accessIdTag metadata teamId url" - ); - - if (!integrationAuth) - throw UnauthorizedRequestError({ - message: "Failed to locate Integration Authentication credentials" - }); - - if (integrationAuth.accessCiphertext && integrationAuth.accessIV && integrationAuth.accessTag) { - accessToken = await BotService.decryptSymmetric({ - workspaceId: integrationAuth.workspace, - ciphertext: integrationAuth.accessCiphertext as string, - iv: integrationAuth.accessIV as string, - tag: integrationAuth.accessTag as string - }); - } - - if (integrationAuth?.refreshCiphertext) { - // there is a access token expiration date - // and refresh token to exchange with the OAuth2 server - const refreshToken = await getIntegrationAuthRefreshHelper({ - integrationAuthId - }); - - if (integrationAuth?.accessExpiresAt && integrationAuth.accessExpiresAt < new Date()) { - // access token is expired - accessToken = await exchangeRefresh({ - integrationAuth, - refreshToken - }); - } - } - - if ( - integrationAuth?.accessIdCiphertext && - integrationAuth?.accessIdIV && - integrationAuth?.accessIdTag - ) { - accessId = await BotService.decryptSymmetric({ - workspaceId: integrationAuth.workspace, - ciphertext: integrationAuth.accessIdCiphertext as string, - iv: integrationAuth.accessIdIV as string, - tag: integrationAuth.accessIdTag as string - }); - } - - if (!accessToken) throw InternalServerError(); - - return { - integrationAuth, - accessId, - accessToken - }; -}; - -/** - * Encrypt refresh token [refreshToken] using the bot's copy - * of the workspace key for workspace belonging to integration auth - * with id [integrationAuthId] and store it - * @param {Object} obj - * @param {String} obj.integrationAuthId - id of integration auth - * @param {String} obj.refreshToken - refresh token - */ -export const setIntegrationAuthRefreshHelper = async ({ - integrationAuthId, - refreshToken -}: { - integrationAuthId: string; - refreshToken: string; -}): Promise => { - let integrationAuth = await IntegrationAuth.findById(integrationAuthId); - - if (!integrationAuth) throw new Error("Failed to find integration auth"); - - const obj = await BotService.encryptSymmetric({ - workspaceId: integrationAuth.workspace, - plaintext: refreshToken - }); - - integrationAuth = await IntegrationAuth.findOneAndUpdate( - { - _id: integrationAuthId - }, - { - refreshCiphertext: obj.ciphertext, - refreshIV: obj.iv, - refreshTag: obj.tag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }, - { - new: true - } - ); - - if (!integrationAuth) throw InternalServerError(); - - return integrationAuth; -}; - -/** - * Encrypt access token [accessToken] and (optionally) access id [accessId] - * using the bot's copy of the workspace key for workspace belonging to - * integration auth with id [integrationAuthId] and store it along with [accessExpiresAt] - * @param {Object} obj - * @param {String} obj.integrationAuthId - id of integration auth - * @param {String} obj.accessToken - access token - * @param {Date} obj.accessExpiresAt - expiration date of access token - */ -export const setIntegrationAuthAccessHelper = async ({ - integrationAuthId, - accessId, - accessToken, - accessExpiresAt -}: { - integrationAuthId: string; - accessId?: string; - accessToken?: string; - accessExpiresAt: Date | undefined; -}) => { - let integrationAuth = await IntegrationAuth.findById(integrationAuthId); - - if (!integrationAuth) throw new Error("Failed to find integration auth"); - - let encryptedAccessTokenObj; - let encryptedAccessIdObj; - - if (accessToken) { - encryptedAccessTokenObj = await BotService.encryptSymmetric({ - workspaceId: integrationAuth.workspace, - plaintext: accessToken - }); - } - - if (accessId) { - encryptedAccessIdObj = await BotService.encryptSymmetric({ - workspaceId: integrationAuth.workspace, - plaintext: accessId - }); - } - - integrationAuth = await IntegrationAuth.findOneAndUpdate( - { - _id: integrationAuthId - }, - { - accessIdCiphertext: encryptedAccessIdObj?.ciphertext ?? undefined, - accessIdIV: encryptedAccessIdObj?.iv, - accessIdTag: encryptedAccessIdObj?.tag, - accessCiphertext: encryptedAccessTokenObj?.ciphertext, - accessIV: encryptedAccessTokenObj?.iv, - accessTag: encryptedAccessTokenObj?.tag, - accessExpiresAt, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }, - { - new: true - } - ); - - return integrationAuth; -}; diff --git a/backend-mongo/src/helpers/key.ts b/backend-mongo/src/helpers/key.ts deleted file mode 100644 index 88bf28f47..000000000 --- a/backend-mongo/src/helpers/key.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { IKey, Key } from "../models"; - -interface Key { - encryptedKey: string; - nonce: string; - userId: string; -} - -/** - * Push (access) [keys] for workspace with id [workspaceId] with - * user with id [userId] as the sender - * @param {Object} obj - * @param {String} obj.userId - id of sender user - * @param {String} obj.workspaceId - id of workspace that keys belong to - * @param {Object[]} obj.keys - (access) keys to push - * @param {String} obj.keys.encryptedKey - encrypted key under receiver's public key - * @param {String} obj.keys.nonce - nonce for encryption - * @param {String} obj.keys.userId - id of receiver user - */ -export const pushKeys = async ({ - userId, - workspaceId, - keys, -}: { - userId: string; - workspaceId: string; - keys: Key[]; -}): Promise => { - // filter out already-inserted keys - const keysSet = new Set( - ( - await Key.find( - { - workspace: workspaceId, - }, - "receiver" - ) - ).map((k: IKey) => k.receiver.toString()) - ); - - keys = keys.filter((key) => !keysSet.has(key.userId)); - - // add new shared keys only - await Key.insertMany( - keys.map((k) => ({ - encryptedKey: k.encryptedKey, - nonce: k.nonce, - sender: userId, - receiver: k.userId, - workspace: workspaceId, - })) - ); -}; \ No newline at end of file diff --git a/backend-mongo/src/helpers/membership.ts b/backend-mongo/src/helpers/membership.ts deleted file mode 100644 index d08d07a45..000000000 --- a/backend-mongo/src/helpers/membership.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { Types } from "mongoose"; -import { Key, Membership } from "../models"; -import { BadRequestError, MembershipNotFoundError } from "../utils/errors"; - -/** - * Validate that user with id [userId] is a member of workspace with id [workspaceId] - * and has at least one of the roles in [acceptedRoles] - * @param {Object} obj - * @param {String} obj.userId - id of user to validate - * @param {String} obj.workspaceId - id of workspace - * @returns {Membership} membership - membership of user with id [userId] for workspace with id [workspaceId] - */ -export const validateMembership = async ({ - userId, - workspaceId, - acceptedRoles -}: { - userId: Types.ObjectId | string; - workspaceId: Types.ObjectId | string; - acceptedRoles?: Array<"admin" | "member" | "custom" | "viewer" | "no-access">; -}) => { - const membership = await Membership.findOne({ - user: userId, - workspace: workspaceId - }).populate("workspace"); - - if (!membership) { - throw MembershipNotFoundError({ - message: "Failed to find workspace membership" - }); - } - - if (acceptedRoles) { - if (!acceptedRoles.includes(membership.role)) { - throw BadRequestError({ - message: "Failed authorization for membership role" - }); - } - } - - return membership; -}; - -/** - * Return membership matching criteria specified in query [queryObj] - * @param {Object} queryObj - query object - * @return {Object} membership - membership - */ -export const findMembership = async (queryObj: any) => { - const membership = await Membership.findOne(queryObj); - return membership; -}; - -/** - * Add memberships for users with ids [userIds] to workspace with - * id [workspaceId] - * @param {Object} obj - * @param {String[]} obj.userIds - id of users. - * @param {String} obj.workspaceId - id of workspace. - * @param {String[]} obj.roles - roles of users. - */ -export const addMemberships = async ({ - userIds, - workspaceId, - roles -}: { - userIds: string[]; - workspaceId: string; - roles: string[]; -}): Promise => { - const operations = userIds.map((userId, idx) => { - return { - updateOne: { - filter: { - user: userId, - workspace: workspaceId, - role: roles[idx] - }, - update: { - user: userId, - workspace: workspaceId, - role: roles[idx] - }, - upsert: true - } - }; - }); - await Membership.bulkWrite(operations as any); -}; - -/** - * Delete membership with id [membershipId] - * @param {Object} obj - * @param {String} obj.membershipId - id of membership to delete - */ -export const deleteMembership = async ({ membershipId }: { membershipId: string }) => { - const deletedMembership = await Membership.findOneAndDelete({ - _id: membershipId - }); - - // delete keys associated with the membership - if (deletedMembership?.user) { - // case: membership had a registered user - await Key.deleteMany({ - receiver: deletedMembership.user, - workspace: deletedMembership.workspace - }); - } - - return deletedMembership; -}; diff --git a/backend-mongo/src/helpers/membershipOrg.ts b/backend-mongo/src/helpers/membershipOrg.ts deleted file mode 100644 index 9f2e8d93c..000000000 --- a/backend-mongo/src/helpers/membershipOrg.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { Types } from "mongoose"; -import { Key, Membership, MembershipOrg, Workspace } from "../models"; -import { MembershipOrgNotFoundError, UnauthorizedRequestError } from "../utils/errors"; - -/** - * Validate that user with id [userId] is a member of organization with id [organizationId] - * and has at least one of the roles in [acceptedRoles] - * @param {Object} obj - * @param {Types.ObjectId} obj.userId - * @param {Types.ObjectId} obj.organizationId - * @param {String[]} obj.acceptedRoles - */ -export const validateMembershipOrg = async ({ - userId, - organizationId, - acceptedRoles, - acceptedStatuses -}: { - userId: Types.ObjectId; - organizationId: Types.ObjectId; - acceptedRoles?: Array<"owner" | "admin" | "member" | "custom" | "no-access">; - acceptedStatuses?: Array<"invited" | "accepted">; -}) => { - const membershipOrg = await MembershipOrg.findOne({ - user: userId, - organization: organizationId - }); - - if (!membershipOrg) { - throw MembershipOrgNotFoundError({ message: "Failed to find organization membership" }); - } - - if (acceptedRoles) { - if (!acceptedRoles.includes(membershipOrg.role)) { - throw UnauthorizedRequestError({ - message: "Failed to validate organization membership role" - }); - } - } - - if (acceptedStatuses) { - if (!acceptedStatuses.includes(membershipOrg.status)) { - throw UnauthorizedRequestError({ - message: "Failed to validate organization membership status" - }); - } - } - - return membershipOrg; -}; - -/** - * Return organization membership matching criteria specified in - * query [queryObj] - * @param {Object} queryObj - query object - * @return {Object} membershipOrg - membership - */ -export const findMembershipOrg = (queryObj: any) => { - const membershipOrg = MembershipOrg.findOne(queryObj); - return membershipOrg; -}; - -/** - * Add organization memberships for users with ids [userIds] to organization with - * id [organizationId] - * @param {Object} obj - * @param {String[]} obj.userIds - id of users. - * @param {String} obj.organizationId - id of organization. - * @param {String[]} obj.roles - roles of users. - */ -export const addMembershipsOrg = async ({ - userIds, - organizationId, - roles, - statuses -}: { - userIds: string[]; - organizationId: string; - roles: string[]; - statuses: string[]; -}) => { - const operations = userIds.map((userId, idx) => { - return { - updateOne: { - filter: { - user: userId, - organization: organizationId, - role: roles[idx], - status: statuses[idx] - }, - update: { - user: userId, - organization: organizationId, - role: roles[idx], - status: statuses[idx] - }, - upsert: true - } - }; - }); - - await MembershipOrg.bulkWrite(operations as any); -}; - -/** - * Delete organization membership with id [membershipOrgId] - * @param {Object} obj - * @param {String} obj.membershipOrgId - id of organization membership to delete - */ -export const deleteMembershipOrg = async ({ membershipOrgId }: { membershipOrgId: string }) => { - const deletedMembershipOrg = await MembershipOrg.findOneAndDelete({ - _id: membershipOrgId - }); - - if (!deletedMembershipOrg) throw new Error("Failed to delete organization membership"); - - // delete keys associated with organization membership - if (deletedMembershipOrg?.user) { - // case: organization membership had a registered user - - const workspaces = ( - await Workspace.find({ - organization: deletedMembershipOrg.organization - }) - ).map((w) => w._id.toString()); - - await Membership.deleteMany({ - user: deletedMembershipOrg.user, - workspace: { - $in: workspaces - } - }); - - await Key.deleteMany({ - receiver: deletedMembershipOrg.user, - workspace: { - $in: workspaces - } - }); - } - - return deletedMembershipOrg; -}; diff --git a/backend-mongo/src/helpers/nodemailer.ts b/backend-mongo/src/helpers/nodemailer.ts deleted file mode 100644 index b83d9bf61..000000000 --- a/backend-mongo/src/helpers/nodemailer.ts +++ /dev/null @@ -1,46 +0,0 @@ -import fs from "fs"; -import path from "path"; -import handlebars from "handlebars"; -import nodemailer from "nodemailer"; -import { getSmtpConfigured, getSmtpFromAddress, getSmtpFromName } from "../config"; - -let smtpTransporter: nodemailer.Transporter; - -/** - * @param {Object} obj - * @param {String} obj.template - email template to use from /templates folder (e.g. testEmail.handlebars) - * @param {String[]} obj.subjectLine - email subject line - * @param {String[]} obj.recipients - email addresses of people to send email to - * @param {Object} obj.substitutions - object containing template substitutions - */ -export const sendMail = async ({ - template, - subjectLine, - recipients, - substitutions, -}: { - template: string; - subjectLine: string; - recipients: string[]; - substitutions: any; -}) => { - if (await getSmtpConfigured()) { - const html = fs.readFileSync( - path.resolve(__dirname, "../templates/" + template), - "utf8" - ); - const temp = handlebars.compile(html); - const htmlToSend = temp(substitutions); - - await smtpTransporter.sendMail({ - from: `"${await getSmtpFromName()}" <${await getSmtpFromAddress()}>`, - to: recipients.join(", "), - subject: subjectLine, - html: htmlToSend, - }); - } -}; - -export const setTransporter = (transporter: nodemailer.Transporter) => { - smtpTransporter = transporter; -}; \ No newline at end of file diff --git a/backend-mongo/src/helpers/organization.ts b/backend-mongo/src/helpers/organization.ts deleted file mode 100644 index 36d1baeb6..000000000 --- a/backend-mongo/src/helpers/organization.ts +++ /dev/null @@ -1,385 +0,0 @@ -import { Types } from "mongoose"; -import { - Bot, - BotKey, - BotOrg, - Folder, - Identity, - IdentityMembership, - IdentityMembershipOrg, - IdentityUniversalAuth, - IdentityUniversalAuthClientSecret, - IncidentContactOrg, - Integration, - IntegrationAuth, - Key, - Membership, - MembershipOrg, - Organization, - Secret, - SecretBlindIndexData, - SecretImport, - ServiceToken, - ServiceTokenData, - Tag, - Webhook, - Workspace -} from "../models"; -import { - AuditLog, - FolderVersion, - GitAppInstallationSession, - GitAppOrganizationInstallation, - GitRisks, - Role, - SSOConfig, - SecretApprovalPolicy, - SecretApprovalRequest, - SecretSnapshot, - SecretVersion, - TrustedIP -} from "../ee/models"; -import { - ACCEPTED, -} from "../variables"; -import { - EELicenseService, -} from "../ee/services"; -import { - getLicenseServerKey, - getLicenseServerUrl, -} from "../config"; -import { - licenseKeyRequest, - licenseServerKeyRequest, -} from "../config/request"; -import { - createBotOrg -} from "./botOrg"; -import { ResourceNotFoundError } from "../utils/errors"; - -/** - * Create an organization with name [name] - * @param {Object} obj - * @param {String} obj.name - name of organization to create. - * @param {String} obj.email - POC email that will receive invoice info - * @param {Object} organization - new organization - */ -export const createOrganization = async ({ - name, - email, -}: { - name: string; - email: string; -}) => { - - const licenseServerKey = await getLicenseServerKey(); - let organization; - - if (licenseServerKey) { - const { data: { customerId } } = await licenseServerKeyRequest.post( - `${await getLicenseServerUrl()}/api/license-server/v1/customers`, - { - email, - name - } - ); - - organization = await new Organization({ - name, - customerId - }).save(); - - } else { - organization = await new Organization({ - name, - }).save(); - } - - // initialize bot for organization - await createBotOrg({ - name, - organizationId: organization._id - }); - - return organization; -}; - -/** - * Delete organization with id [organizationId] - * @param {Object} obj - * @param {Types.ObjectId} obj.organizationId - id of organization to delete - * @returns - */ -export const deleteOrganization = async ({ - organizationId -}: { - organizationId: Types.ObjectId; -}) => { - - const organization = await Organization.findByIdAndDelete( - organizationId - ); - - if (!organization) throw ResourceNotFoundError(); - - await MembershipOrg.deleteMany({ - organization: organization._id - }); - - const identityIds = await IdentityMembershipOrg.distinct("identity", { - organization: organization._id - }); - - await IdentityMembershipOrg.deleteMany({ - organization: organization._id - }); - - await Identity.deleteMany({ - _id: { - $in: identityIds - } - }); - - await IdentityUniversalAuth.deleteMany({ - identity: { - $in: identityIds - } - }); - - await IdentityUniversalAuthClientSecret.deleteMany({ - identity: { - $in: identityIds - } - }); - - await BotOrg.deleteMany({ - organization: organization._id - }); - - await SSOConfig.deleteMany({ - organization: organization._id - }); - - await Role.deleteMany({ - organization: organization._id - }); - - await IncidentContactOrg.deleteMany({ - organization: organization._id - }); - - await GitRisks.deleteMany({ - organization: organization._id - }); - - await GitAppInstallationSession.deleteMany({ - organization: organization._id - }); - - await GitAppOrganizationInstallation.deleteMany({ - organization: organization._id - }); - - const workspaceIds = await Workspace.distinct("_id", { - organization: organization._id - }); - - await Workspace.deleteMany({ - organization: organization._id - }); - - await Membership.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await Key.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await Bot.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await BotKey.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await SecretBlindIndexData.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await Secret.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await SecretVersion.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await SecretSnapshot.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await SecretImport.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await Folder.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await FolderVersion.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await Webhook.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await TrustedIP.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await Tag.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await IntegrationAuth.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await Integration.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await ServiceToken.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await ServiceTokenData.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await IdentityMembership.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await AuditLog.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await SecretApprovalPolicy.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - await SecretApprovalRequest.deleteMany({ - workspace: { - $in: workspaceIds - } - }); - - if (organization.customerId) { - // delete from stripe here - await licenseServerKeyRequest.delete( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${organization.customerId}` - ); - } - - return organization; -} - -/** - * Update organization subscription quantity to reflect number of members in - * the organization. - * @param {Object} obj - * @param {Number} obj.organizationId - id of subscription's organization - */ -export const updateSubscriptionOrgQuantity = async ({ - organizationId, -}: { - organizationId: string; -}) => { - // find organization - const organization = await Organization.findOne({ - _id: organizationId, - }); - - if (organization && organization.customerId) { - if (EELicenseService.instanceType === "cloud") { - // instance of Infisical is a cloud instance - const quantity = await MembershipOrg.countDocuments({ - organization: new Types.ObjectId(organizationId), - status: ACCEPTED, - }); - - await licenseServerKeyRequest.patch( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${organization.customerId}/cloud-plan`, - { - quantity, - } - ); - - EELicenseService.localFeatureSet.del(organizationId); - } - } - - if (EELicenseService.instanceType === "enterprise-self-hosted") { - // instance of Infisical is an enterprise self-hosted instance - - const usedSeats = await MembershipOrg.countDocuments({ - status: ACCEPTED, - }); - - await licenseKeyRequest.patch( - `${await getLicenseServerUrl()}/api/license/v1/license`, - { - usedSeats, - } - ); - } - - await EELicenseService.refreshPlan(new Types.ObjectId(organizationId)); -}; \ No newline at end of file diff --git a/backend-mongo/src/helpers/rateLimiter.ts b/backend-mongo/src/helpers/rateLimiter.ts deleted file mode 100644 index 451291072..000000000 --- a/backend-mongo/src/helpers/rateLimiter.ts +++ /dev/null @@ -1,64 +0,0 @@ -import rateLimit from "express-rate-limit"; -// const MongoStore = require('rate-limit-mongo'); - -// 200 per minute -export const apiLimiter = rateLimit({ - // store: new MongoStore({ - // uri: process.env.MONGO_URL, - // expireTimeMs: 1000 * 60, - // collectionName: "expressRateRecords-apiLimiter", - // errorHandler: console.error.bind(null, 'rate-limit-mongo') - // }), - windowMs: 60 * 1000, - max: 480, - standardHeaders: true, - legacyHeaders: false, - skip: (request) => { - return request.path === "/healthcheck" || request.path === "/api/status" - }, - keyGenerator: (req, res) => { - return req.realIP - }, -}); - -// 50 requests per 1 hours -const authLimit = rateLimit({ - // store: new MongoStore({ - // uri: process.env.MONGO_URL, - // expireTimeMs: 1000 * 60 * 60, - // errorHandler: console.error.bind(null, 'rate-limit-mongo'), - // collectionName: "expressRateRecords-authLimit", - // }), - windowMs: 60 * 1000, - max: 300, - standardHeaders: true, - legacyHeaders: false, - keyGenerator: (req, res) => { - return req.realIP - }, -}); - -// 5 requests per 1 hour -export const passwordLimiter = rateLimit({ - // store: new MongoStore({ - // uri: process.env.MONGO_URL, - // expireTimeMs: 1000 * 60 * 60, - // errorHandler: console.error.bind(null, 'rate-limit-mongo'), - // collectionName: "expressRateRecords-passwordLimiter", - // }), - windowMs: 60 * 1000, - max: 300, - standardHeaders: true, - legacyHeaders: false, - keyGenerator: (req, res) => { - return req.realIP - }, -}); - -export const authLimiter = (req: any, res: any, next: any) => { - if (process.env.NODE_ENV === "production") { - authLimit(req, res, next); - } else { - next(); - } -}; \ No newline at end of file diff --git a/backend-mongo/src/helpers/reminder.ts b/backend-mongo/src/helpers/reminder.ts deleted file mode 100644 index d896a2f3d..000000000 --- a/backend-mongo/src/helpers/reminder.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { ISecret } from "../models"; -import { - createRecurringSecretReminder, - deleteRecurringSecretReminder, - updateRecurringSecretReminder -} from "../queues/reminders/sendSecretReminders"; - -type TPartialSecret = Pick< - ISecret, - "_id" | "secretReminderRepeatDays" | "secretReminderNote" | "workspace" ->; -type TPartialSecretDeleteReminder = Pick; - -export const createReminder = async (oldSecret: TPartialSecret, newSecret: TPartialSecret) => { - if (oldSecret._id !== newSecret._id) { - throw new Error("Secret id's don't match"); - } - - if (!newSecret.secretReminderRepeatDays) { - throw new Error("No repeat days provided"); - } - - const secretId = oldSecret._id.toString(); - const workspaceId = oldSecret.workspace.toString(); - - if (oldSecret.secretReminderRepeatDays) { - // This will first delete the existing recurring job, and then create a new one. - await updateRecurringSecretReminder({ - workspaceId, - secretId, - repeatDays: newSecret.secretReminderRepeatDays, - note: newSecret.secretReminderNote - }); - } else { - // This will create a new recurring job. - await createRecurringSecretReminder({ - workspaceId, - secretId, - repeatDays: newSecret.secretReminderRepeatDays, - note: newSecret.secretReminderNote - }); - } -}; - -export const deleteReminder = async (secret: TPartialSecretDeleteReminder) => { - if (!secret._id) { - throw new Error("No secret id provided"); - } - - if (!secret.secretReminderRepeatDays) { - throw new Error("No repeat days provided"); - } - - await deleteRecurringSecretReminder({ - secretId: secret._id.toString(), - repeatDays: secret.secretReminderRepeatDays - }); -}; diff --git a/backend-mongo/src/helpers/secret.ts b/backend-mongo/src/helpers/secret.ts deleted file mode 100644 index 6bdc21e99..000000000 --- a/backend-mongo/src/helpers/secret.ts +++ /dev/null @@ -1,589 +0,0 @@ -import { Types } from "mongoose"; -import { ISecret, Secret } from "../models"; -import { EESecretService } from "../ee/services"; -import { SecretVersion } from "../ee/models"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_UTF8, - SECRET_PERSONAL, - SECRET_SHARED, -} from "../variables"; - -interface V1PushSecret { - ciphertextKey: string; - ivKey: string; - tagKey: string; - hashKey: string; - ciphertextValue: string; - ivValue: string; - tagValue: string; - hashValue: string; - ciphertextComment: string; - ivComment: string; - tagComment: string; - hashComment: string; - type: "shared" | "personal"; -} - -interface V2PushSecret { - type: string; // personal or shared - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretKeyHash: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretValueHash: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - secretCommentHash?: string; -} - -interface Update { - [index: string]: any; -} - -/** - * Push secrets for user with id [userId] to workspace - * with id [workspaceId] with environment [environment]. Follow steps: - * 1. Handle shared secrets (insert, delete) - * 2. handle personal secrets (insert, delete) - * @param {Object} obj - * @param {String} obj.userId - id of user to push secrets for - * @param {String} obj.workspaceId - id of workspace to push to - * @param {String} obj.environment - environment for secrets - * @param {Object[]} obj.secrets - secrets to push - */ -export const v1PushSecrets = async ({ - userId, - workspaceId, - environment, - secrets, -}: { - userId: string; - workspaceId: string; - environment: string; - secrets: V1PushSecret[]; -}): Promise => { - // TODO: clean up function and fix up types - // construct useful data structures - const oldSecrets = await getSecrets({ - userId, - workspaceId, - environment, - }); - - const oldSecretsObj: any = oldSecrets.reduce( - (accumulator, s: any) => ({ - ...accumulator, - [`${s.type}-${s.secretKeyHash}`]: s, - }), - {} - ); - const newSecretsObj: any = secrets.reduce( - (accumulator, s) => ({ ...accumulator, [`${s.type}-${s.hashKey}`]: s }), - {} - ); - - // handle deleting secrets - const toDelete = oldSecrets - .filter((s: ISecret) => !(`${s.type}-${s.secretKeyHash}` in newSecretsObj)) - .map((s) => s._id); - if (toDelete.length > 0) { - await Secret.deleteMany({ - _id: { $in: toDelete }, - }); - - await EESecretService.markDeletedSecretVersions({ - secretIds: toDelete, - }); - } - - const toUpdate = oldSecrets.filter((s) => { - if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) { - if ( - s.secretValueHash !== - newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue || - s.secretCommentHash !== - newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashComment - ) { - // case: filter secrets where value or comment changed - return true; - } - - if (!s.version) { - // case: filter (legacy) secrets that were not versioned - return true; - } - } - - return false; - }); - - const operations = toUpdate.map((s) => { - const { - ciphertextValue, - ivValue, - tagValue, - hashValue, - ciphertextComment, - ivComment, - tagComment, - hashComment, - } = newSecretsObj[`${s.type}-${s.secretKeyHash}`]; - - const update: Update = { - secretValueCiphertext: ciphertextValue, - secretValueIV: ivValue, - secretValueTag: tagValue, - secretValueHash: hashValue, - secretCommentCiphertext: ciphertextComment, - secretCommentIV: ivComment, - secretCommentTag: tagComment, - secretCommentHash: hashComment, - }; - - if (!s.version) { - // case: (legacy) secret was not versioned - update.version = 1; - } else { - update["$inc"] = { - version: 1, - }; - } - - if (s.type === SECRET_PERSONAL) { - // attach user associated with the personal secret - update["user"] = userId; - } - - return { - updateOne: { - filter: { - _id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id, - }, - update, - }, - }; - }); - await Secret.bulkWrite(operations as any); - - // (EE) add secret versions for updated secrets - await EESecretService.addSecretVersions({ - secretVersions: toUpdate.map(({ _id, version, type, secretKeyHash }) => { - const newSecret = newSecretsObj[`${type}-${secretKeyHash}`]; - return new SecretVersion({ - secret: _id, - version: version ? version + 1 : 1, - workspace: new Types.ObjectId(workspaceId), - type: newSecret.type, - user: new Types.ObjectId(userId), - environment, - isDeleted: false, - secretKeyCiphertext: newSecret.ciphertextKey, - secretKeyIV: newSecret.ivKey, - secretKeyTag: newSecret.tagKey, - secretKeyHash: newSecret.hashKey, - secretValueCiphertext: newSecret.ciphertextValue, - secretValueIV: newSecret.ivValue, - secretValueTag: newSecret.tagValue, - secretValueHash: newSecret.hashValue, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - }); - }), - }); - - // handle adding new secrets - const toAdd = secrets.filter( - (s) => !(`${s.type}-${s.hashKey}` in oldSecretsObj) - ); - - if (toAdd.length > 0) { - // add secrets - const newSecrets: ISecret[] = ( - await Secret.insertMany( - toAdd.map((s, idx) => { - const obj: any = { - version: 1, - workspace: workspaceId, - type: toAdd[idx].type, - environment, - secretKeyCiphertext: s.ciphertextKey, - secretKeyIV: s.ivKey, - secretKeyTag: s.tagKey, - secretKeyHash: s.hashKey, - secretValueCiphertext: s.ciphertextValue, - secretValueIV: s.ivValue, - secretValueTag: s.tagValue, - secretValueHash: s.hashValue, - secretCommentCiphertext: s.ciphertextComment, - secretCommentIV: s.ivComment, - secretCommentTag: s.tagComment, - secretCommentHash: s.hashComment, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - }; - - if (toAdd[idx].type === "personal") { - obj["user" as keyof typeof obj] = userId; - } - - return obj; - }) - ) - ).map((insertedSecret) => insertedSecret.toObject()); - - // (EE) add secret versions for new secrets - EESecretService.addSecretVersions({ - secretVersions: newSecrets.map( - ({ - _id, - version, - workspace, - type, - user, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretKeyHash, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash, - algorithm, - keyEncoding, - }) => - new SecretVersion({ - secret: _id, - version, - workspace, - type, - user, - environment, - isDeleted: false, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretKeyHash, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash, - algorithm, - keyEncoding, - }) - ), - }); - } - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - }); -}; - -/** - * Push secrets for user with id [userId] to workspace - * with id [workspaceId] with environment [environment]. Follow steps: - * 1. Handle shared secrets (insert, delete) - * 2. handle personal secrets (insert, delete) - * @param {Object} obj - * @param {String} obj.userId - id of user to push secrets for - * @param {String} obj.workspaceId - id of workspace to push to - * @param {String} obj.environment - environment for secrets - * @param {Object[]} obj.secrets - secrets to push - * @param {String} obj.channel - channel (web/cli/auto) - * @param {String} obj.ipAddress - ip address of request to push secrets - */ -export const v2PushSecrets = async ({ - userId, - workspaceId, - environment, - secrets, - channel, - ipAddress, -}: { - userId: string; - workspaceId: string; - environment: string; - secrets: V2PushSecret[]; - channel: string; - ipAddress: string; -}): Promise => { - // TODO: clean up function and fix up types - - // construct useful data structures - const oldSecrets = await getSecrets({ - userId, - workspaceId, - environment, - }); - - const oldSecretsObj: any = oldSecrets.reduce( - (accumulator, s: any) => ({ - ...accumulator, - [`${s.type}-${s.secretKeyHash}`]: s, - }), - {} - ); - const newSecretsObj: any = secrets.reduce( - (accumulator, s) => ({ - ...accumulator, - [`${s.type}-${s.secretKeyHash}`]: s, - }), - {} - ); - - // handle deleting secrets - const toDelete = oldSecrets - .filter((s: ISecret) => !(`${s.type}-${s.secretKeyHash}` in newSecretsObj)) - .map((s) => s._id); - if (toDelete.length > 0) { - await Secret.deleteMany({ - _id: { $in: toDelete }, - }); - - await EESecretService.markDeletedSecretVersions({ - secretIds: toDelete, - }); - } - - const toUpdate = oldSecrets.filter((s) => { - if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) { - if ( - s.secretValueHash !== - newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretValueHash || - s.secretCommentHash !== - newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretCommentHash - ) { - // case: filter secrets where value or comment changed - return true; - } - - if (!s.version) { - // case: filter (legacy) secrets that were not versioned - return true; - } - } - - return false; - }); - - if (toUpdate.length > 0) { - const operations = toUpdate.map((s) => { - const { - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - secretCommentHash, - } = newSecretsObj[`${s.type}-${s.secretKeyHash}`]; - - const update: Update = { - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - secretCommentHash, - }; - - if (!s.version) { - // case: (legacy) secret was not versioned - update.version = 1; - } else { - update["$inc"] = { - version: 1, - }; - } - - if (s.type === SECRET_PERSONAL) { - // attach user associated with the personal secret - update["user"] = userId; - } - - return { - updateOne: { - filter: { - _id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id, - }, - update, - }, - }; - }); - await Secret.bulkWrite(operations as any); - - // (EE) add secret versions for updated secrets - await EESecretService.addSecretVersions({ - secretVersions: toUpdate.map((s) => { - return { - ...newSecretsObj[`${s.type}-${s.secretKeyHash}`], - secret: s._id, - version: s.version ? s.version + 1 : 1, - workspace: new Types.ObjectId(workspaceId), - user: s.user, - environment: s.environment, - isDeleted: false, - }; - }), - }); - } - - // handle adding new secrets - const toAdd = secrets.filter( - (s) => !(`${s.type}-${s.secretKeyHash}` in oldSecretsObj) - ); - - if (toAdd.length > 0) { - // add secrets - const newSecrets = await Secret.insertMany( - toAdd.map((s, idx) => ({ - ...s, - version: 1, - workspace: workspaceId, - type: toAdd[idx].type, - environment, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - ...(toAdd[idx].type === "personal" ? { user: userId } : {}), - })) - ); - - // (EE) add secret versions for new secrets - EESecretService.addSecretVersions({ - secretVersions: newSecrets.map((secretDocument) => { - return new SecretVersion({ - ...secretDocument, - secret: secretDocument._id, - isDeleted: false, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - }); - }), - }); - } - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: new Types.ObjectId(workspaceId), - environment, - }); -}; - -/** - * Get secrets for user with id [userId] for workspace - * with id [workspaceId] with environment [environment] - * @param {Object} obj - * @param {String} obj.userId -id of user to pull secrets for - * @param {String} obj.workspaceId - id of workspace to pull from - * @param {String} obj.environment - environment for secrets - */ -export const getSecrets = async ({ - userId, - workspaceId, - environment, -}: { - userId: string; - workspaceId: string; - environment: string; -}): Promise => { - // get shared workspace secrets - const sharedSecrets = await Secret.find({ - workspace: workspaceId, - environment, - type: SECRET_SHARED, - }); - - // get personal workspace secrets - const personalSecrets = await Secret.find({ - workspace: workspaceId, - environment, - type: SECRET_PERSONAL, - user: userId, - }); - - // concat shared and personal workspace secrets - const secrets = personalSecrets.concat(sharedSecrets); - - return secrets; -}; - -/** - * Pull secrets for user with id [userId] for workspace - * with id [workspaceId] with environment [environment] - * @param {Object} obj - * @param {String} obj.userId -id of user to pull secrets for - * @param {String} obj.workspaceId - id of workspace to pull from - * @param {String} obj.environment - environment for secrets - * @param {String} obj.channel - channel (web/cli/auto) - * @param {String} obj.ipAddress - ip address of request to push secrets - */ -export const pullSecrets = async ({ - userId, - workspaceId, - environment, - channel, - ipAddress, -}: { - userId: string; - workspaceId: string; - environment: string; - channel: string; - ipAddress: string; -}): Promise => { - const secrets = await getSecrets({ - userId, - workspaceId, - environment, - }); - - return secrets; -}; - -/** - * Reformat output of pullSecrets() to be compatible with how existing - * web client handle secrets - * @param {Object} obj - * @param {Object} obj.secrets - */ -export const reformatPullSecrets = ({ secrets }: { secrets: ISecret[] }) => { - const reformatedSecrets = secrets.map((s) => ({ - _id: s._id, - workspace: s.workspace, - type: s.type, - environment: s.environment, - secretKey: { - workspace: s.workspace, - ciphertext: s.secretKeyCiphertext, - iv: s.secretKeyIV, - tag: s.secretKeyTag, - hash: s.secretKeyHash, - }, - secretValue: { - workspace: s.workspace, - ciphertext: s.secretValueCiphertext, - iv: s.secretValueIV, - tag: s.secretValueTag, - hash: s.secretValueHash, - }, - secretComment: { - workspace: s.workspace, - ciphertext: s.secretCommentCiphertext, - iv: s.secretCommentIV, - tag: s.secretCommentTag, - hash: s.secretCommentHash, - }, - })); - - return reformatedSecrets; -}; \ No newline at end of file diff --git a/backend-mongo/src/helpers/secrets.ts b/backend-mongo/src/helpers/secrets.ts deleted file mode 100644 index eccef634d..000000000 --- a/backend-mongo/src/helpers/secrets.ts +++ /dev/null @@ -1,1748 +0,0 @@ -import { Types } from "mongoose"; -import { - CreateSecretBatchParams, - CreateSecretParams, - DeleteSecretBatchParams, - DeleteSecretParams, - GetSecretParams, - GetSecretsParams, - UpdateSecretBatchParams, - UpdateSecretParams -} from "../interfaces/services/SecretService"; -import { - Folder, - ISecret, - IServiceTokenData, - Secret, - SecretBlindIndexData, - ServiceTokenData, - TFolderRootSchema -} from "../models"; -import { EventType, SecretVersion } from "../ee/models"; -import { - BadRequestError, - InternalServerError, - SecretBlindIndexDataNotFoundError, - SecretNotFoundError, - UnauthorizedRequestError -} from "../utils/errors"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, - K8_USER_AGENT_NAME, - SECRET_PERSONAL, - SECRET_SHARED -} from "../variables"; -import crypto from "crypto"; -import * as argon2 from "argon2"; -import { - decryptSymmetric128BitHexKeyUTF8, - encryptSymmetric128BitHexKeyUTF8 -} from "../utils/crypto"; -import { TelemetryService } from "../services"; -import { client, getEncryptionKey, getRootEncryptionKey } from "../config"; -import { EEAuditLogService, EESecretService } from "../ee/services"; -import { getAuthDataPayloadUserObj } from "../utils/authn/helpers"; -import { getFolderByPath, getFolderIdFromServiceToken } from "../services/FolderService"; -import picomatch from "picomatch"; -import path from "path"; -import { getAnImportedSecret } from "../services/SecretImportService"; - -/** - * Validate scope for service token v2 - * @param authPayload - * @param environment - * @param secretPath - * @returns - */ -export const isValidScope = ( - authPayload: IServiceTokenData, - environment: string, - secretPath: string -) => { - const { scopes: tkScopes } = authPayload; - const validScope = tkScopes.find( - (scope) => - picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) && - scope.environment === environment - ); - - return Boolean(validScope); -}; - -export function containsGlobPatterns(secretPath: string) { - const globChars = ["*", "?", "[", "]", "{", "}", "**"]; - const normalizedPath = path.normalize(secretPath); - return globChars.some((char) => normalizedPath.includes(char)); -} - -const ERR_FOLDER_NOT_FOUND = BadRequestError({ message: "Folder not found" }); - -/** - * Returns an object containing secret [secret] but with its value, key, comment decrypted. - * - * Precondition: the workspace for secret [secret] must have E2EE disabled - * @param {ISecret} secret - secret to repackage to raw - * @param {String} key - symmetric key to use to decrypt secret - * @returns - */ -export const repackageSecretToRaw = ({ secret, key }: { secret: ISecret; key: string }) => { - const secretKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - key - }); - - const secretValue = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - key - }); - - let secretComment = ""; - - if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) { - secretComment = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretCommentCiphertext, - iv: secret.secretCommentIV, - tag: secret.secretCommentTag, - key - }); - } - - return { - _id: secret._id, - version: secret.version, - workspace: secret.workspace, - type: secret.type, - environment: secret.environment, - user: secret.user, - secretKey, - secretValue, - secretComment - }; -}; - -/** - * Create secret blind index data containing encrypted blind index [salt] - * for workspace with id [workspaceId] - * @param {Object} obj - * @param {Types.ObjectId} obj.workspaceId - */ -export const createSecretBlindIndexDataHelper = async ({ - workspaceId -}: { - workspaceId: Types.ObjectId; -}) => { - // initialize random blind index salt for workspace - const salt = crypto.randomBytes(16).toString("base64"); - - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - if (rootEncryptionKey) { - const { - ciphertext: encryptedSaltCiphertext, - iv: saltIV, - tag: saltTag - } = client.encryptSymmetric(salt, rootEncryptionKey); - - return await new SecretBlindIndexData({ - workspace: workspaceId, - encryptedSaltCiphertext, - saltIV, - saltTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_BASE64 - }).save(); - } else { - const { - ciphertext: encryptedSaltCiphertext, - iv: saltIV, - tag: saltTag - } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: salt, - key: encryptionKey - }); - - return await new SecretBlindIndexData({ - workspace: workspaceId, - encryptedSaltCiphertext, - saltIV, - saltTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }).save(); - } -}; - -/** - * Get secret blind index salt for workspace with id [workspaceId] - * @param {Object} obj - * @param {Types.ObjectId} obj.workspaceId - id of workspace to get salt for - * @returns - */ -export const getSecretBlindIndexSaltHelper = async ({ - workspaceId -}: { - workspaceId: Types.ObjectId; -}) => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - const secretBlindIndexData = await SecretBlindIndexData.findOne({ - workspace: workspaceId - }).select("+algorithm +keyEncoding"); - - if (!secretBlindIndexData) throw SecretBlindIndexDataNotFoundError(); - - if (rootEncryptionKey && secretBlindIndexData.keyEncoding === ENCODING_SCHEME_BASE64) { - return client.decryptSymmetric( - secretBlindIndexData.encryptedSaltCiphertext, - rootEncryptionKey, - secretBlindIndexData.saltIV, - secretBlindIndexData.saltTag - ); - } else if (encryptionKey && secretBlindIndexData.keyEncoding === ENCODING_SCHEME_UTF8) { - // decrypt workspace salt - return decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secretBlindIndexData.encryptedSaltCiphertext, - iv: secretBlindIndexData.saltIV, - tag: secretBlindIndexData.saltTag, - key: encryptionKey - }); - } - - throw InternalServerError({ - message: "Failed to obtain workspace salt needed for secret blind indexing" - }); -}; - -/** - * Generate blind index for secret with name [secretName] - * and salt [salt] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to generate blind index for - * @param {String} obj.salt - base64-salt - */ -export const generateSecretBlindIndexWithSaltHelper = async ({ - secretName, - salt -}: { - secretName: string; - salt: string; -}) => { - // generate secret blind index - const secretBlindIndex = ( - await argon2.hash(secretName, { - type: argon2.argon2id, - salt: Buffer.from(salt, "base64"), - saltLength: 16, // default 16 bytes - memoryCost: 65536, // default pool of 64 MiB per thread. - hashLength: 32, - parallelism: 1, - raw: true - }) - ).toString("base64"); - - return secretBlindIndex; -}; - -/** - * Generate blind index for secret with name [secretName] - * for workspace with id [workspaceId] - * @param {Object} obj - * @param {Stringj} obj.secretName - name of secret to generate blind index for - * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to - */ -export const generateSecretBlindIndexHelper = async ({ - secretName, - workspaceId -}: { - secretName: string; - workspaceId: Types.ObjectId; -}) => { - // check if workspace blind index data exists - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - const secretBlindIndexData = await SecretBlindIndexData.findOne({ - workspace: workspaceId - }).select("+algorithm +keyEncoding"); - - if (!secretBlindIndexData) throw SecretBlindIndexDataNotFoundError(); - - let salt; - if (rootEncryptionKey && secretBlindIndexData.keyEncoding === ENCODING_SCHEME_BASE64) { - salt = client.decryptSymmetric( - secretBlindIndexData.encryptedSaltCiphertext, - rootEncryptionKey, - secretBlindIndexData.saltIV, - secretBlindIndexData.saltTag - ); - - const secretBlindIndex = await generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }); - - return secretBlindIndex; - } else if (encryptionKey && secretBlindIndexData.keyEncoding === ENCODING_SCHEME_UTF8) { - // decrypt workspace salt - salt = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secretBlindIndexData.encryptedSaltCiphertext, - iv: secretBlindIndexData.saltIV, - tag: secretBlindIndexData.saltTag, - key: encryptionKey - }); - - const secretBlindIndex = await generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }); - - return secretBlindIndex; - } - - throw InternalServerError({ - message: "Failed to generate secret blind index" - }); -}; - -/** - * Create secret with name [secretName] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to create - * @param {Types.ObjectId} obj.workspaceId - id of workspace to create secret for - * @param {String} obj.environment - environment in workspace to create secret for - * @param {'shared' | 'personal'} obj.type - type of secret - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ -export const createSecretHelper = async ({ - secretName, - workspaceId, - environment, - type, - authData, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - secretPath = "/", - metadata, - skipMultilineEncoding -}: CreateSecretParams) => { - const secretBlindIndex = await generateSecretBlindIndexHelper({ - secretName, - workspaceId: new Types.ObjectId(workspaceId) - }); - - // if using service token filter towards the folderId by secretpath - if (authData.authPayload instanceof ServiceTokenData) { - if (!isValidScope(authData.authPayload, environment, secretPath)) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - } - const folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath); - - const exists = await Secret.exists({ - secretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - type, - environment, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}) - }); - - if (exists) - throw BadRequestError({ - message: "Failed to create secret that already exists" - }); - - if (type === SECRET_PERSONAL) { - // case: secret type is personal -> check if a corresponding shared secret - // with the same blind index [secretBlindIndex] exists - - const exists = await Secret.exists({ - secretBlindIndex, - folder: folderId, - workspace: new Types.ObjectId(workspaceId), - environment, - type: SECRET_SHARED - }); - - if (!exists) - throw BadRequestError({ - message: "Failed to create personal secret override for no corresponding shared secret" - }); - } - - // create secret - const secret = await new Secret({ - version: 1, - workspace: new Types.ObjectId(workspaceId), - environment, - type, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), - secretBlindIndex, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - skipMultilineEncoding, - folder: folderId, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - metadata - }).save(); - - const secretVersion = new SecretVersion({ - secret: secret._id, - version: secret.version, - workspace: secret.workspace, - type, - folder: folderId, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), - environment: secret.environment, - isDeleted: false, - secretBlindIndex, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - skipMultilineEncoding, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }); - - // (EE) add version for new secret - await EESecretService.addSecretVersions({ - secretVersions: [secretVersion] - }); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.CREATE_SECRET, - metadata: { - environment, - secretPath, - secretId: secret._id.toString(), - secretKey: secretName, - secretVersion: secret.version - } - }, - { - workspaceId - } - ); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId, - environment, - folderId - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - - if (postHogClient && metadata?.source !== "signup") { - postHogClient.capture({ - event: "secrets added", - distinctId: await TelemetryService.getDistinctId({ - authData - }), - properties: { - numberOfSecrets: 1, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - - return secret; -}; - -/** - * Get secrets for workspace with id [workspaceId] and environment [environment] - * @param {Object} obj - * @param {Types.ObjectId} obj.workspaceId - id of workspace - * @param {String} obj.environment - environment in workspace - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ -export const getSecretsHelper = async ({ - workspaceId, - environment, - authData, - secretPath = "/" -}: GetSecretsParams) => { - let secrets: ISecret[] = []; - // if using service token filter towards the folderId by secretpath - - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }); - let folderId = "root"; - if (!folders && folderId !== "root") return []; - // get folder from folder tree - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) return []; - folderId = folder?.id; - } - - // get personal secrets first - secrets = await Secret.find({ - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - type: SECRET_PERSONAL, - ...getAuthDataPayloadUserObj(authData) - }) - .populate("tags") - .lean(); - - // concat with shared secrets - secrets = secrets.concat( - await Secret.find({ - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - type: SECRET_SHARED, - secretBlindIndex: { - $nin: secrets.map((secret) => secret.secretBlindIndex) - } - }) - .populate("tags") - .lean() - ); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.GET_SECRETS, - metadata: { - environment, - secretPath, - numberOfSecrets: secrets.length - } - }, - { - workspaceId - } - ); - - const postHogClient = await TelemetryService.getPostHogClient(); - - // reduce the number of events captured - let shouldRecordK8Event = false; - if (authData.userAgent == K8_USER_AGENT_NAME) { - const randomNumber = Math.random(); - if (randomNumber > 0.9) { - shouldRecordK8Event = true; - } - } - - const numberOfSignupSecrets = secrets.filter( - (secret) => secret?.metadata?.source === "signup" - ).length; - const atLeastOneNonSignUpSecret = secrets.length - numberOfSignupSecrets > 0; - - if (postHogClient && atLeastOneNonSignUpSecret) { - const shouldCapture = authData.userAgent !== K8_USER_AGENT_NAME || shouldRecordK8Event; - const approximateForNoneCapturedEvents = secrets.length * 10; - - if (shouldCapture) { - if (workspaceId.toString() != "650e71fbae3e6c8572f436d4") { - postHogClient.capture({ - event: "secrets pulled", - distinctId: await TelemetryService.getDistinctId({ authData }), - properties: { - numberOfSecrets: shouldRecordK8Event - ? approximateForNoneCapturedEvents - : secrets.length, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - } - } - - return secrets; -}; - -/** - * Get secret with name [secretName] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to get - * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to - * @param {String} obj.environment - environment in workspace that secret belongs to - * @param {'shared' | 'personal'} obj.type - type of secret - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ -export const getSecretHelper = async ({ - secretName, - workspaceId, - environment, - type, - authData, - secretPath = "/", - include_imports = true, - version -}: GetSecretParams) => { - const secretBlindIndex = await generateSecretBlindIndexHelper({ - secretName, - workspaceId: new Types.ObjectId(workspaceId) - }); - let secret: ISecret | null | undefined = null; - - // if using service token filter towards the folderId by secretpath - - const folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath); - - // try getting personal secret first (if exists) - if (version === undefined) { - secret = await Secret.findOne({ - secretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - type: type ?? SECRET_PERSONAL, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}) - }).lean(); - } else { - const secretVersion = await SecretVersion.findOne({ - secretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - type: type ?? SECRET_PERSONAL, - version - }).lean(); - - if (secretVersion) { - secret = await new Secret({ - ...secretVersion, - _id: secretVersion?.secret - }); - } - } - - if (!secret) { - // case: failed to find personal secret matching criteria - // -> find shared secret matching criteria - if (version === undefined) { - secret = await Secret.findOne({ - secretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - type: SECRET_SHARED - }).lean(); - } else { - const secretVersion = await SecretVersion.findOne({ - secretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - type: SECRET_SHARED, - version - }).lean(); - - if (secretVersion) { - secret = await new Secret({ - ...secretVersion, - _id: secretVersion?.secret - }); - } - } - } - - if (!secret && include_imports) { - // if still no secret found search in imported secret and retreive - secret = await getAnImportedSecret( - secretName, - workspaceId.toString(), - environment, - folderId, - version - ); - } - - if (!secret) throw SecretNotFoundError(); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.GET_SECRET, - metadata: { - environment, - secretPath, - secretId: secret._id.toString(), - secretKey: secretName, - secretVersion: secret.version - } - }, - { - workspaceId - } - ); - - const postHogClient = await TelemetryService.getPostHogClient(); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets pulled", - distinctId: await TelemetryService.getDistinctId({ - authData - }), - properties: { - numberOfSecrets: 1, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - - return secret; -}; - -/** - * Update secret with name [secretName] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to update - * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to - * @param {String} obj.environment - environment in workspace that secret belongs to - * @param {'shared' | 'personal'} obj.type - type of secret - * @param {String} obj.secretValueCiphertext - ciphertext of secret value - * @param {String} obj.secretValueIV - IV of secret value - * @param {String} obj.secretValueTag - tag of secret value - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ - -export const updateSecretHelper = async ({ - secretName, - workspaceId, - secretId, - environment, - type, - authData, - newSecretName, - secretKeyTag, - secretKeyCiphertext, - secretKeyIV, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretPath, - secretReminderRepeatDays, - secretReminderNote, - tags, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - skipMultilineEncoding -}: UpdateSecretParams) => { - // get secret blind index salt - const salt = await getSecretBlindIndexSaltHelper({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - let oldSecretBlindIndex = await generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }); - - if (secretId) { - const secret = await Secret.findOne({ - workspace: workspaceId, - environment, - _id: secretId - }).select("secretBlindIndex"); - if (secret && secret.secretBlindIndex) oldSecretBlindIndex = secret.secretBlindIndex; - } - - let secret: ISecret | null = null; - const folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath); - - let newSecretNameBlindIndex = undefined; - if (newSecretName) { - newSecretNameBlindIndex = await generateSecretBlindIndexWithSaltHelper({ - secretName: newSecretName, - salt - }); - const doesSecretAlreadyExist = await Secret.exists({ - secretBlindIndex: newSecretNameBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - type - }); - - if (doesSecretAlreadyExist) { - throw BadRequestError({ message: "Secret with the provided name already exist" }); - } - } - - if (type === SECRET_SHARED) { - // case: update shared secret - secret = await Secret.findOneAndUpdate( - { - secretBlindIndex: oldSecretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - type - }, - { - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentIV, - secretCommentTag, - secretCommentCiphertext, - - secretReminderRepeatDays, - secretReminderNote, - - skipMultilineEncoding, - secretBlindIndex: newSecretNameBlindIndex, - secretKeyIV, - secretKeyTag, - secretKeyCiphertext, - tags, - $inc: { version: 1 } - }, - { - new: true - } - ); - } else { - // case: update personal secret - - secret = await Secret.findOneAndUpdate( - { - secretBlindIndex: oldSecretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - type, - folder: folderId, - ...getAuthDataPayloadUserObj(authData) - }, - { - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretKeyIV, - secretKeyTag, - secretKeyCiphertext, - tags, - skipMultilineEncoding, - secretBlindIndex: newSecretNameBlindIndex, - $inc: { version: 1 } - }, - { - new: true - } - ); - } - - if (!secret) throw SecretNotFoundError(); - - const secretVersion = new SecretVersion({ - secret: secret._id, - version: secret.version, - workspace: secret.workspace, - folder: folderId, - type, - tags, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), - environment: secret.environment, - isDeleted: false, - secretBlindIndex: newSecretName ? newSecretNameBlindIndex : oldSecretBlindIndex, - secretKeyCiphertext: secret.secretKeyCiphertext, - secretKeyIV: secret.secretKeyIV, - secretKeyTag: secret.secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - skipMultilineEncoding, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }); - - // (EE) add version for new secret - await EESecretService.addSecretVersions({ - secretVersions: [secretVersion] - }); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.UPDATE_SECRET, - metadata: { - environment, - secretPath, - secretId: secret._id.toString(), - secretKey: secretName, - secretVersion: secret.version - } - }, - { - workspaceId - } - ); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId, - environment, - folderId: secret?.folder - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets modified", - distinctId: await TelemetryService.getDistinctId({ - authData - }), - properties: { - numberOfSecrets: 1, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - - return secret; -}; - -/** - * Delete secret with name [secretName] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to delete - * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to - * @param {String} obj.environment - environment in workspace that secret belongs to - * @param {'shared' | 'personal'} obj.type - type of secret - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ -export const deleteSecretHelper = async ({ - secretName, - workspaceId, - environment, - type, - authData, - secretPath = "/", - // used for update corner case and blindIndex goes wrong way - secretId -}: DeleteSecretParams) => { - let secretBlindIndex = await generateSecretBlindIndexHelper({ - secretName, - workspaceId: new Types.ObjectId(workspaceId) - }); - if (secretId) { - const secret = await Secret.findOne({ - workspace: workspaceId, - environment, - _id: secretId - }).select("secretBlindIndex"); - if (secret && secret.secretBlindIndex) secretBlindIndex = secret.secretBlindIndex; - } - - const folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath); - - let secrets: ISecret[] = []; - let secret: ISecret | null = null; - - if (type === SECRET_SHARED) { - secrets = await Secret.find({ - secretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId - }).lean(); - - secret = await Secret.findOneAndDelete({ - secretBlindIndex, - workspace: new Types.ObjectId(workspaceId), - environment, - type, - folder: folderId - }).lean(); - - await Secret.deleteMany({ - secretBlindIndex, - workspaceId: new Types.ObjectId(workspaceId), - environment, - folder: folderId - }); - } else { - secret = await Secret.findOneAndDelete({ - secretBlindIndex, - folder: folderId, - workspace: new Types.ObjectId(workspaceId), - environment, - type, - ...getAuthDataPayloadUserObj(authData) - }).lean(); - - if (secret) { - secrets = [secret]; - } - } - - if (!secret) throw SecretNotFoundError(); - - await EESecretService.markDeletedSecretVersions({ - secretIds: secrets.map((secret) => secret._id) - }); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.DELETE_SECRET, - metadata: { - environment, - secretPath, - secretId: secret._id.toString(), - secretKey: secretName, - secretVersion: secret.version - } - }, - { - workspaceId - } - ); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId, - environment, - folderId: secret?.folder - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets deleted", - distinctId: await TelemetryService.getDistinctId({ - authData - }), - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - - return { - secrets, - secret - }; -}; - -const fetchSecretsCrossEnv = (workspaceId: string, folders: TFolderRootSchema[], key: string) => { - const fetchCache: Record> = {}; - - return async (secRefEnv: string, secRefPath: string[], secRefKey: string) => { - const secRefPathUrl = path.join("/", ...secRefPath); - const uniqKey = `${secRefEnv}-${secRefPathUrl}`; - - if (fetchCache?.[uniqKey]) { - return fetchCache[uniqKey][secRefKey]; - } - - let folderId = "root"; - const folder = folders.find(({ environment }) => environment === secRefEnv); - if (!folder && secRefPathUrl !== "/") { - throw BadRequestError({ message: "Folder not found" }); - } - - if (folder) { - const selectedFolder = getFolderByPath(folder.nodes, secRefPathUrl); - if (!selectedFolder) { - throw BadRequestError({ message: "Folder not found" }); - } - folderId = selectedFolder.id; - } - - const secrets = await Secret.find({ - workspace: workspaceId, - environment: secRefEnv, - type: SECRET_SHARED, - folder: folderId - }); - - const decryptedSec = secrets.reduce>((prev, secret) => { - const secretKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - key - }); - const secretValue = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - key - }); - - prev[secretKey] = secretValue; - return prev; - }, {}); - - fetchCache[uniqKey] = decryptedSec; - - return fetchCache[uniqKey][secRefKey]; - }; -}; - -const INTERPOLATION_SYNTAX_REG = new RegExp(/\${([^}]+)}/g); -const recursivelyExpandSecret = async ( - expandedSec: Record, - interpolatedSec: Record, - fetchCrossEnv: (env: string, secPath: string[], secKey: string) => Promise, - recursionChainBreaker: Record, - key: string -) => { - if (expandedSec?.[key]) { - return expandedSec[key]; - } - if (recursionChainBreaker?.[key]) { - return ""; - } - recursionChainBreaker[key] = true; - - let interpolatedValue = interpolatedSec[key]; - if (!interpolatedValue) { - // eslint-disable-next-line no-console - console.error(`Couldn't find referenced value - ${key}`); - return ""; - } - - const refs = interpolatedValue.match(INTERPOLATION_SYNTAX_REG); - if (refs) { - for (const interpolationSyntax of refs) { - const interpolationKey = interpolationSyntax.slice(2, interpolationSyntax.length - 1); - const entities = interpolationKey.trim().split("."); - - if (entities.length === 1) { - const val = await recursivelyExpandSecret( - expandedSec, - interpolatedSec, - fetchCrossEnv, - recursionChainBreaker, - interpolationKey - ); - if (val) { - interpolatedValue = interpolatedValue.replaceAll(interpolationSyntax, val); - } - continue; - } - - if (entities.length > 1) { - const secRefEnv = entities[0]; - const secRefPath = entities.slice(1, entities.length - 1); - const secRefKey = entities[entities.length - 1]; - - const val = await fetchCrossEnv(secRefEnv, secRefPath, secRefKey); - if (val !== undefined) { - interpolatedValue = interpolatedValue.replaceAll(interpolationSyntax, val); - } - } - } - } - expandedSec[key] = interpolatedValue; - return interpolatedValue; -}; - -// used to convert multi line ones to quotes ones with \n -const formatMultiValueEnv = (val?: string) => { - if (!val) return ""; - if (!val.match("\n")) return val; - return `"${val.replace(/\n/g, "\\n")}"`; -}; - -export const expandSecrets = async ( - workspaceId: string, - rootEncKey: string, - secrets: Record -) => { - const expandedSec: Record = {}; - const interpolatedSec: Record = {}; - - const folders = await Folder.find({ workspace: workspaceId }); - const crossSecEnvFetch = fetchSecretsCrossEnv(workspaceId, folders, rootEncKey); - - Object.keys(secrets).forEach((key) => { - if (secrets[key].value.match(INTERPOLATION_SYNTAX_REG)) { - interpolatedSec[key] = secrets[key].value; - } else { - expandedSec[key] = secrets[key].value; - } - }); - - for (const key of Object.keys(secrets)) { - if (expandedSec?.[key]) { - // should not do multi line encoding if user has set it to skip - secrets[key].value = secrets[key].skipMultilineEncoding - ? expandedSec[key] - : formatMultiValueEnv(expandedSec[key]); - continue; - } - - // this is to avoid recursion loop. So the graph should be direct graph rather than cyclic - // so for any recursion building if there is an entity two times same key meaning it will be looped - const recursionChainBreaker: Record = {}; - const expandedVal = await recursivelyExpandSecret( - expandedSec, - interpolatedSec, - crossSecEnvFetch, - recursionChainBreaker, - key - ); - - secrets[key].value = secrets[key].skipMultilineEncoding - ? expandedVal - : formatMultiValueEnv(expandedVal); - } - - return secrets; -}; - -export const createSecretBatchHelper = async ({ - secrets, - workspaceId, - authData, - secretPath, - environment -}: CreateSecretBatchParams) => { - let folderId = "root"; - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }); - - if (!folders && secretPath !== "/") throw ERR_FOLDER_NOT_FOUND; - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) throw ERR_FOLDER_NOT_FOUND; - folderId = folder.id; - } - - // get secret blind index salt - const salt = await getSecretBlindIndexSaltHelper({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - const secretBlindIndexToKey: Record = {}; // used at audit log point - const secretBlindIndexes = await Promise.all( - secrets.map(({ secretName }) => - generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }) - ) - ).then((blindIndexes) => - blindIndexes.reduce>((prev, curr, i) => { - prev[secrets[i].secretName] = curr; - secretBlindIndexToKey[curr] = secrets[i].secretName; - return prev; - }, {}) - ); - - const exists = await Secret.exists({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment - }) - .or( - secrets.map(({ secretName, type }) => ({ - secretBlindIndex: secretBlindIndexes[secretName], - type: type, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}) - })) - ) - .exec(); - - if (exists) - throw BadRequestError({ - message: "Failed to create secret that already exists" - }); - - // create secret - const newlyCreatedSecrets: ISecret[] = await Secret.insertMany( - secrets.map( - ({ - type, - secretName, - secretKeyIV, - metadata, - secretKeyTag, - secretValueIV, - secretValueTag, - secretCommentIV, - secretCommentTag, - secretKeyCiphertext, - secretValueCiphertext, - secretCommentCiphertext, - skipMultilineEncoding - }) => ({ - version: 1, - workspace: new Types.ObjectId(workspaceId), - environment, - type, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - folder: folderId, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - metadata, - skipMultilineEncoding, - secretBlindIndex: secretBlindIndexes[secretName], - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}) - }) - ) - ); - - await EESecretService.addSecretVersions({ - secretVersions: newlyCreatedSecrets.map( - (secret) => - new SecretVersion({ - secret: secret._id, - version: secret.version, - workspace: secret.workspace, - type: secret.type, - folder: folderId, - skipMultilineEncoding: secret?.skipMultilineEncoding, - ...(secret.type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), - environment: secret.environment, - isDeleted: false, - secretBlindIndex: secret.secretBlindIndex, - secretKeyCiphertext: secret.secretKeyCiphertext, - secretKeyIV: secret.secretKeyIV, - secretKeyTag: secret.secretKeyTag, - secretValueCiphertext: secret.secretValueCiphertext, - secretValueIV: secret.secretValueIV, - secretValueTag: secret.secretValueTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }) - ) - }); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.CREATE_SECRETS, - metadata: { - environment, - secretPath, - secrets: newlyCreatedSecrets.map(({ secretBlindIndex, version, _id }) => ({ - secretId: _id.toString(), - secretKey: secretBlindIndexToKey[secretBlindIndex || ""], - secretVersion: version - })) - } - }, - { - workspaceId - } - ); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId, - environment, - folderId - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets added", - distinctId: await TelemetryService.getDistinctId({ - authData - }), - properties: { - numberOfSecrets: 1, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - - return newlyCreatedSecrets; -}; - -export const updateSecretBatchHelper = async ({ - workspaceId, - environment, - authData, - secretPath, - secrets -}: UpdateSecretBatchParams) => { - let folderId = "root"; - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }); - - if (!folders && secretPath !== "/") throw ERR_FOLDER_NOT_FOUND; - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) throw ERR_FOLDER_NOT_FOUND; - folderId = folder.id; - } - - // get secret blind index salt - const salt = await getSecretBlindIndexSaltHelper({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - const secretBlindIndexToKey: Record = {}; // used at audit log point - const secretBlindIndexes = await Promise.all( - secrets.map(({ secretName }) => - generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }) - ) - ).then((blindIndexes) => - blindIndexes.reduce>((prev, curr, i) => { - prev[secrets[i].secretName] = curr; - secretBlindIndexToKey[curr] = secrets[i].secretName; - return prev; - }, {}) - ); - - const secretsToBeUpdated = await Secret.find({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment - }) - .select("+secretBlindIndex") - .or( - secrets.map(({ secretName, type }) => ({ - secretBlindIndex: secretBlindIndexes[secretName], - type: type, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}) - })) - ) - .lean(); - - if (secretsToBeUpdated.length !== secrets.length) - throw BadRequestError({ message: "Some secrets not found" }); - - await Secret.bulkWrite( - secrets.map( - ({ - type, - secretName, - tags, - secretValueIV, - secretValueTag, - secretCommentIV, - secretCommentTag, - secretValueCiphertext, - secretCommentCiphertext, - skipMultilineEncoding - }) => ({ - updateOne: { - filter: { - workspace: new Types.ObjectId(workspaceId), - environment, - folder: folderId, - secretBlindIndex: secretBlindIndexes[secretName], - type, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}) - }, - update: { - $inc: { - version: 1 - }, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - tags, - skipMultilineEncoding - } - } - }) - ) - ); - - const secretsGroupedByBlindIndex = secretsToBeUpdated.reduce>( - (prev, curr) => { - if (curr.secretBlindIndex) prev[curr.secretBlindIndex] = curr; - return prev; - }, - {} - ); - - await EESecretService.addSecretVersions({ - secretVersions: secrets.map((secret) => { - const { - _id, - version, - workspace, - type, - secretBlindIndex, - secretKeyIV, - secretKeyTag, - secretKeyCiphertext, - skipMultilineEncoding - } = secretsGroupedByBlindIndex[secretBlindIndexes[secret.secretName]]; - - return new SecretVersion({ - secret: _id, - version: version + 1, - workspace: workspace, - type, - folder: folderId, - ...(secret.type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), - environment, - isDeleted: false, - secretBlindIndex: secretBlindIndex, - secretKeyCiphertext: secretKeyCiphertext, - secretKeyIV: secretKeyIV, - secretKeyTag: secretKeyTag, - secretValueCiphertext: secret.secretValueCiphertext, - secretValueIV: secret.secretValueIV, - secretValueTag: secret.secretValueTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - skipMultilineEncoding - }); - }) - }); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.UPDATE_SECRETS, - metadata: { - environment, - secretPath, - secrets: secretsToBeUpdated.map(({ _id, version, secretBlindIndex }) => ({ - secretId: _id.toString(), - secretKey: secretBlindIndexToKey[secretBlindIndex || ""], - secretVersion: version + 1 - })) - } - }, - { - workspaceId - } - ); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId, - environment, - folderId - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets modified", - distinctId: await TelemetryService.getDistinctId({ - authData - }), - properties: { - numberOfSecrets: 1, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - - return; -}; - -export const deleteSecretBatchHelper = async ({ - workspaceId, - environment, - authData, - secretPath = "/", - secrets -}: DeleteSecretBatchParams) => { - let folderId = "root"; - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }); - - if (!folders && secretPath !== "/") throw ERR_FOLDER_NOT_FOUND; - if (folders) { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) throw ERR_FOLDER_NOT_FOUND; - folderId = folder.id; - } - - // get secret blind index salt - const salt = await getSecretBlindIndexSaltHelper({ - workspaceId: new Types.ObjectId(workspaceId) - }); - - const secretBlindIndexToKey: Record = {}; // used at audit log point - const secretBlindIndexes = await Promise.all( - secrets.map(({ secretName }) => - generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }) - ) - ).then((blindIndexes) => - blindIndexes.reduce>((prev, curr, i) => { - prev[secrets[i].secretName] = curr; - secretBlindIndexToKey[curr] = secrets[i].secretName; - return prev; - }, {}) - ); - - const deletedSecrets = await Secret.find({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment - }) - .or( - secrets.map(({ secretName, type }) => ({ - secretBlindIndex: secretBlindIndexes[secretName], - type: type === "shared" ? { $in: ["shared", "personal"] } : type, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}) - })) - ) - .select({ secretBlindIndexes: 1 }) - .lean() - .exec(); - - await Secret.deleteMany({ - workspace: new Types.ObjectId(workspaceId), - folder: folderId, - environment - }) - .or( - secrets.map(({ secretName, type }) => ({ - secretBlindIndex: secretBlindIndexes[secretName], - type: type === "shared" ? { $in: ["shared", "personal"] } : type, - ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}) - })) - ) - .exec(); - - await EESecretService.markDeletedSecretVersions({ - secretIds: deletedSecrets.map((secret) => secret._id) - }); - - await EEAuditLogService.createAuditLog( - authData, - { - type: EventType.DELETE_SECRETS, - metadata: { - environment, - secretPath, - secrets: deletedSecrets.map(({ _id, version, secretBlindIndex }) => ({ - secretId: _id.toString(), - secretKey: secretBlindIndexToKey[secretBlindIndex || ""], - secretVersion: version - })) - } - }, - { - workspaceId - } - ); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId, - environment, - folderId - }); - - const postHogClient = await TelemetryService.getPostHogClient(); - - if (postHogClient) { - postHogClient.capture({ - event: "secrets deleted", - distinctId: await TelemetryService.getDistinctId({ - authData - }), - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - folderId, - channel: authData.userAgentType, - userAgent: authData.userAgent - } - }); - } - - return { - secrets: deletedSecrets - }; -}; diff --git a/backend-mongo/src/helpers/signup.ts b/backend-mongo/src/helpers/signup.ts deleted file mode 100644 index 27b1c16ab..000000000 --- a/backend-mongo/src/helpers/signup.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { IUser } from "../models"; -import { createOrganization } from "./organization"; -import { addMembershipsOrg } from "./membershipOrg"; -import { ACCEPTED, ADMIN } from "../variables"; -import { sendMail } from "../helpers/nodemailer"; -import { TokenService } from "../services"; -import { TOKEN_EMAIL_CONFIRMATION } from "../variables"; - -/** - * Send magic link to verify email to [email] - * for user and workspace. - * @param {Object} obj - * @param {String} obj.email - email - * @returns {Boolean} success - whether or not operation was successful - */ -export const sendEmailVerification = async ({ email }: { email: string }) => { - const token = await TokenService.createToken({ - type: TOKEN_EMAIL_CONFIRMATION, - email - }); - - // send mail - await sendMail({ - template: "emailVerification.handlebars", - subjectLine: "Infisical confirmation code", - recipients: [email], - substitutions: { - code: token - } - }); -}; - -/** - * Validate [code] sent to [email] - * @param {Object} obj - * @param {String} obj.email - emai - * @param {String} obj.code - code that was sent to [email] - */ -export const checkEmailVerification = async ({ email, code }: { email: string; code: string }) => { - await TokenService.validateToken({ - type: TOKEN_EMAIL_CONFIRMATION, - email, - token: code - }); -}; - -/** - * Initialize default organization named [organizationName] with workspace - * for user [user] - * @param {Object} obj - * @param {String} obj.organizationName - name of organization to initialize - * @param {IUser} obj.user - user who we are initializing for - */ -export const initializeDefaultOrg = async ({ - organizationName, - user -}: { - organizationName: string; - user: IUser; -}) => { - try { - // create organization with user as owner and initialize a free - // subscription - const organization = await createOrganization({ - email: user.email, - name: organizationName - }); - - await addMembershipsOrg({ - userIds: [user._id.toString()], - organizationId: organization._id.toString(), - roles: [ADMIN], - statuses: [ACCEPTED] - }); - } catch (err) { - throw new Error(`Failed to initialize default organization and workspace [err=${err}]`); - } -}; diff --git a/backend-mongo/src/helpers/token.ts b/backend-mongo/src/helpers/token.ts deleted file mode 100644 index 66bae1a15..000000000 --- a/backend-mongo/src/helpers/token.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { Types } from "mongoose"; -import { TokenData } from "../models"; -import crypto from "crypto"; -import bcrypt from "bcrypt"; -import { - TOKEN_EMAIL_CONFIRMATION, - TOKEN_EMAIL_MFA, - TOKEN_EMAIL_ORG_INVITATION, - TOKEN_EMAIL_PASSWORD_RESET, -} from "../variables"; -import { UnauthorizedRequestError } from "../utils/errors"; -import { getSaltRounds } from "../config"; - -/** - * Create and store a token in the database for purpose [type] - * @param {Object} obj - * @param {String} obj.type - * @param {String} obj.email - * @param {String} obj.phoneNumber - * @param {Types.ObjectId} obj.organizationId - * @returns {String} token - the created token - */ -export const createTokenHelper = async ({ - type, - email, - phoneNumber, - organizationId, -}: { - type: - | "emailConfirmation" - | "emailMfa" - | "organizationInvitation" - | "passwordReset"; - email?: string; - phoneNumber?: string; - organizationId?: Types.ObjectId; -}) => { - let token, expiresAt, triesLeft; - // generate random token based on specified token use-case - // type [type] - switch (type) { - case TOKEN_EMAIL_CONFIRMATION: - // generate random 6-digit code - token = String(crypto.randomInt(Math.pow(10, 5), Math.pow(10, 6) - 1)); - expiresAt = new Date(new Date().getTime() + 86400000); - break; - case TOKEN_EMAIL_MFA: - // generate random 6-digit code - token = String(crypto.randomInt(Math.pow(10, 5), Math.pow(10, 6) - 1)); - triesLeft = 5; - expiresAt = new Date(new Date().getTime() + 300000); - break; - case TOKEN_EMAIL_ORG_INVITATION: - // generate random hex - token = crypto.randomBytes(16).toString("hex"); - expiresAt = new Date(new Date().getTime() + 259200000); - break; - case TOKEN_EMAIL_PASSWORD_RESET: - // generate random hex - token = crypto.randomBytes(16).toString("hex"); - expiresAt = new Date(new Date().getTime() + 86400000); - break; - default: - token = crypto.randomBytes(16).toString("hex"); - expiresAt = new Date(); - break; - } - - interface TokenDataQuery { - type: string; - email?: string; - phoneNumber?: string; - organization?: Types.ObjectId; - } - - interface TokenDataUpdate { - type: string; - email?: string; - phoneNumber?: string; - organization?: Types.ObjectId; - tokenHash: string; - triesLeft?: number; - expiresAt: Date; - } - - const query: TokenDataQuery = { type }; - const update: TokenDataUpdate = { - type, - tokenHash: await bcrypt.hash(token, await getSaltRounds()), - expiresAt, - }; - - if (email) { - query.email = email; - update.email = email; - } - if (phoneNumber) { - query.phoneNumber = phoneNumber; - update.phoneNumber = phoneNumber; - } - if (organizationId) { - query.organization = organizationId; - update.organization = organizationId; - } - - if (triesLeft) { - update.triesLeft = triesLeft; - } - - await TokenData.findOneAndUpdate(query, update, { - new: true, - upsert: true, - }); - - return token; -}; - -/** - * - * @param {Object} obj - * @param {String} obj.email - email associated with the token - * @param {String} obj.token - value of the token - */ -export const validateTokenHelper = async ({ - type, - email, - phoneNumber, - organizationId, - token, -}: { - type: - | "emailConfirmation" - | "emailMfa" - | "organizationInvitation" - | "passwordReset"; - email?: string; - phoneNumber?: string; - organizationId?: Types.ObjectId; - token: string; -}) => { - interface Query { - type: string; - email?: string; - phoneNumber?: string; - organization?: Types.ObjectId; - } - - const query: Query = { type }; - - if (email) { - query.email = email; - } - if (phoneNumber) { - query.phoneNumber = phoneNumber; - } - if (organizationId) { - query.organization = organizationId; - } - - const tokenData = await TokenData.findOne(query).select("+tokenHash"); - - if (!tokenData) throw new Error("Failed to find token to validate"); - - if (tokenData.expiresAt < new Date()) { - // case: token expired - await TokenData.findByIdAndDelete(tokenData._id); - throw UnauthorizedRequestError({ - message: "MFA session expired. Please log in again", - context: { - code: "mfa_expired", - }, - }); - } - - const isValid = await bcrypt.compare(token, tokenData.tokenHash); - if (!isValid) { - // case: token is not valid - if (tokenData?.triesLeft !== undefined) { - // case: token has a try-limit - if (tokenData.triesLeft === 1) { - // case: token is out of tries - await TokenData.findByIdAndDelete(tokenData._id); - } else { - // case: token has more than 1 try left - await TokenData.findByIdAndUpdate( - tokenData._id, - { - triesLeft: tokenData.triesLeft - 1, - }, - { - new: true, - } - ); - } - - throw UnauthorizedRequestError({ - message: "MFA code is invalid", - context: { - code: "mfa_invalid", - triesLeft: tokenData.triesLeft - 1, - }, - }); - } - - throw UnauthorizedRequestError({ - message: "MFA code is invalid", - context: { - code: "mfa_invalid", - }, - }); - } - - // case: token is valid - await TokenData.findByIdAndDelete(tokenData._id); -}; \ No newline at end of file diff --git a/backend-mongo/src/helpers/user.ts b/backend-mongo/src/helpers/user.ts deleted file mode 100644 index 8085dd599..000000000 --- a/backend-mongo/src/helpers/user.ts +++ /dev/null @@ -1,301 +0,0 @@ -import { Types } from "mongoose"; -import { - APIKeyData, - BackupPrivateKey, - IUser, - Key, - Membership, - MembershipOrg, - TokenVersion, - User, - UserAction -} from "../models"; -import { sendMail } from "./nodemailer"; -import { - InternalServerError, - ResourceNotFoundError -} from "../utils/errors"; -import { ADMIN } from "../variables"; -import { deleteOrganization } from "../helpers/organization"; -import { deleteWorkspace } from "../helpers/workspace"; - -/** - * Initialize a user under email [email] - * @param {Object} obj - * @param {String} obj.email - email of user to initialize - * @returns {Object} user - the initialized user - */ -export const setupAccount = async ({ email }: { email: string }) => { - const user = await new User({ - email - }).save(); - - return user; -}; - -/** - * Finish setting up user - * @param {Object} obj - * @param {String} obj.userId - id of user to finish setting up - * @param {String} obj.firstName - first name of user - * @param {String} obj.lastName - last name of user - * @param {Number} obj.encryptionVersion - version of auth encryption scheme used - * @param {String} obj.protectedKey - protected key in encryption version 2 - * @param {String} obj.protectedKeyIV - IV of protected key in encryption version 2 - * @param {String} obj.protectedKeyTag - tag of protected key in encryption version 2 - * @param {String} obj.publicKey - publickey of user - * @param {String} obj.encryptedPrivateKey - (encrypted) private key of user - * @param {String} obj.encryptedPrivateKeyIV - iv for (encrypted) private key of user - * @param {String} obj.encryptedPrivateKeyTag - tag for (encrypted) private key of user - * @param {String} obj.salt - salt for auth SRP - * @param {String} obj.verifier - verifier for auth SRP - * @returns {Object} user - the completed user - */ -export const completeAccount = async ({ - userId, - firstName, - lastName, - encryptionVersion, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier -}: { - userId: string; - firstName: string; - lastName?: string; - encryptionVersion: number; - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - publicKey: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; - salt: string; - verifier: string; -}) => { - const options = { - new: true - }; - const user = await User.findByIdAndUpdate( - userId, - { - firstName, - lastName, - encryptionVersion, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag, - salt, - verifier - }, - options - ); - - return user; -}; - -/** - * Check if device with ip [ip] and user-agent [userAgent] has been seen for user [user]. - * If the device is unseen, then notify the user of the new device - * @param {Object} obj - * @param {String} obj.ip - login ip address - * @param {String} obj.userAgent - login user-agent - */ -export const checkUserDevice = async ({ - user, - ip, - userAgent -}: { - user: IUser; - ip: string; - userAgent: string; -}) => { - const isDeviceSeen = user.devices.some( - (device) => device.ip === ip && device.userAgent === userAgent - ); - - if (!isDeviceSeen) { - // case: unseen login ip detected for user - // -> notify user about the sign-in from new ip - - user.devices = user.devices.concat([ - { - ip: String(ip), - userAgent - } - ]); - - await user.save(); - - // send MFA code [code] to [email] - await sendMail({ - template: "newDevice.handlebars", - subjectLine: "Successful login from new device", - recipients: [user.email], - substitutions: { - email: user.email, - timestamp: new Date().toString(), - ip, - userAgent - } - }); - } -}; - -/** - * Check that if we delete user with id [userId] then - * there won't be any admin-less organizations or projects - * @param {Object} obj - * @param {String} obj.userId - id of user to check deletion conditions for - */ -const checkDeleteUserConditions = async ({ - userId -}: { - userId: Types.ObjectId; -}) => { - const memberships = await Membership.find({ - user: userId - }); - - const membershipOrgs = await MembershipOrg.find({ - user: userId - }); - - // delete organizations where user is only member - for await (const membershipOrg of membershipOrgs) { - const orgMemberCount = await MembershipOrg.countDocuments({ - organization: membershipOrg.organization, - }); - - const otherOrgAdminCount = await MembershipOrg.countDocuments({ - organization: membershipOrg.organization, - user: { $ne: userId }, - role: ADMIN - }); - - if (orgMemberCount > 1 && otherOrgAdminCount === 0) { - throw InternalServerError({ - message: "Failed to delete account because an org would be admin-less" - }); - } - } - - // delete workspaces where user is only member - for await (const membership of memberships) { - const workspaceMemberCount = await Membership.countDocuments({ - workspace: membership.workspace - }); - - const otherWorkspaceAdminCount = await Membership.countDocuments({ - workspace: membership.workspace, - user: { $ne: userId }, - role: ADMIN - }); - - if (workspaceMemberCount > 1 && otherWorkspaceAdminCount === 0) { - throw InternalServerError({ - message: "Failed to delete account because a workspace would be admin-less" - }); - } - } -} - -/** - * Delete account with id [userId] - * @param {Object} obj - * @param {Types.ObjectId} obj.userId - id of user to delete - * @returns {User} user - deleted user - */ -export const deleteUser = async ({ - userId -}: { - userId: Types.ObjectId; -}) => { - - const user = await User.findByIdAndDelete(userId); - - if (!user) throw ResourceNotFoundError(); - - await checkDeleteUserConditions({ - userId: user._id - }); - - await UserAction.deleteMany({ - user: user._id - }); - - await BackupPrivateKey.deleteMany({ - user: user._id - }); - - await APIKeyData.deleteMany({ - user: user._id - }); - - await TokenVersion.deleteMany({ - user: user._id - }); - - await Key.deleteMany({ - receiver: user._id - }); - - const membershipOrgs = await MembershipOrg.find({ - user: userId - }); - - // delete organizations where user is only member - for await (const membershipOrg of membershipOrgs) { - const memberCount = await MembershipOrg.countDocuments({ - organization: membershipOrg.organization - }); - - if (memberCount === 1) { - // organization only has 1 member (the current user) - - await deleteOrganization({ - organizationId: membershipOrg.organization - }); - } - } - - const memberships = await Membership.find({ - user: userId - }); - - // delete workspaces where user is only member - for await (const membership of memberships) { - const memberCount = await Membership.countDocuments({ - workspace: membership.workspace - }); - - if (memberCount === 1) { - // workspace only has 1 member (the current user) -> delete workspace - - await deleteWorkspace({ - workspaceId: membership.workspace - }); - } - } - - await MembershipOrg.deleteMany({ - user: userId - }); - - await Membership.deleteMany({ - user: userId - }); - - return user; -} \ No newline at end of file diff --git a/backend-mongo/src/helpers/validation.ts b/backend-mongo/src/helpers/validation.ts deleted file mode 100644 index f552eb69b..000000000 --- a/backend-mongo/src/helpers/validation.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Request } from "express"; -import { AnyZodObject, ZodError, z } from "zod"; -import { BadRequestError } from "../utils/errors"; - -export async function validateRequest( - schema: T, - req: Request -): Promise> { - try { - return schema.parseAsync(req); - } catch (error) { - if (error instanceof ZodError) { - throw BadRequestError({ message: error.message }); - } - return BadRequestError({ message: JSON.stringify(error) }); - } -} diff --git a/backend-mongo/src/helpers/workspace.ts b/backend-mongo/src/helpers/workspace.ts deleted file mode 100644 index 3a031a066..000000000 --- a/backend-mongo/src/helpers/workspace.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { Types } from "mongoose"; -import { - Bot, - BotKey, - Folder, - IdentityMembership, - Integration, - IntegrationAuth, - Key, - Membership, - Secret, - SecretBlindIndexData, - SecretImport, - ServiceToken, - ServiceTokenData, - Tag, - Webhook, - Workspace -} from "../models"; -import { - AuditLog, - FolderVersion, - IPType, - SecretApprovalPolicy, - SecretApprovalRequest, - SecretSnapshot, - SecretVersion, - TrustedIP -} from "../ee/models"; -import { createBot } from "../helpers/bot"; -import { EELicenseService } from "../ee/services"; -import { SecretService } from "../services"; -import { - ResourceNotFoundError -} from "../utils/errors"; - -/** - * Create a workspace with name [name] in organization with id [organizationId] - * and a bot for it. - * @param {String} name - name of workspace to create. - * @param {String} organizationId - id of organization to create workspace in - * @param {Object} workspace - new workspace - */ -export const createWorkspace = async ({ - name, - organizationId, -}: { - name: string; - organizationId: Types.ObjectId; -}) => { - // create workspace - const workspace = await new Workspace({ - name, - organization: organizationId, - autoCapitalization: true, - }).save(); - - // initialize bot for workspace - await createBot({ - name: "Infisical Bot", - workspaceId: workspace._id, - }); - - // initialize blind index salt for workspace - await SecretService.createSecretBlindIndexData({ - workspaceId: workspace._id, - }); - - // initialize default trusted IPv4 CIDR - 0.0.0.0/0 - await new TrustedIP({ - workspace: workspace._id, - ipAddress: "0.0.0.0", - type: IPType.IPV4, - prefix: 0, - isActive: true, - comment: "" - }).save() - - // initialize default trusted IPv6 CIDR - ::/0 - await new TrustedIP({ - workspace: workspace._id, - ipAddress: "::", - type: IPType.IPV6, - prefix: 0, - isActive: true, - comment: "" - }); - - await EELicenseService.refreshPlan(organizationId); - - return workspace; -}; - -/** - * Delete workspace and all associated materials including memberships, - * secrets, keys, etc. - * @param {Object} obj - * @param {String} obj.id - id of workspace to delete - */ -export const deleteWorkspace = async ({ - workspaceId -}: { - workspaceId: Types.ObjectId; -}) => { - const workspace = await Workspace.findByIdAndDelete(workspaceId); - - if (!workspace) throw ResourceNotFoundError(); - - await Membership.deleteMany({ - workspace: workspace._id - }); - - await Key.deleteMany({ - workspace: workspace._id - }); - - await Bot.deleteMany({ - workspace: workspace._id - }); - - await BotKey.deleteMany({ - workspace: workspace._id - }); - - await SecretBlindIndexData.deleteMany({ - workspace: workspace._id - }); - - await Secret.deleteMany({ - workspace: workspace._id - }); - - await SecretVersion.deleteMany({ - workspace: workspace._id - }); - - await SecretSnapshot.deleteMany({ - workspace: workspace._id - }); - - await SecretImport.deleteMany({ - workspace: workspace._id - }); - - await Folder.deleteMany({ - workspace: workspace._id - }); - - await FolderVersion.deleteMany({ - workspace: workspace._id - }); - - await Webhook.deleteMany({ - workspace: workspace._id - }); - - await TrustedIP.deleteMany({ - workspace: workspace._id - }); - - await Tag.deleteMany({ - workspace: workspace._id - }); - - await IntegrationAuth.deleteMany({ - workspace: workspace._id - }); - - await Integration.deleteMany({ - workspace: workspace._id - }); - - await ServiceToken.deleteMany({ - workspace: workspace._id - }); - - await ServiceTokenData.deleteMany({ - workspace: workspace._id - }); - - await IdentityMembership.deleteMany({ - workspace: workspace._id - }); - - await AuditLog.deleteMany({ - workspace: workspace._id - }); - - await SecretApprovalPolicy.deleteMany({ - workspace: workspace._id - }); - - await SecretApprovalRequest.deleteMany({ - workspace: workspace._id - }); - - return workspace; -}; diff --git a/backend-mongo/src/index.ts b/backend-mongo/src/index.ts deleted file mode 100644 index 3f85221c6..000000000 --- a/backend-mongo/src/index.ts +++ /dev/null @@ -1,344 +0,0 @@ -import dotenv from "dotenv"; -dotenv.config(); -import express from "express"; -// eslint-disable-next-line @typescript-eslint/no-var-requires -import "express-async-errors"; -import helmet from "helmet"; -import cors from "cors"; -import { initLogger, logger } from "./utils/logging"; -import httpLogger from "pino-http"; -import { DatabaseService } from "./services"; -import { EELicenseService, GithubSecretScanningService } from "./ee/services"; -import { setUpHealthEndpoint } from "./services/health"; -import cookieParser from "cookie-parser"; -import swaggerUi = require("swagger-ui-express"); -import { Probot, createNodeMiddleware } from "probot"; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const swaggerFile = require("../spec.json"); -// eslint-disable-next-line @typescript-eslint/no-var-requires -import { apiLimiter } from "./helpers/rateLimiter"; -import { - cloudProducts as eeCloudProductsRouter, - organizations as eeOrganizationsRouter, - sso as eeSSORouter, - secret as eeSecretRouter, - secretSnapshot as eeSecretSnapshotRouter, - users as eeUsersRouter, - workspace as eeWorkspaceRouter, - identities as v1IdentitiesRouter, - roles as v1RoleRouter, - secretApprovalPolicy as v1SecretApprovalPolicyRouter, - secretApprovalRequest as v1SecretApprovalRequestRouter, - secretRotation as v1SecretRotation, - secretRotationProvider as v1SecretRotationProviderRouter, - secretScanning as v1SecretScanningRouter -} from "./ee/routes/v1"; -import { apiKeyData as v3apiKeyDataRouter } from "./ee/routes/v3"; -import { - admin as v1AdminRouter, - auth as v1AuthRouter, - bot as v1BotRouter, - integrationAuth as v1IntegrationAuthRouter, - integration as v1IntegrationRouter, - inviteOrg as v1InviteOrgRouter, - key as v1KeyRouter, - membershipOrg as v1MembershipOrgRouter, - membership as v1MembershipRouter, - organization as v1OrganizationRouter, - password as v1PasswordRouter, - sso as v1SSORouter, - secretImps as v1SecretImpsRouter, - secret as v1SecretRouter, - secretsFolder as v1SecretsFolder, - serviceToken as v1ServiceTokenRouter, - signup as v1SignupRouter, - universalAuth as v1UniversalAuthRouter, - userAction as v1UserActionRouter, - user as v1UserRouter, - webhooks as v1WebhooksRouter, - workspace as v1WorkspaceRouter -} from "./routes/v1"; -import { - auth as v2AuthRouter, - environment as v2EnvironmentRouter, - organizations as v2OrganizationsRouter, - secret as v2SecretRouter, // begin to phase out - secrets as v2SecretsRouter, - serviceTokenData as v2ServiceTokenDataRouter, - signup as v2SignupRouter, - tags as v2TagsRouter, - users as v2UsersRouter, - workspace as v2WorkspaceRouter, - membership as v2MembershipController -} from "./routes/v2"; -import { - auth as v3AuthRouter, - secrets as v3SecretsRouter, - signup as v3SignupRouter, - users as v3UsersRouter, - workspaces as v3WorkspacesRouter -} from "./routes/v3"; -import { healthCheck } from "./routes/status"; -// import { getLogger } from "./utils/logger"; -import { RouteNotFoundError } from "./utils/errors"; -import { requestErrorHandler } from "./middleware/requestErrorHandler"; -import { - getIsMigrationMode, - getMongoURL, - getNodeEnv, - getPort, - getSecretScanningGitAppId, - getSecretScanningPrivateKey, - getSecretScanningWebhookProxy, - getSecretScanningWebhookSecret, - getSiteURL -} from "./config"; -import { setup } from "./utils/setup"; -import { syncSecretsToThirdPartyServices } from "./queues/integrations/syncSecretsToThirdPartyServices"; -import { githubPushEventSecretScan } from "./queues/secret-scanning/githubScanPushEvent"; -const SmeeClient = require("smee-client"); // eslint-disable-line -import path from "path"; -import { serverConfigInit } from "./config/serverConfig"; -import { initRedis } from "./services/RedisService"; - -let handler: null | any = null; - -const main = async () => { - await initLogger(); - - const port = await getPort(); - - // initializing the database connection + redis - await initRedis(); - await DatabaseService.initDatabase(await getMongoURL()); - const serverCfg = await serverConfigInit(); - await setup(); - - await EELicenseService.initGlobalFeatureSet(); - - const app = express(); - app.enable("trust proxy"); - - app.use( - httpLogger({ - logger, - autoLogging: false - }) - ); - - app.use(express.json()); - app.use(express.urlencoded({ extended: false })); - app.use(cookieParser()); - app.use( - cors({ - credentials: true, - origin: await getSiteURL() - }) - ); - - if ( - (await getSecretScanningGitAppId()) && - (await getSecretScanningWebhookSecret()) && - (await getSecretScanningPrivateKey()) - ) { - const probot = new Probot({ - appId: await getSecretScanningGitAppId(), - privateKey: await getSecretScanningPrivateKey(), - secret: await getSecretScanningWebhookSecret() - }); - - if ((await getNodeEnv()) != "production") { - const smee = new SmeeClient({ - source: await getSecretScanningWebhookProxy(), - target: "http://backend:4000/ss-webhook", - logger: console - }); - - smee.start(); - } - - app.use( - createNodeMiddleware(GithubSecretScanningService, { probot, webhooksPath: "/ss-webhook" }) - ); // secret scanning webhook - } - - if ((await getNodeEnv()) === "production") { - // enable app-wide rate-limiting + helmet security - // in production - app.disable("x-powered-by"); - app.use(apiLimiter); - app.use(helmet()); - } - - app.use((req, res, next) => { - // default to IP address provided by Cloudflare - // #swagger.ignore = true - const cfIp = req.headers["cf-connecting-ip"]; - req.realIP = Array.isArray(cfIp) ? cfIp[0] : (cfIp as string) || req.ip; - next(); - }); - - if ((await getNodeEnv()) === "production" && process.env.STANDALONE_BUILD === "true") { - const nextJsBuildPath = path.join(__dirname, "../frontend-build"); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-var-requires - const conf = require("../frontend-build/.next/required-server-files.json").config; - const NextServer = - // eslint-disable-next-line @typescript-eslint/no-var-requires - require("../frontend-build/node_modules/next/dist/server/next-server").default; - const nextApp = new NextServer({ - dev: false, - dir: nextJsBuildPath, - port, - conf, - hostname: "local", - customServer: false - }); - - handler = nextApp.getRequestHandler(); - } - - app.use((req, _res, next) => { - getIsMigrationMode() - .then((el) => { - if (el && req.method !== "GET") { - next(new Error("Migration mode")); - } else { - next(); - } - }) - .catch(next); - }); - - // (EE) routes - app.use("/api/v1/identities", v1IdentitiesRouter); - app.use("/api/v1/secret", eeSecretRouter); - app.use("/api/v1/secret-snapshot", eeSecretSnapshotRouter); - app.use("/api/v1/users", eeUsersRouter); - app.use("/api/v1/workspace", eeWorkspaceRouter); - app.use("/api/v1/organizations", eeOrganizationsRouter); - app.use("/api/v1/sso", eeSSORouter); - app.use("/api/v1/cloud-products", eeCloudProductsRouter); - app.use("/api/v3/api-key", v3apiKeyDataRouter); - app.use("/api/v1/secret-rotation-providers", v1SecretRotationProviderRouter); - app.use("/api/v1/secret-rotations", v1SecretRotation); - - // v1 routes - app.use("/api/v1/signup", v1SignupRouter); - app.use("/api/v1/auth", v1AuthRouter); - app.use("/api/v1/auth", v1UniversalAuthRouter); // new - app.use("/api/v1/admin", v1AdminRouter); - app.use("/api/v1/bot", v1BotRouter); - app.use("/api/v1/user", v1UserRouter); - app.use("/api/v1/user-action", v1UserActionRouter); - app.use("/api/v1/organization", v1OrganizationRouter); - app.use("/api/v1/workspace", v1WorkspaceRouter); - app.use("/api/v1/membership-org", v1MembershipOrgRouter); - app.use("/api/v1/membership", v1MembershipRouter); - app.use("/api/v1/key", v1KeyRouter); - app.use("/api/v1/invite-org", v1InviteOrgRouter); - app.use("/api/v1/secret", v1SecretRouter); // deprecate - app.use("/api/v1/service-token", v1ServiceTokenRouter); // deprecate - app.use("/api/v1/password", v1PasswordRouter); - app.use("/api/v1/integration", v1IntegrationRouter); - app.use("/api/v1/integration-auth", v1IntegrationAuthRouter); - app.use("/api/v1/folders", v1SecretsFolder); - app.use("/api/v1/secret-scanning", v1SecretScanningRouter); - app.use("/api/v1/webhooks", v1WebhooksRouter); - app.use("/api/v1/secret-imports", v1SecretImpsRouter); - app.use("/api/v1/roles", v1RoleRouter); - app.use("/api/v1/secret-approvals", v1SecretApprovalPolicyRouter); - app.use("/api/v1/sso", v1SSORouter); - app.use("/api/v1/secret-approval-requests", v1SecretApprovalRequestRouter); - - // v2 routes (improvements) - app.use("/api/v2/signup", v2SignupRouter); - app.use("/api/v2/auth", v2AuthRouter); - app.use("/api/v2/users", v2UsersRouter); - app.use("/api/v2/organizations", v2OrganizationsRouter); - app.use("/api/v2/workspace", v2MembershipController); - app.use("/api/v2/workspace", v2EnvironmentRouter); - app.use("/api/v2/workspace", v2TagsRouter); - app.use("/api/v2/workspace", v2WorkspaceRouter); - app.use("/api/v2/secret", v2SecretRouter); // deprecate - app.use("/api/v2/secrets", v2SecretsRouter); - app.use("/api/v2/service-token", v2ServiceTokenDataRouter); - - // v3 routes (experimental) - app.use("/api/v3/auth", v3AuthRouter); - app.use("/api/v3/secrets", v3SecretsRouter); - app.use("/api/v3/workspaces", v3WorkspacesRouter); - app.use("/api/v3/signup", v3SignupRouter); - app.use("/api/v3/us", v3UsersRouter); - - // api docs - app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerFile)); - - // server status - app.use("/api", healthCheck); - - if (handler) { - app.all("*", (req, res) => { - return handler(req, res); - }); - } - - //* Handle unrouted requests and respond with proper error message as well as status code - app.use((req, res, next) => { - if (res.headersSent) return next(); - next( - RouteNotFoundError({ - message: `The requested source '(${req.method})${req.url}' was not found` - }) - ); - }); - - app.use(requestErrorHandler); - - const server = app.listen(port, async () => { - if (!serverCfg.initialized) { - logger.info(`Welcome to Infisical - -Create your Infisical administrator account at: -http://localhost:${port}/admin/signup -`); - } else { - logger.info(`Welcome back! - -To access Infisical Administrator Panel open -http://localhost:${port}/admin - -To access Infisical server -http://localhost:${port} -`); - } - }); - - // await createTestUserForDevelopment(); - setUpHealthEndpoint(server); - - const serverCleanup = async () => { - await DatabaseService.closeDatabase(); - syncSecretsToThirdPartyServices.close(); - githubPushEventSecretScan.close(); - - process.exit(0); - }; - - process.on("SIGINT", function () { - server.close(async () => { - await serverCleanup(); - }); - }); - - process.on("SIGTERM", function () { - server.close(async () => { - await serverCleanup(); - }); - }); - - return server; -}; - -export default main(); diff --git a/backend-mongo/src/integrations/apps.ts b/backend-mongo/src/integrations/apps.ts deleted file mode 100644 index 00196b3d0..000000000 --- a/backend-mongo/src/integrations/apps.ts +++ /dev/null @@ -1,1355 +0,0 @@ -import { - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_BITBUCKET, - INTEGRATION_BITBUCKET_API_URL, - INTEGRATION_CHECKLY, - INTEGRATION_CHECKLY_API_URL, - INTEGRATION_CIRCLECI, - INTEGRATION_CIRCLECI_API_URL, - INTEGRATION_CLOUDFLARE_PAGES, - INTEGRATION_CLOUDFLARE_PAGES_API_URL, - INTEGRATION_CLOUDFLARE_WORKERS, - INTEGRATION_CLOUDFLARE_WORKERS_API_URL, - INTEGRATION_CLOUD_66, - INTEGRATION_CLOUD_66_API_URL, - INTEGRATION_CODEFRESH, - INTEGRATION_CODEFRESH_API_URL, - INTEGRATION_DIGITAL_OCEAN_API_URL, - INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, - INTEGRATION_FLYIO, - INTEGRATION_FLYIO_API_URL, - INTEGRATION_GCP_API_URL, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_GCP_SECRET_MANAGER_SERVICE_NAME, - INTEGRATION_GCP_SERVICE_USAGE_URL, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_GITLAB_API_URL, - INTEGRATION_HASURA_CLOUD, - INTEGRATION_HASURA_CLOUD_API_URL, - INTEGRATION_HEROKU, - INTEGRATION_HEROKU_API_URL, - INTEGRATION_LARAVELFORGE, - INTEGRATION_LARAVELFORGE_API_URL, - INTEGRATION_NETLIFY, - INTEGRATION_NETLIFY_API_URL, - INTEGRATION_NORTHFLANK, - INTEGRATION_NORTHFLANK_API_URL, - INTEGRATION_RAILWAY, - INTEGRATION_RAILWAY_API_URL, - INTEGRATION_RENDER, - INTEGRATION_RENDER_API_URL, - INTEGRATION_SUPABASE, - INTEGRATION_SUPABASE_API_URL, - INTEGRATION_TEAMCITY, - INTEGRATION_TERRAFORM_CLOUD, - INTEGRATION_TERRAFORM_CLOUD_API_URL, - INTEGRATION_TRAVISCI, - INTEGRATION_TRAVISCI_API_URL, - INTEGRATION_VERCEL, - INTEGRATION_VERCEL_API_URL, - INTEGRATION_WINDMILL, - INTEGRATION_WINDMILL_API_URL -} from "../variables"; -import { IIntegrationAuth } from "../models"; -import { Octokit } from "@octokit/rest"; -import { standardRequest } from "../config/request"; - -interface App { - name: string; - appId?: string; - owner?: string; -} - -/** - * Return list of names of apps for integration named [integration] - * @param {Object} obj - * @param {String} obj.integration - name of integration - * @param {String} obj.accessToken - access token for integration - * @param {String} obj.teamId - (optional) id of team for getting integration apps (used for integrations like GitLab) - * @returns {Object[]} apps - names of integration apps - * @returns {String} apps.name - name of integration app - */ -const getApps = async ({ - integrationAuth, - accessToken, - accessId, - teamId, - workspaceSlug -}: { - integrationAuth: IIntegrationAuth; - accessToken: string; - accessId?: string; - teamId?: string; - workspaceSlug?: string; -}) => { - let apps: App[] = []; - switch (integrationAuth.integration) { - case INTEGRATION_GCP_SECRET_MANAGER: - apps = await getAppsGCPSecretManager({ - accessToken - }); - break; - case INTEGRATION_AZURE_KEY_VAULT: - apps = []; - break; - case INTEGRATION_AWS_PARAMETER_STORE: - apps = []; - break; - case INTEGRATION_AWS_SECRET_MANAGER: - apps = []; - break; - case INTEGRATION_HEROKU: - apps = await getAppsHeroku({ - accessToken - }); - break; - case INTEGRATION_VERCEL: - apps = await getAppsVercel({ - integrationAuth, - accessToken - }); - break; - case INTEGRATION_NETLIFY: - apps = await getAppsNetlify({ - accessToken - }); - break; - case INTEGRATION_GITHUB: - apps = await getAppsGithub({ - accessToken - }); - break; - case INTEGRATION_GITLAB: - apps = await getAppsGitlab({ - integrationAuth, - accessToken, - teamId - }); - break; - case INTEGRATION_RENDER: - apps = await getAppsRender({ - accessToken - }); - break; - case INTEGRATION_RAILWAY: - apps = await getAppsRailway({ - accessToken - }); - break; - case INTEGRATION_FLYIO: - apps = await getAppsFlyio({ - accessToken - }); - break; - case INTEGRATION_CIRCLECI: - apps = await getAppsCircleCI({ - accessToken - }); - break; - case INTEGRATION_LARAVELFORGE: - apps = await getAppsLaravelForge({ - accessToken, - serverId: accessId - }); - break; - case INTEGRATION_TERRAFORM_CLOUD: - apps = await getAppsTerraformCloud({ - accessToken, - workspacesId: accessId - }); - break; - case INTEGRATION_TRAVISCI: - apps = await getAppsTravisCI({ - accessToken - }); - break; - case INTEGRATION_TEAMCITY: - apps = await getAppsTeamCity({ - integrationAuth, - accessToken - }); - break; - case INTEGRATION_SUPABASE: - apps = await getAppsSupabase({ - accessToken - }); - break; - case INTEGRATION_CHECKLY: - apps = await getAppsCheckly({ - accessToken - }); - break; - case INTEGRATION_CLOUDFLARE_PAGES: - apps = await getAppsCloudflarePages({ - accessToken, - accountId: accessId - }); - break; - case INTEGRATION_CLOUDFLARE_WORKERS: - apps = await getAppsCloudflareWorkers({ - accessToken, - accountId: accessId - }); - break; - case INTEGRATION_NORTHFLANK: - apps = await getAppsNorthflank({ - accessToken - }); - break; - case INTEGRATION_BITBUCKET: - apps = await getAppsBitBucket({ - accessToken, - workspaceSlug - }); - break; - case INTEGRATION_CODEFRESH: - apps = await getAppsCodefresh({ - accessToken - }); - break; - case INTEGRATION_WINDMILL: - apps = await getAppsWindmill({ - accessToken - }); - break; - case INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM: - apps = await getAppsDigitalOceanAppPlatform({ - accessToken - }); - break; - case INTEGRATION_CLOUD_66: - apps = await getAppsCloud66({ - accessToken - }); - break; - - case INTEGRATION_HASURA_CLOUD: - apps = await getAppsHasuraCloud({ - accessToken - }); - break; - } - - return apps; -}; - -/** - * Return list of apps for GCP secret manager integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for GCP API - * @returns {Object[]} apps - list of GCP projects - * @returns {String} apps.name - name of GCP project - * @returns {String} apps.appId - id of GCP project - */ -const getAppsGCPSecretManager = async ({ accessToken }: { accessToken: string }) => { - interface GCPApp { - projectNumber: string; - projectId: string; - lifecycleState: - | "ACTIVE" - | "LIFECYCLE_STATE_UNSPECIFIED" - | "DELETE_REQUESTED" - | "DELETE_IN_PROGRESS"; - name: string; - createTime: string; - parent: { - type: "organization" | "folder" | "project"; - id: string; - }; - } - - interface GCPGetProjectsRes { - projects: GCPApp[]; - nextPageToken?: string; - } - - interface GCPGetServiceRes { - name: string; - parent: string; - state: "ENABLED" | "DISABLED" | "STATE_UNSPECIFIED"; - } - - let gcpApps: GCPApp[] = []; - const apps: App[] = []; - - const pageSize = 100; - let pageToken: string | undefined; - let hasMorePages = true; - - while (hasMorePages) { - const params = new URLSearchParams({ - pageSize: String(pageSize), - ...(pageToken ? { pageToken } : {}) - }); - - const res: GCPGetProjectsRes = ( - await standardRequest.get(`${INTEGRATION_GCP_API_URL}/v1/projects`, { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }) - ).data; - - gcpApps = gcpApps.concat(res.projects); - - if (!res.nextPageToken) { - hasMorePages = false; - } - - pageToken = res.nextPageToken; - } - - for await (const gcpApp of gcpApps) { - try { - const res: GCPGetServiceRes = ( - await standardRequest.get( - `${INTEGRATION_GCP_SERVICE_USAGE_URL}/v1/projects/${gcpApp.projectId}/services/${INTEGRATION_GCP_SECRET_MANAGER_SERVICE_NAME}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ) - ).data; - - if (res.state === "ENABLED") { - apps.push({ - name: gcpApp.name, - appId: gcpApp.projectId - }); - } - } catch { - continue; - } - } - - return apps; -}; - -/** - * Return list of apps for Heroku integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Heroku API - * @returns {Object[]} apps - names of Heroku apps - * @returns {String} apps.name - name of Heroku app - */ -const getAppsHeroku = async ({ accessToken }: { accessToken: string }) => { - const res = ( - await standardRequest.get(`${INTEGRATION_HEROKU_API_URL}/apps`, { - headers: { - Accept: "application/vnd.heroku+json; version=3", - Authorization: `Bearer ${accessToken}` - } - }) - ).data; - - const apps = res.map((a: any) => ({ - name: a.name - })); - - return apps; -}; - -/** - * Return list of names of apps for Vercel integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Vercel API - * @returns {Object[]} apps - names of Vercel apps - * @returns {String} apps.name - name of Vercel app - */ -const getAppsVercel = async ({ - integrationAuth, - accessToken -}: { - integrationAuth: IIntegrationAuth; - accessToken: string; -}) => { - const res = ( - await standardRequest.get(`${INTEGRATION_VERCEL_API_URL}/v9/projects`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - }, - ...(integrationAuth?.teamId - ? { - params: { - teamId: integrationAuth.teamId - } - } - : {}) - }) - ).data; - - const apps = res.projects.map((a: any) => ({ - name: a.name, - appId: a.id - })); - - return apps; -}; - -/** - * Return list of sites for Netlify integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Netlify API - * @returns {Object[]} apps - names of Netlify sites - * @returns {String} apps.name - name of Netlify site - */ -const getAppsNetlify = async ({ accessToken }: { accessToken: string }) => { - const apps: any = []; - let page = 1; - const perPage = 10; - let hasMorePages = true; - - // paginate through all sites - while (hasMorePages) { - const params = new URLSearchParams({ - page: String(page), - per_page: String(perPage), - filter: "all" - }); - - const { data } = await standardRequest.get(`${INTEGRATION_NETLIFY_API_URL}/api/v1/sites`, { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }); - - data.map((a: any) => { - apps.push({ - name: a.name, - appId: a.site_id - }); - }); - - if (data.length < perPage) { - hasMorePages = false; - } - - page++; - } - - return apps; -}; - -/** - * Return list of repositories for Github integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Github API - * @returns {Object[]} apps - names of Github sites - * @returns {String} apps.name - name of Github site - */ -const getAppsGithub = async ({ accessToken }: { accessToken: string }) => { - interface GitHubApp { - id: string; - name: string; - permissions: { - admin: boolean; - }; - owner: { - login: string; - }; - } - - const octokit = new Octokit({ - auth: accessToken - }); - - const getAllRepos = async () => { - let repos: GitHubApp[] = []; - let page = 1; - const per_page = 100; - let hasMore = true; - - while (hasMore) { - const response = await octokit.request( - "GET /user/repos{?visibility,affiliation,type,sort,direction,per_page,page,since,before}", - { - per_page, - page - } - ); - - if (response.data.length > 0) { - repos = repos.concat(response.data); - page++; - } else { - hasMore = false; - } - } - - return repos; - }; - - const repos = await getAllRepos(); - - const apps = repos - .filter((a: GitHubApp) => a.permissions.admin === true) - .map((a: GitHubApp) => { - return { - appId: a.id, - name: a.name, - owner: a.owner.login - }; - }); - - return apps; -}; - -/** - * Return list of services for Render integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Render API - * @returns {Object[]} apps - names and ids of Render services - * @returns {String} apps.name - name of Render service - * @returns {String} apps.appId - id of Render service - */ -const getAppsRender = async ({ accessToken }: { accessToken: string }) => { - const res = ( - await standardRequest.get(`${INTEGRATION_RENDER_API_URL}/v1/services`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "Accept-Encoding": "application/json" - } - }) - ).data; - - const apps = res.map((a: any) => ({ - name: a.service.name, - appId: a.service.id - })); - - return apps; -}; - -/** - * Return list of projects for Railway integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Railway API - * @returns {Object[]} apps - names and ids of Railway services - * @returns {String} apps.name - name of Railway project - * @returns {String} apps.appId - id of Railway project - * - */ -const getAppsRailway = async ({ accessToken }: { accessToken: string }) => { - const query = ` - query GetProjects($userId: String, $teamId: String) { - projects(userId: $userId, teamId: $teamId) { - edges { - node { - id - name - } - } - } - } - `; - - const variables = {}; - - const { - data: { - data: { - projects: { edges } - } - } - } = await standardRequest.post( - INTEGRATION_RAILWAY_API_URL, - { - query, - variables - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); - - const apps = edges.map((e: any) => ({ - name: e.node.name, - appId: e.node.id - })); - - return apps; -}; - -/** - * Return list of sites for Laravel Forge integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Laravel Forge API - * @param {String} obj.serverId - server id of Laravel Forge - * @returns {Object[]} apps - names and ids of Laravel Forge sites - * @returns {String} apps.name - name of Laravel Forge sites - * @returns {String} apps.appId - id of Laravel Forge sites - */ -const getAppsLaravelForge = async ({ - accessToken, - serverId -}: { - accessToken: string; - serverId?: string; -}) => { - const res = ( - await standardRequest.get( - `${INTEGRATION_LARAVELFORGE_API_URL}/api/v1/servers/${serverId}/sites`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "Content-Type": "application/json" - } - } - ) - ).data.sites; - - const apps = res.map((a: any) => ({ - name: a.name, - appId: a.id - })); - - return apps; -}; - -/** - * Return list of apps for Fly.io integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Fly.io API - * @returns {Object[]} apps - names and ids of Fly.io apps - * @returns {String} apps.name - name of Fly.io apps - */ -const getAppsFlyio = async ({ accessToken }: { accessToken: string }) => { - interface FlyioApp { - id: string; - name: string; - hostname: string; - } - - const query = ` - query($role: String) { - apps(type: "container", first: 400, role: $role) { - nodes { - id - name - hostname - } - } - } - `; - - const res: FlyioApp[] = ( - await standardRequest.post( - INTEGRATION_FLYIO_API_URL, - { - query, - variables: { - role: null - } - }, - { - headers: { - Authorization: "Bearer " + accessToken, - Accept: "application/json", - "Accept-Encoding": "application/json" - } - } - ) - ).data.data.apps.nodes; - - const apps = res.map((a: FlyioApp) => ({ - name: a.name, - appId: a.id - })); - - return apps; -}; - -/** - * Return list of projects for CircleCI integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for CircleCI API - * @returns {Object[]} apps - - * @returns {String} apps.name - name of CircleCI apps - */ -const getAppsCircleCI = async ({ accessToken }: { accessToken: string }) => { - const res = ( - await standardRequest.get(`${INTEGRATION_CIRCLECI_API_URL}/v1.1/projects`, { - headers: { - "Circle-Token": accessToken, - "Accept-Encoding": "application/json" - } - }) - ).data; - - const apps = res?.map((a: any) => { - return { - name: a?.reponame - }; - }); - - return apps; -}; - -const getAppsTravisCI = async ({ accessToken }: { accessToken: string }) => { - const res = ( - await standardRequest.get(`${INTEGRATION_TRAVISCI_API_URL}/repos`, { - headers: { - Authorization: `token ${accessToken}`, - "Accept-Encoding": "application/json" - } - }) - ).data; - - const apps = res?.map((a: any) => { - return { - name: a?.slug?.split("/")[1], - appId: a?.id - }; - }); - - return apps; -}; - -/** - * Return list of projects for Terraform Cloud integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Terraform Cloud API - * @param {String} obj.workspacesId - workspace id of Terraform Cloud projects - * @returns {Object[]} apps - names and ids of Terraform Cloud projects - * @returns {String} apps.name - name of Terraform Cloud projects - */ -const getAppsTerraformCloud = async ({ - accessToken, - workspacesId -}: { - accessToken: string; - workspacesId?: string; -}) => { - const res = ( - await standardRequest.get( - `${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${workspacesId}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ) - ).data.data; - - const apps = []; - - const appsObj = { - name: res?.attributes.name, - appId: res?.id - }; - - apps.push(appsObj); - - return apps; -}; - -/** - * Return list of repositories for GitLab integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for GitLab API - * @returns {Object[]} apps - names of GitLab sites - * @returns {String} apps.name - name of GitLab site - */ -const getAppsGitlab = async ({ - integrationAuth, - accessToken, - teamId -}: { - integrationAuth: IIntegrationAuth; - accessToken: string; - teamId?: string; -}) => { - const gitLabApiUrl = integrationAuth.url - ? `${integrationAuth.url}/api` - : INTEGRATION_GITLAB_API_URL; - - const apps: App[] = []; - - let page = 1; - const perPage = 10; - let hasMorePages = true; - - if (teamId) { - // case: fetch projects for group with id [teamId] in GitLab - - while (hasMorePages) { - const params = new URLSearchParams({ - page: String(page), - per_page: String(perPage) - }); - - const { data } = await standardRequest.get(`${gitLabApiUrl}/v4/groups/${teamId}/projects`, { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }); - - data.map((a: any) => { - apps.push({ - name: a.name, - appId: a.id - }); - }); - - if (data.length < perPage) { - hasMorePages = false; - } - - page++; - } - } else { - // case: fetch projects for individual in GitLab - - const { id } = ( - await standardRequest.get(`${gitLabApiUrl}/v4/user`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }) - ).data; - - while (hasMorePages) { - const params = new URLSearchParams({ - page: String(page), - per_page: String(perPage) - }); - - const { data } = await standardRequest.get(`${gitLabApiUrl}/v4/users/${id}/projects`, { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }); - - data.map((a: any) => { - apps.push({ - name: a.name, - appId: a.id - }); - }); - - if (data.length < perPage) { - hasMorePages = false; - } - - page++; - } - } - - return apps; -}; - -/** - * Return list of projects for TeamCity integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for TeamCity API - * @returns {Object[]} apps - names and ids of TeamCity projects - * @returns {String} apps.name - name of TeamCity projects - */ -const getAppsTeamCity = async ({ - integrationAuth, - accessToken -}: { - integrationAuth: IIntegrationAuth; - accessToken: string; -}) => { - const res = ( - await standardRequest.get(`${integrationAuth.url}/app/rest/projects`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - }) - ).data.project.slice(1); - - const apps = res.map((a: any) => { - return { - name: a.name, - appId: a.id - }; - }); - - return apps; -}; - -/** - * Return list of projects for Supabase integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Supabase API - * @returns {Object[]} apps - names of Supabase apps - * @returns {String} apps.name - name of Supabase app - */ -const getAppsSupabase = async ({ accessToken }: { accessToken: string }) => { - const { data } = await standardRequest.get(`${INTEGRATION_SUPABASE_API_URL}/v1/projects`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }); - - const apps = data.map((a: any) => { - return { - name: a.name, - appId: a.id - }; - }); - - return apps; -}; - -/** - * Return list of accounts for the Checkly integration - * @param {Object} obj - * @param {String} obj.accessToken - api key for the Checkly API - * @returns {Object[]} apps - Сheckly accounts - * @returns {String} apps.name - name of Checkly account - */ -const getAppsCheckly = async ({ accessToken }: { accessToken: string }) => { - const { data } = await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/accounts`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - }); - - const apps = data.map((a: any) => { - return { - name: a.name, - appId: a.id - }; - }); - - return apps; -}; - -/** - * Return list of projects for the Cloudflare Pages integration - * @param {Object} obj - * @param {String} obj.accessToken - api key for the Cloudflare API - * @returns {Object[]} apps - Cloudflare Pages projects - * @returns {String} apps.name - name of Cloudflare Pages project - */ -const getAppsCloudflarePages = async ({ - accessToken, - accountId -}: { - accessToken: string; - accountId?: string; -}) => { - const { data } = await standardRequest.get( - `${INTEGRATION_CLOUDFLARE_PAGES_API_URL}/client/v4/accounts/${accountId}/pages/projects`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - - const apps = data.result.map((a: any) => { - return { - name: a.name, - appId: a.id - }; - }); - return apps; -}; - -/** - * Return list of projects for the Cloudflare Workers integration - * @param {Object} obj - * @param {String} obj.accessToken - api key for the Cloudflare API - * @returns {Object[]} apps - Cloudflare Workers projects - * @returns {String} apps.id - Id of Cloudflare Workers project - * @returns {String} apps.name - Id of Cloudflare Workers project (Cloudflare workers API does not return the name) - */ -const getAppsCloudflareWorkers = async ({ - accessToken, - accountId -}: { - accessToken: string; - accountId?: string; -}) => { - const { data } = await standardRequest.get( - `${INTEGRATION_CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accountId}/workers/services`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - - const apps = data.result.map((a: any) => { - return { - name: a.id, - appId: a.id - }; - }); - return apps; -}; - -/** - * Return list of repositories for the BitBucket integration based on provided BitBucket workspace - * @param {Object} obj - * @param {String} obj.accessToken - access token for BitBucket API - * @param {String} obj.workspaceSlug - Workspace identifier for fetching BitBucket repositories - * @returns {Object[]} apps - BitBucket repositories - * @returns {String} apps.name - name of BitBucket repository - */ -const getAppsBitBucket = async ({ - accessToken, - workspaceSlug -}: { - accessToken: string; - workspaceSlug?: string; -}) => { - interface RepositoriesResponse { - size: number; - page: number; - pageLen: number; - next: string; - previous: string; - values: Array; - } - - interface Repository { - type: string; - uuid: string; - name: string; - is_private: boolean; - created_on: string; - updated_on: string; - } - - if (!workspaceSlug) { - return []; - } - - const repositories: Repository[] = []; - let hasNextPage = true; - let repositoriesUrl = `${INTEGRATION_BITBUCKET_API_URL}/2.0/repositories/${workspaceSlug}`; - - while (hasNextPage) { - const { data }: { data: RepositoriesResponse } = await standardRequest.get(repositoriesUrl, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - }); - - if (data?.values.length > 0) { - data.values.forEach((repository) => { - repositories.push(repository); - }); - } - - if (data.next) { - repositoriesUrl = data.next; - } else { - hasNextPage = false; - } - } - - const apps = repositories.map((repository) => { - return { - name: repository.name, - appId: repository.uuid - }; - }); - return apps; -}; - -/** Return list of projects for Northflank integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Northflank API - * @returns {Object[]} apps - names of Northflank apps - * @returns {String} apps.name - name of Northflank app - */ -const getAppsNorthflank = async ({ accessToken }: { accessToken: string }) => { - const { - data: { - data: { projects } - } - } = await standardRequest.get(`${INTEGRATION_NORTHFLANK_API_URL}/v1/projects`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }); - - const apps = projects.map((a: any) => { - return { - name: a.name, - appId: a.id - }; - }); - - return apps; -}; - -/** - * Return list of projects for Supabase integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Supabase API - * @returns {Object[]} apps - names of Supabase apps - * @returns {String} apps.name - name of Supabase app - */ -const getAppsCodefresh = async ({ accessToken }: { accessToken: string }) => { - const res = ( - await standardRequest.get(`${INTEGRATION_CODEFRESH_API_URL}/projects`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }) - ).data; - - const apps = res.projects.map((a: any) => ({ - name: a.projectName, - appId: a.id - })); - - return apps; -}; - -/** - * Return list of projects for Windmill integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for Windmill API - * @returns {Object[]} apps - names of Windmill workspaces - * @returns {String} apps.name - name of Windmill workspace - */ -const getAppsWindmill = async ({ accessToken }: { accessToken: string }) => { - const { data } = await standardRequest.get(`${INTEGRATION_WINDMILL_API_URL}/workspaces/list`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }); - - // check for write access of secrets in windmill workspaces - const writeAccessCheck = data.map(async (app: any) => { - try { - const userPath = "u/user/variable"; - const folderPath = "f/folder/variable"; - - const { data: writeUser } = await standardRequest.post( - `${INTEGRATION_WINDMILL_API_URL}/w/${app.id}/variables/create`, - { - path: userPath, - value: "variable", - is_secret: true, - description: "variable description" - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - const { data: writeFolder } = await standardRequest.post( - `${INTEGRATION_WINDMILL_API_URL}/w/${app.id}/variables/create`, - { - path: folderPath, - value: "variable", - is_secret: true, - description: "variable description" - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - // is write access is allowed then delete the created secrets from workspace - if (writeUser && writeFolder) { - await standardRequest.delete( - `${INTEGRATION_WINDMILL_API_URL}/w/${app.id}/variables/delete/${userPath}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - await standardRequest.delete( - `${INTEGRATION_WINDMILL_API_URL}/w/${app.id}/variables/delete/${folderPath}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - return app; - } else { - return { error: "cannot write secret" }; - } - } catch (err: any) { - return { error: err.message }; - } - }); - - const appsWriteResponses = await Promise.all(writeAccessCheck); - const appsWithWriteAccess = appsWriteResponses.filter((appRes: any) => !appRes.error); - - const apps = appsWithWriteAccess.map((a: any) => { - return { - name: a.name, - appId: a.id - }; - }); - - return apps; -}; - -/** - * Return list of applications for DigitalOcean App Platform integration - * @param {Object} obj - * @param {String} obj.accessToken - personal access token for DigitalOcean - * @returns {Object[]} apps - names of DigitalOcean apps - * @returns {String} apps.name - name of DigitalOcean app - * @returns {String} apps.appId - id of DigitalOcean app - */ -const getAppsDigitalOceanAppPlatform = async ({ accessToken }: { accessToken: string }) => { - interface DigitalOceanApp { - id: string; - owner_uuid: string; - spec: Spec; - } - - interface Spec { - name: string; - region: string; - envs: Env[]; - } - - interface Env { - key: string; - value: string; - scope: string; - } - - const res = ( - await standardRequest.get(`${INTEGRATION_DIGITAL_OCEAN_API_URL}/v2/apps`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }) - ).data; - - return (res.apps ?? []).map((a: DigitalOceanApp) => ({ - name: a.spec.name, - appId: a.id - })); -}; - -const getAppsHasuraCloud = async ({ accessToken }: { accessToken: string }) => { - const res = await standardRequest.post( - INTEGRATION_HASURA_CLOUD_API_URL, - { - query: "query MyQuery { projects { name tenant { id } } }" - }, - { - headers: { - Authorization: `pat ${accessToken}`, - "Content-Type": "application/json" - } - } - ); - - const data = (res?.data?.data?.projects ?? []).map( - ({ name, tenant: { id: appId } }: { name: string; tenant: { id: string } }) => ({ name, appId }) - ); - return data; -}; - -/** - * Return list of applications for Cloud66 integration - * @param {Object} obj - * @param {String} obj.accessToken - personal access token for Cloud66 API - * @returns {Object[]} apps - Cloud66 apps - * @returns {String} apps.name - name of Cloud66 app - * @returns {String} apps.appId - uid of Cloud66 app - */ -const getAppsCloud66 = async ({ accessToken }: { accessToken: string }) => { - interface Cloud66Apps { - uid: string; - name: string; - account_id: number; - git: string; - git_branch: string; - environment: string; - cloud: string; - fqdn: string; - language: string; - framework: string; - status: number; - health: number; - last_activity: string; - last_activity_iso: string; - maintenance_mode: boolean; - has_loadbalancer: boolean; - created_at: string; - updated_at: string; - deploy_directory: string; - cloud_status: string; - backend: string; - version: string; - revision: string; - is_busy: boolean; - account_name: string; - is_cluster: boolean; - is_inside_cluster: boolean; - cluster_name: any; - application_address: string; - configstore_namespace: string; - } - - const stacks = ( - await standardRequest.get(`${INTEGRATION_CLOUD_66_API_URL}/3/stacks`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }) - ).data.response as Cloud66Apps[]; - - const apps = stacks.map((app) => ({ - name: app.name, - appId: app.uid - })); - - return apps; -}; - -export { getApps }; diff --git a/backend-mongo/src/integrations/exchange.ts b/backend-mongo/src/integrations/exchange.ts deleted file mode 100644 index 37382e79e..000000000 --- a/backend-mongo/src/integrations/exchange.ts +++ /dev/null @@ -1,469 +0,0 @@ -import { standardRequest } from "../config/request"; -import { - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_AZURE_TOKEN_URL, - INTEGRATION_BITBUCKET, - INTEGRATION_BITBUCKET_TOKEN_URL, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_GCP_TOKEN_URL, - INTEGRATION_GITHUB, - INTEGRATION_GITHUB_TOKEN_URL, - INTEGRATION_GITLAB, - INTEGRATION_GITLAB_TOKEN_URL, - INTEGRATION_HEROKU, - INTEGRATION_HEROKU_TOKEN_URL, - INTEGRATION_NETLIFY, - INTEGRATION_NETLIFY_TOKEN_URL, - INTEGRATION_VERCEL, - INTEGRATION_VERCEL_TOKEN_URL -} from "../variables"; -import { - getClientIdAzure, - getClientIdBitBucket, - getClientIdGCPSecretManager, - getClientIdGitHub, - getClientIdGitLab, - getClientIdNetlify, - getClientIdVercel, - getClientSecretAzure, - getClientSecretBitBucket, - getClientSecretGCPSecretManager, - getClientSecretGitHub, - getClientSecretGitLab, - getClientSecretHeroku, - getClientSecretNetlify, - getClientSecretVercel, - getSiteURL, -} from "../config"; - -interface ExchangeCodeAzureResponse { - token_type: string; - scope: string; - expires_in: number; - ext_expires_in: number; - access_token: string; - refresh_token: string; - id_token: string; -} - -interface ExchangeCodeGCPResponse { - access_token: string; - expires_in: number; - refresh_token: string; - scope: string; - token_type: string; -} - -interface ExchangeCodeHerokuResponse { - token_type: string; - access_token: string; - expires_in: number; - refresh_token: string; - user_id: string; - session_nonce?: string; -} - -interface ExchangeCodeVercelResponse { - token_type: string; - access_token: string; - installation_id: string; - user_id: string; - team_id?: string; -} - -interface ExchangeCodeNetlifyResponse { - access_token: string; - token_type: string; - refresh_token: string; - scope: string; - created_at: number; -} - -interface ExchangeCodeGithubResponse { - access_token: string; - scope: string; - token_type: string; -} - -interface ExchangeCodeGitlabResponse { - access_token: string; - token_type: string; - expires_in: number; - refresh_token: string; - scope: string; - created_at: number; -} - -interface ExchangeCodeBitBucketResponse { - access_token: string; - token_type: string; - expires_in: number; - refresh_token: string; - scopes: string; - state: string; -} - -/** - * Return [accessToken], [accessExpiresAt], and [refreshToken] for OAuth2 - * code-token exchange for integration named [integration] - * @param {Object} obj1 - * @param {String} obj1.integration - name of integration - * @param {String} obj1.code - code for code-token exchange - * @returns {Object} obj - * @returns {String} obj.accessToken - access token for integration - * @returns {String} obj.refreshToken - refresh token for integration - * @returns {Date} obj.accessExpiresAt - date of expiration for access token - * @returns {String} obj.action - integration action for bot sequence - */ -const exchangeCode = async ({ - integration, - code, - url -}: { - integration: string; - code: string; - url?: string; -}) => { - let obj = {} as any; - - switch (integration) { - case INTEGRATION_GCP_SECRET_MANAGER: - obj = await exchangeCodeGCP({ - code, - }); - break; - case INTEGRATION_AZURE_KEY_VAULT: - obj = await exchangeCodeAzure({ - code, - }); - break; - case INTEGRATION_HEROKU: - obj = await exchangeCodeHeroku({ - code, - }); - break; - case INTEGRATION_VERCEL: - obj = await exchangeCodeVercel({ - code, - }); - break; - case INTEGRATION_NETLIFY: - obj = await exchangeCodeNetlify({ - code, - }); - break; - case INTEGRATION_GITHUB: - obj = await exchangeCodeGithub({ - code, - }); - break; - case INTEGRATION_GITLAB: - obj = await exchangeCodeGitlab({ - code, - url - }); - break; - case INTEGRATION_BITBUCKET: - obj = await exchangeCodeBitBucket({ - code, - }); - break; - } - - return obj; -}; - -/** - * Return [accessToken] for GCP OAuth2 code-token exchange - * @param {Object} obj - * @param {String} obj.code - code for code-token exchange - * @returns {Object} obj2 - * @returns {String} obj2.accessToken - access token for GCP API - * @returns {String} obj2.refreshToken - refresh token for GCP API - * @returns {Date} obj2.accessExpiresAt - date of expiration for access token - */ -const exchangeCodeGCP = async ({ code }: { code: string }) => { - const accessExpiresAt = new Date(); - - const res: ExchangeCodeGCPResponse = ( - await standardRequest.post( - INTEGRATION_GCP_TOKEN_URL, - new URLSearchParams({ - grant_type: "authorization_code", - code: code, - client_id: await getClientIdGCPSecretManager(), - client_secret: await getClientSecretGCPSecretManager(), - redirect_uri: `${await getSiteURL()}/integrations/gcp-secret-manager/oauth2/callback`, - } as any) - ) - ).data; - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in); - - return { - accessToken: res.access_token, - refreshToken: res.refresh_token, - accessExpiresAt, - }; -}; - -/** - * Return [accessToken] for Azure OAuth2 code-token exchange - * @param param0 - */ -const exchangeCodeAzure = async ({ code }: { code: string }) => { - const accessExpiresAt = new Date(); - - const res: ExchangeCodeAzureResponse = ( - await standardRequest.post( - INTEGRATION_AZURE_TOKEN_URL, - new URLSearchParams({ - grant_type: "authorization_code", - code: code, - scope: "https://vault.azure.net/.default openid offline_access", - client_id: await getClientIdAzure(), - client_secret: await getClientSecretAzure(), - redirect_uri: `${await getSiteURL()}/integrations/azure-key-vault/oauth2/callback`, - } as any) - ) - ).data; - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in); - - return { - accessToken: res.access_token, - refreshToken: res.refresh_token, - accessExpiresAt, - }; -}; - -/** - * Return [accessToken], [accessExpiresAt], and [refreshToken] for Heroku - * OAuth2 code-token exchange - * @param {Object} obj1 - * @param {Object} obj1.code - code for code-token exchange - * @returns {Object} obj2 - * @returns {String} obj2.accessToken - access token for Heroku API - * @returns {String} obj2.refreshToken - refresh token for Heroku API - * @returns {Date} obj2.accessExpiresAt - date of expiration for access token - */ -const exchangeCodeHeroku = async ({ code }: { code: string }) => { - const accessExpiresAt = new Date(); - - const res: ExchangeCodeHerokuResponse = ( - await standardRequest.post( - INTEGRATION_HEROKU_TOKEN_URL, - new URLSearchParams({ - grant_type: "authorization_code", - code: code, - client_secret: await getClientSecretHeroku(), - } as any) - ) - ).data; - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in); - - return { - accessToken: res.access_token, - refreshToken: res.refresh_token, - accessExpiresAt, - }; -}; - -/** - * Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel - * code-token exchange - * @param {Object} obj1 - * @param {Object} obj1.code - code for code-token exchange - * @returns {Object} obj2 - * @returns {String} obj2.accessToken - access token for Heroku API - * @returns {String} obj2.refreshToken - refresh token for Heroku API - * @returns {Date} obj2.accessExpiresAt - date of expiration for access token - */ -const exchangeCodeVercel = async ({ code }: { code: string }) => { - const res: ExchangeCodeVercelResponse = ( - await standardRequest.post( - INTEGRATION_VERCEL_TOKEN_URL, - new URLSearchParams({ - code: code, - client_id: await getClientIdVercel(), - client_secret: await getClientSecretVercel(), - redirect_uri: `${await getSiteURL()}/integrations/vercel/oauth2/callback`, - } as any) - ) - ).data; - - return { - accessToken: res.access_token, - refreshToken: null, - accessExpiresAt: null, - teamId: res.team_id, - }; -}; - -/** - * Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel - * code-token exchange - * @param {Object} obj1 - * @param {Object} obj1.code - code for code-token exchange - * @returns {Object} obj2 - * @returns {String} obj2.accessToken - access token for Heroku API - * @returns {String} obj2.refreshToken - refresh token for Heroku API - * @returns {Date} obj2.accessExpiresAt - date of expiration for access token - */ -const exchangeCodeNetlify = async ({ code }: { code: string }) => { - const res: ExchangeCodeNetlifyResponse = ( - await standardRequest.post( - INTEGRATION_NETLIFY_TOKEN_URL, - new URLSearchParams({ - grant_type: "authorization_code", - code: code, - client_id: await getClientIdNetlify(), - client_secret: await getClientSecretNetlify(), - redirect_uri: `${await getSiteURL()}/integrations/netlify/oauth2/callback`, - } as any) - ) - ).data; - - const res2 = await standardRequest.get("https://api.netlify.com/api/v1/sites", { - headers: { - Authorization: `Bearer ${res.access_token}`, - }, - }); - - const res3 = ( - await standardRequest.get("https://api.netlify.com/api/v1/accounts", { - headers: { - Authorization: `Bearer ${res.access_token}`, - }, - }) - ).data; - - const accountId = res3[0].id; - - return { - accessToken: res.access_token, - refreshToken: res.refresh_token, - accountId, - }; -}; - -/** - * Return [accessToken], [accessExpiresAt], and [refreshToken] for Github - * code-token exchange - * @param {Object} obj1 - * @param {Object} obj1.code - code for code-token exchange - * @returns {Object} obj2 - * @returns {String} obj2.accessToken - access token for Github API - * @returns {String} obj2.refreshToken - refresh token for Github API - * @returns {Date} obj2.accessExpiresAt - date of expiration for access token - */ -const exchangeCodeGithub = async ({ code }: { code: string }) => { - const res: ExchangeCodeGithubResponse = ( - await standardRequest.get(INTEGRATION_GITHUB_TOKEN_URL, { - params: { - client_id: await getClientIdGitHub(), - client_secret: await getClientSecretGitHub(), - code: code, - redirect_uri: `${await getSiteURL()}/integrations/github/oauth2/callback`, - }, - headers: { - Accept: "application/json", - "Accept-Encoding": "application/json", - }, - }) - ).data; - - return { - accessToken: res.access_token, - refreshToken: null, - accessExpiresAt: null, - }; -}; - -/** - * Return [accessToken], [accessExpiresAt], and [refreshToken] for Gitlab - * code-token exchange - * @param {Object} obj1 - * @param {Object} obj1.code - code for code-token exchange - * @returns {Object} obj2 - * @returns {String} obj2.accessToken - access token for Gitlab API - * @returns {String} obj2.refreshToken - refresh token for Gitlab API - * @returns {Date} obj2.accessExpiresAt - date of expiration for access token - */ -const exchangeCodeGitlab = async ({ - code, - url -}: { - code: string, - url?: string; -}) => { - const accessExpiresAt = new Date(); - const res: ExchangeCodeGitlabResponse = ( - await standardRequest.post( - url ? `${url}/oauth/token` : INTEGRATION_GITLAB_TOKEN_URL, - new URLSearchParams({ - grant_type: "authorization_code", - code: code, - client_id: await getClientIdGitLab(), - client_secret: await getClientSecretGitLab(), - redirect_uri: `${await getSiteURL()}/integrations/gitlab/oauth2/callback`, - } as any), - { - headers: { - "Accept-Encoding": "application/json", - }, - } - ) - ).data; - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in); - - return { - accessToken: res.access_token, - refreshToken: res.refresh_token, - accessExpiresAt, - url - }; -}; - -/** - * Return [accessToken], [accessExpiresAt], and [refreshToken] for BitBucket - * code-token exchange - * @param {Object} obj1 - * @param {Object} obj1.code - code for code-token exchange - * @returns {Object} obj2 - * @returns {String} obj2.accessToken - access token for BitBucket API - * @returns {String} obj2.refreshToken - refresh token for BitBucket API - * @returns {Date} obj2.accessExpiresAt - date of expiration for access token - */ -const exchangeCodeBitBucket = async ({ code }: { code: string }) => { - const accessExpiresAt = new Date(); - const res: ExchangeCodeBitBucketResponse = ( - await standardRequest.post( - INTEGRATION_BITBUCKET_TOKEN_URL, - new URLSearchParams({ - grant_type: "authorization_code", - code: code, - client_id: await getClientIdBitBucket(), - client_secret: await getClientSecretBitBucket(), - redirect_uri: `${await getSiteURL()}/integrations/bitbucket/oauth2/callback`, - } as any), - { - headers: { - "Accept-Encoding": "application/json", - }, - } - ) - ).data; - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in); - - return { - accessToken: res.access_token, - refreshToken: res.refresh_token, - accessExpiresAt, - }; -}; - -export { exchangeCode }; diff --git a/backend-mongo/src/integrations/index.ts b/backend-mongo/src/integrations/index.ts deleted file mode 100644 index e1bf23ba1..000000000 --- a/backend-mongo/src/integrations/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { exchangeCode } from "./exchange"; -import { exchangeRefresh } from "./refresh"; -import { getApps } from "./apps"; -import { getTeams } from "./teams"; -import { revokeAccess } from "./revoke"; - -export { - exchangeCode, - exchangeRefresh, - getApps, - getTeams, - revokeAccess, -} \ No newline at end of file diff --git a/backend-mongo/src/integrations/refresh.ts b/backend-mongo/src/integrations/refresh.ts deleted file mode 100644 index dee4931c8..000000000 --- a/backend-mongo/src/integrations/refresh.ts +++ /dev/null @@ -1,382 +0,0 @@ -import jwt from "jsonwebtoken"; -import { standardRequest } from "../config/request"; -import { IIntegrationAuth } from "../models"; -import { - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_BITBUCKET, - INTEGRATION_BITBUCKET_TOKEN_URL, - INTEGRATION_GCP_CLOUD_PLATFORM_SCOPE, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_GCP_TOKEN_URL, - INTEGRATION_GITLAB, - INTEGRATION_HEROKU -} from "../variables"; -import { - INTEGRATION_AZURE_TOKEN_URL, - INTEGRATION_GITLAB_TOKEN_URL, - INTEGRATION_HEROKU_TOKEN_URL, -} from "../variables"; -import { IntegrationService } from "../services"; -import { - getClientIdAzure, - getClientIdBitBucket, - getClientIdGCPSecretManager, - getClientIdGitLab, - getClientSecretAzure, - getClientSecretBitBucket, - getClientSecretGCPSecretManager, - getClientSecretGitLab, - getClientSecretHeroku, - getSiteURL, -} from "../config"; - -interface RefreshTokenAzureResponse { - token_type: string; - scope: string; - expires_in: number; - ext_expires_in: 4871; - access_token: string; - refresh_token: string; -} - -interface RefreshTokenHerokuResponse { - access_token: string; - expires_in: number; - refresh_token: string; - token_type: string; - user_id: string; -} - -interface RefreshTokenGitLabResponse { - token_type: string; - scope: string; - expires_in: number; - access_token: string; - refresh_token: string; - created_at: number; -} - -interface RefreshTokenBitBucketResponse { - access_token: string; - token_type: string; - expires_in: number; - refresh_token: string; - scopes: string; - state: string; -} - -interface ServiceAccountAccessTokenGCPSecretManagerResponse { - access_token: string; - expires_in: number; - token_type: string; -} - -interface RefreshTokenGCPSecretManagerResponse { - access_token: string; - expires_in: number; - scope: string; - token_type: string; -} - -/** - * Return new access token by exchanging refresh token [refreshToken] for integration - * named [integration] - * @param {Object} obj - * @param {String} obj.integration - name of integration - * @param {String} obj.refreshToken - refresh token to use to get new access token for Heroku - */ -const exchangeRefresh = async ({ - integrationAuth, - refreshToken, -}: { - integrationAuth: IIntegrationAuth; - refreshToken: string; -}) => { - interface TokenDetails { - accessToken: string; - refreshToken: string; - accessExpiresAt: Date; - } - - let tokenDetails: TokenDetails; - switch (integrationAuth.integration) { - case INTEGRATION_AZURE_KEY_VAULT: - tokenDetails = await exchangeRefreshAzure({ - refreshToken, - }); - break; - case INTEGRATION_HEROKU: - tokenDetails = await exchangeRefreshHeroku({ - refreshToken, - }); - break; - case INTEGRATION_GITLAB: - tokenDetails = await exchangeRefreshGitLab({ - integrationAuth, - refreshToken, - }); - break; - case INTEGRATION_BITBUCKET: - tokenDetails = await exchangeRefreshBitBucket({ - refreshToken, - }); - break; - case INTEGRATION_GCP_SECRET_MANAGER: - tokenDetails = await exchangeRefreshGCPSecretManager({ - integrationAuth, - refreshToken, - }); - break; - default: - throw new Error("Failed to exchange token for incompatible integration"); - } - - if ( - tokenDetails.accessToken && - tokenDetails.refreshToken && - tokenDetails.accessExpiresAt - ) { - await IntegrationService.setIntegrationAuthAccess({ - integrationAuthId: integrationAuth._id.toString(), - accessToken: tokenDetails.accessToken, - accessExpiresAt: tokenDetails.accessExpiresAt, - }); - - await IntegrationService.setIntegrationAuthRefresh({ - integrationAuthId: integrationAuth._id.toString(), - refreshToken: tokenDetails.refreshToken, - }); - } - - return tokenDetails.accessToken; -}; - -/** - * Return new access token by exchanging refresh token [refreshToken] for the - * Azure integration - * @param {Object} obj - * @param {String} obj.refreshToken - refresh token to use to get new access token for Azure - * @returns - */ -const exchangeRefreshAzure = async ({ - refreshToken, -}: { - refreshToken: string; -}) => { - const accessExpiresAt = new Date(); - const { data }: { data: RefreshTokenAzureResponse } = await standardRequest.post( - INTEGRATION_AZURE_TOKEN_URL, - new URLSearchParams({ - client_id: await getClientIdAzure(), - scope: "openid offline_access", - refresh_token: refreshToken, - grant_type: "refresh_token", - client_secret: await getClientSecretAzure(), - } as any) - ); - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); - - return { - accessToken: data.access_token, - refreshToken: data.refresh_token, - accessExpiresAt, - }; -}; - -/** - * Return new access token by exchanging refresh token [refreshToken] for the - * Heroku integration - * @param {Object} obj - * @param {String} obj.refreshToken - refresh token to use to get new access token for Heroku - * @returns - */ -const exchangeRefreshHeroku = async ({ - refreshToken, -}: { - refreshToken: string; -}) => { - const accessExpiresAt = new Date(); - const { - data, - }: { - data: RefreshTokenHerokuResponse; - } = await standardRequest.post( - INTEGRATION_HEROKU_TOKEN_URL, - new URLSearchParams({ - grant_type: "refresh_token", - refresh_token: refreshToken, - client_secret: await getClientSecretHeroku(), - } as any) - ); - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); - - return { - accessToken: data.access_token, - refreshToken: data.refresh_token, - accessExpiresAt, - }; -}; - -/** - * Return new access token by exchanging refresh token [refreshToken] for the - * GitLab integration - * @param {Object} obj - * @param {String} obj.refreshToken - refresh token to use to get new access token for GitLab - * @returns - */ -const exchangeRefreshGitLab = async ({ - integrationAuth, - refreshToken, -}: { - integrationAuth: IIntegrationAuth; - refreshToken: string; -}) => { - const accessExpiresAt = new Date(); - const url = integrationAuth.url; - - const { - data, - }: { - data: RefreshTokenGitLabResponse; - } = await standardRequest.post( - url ? `${url}/oauth/token` : INTEGRATION_GITLAB_TOKEN_URL, - new URLSearchParams({ - grant_type: "refresh_token", - refresh_token: refreshToken, - client_id: await getClientIdGitLab(), - client_secret: await getClientSecretGitLab(), - redirect_uri: `${await getSiteURL()}/integrations/gitlab/oauth2/callback`, - } as any), - { - headers: { - "Accept-Encoding": "application/json", - }, - } - ); - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); - - return { - accessToken: data.access_token, - refreshToken: data.refresh_token, - accessExpiresAt, - }; -}; - -/** - * Return new access token by exchanging refresh token [refreshToken] for the - * BitBucket integration - * @param {Object} obj - * @param {String} obj.refreshToken - refresh token to use to get new access token for BitBucket - * @returns - */ -const exchangeRefreshBitBucket = async ({ - refreshToken, -}: { - refreshToken: string; -}) => { - const accessExpiresAt = new Date(); - const { - data, - }: { - data: RefreshTokenBitBucketResponse; - } = await standardRequest.post( - INTEGRATION_BITBUCKET_TOKEN_URL, - new URLSearchParams({ - grant_type: "refresh_token", - refresh_token: refreshToken, - client_id: await getClientIdBitBucket(), - client_secret: await getClientSecretBitBucket(), - redirect_uri: `${await getSiteURL()}/integrations/bitbucket/oauth2/callback`, - } as any), - { - headers: { - "Accept-Encoding": "application/json", - }, - } - ); - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); - - return { - accessToken: data.access_token, - refreshToken: data.refresh_token, - accessExpiresAt, - }; -}; - -/** - * Return new access token by exchanging refresh token [refreshToken] for the - * GCP Secret Manager integration - * @param {Object} obj - * @param {String} obj.refreshToken - refresh token to use to get new access token for GCP Secret Manager - * @returns - */ -const exchangeRefreshGCPSecretManager = async ({ - integrationAuth, - refreshToken, -}: { - integrationAuth: IIntegrationAuth; - refreshToken: string; -}) => { - const accessExpiresAt = new Date(); - - if (integrationAuth.metadata?.authMethod === "serviceAccount") { - const serviceAccount = JSON.parse(refreshToken); - - const payload = { - iss: serviceAccount.client_email, - aud: serviceAccount.token_uri, - scope: INTEGRATION_GCP_CLOUD_PLATFORM_SCOPE, - iat: Math.floor(Date.now() / 1000), - exp: Math.floor(Date.now() / 1000) + 3600, - }; - - const token = jwt.sign(payload, serviceAccount.private_key, { algorithm: "RS256" }); - - const { data }: { data: ServiceAccountAccessTokenGCPSecretManagerResponse } = await standardRequest.post( - INTEGRATION_GCP_TOKEN_URL, - new URLSearchParams({ - grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer", - assertion: token - }).toString(), - { - headers: { - "Content-Type": "application/x-www-form-urlencoded" - } - } - ); - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); - - return { - accessToken: data.access_token, - refreshToken, - accessExpiresAt - }; - } - - const { data }: { data: RefreshTokenGCPSecretManagerResponse } = ( - await standardRequest.post( - INTEGRATION_GCP_TOKEN_URL, - new URLSearchParams({ - client_id: await getClientIdGCPSecretManager(), - client_secret: await getClientSecretGCPSecretManager(), - refresh_token: refreshToken, - grant_type: "refresh_token", - } as any) - ) - ); - - accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); - - return { - accessToken: data.access_token, - refreshToken, - accessExpiresAt, - }; -}; - -export { exchangeRefresh }; \ No newline at end of file diff --git a/backend-mongo/src/integrations/revoke.ts b/backend-mongo/src/integrations/revoke.ts deleted file mode 100644 index 4d4f790c6..000000000 --- a/backend-mongo/src/integrations/revoke.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { - IIntegrationAuth, - Integration, - IntegrationAuth, -} from "../models"; -import { - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_HEROKU, - INTEGRATION_NETLIFY, - INTEGRATION_VERCEL, -} from "../variables"; - -const revokeAccess = async ({ - integrationAuth, - accessToken, -}: { - integrationAuth: IIntegrationAuth; - accessToken: string; -}) => { - // add any integration-specific revocation logic - switch (integrationAuth.integration) { - case INTEGRATION_HEROKU: - break; - case INTEGRATION_VERCEL: - break; - case INTEGRATION_NETLIFY: - break; - case INTEGRATION_GITHUB: - break; - case INTEGRATION_GITLAB: - break; - } - - const deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({ - _id: integrationAuth._id, - }); - - if (deletedIntegrationAuth) { - await Integration.deleteMany({ - integrationAuth: deletedIntegrationAuth._id, - }); - } - - return deletedIntegrationAuth; -}; - -export { revokeAccess }; diff --git a/backend-mongo/src/integrations/sync.ts b/backend-mongo/src/integrations/sync.ts deleted file mode 100644 index 615e3114c..000000000 --- a/backend-mongo/src/integrations/sync.ts +++ /dev/null @@ -1,3383 +0,0 @@ -import { - CreateSecretCommand, - GetSecretValueCommand, - ResourceNotFoundException, - SecretsManagerClient, - UpdateSecretCommand -} from "@aws-sdk/client-secrets-manager"; -import { IIntegration, IIntegrationAuth } from "../models"; -import { - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_BITBUCKET, - INTEGRATION_BITBUCKET_API_URL, - INTEGRATION_CHECKLY, - INTEGRATION_CHECKLY_API_URL, - INTEGRATION_CIRCLECI, - INTEGRATION_CIRCLECI_API_URL, - INTEGRATION_CLOUDFLARE_PAGES, - INTEGRATION_CLOUDFLARE_PAGES_API_URL, - INTEGRATION_CLOUDFLARE_WORKERS, - INTEGRATION_CLOUDFLARE_WORKERS_API_URL, - INTEGRATION_CLOUD_66, - INTEGRATION_CLOUD_66_API_URL, - INTEGRATION_CODEFRESH, - INTEGRATION_CODEFRESH_API_URL, - INTEGRATION_DIGITAL_OCEAN_API_URL, - INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, - INTEGRATION_FLYIO, - INTEGRATION_FLYIO_API_URL, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_GCP_SECRET_MANAGER_URL, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_GITLAB_API_URL, - INTEGRATION_HASHICORP_VAULT, - INTEGRATION_HASURA_CLOUD, - INTEGRATION_HASURA_CLOUD_API_URL, - INTEGRATION_HEROKU, - INTEGRATION_HEROKU_API_URL, - INTEGRATION_LARAVELFORGE, - INTEGRATION_LARAVELFORGE_API_URL, - INTEGRATION_NETLIFY, - INTEGRATION_NETLIFY_API_URL, - INTEGRATION_NORTHFLANK, - INTEGRATION_NORTHFLANK_API_URL, - INTEGRATION_QOVERY, - INTEGRATION_QOVERY_API_URL, - INTEGRATION_RAILWAY, - INTEGRATION_RAILWAY_API_URL, - INTEGRATION_RENDER, - INTEGRATION_RENDER_API_URL, - INTEGRATION_SUPABASE, - INTEGRATION_SUPABASE_API_URL, - INTEGRATION_TEAMCITY, - INTEGRATION_TERRAFORM_CLOUD, - INTEGRATION_TERRAFORM_CLOUD_API_URL, - INTEGRATION_TRAVISCI, - INTEGRATION_TRAVISCI_API_URL, - INTEGRATION_VERCEL, - INTEGRATION_VERCEL_API_URL, - INTEGRATION_WINDMILL, - INTEGRATION_WINDMILL_API_URL -} from "../variables"; -import AWS from "aws-sdk"; -import { Octokit } from "@octokit/rest"; -import _ from "lodash"; -import sodium from "libsodium-wrappers"; -import { standardRequest } from "../config/request"; -import { - ZGetTenantEnv, - ZUpdateTenantEnv -} from "../validation/hasuraCloudIntegration"; - -const getSecretKeyValuePair = ( - secrets: Record -) => - Object.keys(secrets).reduce>((prev, key) => { - prev[key] = secrets?.[key] === null ? null : secrets?.[key]?.value; - return prev; - }, {}); - -/** - * Sync/push [secrets] to [app] in integration named [integration] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessId - access id for integration - * @param {String} obj.accessToken - access token for integration - * @param {Object} obj.secretComments - secret comments to push to integration (object where keys are secret keys and values are comment values) - */ -const syncSecrets = async ({ - integration, - integrationAuth, - secrets, - accessId, - accessToken, - appendices -}: { - integration: IIntegration; - integrationAuth: IIntegrationAuth; - secrets: Record; - accessId: string | null; - accessToken: string; - appendices?: { prefix: string; suffix: string }; -}) => { - switch (integration.integration) { - case INTEGRATION_GCP_SECRET_MANAGER: - await syncSecretsGCPSecretManager({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_AZURE_KEY_VAULT: - await syncSecretsAzureKeyVault({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_AWS_PARAMETER_STORE: - await syncSecretsAWSParameterStore({ - integration, - secrets, - accessId, - accessToken - }); - break; - case INTEGRATION_AWS_SECRET_MANAGER: - await syncSecretsAWSSecretManager({ - integration, - secrets, - accessId, - accessToken - }); - break; - case INTEGRATION_HEROKU: - await syncSecretsHeroku({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_VERCEL: - await syncSecretsVercel({ - integration, - integrationAuth, - secrets, - accessToken - }); - break; - case INTEGRATION_NETLIFY: - await syncSecretsNetlify({ - integration, - integrationAuth, - secrets, - accessToken - }); - break; - case INTEGRATION_GITHUB: - await syncSecretsGitHub({ - integration, - secrets, - accessToken, - appendices - }); - break; - case INTEGRATION_GITLAB: - await syncSecretsGitLab({ - integrationAuth, - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_RENDER: - await syncSecretsRender({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_RAILWAY: - await syncSecretsRailway({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_FLYIO: - await syncSecretsFlyio({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_CIRCLECI: - await syncSecretsCircleCI({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_LARAVELFORGE: - await syncSecretsLaravelForge({ - integration, - secrets, - accessId, - accessToken - }); - break; - case INTEGRATION_TRAVISCI: - await syncSecretsTravisCI({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_SUPABASE: - await syncSecretsSupabase({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_CHECKLY: - await syncSecretsCheckly({ - integration, - secrets, - accessToken, - appendices - }); - break; - case INTEGRATION_QOVERY: - await syncSecretsQovery({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_TERRAFORM_CLOUD: - await syncSecretsTerraformCloud({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_HASHICORP_VAULT: - await syncSecretsHashiCorpVault({ - integration, - integrationAuth, - secrets, - accessId, - accessToken - }); - break; - case INTEGRATION_CLOUDFLARE_PAGES: - await syncSecretsCloudflarePages({ - integration, - secrets, - accessId, - accessToken - }); - break; - case INTEGRATION_CLOUDFLARE_WORKERS: - await syncSecretsCloudflareWorkers({ - integration, - secrets, - accessId, - accessToken - }); - break; - case INTEGRATION_CODEFRESH: - await syncSecretsCodefresh({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_TEAMCITY: - await syncSecretsTeamCity({ - integrationAuth, - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_BITBUCKET: - await syncSecretsBitBucket({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM: - await syncSecretsDigitalOceanAppPlatform({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_CLOUD_66: - await syncSecretsCloud66({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_NORTHFLANK: - await syncSecretsNorthflank({ - integration, - secrets, - accessToken - }); - break; - case INTEGRATION_WINDMILL: - await syncSecretsWindmill({ - integration, - secrets, - accessToken - }); - break; - - case INTEGRATION_HASURA_CLOUD: - await syncSecretsHasuraCloud({ - integration, - secrets, - accessToken - }); - break; - } -}; - -/** - * Sync/push [secrets] to GCP secret manager project - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for GCP secret manager - */ -const syncSecretsGCPSecretManager = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - interface GCPSecret { - name: string; - createTime: string; - } - - interface GCPSMListSecretsRes { - secrets?: GCPSecret[]; - totalSize?: number; - nextPageToken?: string; - } - - let gcpSecrets: GCPSecret[] = []; - - const pageSize = 100; - let pageToken: string | undefined; - let hasMorePages = true; - - const filterParam = integration.metadata.secretGCPLabel - ? `?filter=labels.${integration.metadata.secretGCPLabel.labelName}=${integration.metadata.secretGCPLabel.labelValue}` - : ""; - - while (hasMorePages) { - const params = new URLSearchParams({ - pageSize: String(pageSize), - ...(pageToken ? { pageToken } : {}) - }); - - const res: GCPSMListSecretsRes = ( - await standardRequest.get( - `${INTEGRATION_GCP_SECRET_MANAGER_URL}/v1/projects/${integration.appId}/secrets${filterParam}`, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ) - ).data; - - if (res.secrets) { - const filteredSecrets = res.secrets?.filter((gcpSecret) => { - const arr = gcpSecret.name.split("/"); - const key = arr[arr.length - 1]; - - let isValid = true; - - if ( - integration.metadata.secretPrefix && - !key.startsWith(integration.metadata.secretPrefix) - ) { - isValid = false; - } - - if (integration.metadata.secretSuffix && !key.endsWith(integration.metadata.secretSuffix)) { - isValid = false; - } - - return isValid; - }); - - gcpSecrets = gcpSecrets.concat(filteredSecrets); - } - - if (!res.nextPageToken) { - hasMorePages = false; - } - - pageToken = res.nextPageToken; - } - - const res: { [key: string]: string } = {}; - - interface GCPLatestSecretVersionAccess { - name: string; - payload: { - data: string; - }; - } - - for await (const gcpSecret of gcpSecrets) { - const arr = gcpSecret.name.split("/"); - const key = arr[arr.length - 1]; - - const secretLatest: GCPLatestSecretVersionAccess = ( - await standardRequest.get( - `${INTEGRATION_GCP_SECRET_MANAGER_URL}/v1/projects/${integration.appId}/secrets/${key}/versions/latest:access`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ) - ).data; - - res[key] = Buffer.from(secretLatest.payload.data, "base64").toString("utf-8"); - } - - for await (const key of Object.keys(secrets)) { - if (!(key in res)) { - // case: create secret - await standardRequest.post( - `${INTEGRATION_GCP_SECRET_MANAGER_URL}/v1/projects/${integration.appId}/secrets`, - { - replication: { - automatic: {} - }, - ...(integration.metadata.secretGCPLabel - ? { - labels: { - [integration.metadata.secretGCPLabel.labelName]: - integration.metadata.secretGCPLabel.labelValue - } - } - : {}) - }, - { - params: { - secretId: key - }, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - await standardRequest.post( - `${INTEGRATION_GCP_SECRET_MANAGER_URL}/v1/projects/${integration.appId}/secrets/${key}:addVersion`, - { - payload: { - data: Buffer.from(secrets[key].value).toString("base64") - } - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } - } - - for await (const key of Object.keys(res)) { - if (!(key in secrets)) { - // case: delete secret - await standardRequest.delete( - `${INTEGRATION_GCP_SECRET_MANAGER_URL}/v1/projects/${integration.appId}/secrets/${key}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } else { - // case: update secret - if (secrets[key].value !== res[key]) { - await standardRequest.post( - `${INTEGRATION_GCP_SECRET_MANAGER_URL}/v1/projects/${integration.appId}/secrets/${key}:addVersion`, - { - payload: { - data: Buffer.from(secrets[key].value).toString("base64") - } - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } - } - } -}; - -/** - * Sync/push [secrets] to Azure Key Vault with vault URI [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Azure Key Vault integration - */ -const syncSecretsAzureKeyVault = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - interface GetAzureKeyVaultSecret { - id: string; // secret URI - attributes: { - enabled: true; - created: number; - updated: number; - recoveryLevel: string; - recoverableDays: number; - }; - } - - interface AzureKeyVaultSecret extends GetAzureKeyVaultSecret { - key: string; - } - - /** - * Return all secrets from Azure Key Vault by paginating through URL [url] - * @param {String} url - pagination URL to get next set of secrets from Azure Key Vault - * @returns - */ - const paginateAzureKeyVaultSecrets = async (url: string) => { - let result: GetAzureKeyVaultSecret[] = []; - while (url) { - const res = await standardRequest.get(url, { - headers: { - Authorization: `Bearer ${accessToken}` - } - }); - - result = result.concat(res.data.value); - - url = res.data.nextLink; - } - - return result; - }; - - const getAzureKeyVaultSecrets = await paginateAzureKeyVaultSecrets( - `${integration.app}/secrets?api-version=7.3` - ); - - let lastSlashIndex: number; - const res = ( - await Promise.all( - getAzureKeyVaultSecrets.map(async (getAzureKeyVaultSecret) => { - if (!lastSlashIndex) { - lastSlashIndex = getAzureKeyVaultSecret.id.lastIndexOf("/"); - } - - const azureKeyVaultSecret = await standardRequest.get( - `${getAzureKeyVaultSecret.id}?api-version=7.3`, - { - headers: { - Authorization: `Bearer ${accessToken}` - } - } - ); - - return { - ...azureKeyVaultSecret.data, - key: getAzureKeyVaultSecret.id.substring(lastSlashIndex + 1) - }; - }) - ) - ).reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.key]: secret - }), - {} - ); - - const setSecrets: { - key: string; - value: string; - }[] = []; - - Object.keys(secrets).forEach((key) => { - const hyphenatedKey = key.replace(/_/g, "-"); - if (!(hyphenatedKey in res)) { - // case: secret has been created - setSecrets.push({ - key: hyphenatedKey, - value: secrets[key].value - }); - } else { - if (secrets[key] !== res[hyphenatedKey].value) { - // case: secret has been updated - setSecrets.push({ - key: hyphenatedKey, - value: secrets[key].value - }); - } - } - }); - - const deleteSecrets: AzureKeyVaultSecret[] = []; - - Object.keys(res).forEach((key) => { - const underscoredKey = key.replace(/-/g, "_"); - if (!(underscoredKey in secrets)) { - deleteSecrets.push(res[key]); - } - }); - - const setSecretAzureKeyVault = async ({ - key, - value, - integration, - accessToken - }: { - key: string; - value: string; - integration: IIntegration; - accessToken: string; - }) => { - let isSecretSet = false; - let maxTries = 6; - - while (!isSecretSet && maxTries > 0) { - // try to set secret - try { - await standardRequest.put( - `${integration.app}/secrets/${key}?api-version=7.3`, - { - value - }, - { - headers: { - Authorization: `Bearer ${accessToken}` - } - } - ); - - isSecretSet = true; - } catch (err) { - const error: any = err; - if (error?.response?.data?.error?.innererror?.code === "ObjectIsDeletedButRecoverable") { - await standardRequest.post( - `${integration.app}/deletedsecrets/${key}/recover?api-version=7.3`, - {}, - { - headers: { - Authorization: `Bearer ${accessToken}` - } - } - ); - await new Promise((resolve) => setTimeout(resolve, 10000)); - } else { - await new Promise((resolve) => setTimeout(resolve, 10000)); - maxTries--; - } - } - } - }; - - // Sync/push set secrets - for await (const setSecret of setSecrets) { - const { key, value } = setSecret; - setSecretAzureKeyVault({ - key, - value, - integration, - accessToken - }); - } - - for await (const deleteSecret of deleteSecrets) { - const { key } = deleteSecret; - await standardRequest.delete(`${integration.app}/secrets/${key}?api-version=7.3`, { - headers: { - Authorization: `Bearer ${accessToken}` - } - }); - } -}; - -/** - * Sync/push [secrets] to AWS parameter store - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessId - access id for AWS parameter store integration - * @param {String} obj.accessToken - access token for AWS parameter store integration - */ -const syncSecretsAWSParameterStore = async ({ - integration, - secrets, - accessId, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessId: string | null; - accessToken: string; -}) => { - if (!accessId) return; - - AWS.config.update({ - region: integration.region, - accessKeyId: accessId, - secretAccessKey: accessToken - }); - - const ssm = new AWS.SSM({ - apiVersion: "2014-11-06", - region: integration.region - }); - - const params = { - Path: integration.path, - Recursive: true, - WithDecryption: true - }; - - const parameterList = (await ssm.getParametersByPath(params).promise()).Parameters; - - let awsParameterStoreSecretsObj: { - [key: string]: any; - } = {}; - - if (parameterList) { - awsParameterStoreSecretsObj = parameterList.reduce((obj: any, secret: any) => { - return { - ...obj, - [secret.Name.substring(integration.path.length)]: secret - }; - }, {}); - } - - // Identify secrets to create - Object.keys(secrets).map(async (key) => { - if (!(key in awsParameterStoreSecretsObj)) { - // case: secret does not exist in AWS parameter store - // -> create secret - await ssm - .putParameter({ - Name: `${integration.path}${key}`, - Type: "SecureString", - Value: secrets[key].value, - Overwrite: true - }) - .promise(); - } else { - // case: secret exists in AWS parameter store - - if (awsParameterStoreSecretsObj[key].Value !== secrets[key].value) { - // case: secret value doesn't match one in AWS parameter store - // -> update secret - await ssm - .putParameter({ - Name: `${integration.path}${key}`, - Type: "SecureString", - Value: secrets[key].value, - Overwrite: true - }) - .promise(); - } - } - }); - - // Identify secrets to delete - Object.keys(awsParameterStoreSecretsObj).map(async (key) => { - if (!(key in secrets)) { - // case: - // -> delete secret - await ssm - .deleteParameter({ - Name: awsParameterStoreSecretsObj[key].Name - }) - .promise(); - } - }); - - AWS.config.update({ - region: undefined, - accessKeyId: undefined, - secretAccessKey: undefined - }); -}; - -/** - * Sync/push [secrets] to AWS Secrets Manager - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessId - access id for AWS Secrets Manager integration - * @param {String} obj.accessToken - access token for AWS Secrets Manager integration - */ -const syncSecretsAWSSecretManager = async ({ - integration, - secrets, - accessId, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessId: string | null; - accessToken: string; -}) => { - let secretsManager; - const secKeyVal = getSecretKeyValuePair(secrets); - try { - if (!accessId) return; - - AWS.config.update({ - region: integration.region, - accessKeyId: accessId, - secretAccessKey: accessToken - }); - - secretsManager = new SecretsManagerClient({ - region: integration.region, - credentials: { - accessKeyId: accessId, - secretAccessKey: accessToken - } - }); - - const awsSecretManagerSecret = await secretsManager.send( - new GetSecretValueCommand({ - SecretId: integration.app - }) - ); - - let awsSecretManagerSecretObj: { [key: string]: any } = {}; - - if (awsSecretManagerSecret?.SecretString) { - awsSecretManagerSecretObj = JSON.parse(awsSecretManagerSecret.SecretString); - } - - if (!_.isEqual(awsSecretManagerSecretObj, secKeyVal)) { - await secretsManager.send( - new UpdateSecretCommand({ - SecretId: integration.app, - SecretString: JSON.stringify(secKeyVal) - }) - ); - } - - AWS.config.update({ - region: undefined, - accessKeyId: undefined, - secretAccessKey: undefined - }); - } catch (err) { - if (err instanceof ResourceNotFoundException && secretsManager) { - await secretsManager.send( - new CreateSecretCommand({ - Name: integration.app, - SecretString: JSON.stringify(secKeyVal) - }) - ); - } - AWS.config.update({ - region: undefined, - accessKeyId: undefined, - secretAccessKey: undefined - }); - } -}; - -/** - * Sync/push [secrets] to Heroku app named [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Heroku integration - */ -const syncSecretsHeroku = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - const herokuSecrets = ( - await standardRequest.get(`${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`, { - headers: { - Accept: "application/vnd.heroku+json; version=3", - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }) - ).data; - - Object.keys(herokuSecrets).forEach((key) => { - if (!(key in secrets)) { - secrets[key] = null; - } - }); - - await standardRequest.patch( - `${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`, - getSecretKeyValuePair(secrets), - { - headers: { - Accept: "application/vnd.heroku+json; version=3", - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); -}; - -/** - * Sync/push [secrets] to Vercel project named [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - */ -const syncSecretsVercel = async ({ - integration, - integrationAuth, - secrets, - accessToken -}: { - integration: IIntegration; - integrationAuth: IIntegrationAuth; - secrets: Record; - accessToken: string; -}) => { - interface VercelSecret { - id?: string; - type: string; - key: string; - value: string; - target: string[]; - gitBranch?: string; - } - // Get all (decrypted) secrets back from Vercel in - // decrypted format - const params: { [key: string]: string } = { - decrypt: "true", - ...(integrationAuth?.teamId - ? { - teamId: integrationAuth.teamId - } - : {}), - ...(integration?.path - ? { - gitBranch: integration?.path - } - : {}) - }; - - const vercelSecrets: VercelSecret[] = ( - await standardRequest.get(`${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`, { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - }) - ).data.envs.filter((secret: VercelSecret) => { - if (!secret.target.includes(integration.targetEnvironment)) { - // case: secret does not have the same target environment - return false; - } - - if ( - integration.targetEnvironment === "preview" && - secret.gitBranch && - integration.path !== secret.gitBranch - ) { - // case: secret on preview environment does not have same target git branch - return false; - } - - return true; - }); - - const res: { [key: string]: VercelSecret } = {}; - - for await (const vercelSecret of vercelSecrets) { - if (vercelSecret.type === "encrypted") { - // case: secret is encrypted -> need to decrypt - const decryptedSecret = ( - await standardRequest.get( - `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${vercelSecret.id}`, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ) - ).data; - - res[vercelSecret.key] = decryptedSecret; - } else { - res[vercelSecret.key] = vercelSecret; - } - } - - const updateSecrets: VercelSecret[] = []; - const deleteSecrets: VercelSecret[] = []; - const newSecrets: VercelSecret[] = []; - - // Identify secrets to create - Object.keys(secrets).map((key) => { - if (!(key in res)) { - // case: secret has been created - newSecrets.push({ - key: key, - value: secrets[key].value, - type: "encrypted", - target: [integration.targetEnvironment], - ...(integration.path - ? { - gitBranch: integration.path - } - : {}) - }); - } - }); - - // Identify secrets to update and delete - Object.keys(res).map((key) => { - if (key in secrets) { - if (res[key].value !== secrets[key].value) { - // case: secret value has changed - updateSecrets.push({ - id: res[key].id, - key: key, - value: secrets[key].value, - type: res[key].type, - target: res[key].target.includes(integration.targetEnvironment) - ? [...res[key].target] - : [...res[key].target, integration.targetEnvironment], - ...(integration.path - ? { - gitBranch: integration.path - } - : {}) - }); - } - } else { - // case: secret has been deleted - deleteSecrets.push({ - id: res[key].id, - key: key, - value: res[key].value, - type: "encrypted", // value doesn't matter - target: [integration.targetEnvironment], - ...(integration.path - ? { - gitBranch: integration.path - } - : {}) - }); - } - }); - - // Sync/push new secrets - if (newSecrets.length > 0) { - await standardRequest.post( - `${INTEGRATION_VERCEL_API_URL}/v10/projects/${integration.app}/env`, - newSecrets, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } - - for await (const secret of updateSecrets) { - if (secret.type !== "sensitive") { - const { id, ...updatedSecret } = secret; - await standardRequest.patch( - `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${id}`, - updatedSecret, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } - } - - for await (const secret of deleteSecrets) { - await standardRequest.delete( - `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } -}; - -/** - * Sync/push [secrets] to Netlify site with id [integration.appId] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {Object} obj.accessToken - access token for Netlify integration - */ -const syncSecretsNetlify = async ({ - integration, - integrationAuth, - secrets, - accessToken -}: { - integration: IIntegration; - integrationAuth: IIntegrationAuth; - secrets: Record; - accessToken: string; -}) => { - interface NetlifyValue { - id?: string; - context: string; // 'dev' | 'branch-deploy' | 'deploy-preview' | 'production', - value: string; - } - - interface NetlifySecret { - key: string; - values: NetlifyValue[]; - } - - const getParams = new URLSearchParams({ - context_name: "all", // integration.context or all - site_id: integration.appId - }); - - const res = ( - await standardRequest.get( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`, - { - params: getParams, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ) - ).data.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.key]: secret - }), - {} - ); - - const newSecrets: NetlifySecret[] = []; // createEnvVars - const deleteSecrets: string[] = []; // deleteEnvVar - const deleteSecretValues: NetlifySecret[] = []; // deleteEnvVarValue - const updateSecrets: NetlifySecret[] = []; // setEnvVarValue - - // identify secrets to create and update - Object.keys(secrets).map((key) => { - if (!(key in res)) { - // case: Infisical secret does not exist in Netlify -> create secret - newSecrets.push({ - key, - values: [ - { - value: secrets[key].value, - context: integration.targetEnvironment - } - ] - }); - } else { - // case: Infisical secret exists in Netlify - const contexts = res[key].values.reduce( - (obj: any, value: NetlifyValue) => ({ - ...obj, - [value.context]: value - }), - {} - ); - - if (integration.targetEnvironment in contexts) { - // case: Netlify secret value exists in integration context - if (secrets[key] !== contexts[integration.targetEnvironment].value) { - // case: Infisical and Netlify secret values are different - // -> update Netlify secret context and value - updateSecrets.push({ - key, - values: [ - { - context: integration.targetEnvironment, - value: secrets[key].value - } - ] - }); - } - } else { - // case: Netlify secret value does not exist in integration context - // -> add the new Netlify secret context and value - updateSecrets.push({ - key, - values: [ - { - context: integration.targetEnvironment, - value: secrets[key].value - } - ] - }); - } - } - }); - - // identify secrets to delete - // TODO: revise (patch case where 1 context was deleted but others still there - Object.keys(res).map((key) => { - // loop through each key's context - if (!(key in secrets)) { - // case: Netlify secret does not exist in Infisical - - const numberOfValues = res[key].values.length; - - res[key].values.forEach((value: NetlifyValue) => { - if (value.context === integration.targetEnvironment) { - if (numberOfValues <= 1) { - // case: Netlify secret value has less than 1 context -> delete secret - deleteSecrets.push(key); - } else { - // case: Netlify secret value has more than 1 context -> delete secret value context - deleteSecretValues.push({ - key, - values: [ - { - id: value.id, - context: integration.targetEnvironment, - value: value.value - } - ] - }); - } - } - }); - } - }); - - const syncParams = new URLSearchParams({ - site_id: integration.appId - }); - - if (newSecrets.length > 0) { - await standardRequest.post( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`, - newSecrets, - { - params: syncParams, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } - - if (updateSecrets.length > 0) { - updateSecrets.forEach(async (secret: NetlifySecret) => { - await standardRequest.patch( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`, - { - context: secret.values[0].context, - value: secret.values[0].value - }, - { - params: syncParams, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - }); - } - - if (deleteSecrets.length > 0) { - deleteSecrets.forEach(async (key: string) => { - await standardRequest.delete( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${key}`, - { - params: syncParams, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - }); - } - - if (deleteSecretValues.length > 0) { - deleteSecretValues.forEach(async (secret: NetlifySecret) => { - await standardRequest.delete( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}/value/${secret.values[0].id}`, - { - params: syncParams, - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - }); - } -}; - -/** - * Sync/push [secrets] to GitHub repo with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for GitHub integration - */ -const syncSecretsGitHub = async ({ - integration, - secrets, - accessToken, - appendices -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; - appendices?: { prefix: string; suffix: string }; -}) => { - interface GitHubRepoKey { - key_id: string; - key: string; - } - - interface GitHubSecret { - name: string; - created_at: string; - updated_at: string; - } - - interface GitHubSecretRes { - [index: string]: GitHubSecret; - } - - const octokit = new Octokit({ - auth: accessToken - }); - - // const user = (await octokit.request('GET /user', {})).data; - const repoPublicKey: GitHubRepoKey = ( - await octokit.request("GET /repos/{owner}/{repo}/actions/secrets/public-key", { - owner: integration.owner, - repo: integration.app - }) - ).data; - - // Get local copy of decrypted secrets. We cannot decrypt them as we dont have access to GH private key - let encryptedSecrets: GitHubSecretRes = ( - await octokit.request("GET /repos/{owner}/{repo}/actions/secrets", { - owner: integration.owner, - repo: integration.app - }) - ).data.secrets.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.name]: secret - }), - {} - ); - - encryptedSecrets = Object.keys(encryptedSecrets).reduce( - ( - result: { - [key: string]: GitHubSecret; - }, - key - ) => { - if ( - (appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) && - (appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true) - ) { - result[key] = encryptedSecrets[key]; - } - return result; - }, - {} - ); - - Object.keys(encryptedSecrets).map(async (key) => { - if (!(key in secrets)) { - await octokit.request("DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}", { - owner: integration.owner, - repo: integration.app, - secret_name: key - }); - } - }); - - Object.keys(secrets).map((key) => { - // let encryptedSecret; - sodium.ready.then(async () => { - // convert secret & base64 key to Uint8Array. - const binkey = sodium.from_base64(repoPublicKey.key, sodium.base64_variants.ORIGINAL); - const binsec = sodium.from_string(secrets[key].value); - - // encrypt secret using libsodium - const encBytes = sodium.crypto_box_seal(binsec, binkey); - - // convert encrypted Uint8Array to base64 - const encryptedSecret = sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL); - - await octokit.request("PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}", { - owner: integration.owner, - repo: integration.app, - secret_name: key, - encrypted_value: encryptedSecret, - key_id: repoPublicKey.key_id - }); - }); - }); -}; - -/** - * Sync/push [secrets] to Render service with id [integration.appId] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Render integration - */ -const syncSecretsRender = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - await standardRequest.put( - `${INTEGRATION_RENDER_API_URL}/v1/services/${integration.appId}/env-vars`, - Object.keys(secrets).map((key) => ({ - key, - value: secrets[key].value - })), - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); -}; - -/** - * Sync/push [secrets] to Laravel Forge sites with id [integration.appId] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Laravel Forge integration - */ -const syncSecretsLaravelForge = async ({ - integration, - secrets, - accessId, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessId: string | null; - accessToken: string; -}) => { - function transformObjectToString(obj: any) { - let result = ""; - for (const key in obj) { - result += `${key}=${obj[key].value}\n`; - } - return result; - } - - await standardRequest.put( - `${INTEGRATION_LARAVELFORGE_API_URL}/api/v1/servers/${accessId}/sites/${integration.appId}/env`, - { - content: transformObjectToString(secrets) - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "Content-Type": "application/json" - } - } - ); -}; - -/** - * Sync/push [secrets] to Railway project with id [integration.appId] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Railway integration - */ -const syncSecretsRailway = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - const query = ` - mutation UpsertVariables($input: VariableCollectionUpsertInput!) { - variableCollectionUpsert(input: $input) - } - `; - - const input = { - projectId: integration.appId, - environmentId: integration.targetEnvironmentId, - ...(integration.targetServiceId ? { serviceId: integration.targetServiceId } : {}), - replace: true, - variables: getSecretKeyValuePair(secrets) - }; - - await standardRequest.post( - INTEGRATION_RAILWAY_API_URL, - { - query, - variables: { - input - } - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); -}; - -/** - * Sync/push [secrets] to Fly.io app - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Render integration - */ -const syncSecretsFlyio = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - // set secrets - const SetSecrets = ` - mutation($input: SetSecretsInput!) { - setSecrets(input: $input) { - release { - id - version - reason - description - user { - id - email - name - } - evaluationId - createdAt - } - } - } - `; - - await standardRequest.post( - INTEGRATION_FLYIO_API_URL, - { - query: SetSecrets, - variables: { - input: { - appId: integration.app, - secrets: Object.entries(secrets).map(([key, data]) => ({ - key, - value: data.value - })) - } - } - }, - { - headers: { - Authorization: "Bearer " + accessToken, - "Accept-Encoding": "application/json" - } - } - ); - - // get secrets - interface FlyioSecret { - name: string; - digest: string; - createdAt: string; - } - - const GetSecrets = `query ($appName: String!) { - app(name: $appName) { - secrets { - name - digest - createdAt - } - } - }`; - - const getSecretsRes = ( - await standardRequest.post( - INTEGRATION_FLYIO_API_URL, - { - query: GetSecrets, - variables: { - appName: integration.app - } - }, - { - headers: { - Authorization: "Bearer " + accessToken, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ) - ).data.data.app.secrets; - - const deleteSecretsKeys = getSecretsRes - .filter((secret: FlyioSecret) => !(secret.name in secrets)) - .map((secret: FlyioSecret) => secret.name); - - // unset (delete) secrets - const DeleteSecrets = `mutation($input: UnsetSecretsInput!) { - unsetSecrets(input: $input) { - release { - id - version - reason - description - user { - id - email - name - } - evaluationId - createdAt - } - } - }`; - - await standardRequest.post( - INTEGRATION_FLYIO_API_URL, - { - query: DeleteSecrets, - variables: { - input: { - appId: integration.app, - keys: deleteSecretsKeys - } - } - }, - { - headers: { - Authorization: "Bearer " + accessToken, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); -}; - -/** - * Sync/push [secrets] to CircleCI project - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for CircleCI integration - */ -const syncSecretsCircleCI = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - const circleciOrganizationDetail = ( - await standardRequest.get(`${INTEGRATION_CIRCLECI_API_URL}/v2/me/collaborations`, { - headers: { - "Circle-Token": accessToken, - "Accept-Encoding": "application/json" - } - }) - ).data[0]; - - const { slug } = circleciOrganizationDetail; - - // sync secrets to CircleCI - Object.keys(secrets).forEach( - async (key) => - await standardRequest.post( - `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar`, - { - name: key, - value: secrets[key].value - }, - { - headers: { - "Circle-Token": accessToken, - "Content-Type": "application/json" - } - } - ) - ); - - // get secrets from CircleCI - const getSecretsRes = ( - await standardRequest.get( - `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar`, - { - headers: { - "Circle-Token": accessToken, - "Accept-Encoding": "application/json" - } - } - ) - ).data?.items; - - // delete secrets from CircleCI - getSecretsRes.forEach(async (sec: any) => { - if (!(sec.name in secrets)) { - await standardRequest.delete( - `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar/${sec.name}`, - { - headers: { - "Circle-Token": accessToken, - "Content-Type": "application/json" - } - } - ); - } - }); -}; - -/** - * Sync/push [secrets] to TravisCI project - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for TravisCI integration - */ -const syncSecretsTravisCI = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - // get secrets from travis-ci - const getSecretsRes = ( - await standardRequest.get( - `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars?repository_id=${integration.appId}`, - { - headers: { - Authorization: `token ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ) - ).data?.env_vars.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.name]: secret - }), - {} - ); - - // add secrets - for await (const key of Object.keys(secrets)) { - if (!(key in getSecretsRes)) { - // case: secret does not exist in travis ci - // -> add secret - await standardRequest.post( - `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars?repository_id=${integration.appId}`, - { - env_var: { - name: key, - value: secrets[key].value - } - }, - { - headers: { - Authorization: `token ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); - } else { - // case: secret exists in travis ci - // -> update/set secret - await standardRequest.patch( - `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars/${getSecretsRes[key].id}?repository_id=${getSecretsRes[key].repository_id}`, - { - env_var: { - name: key, - value: secrets[key].value - } - }, - { - headers: { - Authorization: `token ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); - } - } - - for await (const key of Object.keys(getSecretsRes)) { - if (!(key in secrets)) { - // delete secret - await standardRequest.delete( - `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars/${getSecretsRes[key].id}?repository_id=${getSecretsRes[key].repository_id}`, - { - headers: { - Authorization: `token ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); - } - } -}; - -/** - * Sync/push [secrets] to GitLab repo with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for GitLab integration - */ -const syncSecretsGitLab = async ({ - integrationAuth, - integration, - secrets, - accessToken -}: { - integrationAuth: IIntegrationAuth; - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - interface GitLabSecret { - key: string; - value: string; - environment_scope: string; - } - - const gitLabApiUrl = integrationAuth.url - ? `${integrationAuth.url}/api` - : INTEGRATION_GITLAB_API_URL; - - const getAllEnvVariables = async (integrationAppId: string, accessToken: string) => { - const headers = { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json", - "Content-Type": "application/json" - }; - - let allEnvVariables: GitLabSecret[] = []; - let url: - | string - | null = `${gitLabApiUrl}/v4/projects/${integrationAppId}/variables?per_page=100`; - - while (url) { - const response: any = await standardRequest.get(url, { headers }); - allEnvVariables = [...allEnvVariables, ...response.data]; - - const linkHeader = response.headers.link; - const nextLink = linkHeader?.split(",").find((part: string) => part.includes('rel="next"')); - - if (nextLink) { - url = nextLink.trim().split(";")[0].slice(1, -1); - } else { - url = null; - } - } - - return allEnvVariables; - }; - - const allEnvVariables = await getAllEnvVariables(integration?.appId, accessToken); - const getSecretsRes: GitLabSecret[] = allEnvVariables - .filter((secret: GitLabSecret) => secret.environment_scope === integration.targetEnvironment) - .filter((gitLabSecret) => { - let isValid = true; - - if ( - integration.metadata.secretPrefix && - !gitLabSecret.key.startsWith(integration.metadata.secretPrefix) - ) { - isValid = false; - } - - if ( - integration.metadata.secretSuffix && - !gitLabSecret.key.endsWith(integration.metadata.secretSuffix) - ) { - isValid = false; - } - - return isValid; - }); - - for await (const key of Object.keys(secrets)) { - const existingSecret = getSecretsRes.find((s: any) => s.key == key); - if (!existingSecret) { - await standardRequest.post( - `${gitLabApiUrl}/v4/projects/${integration?.appId}/variables`, - { - key: key, - value: secrets[key].value, - protected: false, - masked: false, - raw: false, - environment_scope: integration.targetEnvironment - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); - } else { - // update secret - if (secrets[key].value !== existingSecret.value) { - await standardRequest.put( - `${gitLabApiUrl}/v4/projects/${integration?.appId}/variables/${existingSecret.key}?filter[environment_scope]=${integration.targetEnvironment}`, - { - ...existingSecret, - value: secrets[existingSecret.key].value - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); - } - } - } - - // delete secrets - for await (const sec of getSecretsRes) { - if (!(sec.key in secrets)) { - await standardRequest.delete( - `${gitLabApiUrl}/v4/projects/${integration?.appId}/variables/${sec.key}?filter[environment_scope]=${integration.targetEnvironment}`, - { - headers: { - Authorization: `Bearer ${accessToken}` - } - } - ); - } - } -}; - -/** - * Sync/push [secrets] to Supabase with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Supabase integration - */ -const syncSecretsSupabase = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - const { data: getSecretsRes } = await standardRequest.get( - `${INTEGRATION_SUPABASE_API_URL}/v1/projects/${integration.appId}/secrets`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - // convert the secrets to [{}] format - const modifiedFormatForSecretInjection = Object.keys(secrets).map((key) => { - return { - name: key, - value: secrets[key].value - }; - }); - - await standardRequest.post( - `${INTEGRATION_SUPABASE_API_URL}/v1/projects/${integration.appId}/secrets`, - modifiedFormatForSecretInjection, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - - const secretsToDelete: any = []; - getSecretsRes?.forEach((secretObj: any) => { - if ( - !(secretObj.name in secrets) && - // supbase reserved secret ref: https://supabase.com/docs/guides/functions/secrets#default-secrets - ![ - "SUPABASE_ANON_KEY", - "SUPABASE_SERVICE_ROLE_KEY", - "SUPABASE_DB_URL", - "SUPABASE_URL" - ].includes(secretObj.name) - ) { - secretsToDelete.push(secretObj.name); - } - }); - - await standardRequest.delete( - `${INTEGRATION_SUPABASE_API_URL}/v1/projects/${integration.appId}/secrets`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - }, - data: secretsToDelete - } - ); -}; - -/** - * Sync/push [secrets] to Checkly app/group - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Checkly integration - */ -const syncSecretsCheckly = async ({ - integration, - secrets, - accessToken, - appendices -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; - appendices?: { prefix: string; suffix: string }; -}) => { - - if (integration.targetServiceId) { - // sync secrets to checkly group envars - - let getGroupSecretsRes = ( - await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/check-groups/${integration.targetServiceId}`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "X-Checkly-Account": integration.appId - } - }) - ).data.environmentVariables.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.key]: secret.value - }), - {} - ); - - getGroupSecretsRes = Object.keys(getGroupSecretsRes).reduce( - ( - result: { - [key: string]: string; - }, - key - ) => { - if ( - (appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) && - (appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true) - ) { - result[key] = getGroupSecretsRes[key]; - } - return result; - }, - {} - ); - - const groupEnvironmentVariables = Object.keys(secrets).map(key => ({ - key, - value: secrets[key].value - })); - - await standardRequest.put( - `${INTEGRATION_CHECKLY_API_URL}/v1/check-groups/${integration.targetServiceId}`, - { - environmentVariables: groupEnvironmentVariables - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "X-Checkly-Account": integration.appId - } - } - ); - } else { - // sync secrets to checkly global envars - - let getSecretsRes = ( - await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/variables`, { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json", - "X-Checkly-Account": integration.appId - } - }) - ).data.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.key]: secret.value - }), - {} - ); - - getSecretsRes = Object.keys(getSecretsRes).reduce( - ( - result: { - [key: string]: string; - }, - key - ) => { - if ( - (appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) && - (appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true) - ) { - result[key] = getSecretsRes[key]; - } - return result; - }, - {} - ); - - // add secrets - for await (const key of Object.keys(secrets)) { - if (!(key in getSecretsRes)) { - // case: secret does not exist in checkly - // -> add secret - await standardRequest.post( - `${INTEGRATION_CHECKLY_API_URL}/v1/variables`, - { - key, - value: secrets[key].value - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "Content-Type": "application/json", - "X-Checkly-Account": integration.appId - } - } - ); - } else { - // case: secret exists in checkly - // -> update/set secret - - if (secrets[key] !== getSecretsRes[key]) { - await standardRequest.put( - `${INTEGRATION_CHECKLY_API_URL}/v1/variables/${key}`, - { - value: secrets[key].value - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - Accept: "application/json", - "X-Checkly-Account": integration.appId - } - } - ); - } - } - } - - for await (const key of Object.keys(getSecretsRes)) { - if (!(key in secrets)) { - // delete secret - await standardRequest.delete(`${INTEGRATION_CHECKLY_API_URL}/v1/variables/${key}`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "X-Checkly-Account": integration.appId - } - }); - } - } - } -}; - -/** - * Sync/push [secrets] to Qovery app - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Qovery integration - */ -const syncSecretsQovery = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - const getSecretsRes = ( - await standardRequest.get( - `${INTEGRATION_QOVERY_API_URL}/${integration.scope}/${integration.appId}/environmentVariable`, - { - headers: { - Authorization: `Token ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ) - ).data.results.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.key]: { id: secret.id, value: secret.value } - }), - {} - ); - - // add secrets - for await (const key of Object.keys(secrets)) { - if (!(key in getSecretsRes)) { - // case: secret does not exist in qovery - // -> add secret - await standardRequest.post( - `${INTEGRATION_QOVERY_API_URL}/${integration.scope}/${integration.appId}/environmentVariable`, - { - key, - value: secrets[key].value - }, - { - headers: { - Authorization: `Token ${accessToken}`, - Accept: "application/json", - "Content-Type": "application/json" - } - } - ); - } else { - // case: secret exists in qovery - // -> update/set secret - - if (secrets[key].value !== getSecretsRes[key].value) { - await standardRequest.put( - `${INTEGRATION_QOVERY_API_URL}/${integration.scope}/${integration.appId}/environmentVariable/${getSecretsRes[key].id}`, - { - key, - value: secrets[key].value - }, - { - headers: { - Authorization: `Token ${accessToken}`, - "Content-Type": "application/json", - Accept: "application/json" - } - } - ); - } - } - } - - // This one is dangerous because there might be a lot of qovery-specific secrets - - // for await (const key of Object.keys(getSecretsRes)) { - // if (!(key in secrets)) { - // console.log(3) - // // delete secret - // await standardRequest.delete(`${INTEGRATION_QOVERY_API_URL}/application/${integration.appId}/environmentVariable/${getSecretsRes[key].id}`, { - // headers: { - // Authorization: `Token ${accessToken}`, - // Accept: "application/json", - // "X-Qovery-Account": integration.appId - // } - // }); - // } - // } -}; - -/** - * Sync/push [secrets] to Terraform Cloud project with id [integration.appId] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Terraform Cloud API - */ -const syncSecretsTerraformCloud = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - // get secrets from Terraform Cloud - const getSecretsRes = ( - await standardRequest.get( - `${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${integration.appId}/vars`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ) - ).data.data.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.attributes.key]: secret - }), - {} - ); - - // create or update secrets on Terraform Cloud - for await (const key of Object.keys(secrets)) { - if (!(key in getSecretsRes)) { - // case: secret does not exist in Terraform Cloud - // -> add secret - await standardRequest.post( - `${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${integration.appId}/vars`, - { - data: { - type: "vars", - attributes: { - key, - value: secrets[key].value, - category: integration.targetService - } - } - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/vnd.api+json", - Accept: "application/vnd.api+json" - } - } - ); - } else { - // case: secret exists in Terraform Cloud - if (secrets[key].value !== getSecretsRes[key].attributes.value) { - // -> update secret - await standardRequest.patch( - `${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${integration.appId}/vars/${getSecretsRes[key].id}`, - { - data: { - type: "vars", - id: getSecretsRes[key].id, - attributes: { - ...getSecretsRes[key], - value: secrets[key].value - } - } - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/vnd.api+json", - Accept: "application/vnd.api+json" - } - } - ); - } - } - } - - for await (const key of Object.keys(getSecretsRes)) { - if (!(key in secrets)) { - // case: delete secret - await standardRequest.delete( - `${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${integration.appId}/vars/${getSecretsRes[key].id}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/vnd.api+json", - Accept: "application/vnd.api+json" - } - } - ); - } - } -}; - -/** - * Sync/push [secrets] to TeamCity project (and optionally build config) - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration - * @param {String} obj.accessToken - access token for TeamCity integration - */ -const syncSecretsTeamCity = async ({ - integrationAuth, - integration, - secrets, - accessToken -}: { - integrationAuth: IIntegrationAuth; - integration: IIntegration; - secrets: any; - accessToken: string; -}) => { - interface TeamCitySecret { - name: string; - value: string; - } - - interface TeamCityBuildConfigParameter { - name: string; - value: string; - inherited: boolean; - } - interface GetTeamCityBuildConfigParametersRes { - href: string; - count: number; - property: TeamCityBuildConfigParameter[]; - } - - if (integration.targetEnvironment && integration.targetEnvironmentId) { - // case: sync to specific build-config in TeamCity project - const res = ( - await standardRequest.get( - `${integrationAuth.url}/app/rest/buildTypes/${integration.targetEnvironmentId}/parameters`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ) - ).data.property - .filter((parameter) => !parameter.inherited) - .reduce((obj: any, secret: TeamCitySecret) => { - const secretName = secret.name.replace(/^env\./, ""); - return { - ...obj, - [secretName]: secret.value - }; - }, {}); - - for await (const key of Object.keys(secrets)) { - if (!(key in res) || (key in res && secrets[key].value !== res[key])) { - // case: secret does not exist in TeamCity or secret value has changed - // -> create/update secret - await standardRequest.post( - `${integrationAuth.url}/app/rest/buildTypes/${integration.targetEnvironmentId}/parameters`, - { - name: `env.${key}`, - value: secrets[key].value - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } - } - - for await (const key of Object.keys(res)) { - if (!(key in secrets)) { - // delete secret - await standardRequest.delete( - `${integrationAuth.url}/app/rest/buildTypes/${integration.targetEnvironmentId}/parameters/env.${key}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } - } - } else { - // case: sync to TeamCity project - const res = ( - await standardRequest.get( - `${integrationAuth.url}/app/rest/projects/id:${integration.appId}/parameters`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ) - ).data.property.reduce((obj: any, secret: TeamCitySecret) => { - const secretName = secret.name.replace(/^env\./, ""); - return { - ...obj, - [secretName]: secret.value - }; - }, {}); - - for await (const key of Object.keys(secrets)) { - if (!(key in res) || (key in res && secrets[key] !== res[key])) { - // case: secret does not exist in TeamCity or secret value has changed - // -> create/update secret - await standardRequest.post( - `${integrationAuth.url}/app/rest/projects/id:${integration.appId}/parameters`, - { - name: `env.${key}`, - value: secrets[key].value - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } - } - - for await (const key of Object.keys(res)) { - if (!(key in secrets)) { - // delete secret - await standardRequest.delete( - `${integrationAuth.url}/app/rest/projects/id:${integration.appId}/parameters/env.${key}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } - } - } -}; - -/** - * Sync/push [secrets] to HashiCorp Vault path - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for HashiCorp Vault integration - */ -const syncSecretsHashiCorpVault = async ({ - integration, - integrationAuth, - secrets, - accessId, - accessToken -}: { - integration: IIntegration; - integrationAuth: IIntegrationAuth; - secrets: Record; - accessId: string | null; - accessToken: string; -}) => { - if (!accessId) return; - - interface LoginAppRoleRes { - auth: { - client_token: string; - }; - } - - // get Vault client token (could be optimized) - const { data }: { data: LoginAppRoleRes } = await standardRequest.post( - `${integrationAuth.url}/v1/auth/approle/login`, - { - role_id: accessId, - secret_id: accessToken - }, - { - headers: { - "X-Vault-Namespace": integrationAuth.namespace - } - } - ); - - const clientToken = data.auth.client_token; - - await standardRequest.post( - `${integrationAuth.url}/v1/${integration.app}/data/${integration.path}`, - { - data: getSecretKeyValuePair(secrets) - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "Content-Type": "application/json", - "X-Vault-Token": clientToken, - "X-Vault-Namespace": integrationAuth.namespace - } - } - ); -}; - -/** - * Sync/push [secrets] to Cloudflare Pages project with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - API token for Cloudflare - */ -const syncSecretsCloudflarePages = async ({ - integration, - secrets, - accessId, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessId: string | null; - accessToken: string; -}) => { - // get secrets from cloudflare pages - const getSecretsRes = ( - await standardRequest.get( - `${INTEGRATION_CLOUDFLARE_PAGES_API_URL}/client/v4/accounts/${accessId}/pages/projects/${integration.app}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ) - ).data.result["deployment_configs"][integration.targetEnvironment]["env_vars"]; - - // copy the secrets object, so we can set deleted keys to null - const secretsObj: any = getSecretKeyValuePair(secrets); - - for (const [key, val] of Object.entries(secretsObj)) { - secretsObj[key] = { type: "secret_text", value: val }; - } - - if (getSecretsRes) { - for await (const key of Object.keys(getSecretsRes)) { - if (!(key in secrets)) { - // case: secret does not exist in infisical - // -> delete secret from cloudflare pages - secretsObj[key] = null; - } - } - } - - const data = { - deployment_configs: { - [integration.targetEnvironment]: { - env_vars: secretsObj - } - } - }; - - await standardRequest.patch( - `${INTEGRATION_CLOUDFLARE_PAGES_API_URL}/client/v4/accounts/${accessId}/pages/projects/${integration.app}`, - data, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); -}; - -/** - * Sync/push [secrets] to Cloudflare Workers project with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - API token for Cloudflare workers - */ -const syncSecretsCloudflareWorkers = async ({ - integration, - secrets, - accessId, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessId: string | null; - accessToken: string; -}) => { - // get secrets from cloudflare workers - const getSecretsRes = ( - await standardRequest.get( - `${INTEGRATION_CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accessId}/workers/scripts/${integration.app}/secrets`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ) - ).data.result; - - const secretsObj: any = getSecretKeyValuePair(secrets); - - for (const [key, val] of Object.entries(secretsObj)) { - secretsObj[key] = { type: "secret_text", value: val }; - } - - // get deleted secrets list - const deletedSecretKeys: string[] = []; - if (getSecretsRes) { - getSecretsRes.forEach((secretRes: any) => { - if (!(Object.keys(secrets).includes(secretRes.name))) { - deletedSecretKeys.push(secretRes.name); - } - }) - } - - deletedSecretKeys.forEach(async (secretKey) => { - await standardRequest.delete( - `${INTEGRATION_CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accessId}/workers/scripts/${integration.app}/secrets/${secretKey}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - }); - - interface ConvertedSecret { - name: string; - text: string; - type: string; - } - - interface SecretsObj { - [key: string]: { - type: string; - value: string; - }; - } - - const data: ConvertedSecret[] = Object.entries(secretsObj as SecretsObj).map(([name, secret]) => ({ - name, - text: secret.value, - type: "secret_text" - })); - - data.forEach(async (secret) => { - await standardRequest.put( - `${INTEGRATION_CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accessId}/workers/scripts/${integration.app}/secrets`, - secret, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - }) -}; - -/** - * Sync/push [secrets] to BitBucket repo with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for BitBucket integration - */ -const syncSecretsBitBucket = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - interface VariablesResponse { - size: number; - page: number; - pageLen: number; - next: string; - previous: string; - values: Array; - } - - interface BitbucketVariable { - type: string; - uuid: string; - key: string; - value: string; - secured: boolean; - } - - const res: { [key: string]: BitbucketVariable } = {}; - - let hasNextPage = true; - let variablesUrl = `${INTEGRATION_BITBUCKET_API_URL}/2.0/repositories/${integration.targetEnvironmentId}/${integration.appId}/pipelines_config/variables`; - - while (hasNextPage) { - const { data }: { data: VariablesResponse } = await standardRequest.get(variablesUrl, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - }); - - if (data?.values.length > 0) { - data.values.forEach((variable) => { - res[variable.key] = variable; - }); - } - - if (data.next) { - variablesUrl = data.next; - } else { - hasNextPage = false; - } - } - - for await (const key of Object.keys(secrets)) { - if (key in res) { - // update existing secret - await standardRequest.put( - `${variablesUrl}/${res[key].uuid}`, - { - key, - value: secrets[key].value, - secured: true - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } else { - // create new secret - await standardRequest.post( - variablesUrl, - { - key, - value: secrets[key].value, - secured: true - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } - } - - for await (const key of Object.keys(res)) { - if (!(key in secrets)) { - // delete secret - await standardRequest.delete(`${variablesUrl}/${res[key].uuid}`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - }); - } - } -}; - -/** - * Sync/push [secrets] to Codefresh project with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Codefresh integration - */ -const syncSecretsCodefresh = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - await standardRequest.patch( - `${INTEGRATION_CODEFRESH_API_URL}/projects/${integration.appId}`, - { - variables: Object.keys(secrets).map((key) => ({ - key, - value: secrets[key].value - })) - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); -}; - -/** - * Sync/push [secrets] to DigitalOcean App Platform application with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for integration - */ -const syncSecretsDigitalOceanAppPlatform = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - // get current app settings - const appSettings = ( - await standardRequest.get(`${INTEGRATION_DIGITAL_OCEAN_API_URL}/v2/apps/${integration.appId}`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - }) - ).data.app.spec; - - await standardRequest.put( - `${INTEGRATION_DIGITAL_OCEAN_API_URL}/v2/apps/${integration.appId}`, - { - spec: { - name: integration.app, - ...appSettings, - envs: Object.entries(secrets).map(([key, data]) => ({ key, value: data.value })) - } - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); -}; - -/** - * Sync/push [secrets] to Windmill with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for windmill integration - * @param {Object} obj.secretComments - secret comments to push to integration (object where keys are secret keys and values are comment values) - */ -const syncSecretsWindmill = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - interface WindmillSecret { - path: string; - value: string; - is_secret: boolean; - description?: string; - } - - // get secrets stored in windmill workspace - const res = ( - await standardRequest.get( - `${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/list`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ) - ).data.reduce( - (obj: any, secret: WindmillSecret) => ({ - ...obj, - [secret.path]: secret - }), - {} - ); - - // eslint-disable-next-line no-useless-escape - const pattern = new RegExp("^(u/|f/)[a-zA-Z0-9_-]+/([a-zA-Z0-9_-]+/)*[a-zA-Z0-9_-]*[^/]$"); - - for await (const key of Object.keys(secrets)) { - if ((key.startsWith("u/") || key.startsWith("f/")) && pattern.test(key)) { - if (!(key in res)) { - // case: secret does not exist in windmill - // -> create secret - - await standardRequest.post( - `${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/create`, - { - path: key, - value: secrets[key].value, - is_secret: true, - description: secrets[key]?.comment || "" - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } else { - // -> update secret - await standardRequest.post( - `${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/update/${res[key].path}`, - { - path: key, - value: secrets[key].value, - is_secret: true, - description: secrets[key]?.comment || "" - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); - } - } - } - - for await (const key of Object.keys(res)) { - if (!(key in secrets)) { - // -> delete secret - await standardRequest.delete( - `${INTEGRATION_WINDMILL_API_URL}/w/${integration.appId}/variables/delete/${res[key].path}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json" - } - } - ); - } - } -}; - -/** - * Sync/push [secrets] to Cloud66 application with name [integration.app] - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {IIntegrationAuth} obj.integrationAuth - integration auth details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Cloud66 integration - */ -const syncSecretsCloud66 = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - interface Cloud66Secret { - id: number; - key: string; - value: string; - readonly: boolean; - created_at: string; - updated_at: string; - is_password: boolean; - is_generated: boolean; - history: any[]; - } - - // get all current secrets - const res = ( - await standardRequest.get( - `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ) - ).data.response - .filter((secret: Cloud66Secret) => !secret.readonly || !secret.is_generated) - .reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.key]: secret - }), - {} - ); - - for await (const key of Object.keys(secrets)) { - if (key in res) { - // update existing secret - await standardRequest.put( - `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments/${key}`, - { - key, - value: secrets[key].value - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } else { - // create new secret - await standardRequest.post( - `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments`, - { - key, - value: secrets[key].value - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } - } - - for await (const key of Object.keys(res)) { - if (!(key in secrets)) { - // delete secret - await standardRequest.delete( - `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments/${key}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ); - } - } -}; - -/** Sync/push [secrets] to Northflank - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Northflank integration - */ -const syncSecretsNorthflank = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - await standardRequest.patch( - `${INTEGRATION_NORTHFLANK_API_URL}/v1/projects/${integration.appId}/secrets/${integration.targetServiceId}`, - { - secrets: { - variables: getSecretKeyValuePair(secrets) - } - }, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } - } - ); -}; - -/** Sync/push [secrets] to Hasura Cloud - * @param {Object} obj - * @param {IIntegration} obj.integration - integration details - * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) - * @param {String} obj.accessToken - access token for Hasura Cloud integration - */ -const syncSecretsHasuraCloud = async ({ - integration, - secrets, - accessToken -}: { - integration: IIntegration; - secrets: Record; - accessToken: string; -}) => { - const res = await standardRequest.post( - INTEGRATION_HASURA_CLOUD_API_URL, - { - query: - "query MyQuery($tenantId: uuid!) { getTenantEnv(tenantId: $tenantId) { hash envVars } }", - variables: { - tenantId: integration.appId - } - }, - { - headers: { - Authorization: `pat ${accessToken}`, - "Content-Type": "application/json" - } - } - ); - - const { - data: { - getTenantEnv: { hash, envVars } - } - } = ZGetTenantEnv.parse(res.data); - - let currentHash = hash; - - const secretsToUpdate = Object.keys(secrets).map((key) => { - return ({ - key, - value: secrets[key].value - }); - }); - - if (secretsToUpdate.length) { - // update secrets - - const addRequest = await standardRequest.post( - INTEGRATION_HASURA_CLOUD_API_URL, - { - query: - "mutation MyQuery($currentHash: String!, $envs: [UpdateEnvObject!]!, $tenantId: uuid!) { updateTenantEnv(currentHash: $currentHash, envs: $envs, tenantId: $tenantId) { hash envVars} }", - variables: { - currentHash, - envs: secretsToUpdate, - tenantId: integration.appId - } - }, - { - headers: { - Authorization: `pat ${accessToken}`, - "Content-Type": "application/json" - } - } - ); - - const addRequestResponse = ZUpdateTenantEnv.safeParse(addRequest.data); - if (addRequestResponse.success) { - currentHash = addRequestResponse.data.data.updateTenantEnv.hash; - } - } - - const secretsToDelete = envVars.environment - ? Object.keys(envVars.environment).filter((key) => !(key in secrets)) - : []; - - if (secretsToDelete.length) { - await standardRequest.post( - INTEGRATION_HASURA_CLOUD_API_URL, - { - query: ` - mutation deleteTenantEnv($id: uuid!, $currentHash: String!, $env: [String!]!) { - deleteTenantEnv(tenantId: $id, currentHash: $currentHash, deleteEnvs: $env) { - hash - envVars - } - } - `, - variables: { - id: integration.appId, - currentHash, - env: secretsToDelete - } - }, - { - headers: { - Authorization: `pat ${accessToken}`, - "Content-Type": "application/json" - } - } - ); - } -}; - -export { syncSecrets }; diff --git a/backend-mongo/src/integrations/teams.ts b/backend-mongo/src/integrations/teams.ts deleted file mode 100644 index 46791c5b3..000000000 --- a/backend-mongo/src/integrations/teams.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { - IIntegrationAuth, -} from "../models"; -import { - INTEGRATION_GITLAB, - INTEGRATION_GITLAB_API_URL, -} from "../variables"; -import { standardRequest } from "../config/request"; - -interface Team { - name: string; - teamId: string; -} - -/** - * Return list of teams for integration authorization [integrationAuth] - * @param {Object} obj - * @param {String} obj.integrationAuth - integration authorization to get teams for - * @param {String} obj.accessToken - access token for integration authorization - * @returns {Object[]} teams - teams of integration authorization - * @returns {String} teams.name - name of team - * @returns {String} teams.teamId - id of team -*/ -const getTeams = async ({ - integrationAuth, - accessToken, -}: { - integrationAuth: IIntegrationAuth; - accessToken: string; -}) => { - - let teams: Team[] = []; - - switch (integrationAuth.integration) { - case INTEGRATION_GITLAB: - teams = await getTeamsGitLab({ - integrationAuth, - accessToken, - }); - break; - } - - return teams; -} - -/** - * Return list of teams for GitLab integration - * @param {Object} obj - * @param {String} obj.accessToken - access token for GitLab API - * @returns {Object[]} teams - teams that user is part of in GitLab - * @returns {String} teams.name - name of team - * @returns {String} teams.teamId - id of team -*/ -const getTeamsGitLab = async ({ - integrationAuth, - accessToken, -}: { - integrationAuth: IIntegrationAuth; - accessToken: string; -}) => { - const gitLabApiUrl = integrationAuth.url ? `${integrationAuth.url}/api` : INTEGRATION_GITLAB_API_URL; - - let teams: Team[] = []; - const res = (await standardRequest.get( - `${gitLabApiUrl}/v4/groups`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json", - }, - } - )).data; - - teams = res.map((t: any) => ({ - name: t.name, - teamId: t.id, - })); - - return teams; -} - -export { - getTeams, -} diff --git a/backend-mongo/src/interfaces/middleware/index.ts b/backend-mongo/src/interfaces/middleware/index.ts deleted file mode 100644 index acd992162..000000000 --- a/backend-mongo/src/interfaces/middleware/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Types } from "mongoose"; -import { IIdentity, IServiceTokenData, IUser } from "../../models"; -import { IdentityActor, ServiceActor, UserActor, UserAgentType } from "../../ee/models"; - -interface BaseAuthData { - ipAddress: string; - userAgent: string; - userAgentType: UserAgentType; - tokenVersionId?: Types.ObjectId; -} - -export interface UserAuthData extends BaseAuthData { - actor: UserActor; - authPayload: IUser; -} - -export interface IdentityAuthData extends BaseAuthData { - actor: IdentityActor; - authPayload: IIdentity; -} - -export interface ServiceTokenAuthData extends BaseAuthData { - actor: ServiceActor; - authPayload: IServiceTokenData; -} - -export type AuthData = UserAuthData | IdentityAuthData | ServiceTokenAuthData; \ No newline at end of file diff --git a/backend-mongo/src/interfaces/services/BotService/index.ts b/backend-mongo/src/interfaces/services/BotService/index.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/backend-mongo/src/interfaces/services/SecretService/index.ts b/backend-mongo/src/interfaces/services/SecretService/index.ts deleted file mode 100644 index 495abf726..000000000 --- a/backend-mongo/src/interfaces/services/SecretService/index.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { Types } from "mongoose"; -import { AuthData } from "../../middleware"; - -export interface CreateSecretParams { - secretName: string; - workspaceId: Types.ObjectId; - environment: string; - type: "shared" | "personal"; - authData: AuthData; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - skipMultilineEncoding?: boolean; - secretPath: string; - metadata?: { - source?: string; - }; -} - -export interface GetSecretsParams { - workspaceId: Types.ObjectId; - environment: string; - secretPath: string; - authData: AuthData; -} - -export interface GetSecretParams { - secretName: string; - workspaceId: Types.ObjectId; - secretPath: string; - environment: string; - type?: "shared" | "personal"; - authData: AuthData; - include_imports?: boolean; - version?: number; -} - -export interface UpdateSecretParams { - secretName: string; - newSecretName?: string; - secretId?: string; - secretKeyCiphertext?: string; - secretKeyIV?: string; - secretKeyTag?: string; - workspaceId: Types.ObjectId; - environment: string; - type: "shared" | "personal"; - authData: AuthData; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretPath: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - - secretReminderRepeatDays?: number | null; - secretReminderNote?: string | null; - - skipMultilineEncoding?: boolean; - tags?: string[]; -} - -export interface DeleteSecretParams { - secretName: string; - secretId?: string; - workspaceId: Types.ObjectId; - environment: string; - type: "shared" | "personal"; - authData: AuthData; - secretPath: string; -} - -export interface CreateSecretBatchParams { - workspaceId: Types.ObjectId; - environment: string; - authData: AuthData; - secretPath: string; - secrets: Array<{ - secretName: string; - type: "shared" | "personal"; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - skipMultilineEncoding?: boolean; - metadata?: { - source?: string; - }; - }>; -} - -export interface UpdateSecretBatchParams { - workspaceId: Types.ObjectId; - environment: string; - authData: AuthData; - secretPath: string; - secrets: Array<{ - secretName: string; - type: "shared" | "personal"; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - skipMultilineEncoding?: boolean; - tags?: string[]; - }>; -} - -export interface DeleteSecretBatchParams { - workspaceId: Types.ObjectId; - environment: string; - authData: AuthData; - secretPath: string; - secrets: Array<{ - secretName: string; - type: "shared" | "personal"; - }>; -} diff --git a/backend-mongo/src/interfaces/utils/crypto.ts b/backend-mongo/src/interfaces/utils/crypto.ts deleted file mode 100644 index cc2c54e3b..000000000 --- a/backend-mongo/src/interfaces/utils/crypto.ts +++ /dev/null @@ -1,41 +0,0 @@ -export interface IGenerateKeyPairOutput { - publicKey: string; - privateKey: string -} - -export interface IEncryptAsymmetricInput { - plaintext: string; - publicKey: string; - privateKey: string; -} - -export interface IEncryptAsymmetricOutput { - ciphertext: string; - nonce: string; -} - -export interface IDecryptAsymmetricInput { - ciphertext: string; - nonce: string; - publicKey: string; - privateKey: string; -} - -export interface IEncryptSymmetricInput { - plaintext: string; - key: string; -} - -export interface IEncryptSymmetricOutput { - ciphertext: string; - iv: string; - tag: string; -} - -export interface IDecryptSymmetricInput { - ciphertext: string; - iv: string; - tag: string; - key: string; -} - diff --git a/backend-mongo/src/interfaces/utils/index.ts b/backend-mongo/src/interfaces/utils/index.ts deleted file mode 100644 index b781a39bb..000000000 --- a/backend-mongo/src/interfaces/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./crypto"; \ No newline at end of file diff --git a/backend-mongo/src/middleware/index.ts b/backend-mongo/src/middleware/index.ts deleted file mode 100644 index 347519b6e..000000000 --- a/backend-mongo/src/middleware/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import requireAuth from "./requireAuth"; -import requireMfaAuth from "./requireMfaAuth"; -import requireSignupAuth from "./requireSignupAuth"; -import requireWorkspaceAuth from "./requireWorkspaceAuth"; -import requireServiceTokenAuth from "./requireServiceTokenAuth"; -import requireSecretAuth from "./requireSecretAuth"; -import requireSecretsAuth from "./requireSecretsAuth"; -import requireBlindIndicesEnabled from "./requireBlindIndicesEnabled"; -import requireE2EEOff from "./requireE2EEOff"; -import { requireSuperAdminAccess } from "./requireSuperAdminAccess"; -import validateRequest from "./validateRequest"; -import { disableSignUpByServerCfg } from "./serverAdmin"; - -export { - requireAuth, - requireMfaAuth, - requireSignupAuth, - requireWorkspaceAuth, - requireServiceTokenAuth, - requireSecretAuth, - requireSecretsAuth, - requireBlindIndicesEnabled, - requireE2EEOff, - validateRequest, - requireSuperAdminAccess, - disableSignUpByServerCfg -}; diff --git a/backend-mongo/src/middleware/requestErrorHandler.ts b/backend-mongo/src/middleware/requestErrorHandler.ts deleted file mode 100644 index 99417d030..000000000 --- a/backend-mongo/src/middleware/requestErrorHandler.ts +++ /dev/null @@ -1,47 +0,0 @@ -import * as Sentry from "@sentry/node"; -import { ErrorRequestHandler } from "express"; -import { TokenExpiredError } from "jsonwebtoken"; -import { InternalServerError, UnauthorizedRequestError } from "../utils/errors"; -import { logger } from "../utils/logging"; -import RequestError, { mapToPinoLogLevel } from "../utils/requestError"; -import { ForbiddenError } from "@casl/ability"; - -export const requestErrorHandler: ErrorRequestHandler = async ( - err: RequestError | Error, - req, - res, - next -) => { - if (res.headersSent) return next(); - - let error: RequestError; - - switch (true) { - case err instanceof TokenExpiredError: - error = UnauthorizedRequestError({ stack: err.stack, message: "Token expired" }); - break; - case err instanceof ForbiddenError: - error = UnauthorizedRequestError({ context: { exception: err.message }, stack: err.stack }) - break; - case err instanceof RequestError: - error = err as RequestError; - break; - default: - error = InternalServerError({ context: { exception: err.message }, stack: err.stack }); - break; - } - - logger[mapToPinoLogLevel(error.level)]({ msg: error }); - - if (req.user) { - Sentry.setUser({ email: (req.user as any).email }); - } - - Sentry.captureException(error); - - res.status((error).statusCode).send( - await error.format(req) - ); - - next(); -}; diff --git a/backend-mongo/src/middleware/requireAuth.ts b/backend-mongo/src/middleware/requireAuth.ts deleted file mode 100644 index e68de3133..000000000 --- a/backend-mongo/src/middleware/requireAuth.ts +++ /dev/null @@ -1,73 +0,0 @@ -import jwt from "jsonwebtoken"; -import { NextFunction, Request, Response } from "express"; -import { AuthMode } from "../variables"; -import { AuthData } from "../interfaces/middleware"; -import { extractAuthMode, getAuthData } from "../utils/authn/helpers"; -import { UnauthorizedRequestError } from "../utils/errors"; - -declare module "jsonwebtoken" { - export interface UserIDJwtPayload extends jwt.JwtPayload { - userId: string; - } -} - -/** - * Validate if token on request is valid (e.g. not expired) for various auth modes: - * - If token is a JWT token, then check if there is an associated user - * and if user is fully setup. - * - If token is a service token (st), then check if there is associated - * service token data. - * @param {Object} obj - * @param {String[]} obj.acceptedAuthModes - accepted modes of authentication (jwt/st) - * @returns - */ -const requireAuth = ({ - acceptedAuthModes = [AuthMode.JWT], -}: { - acceptedAuthModes: AuthMode[]; -}) => { - return async (req: Request, res: Response, next: NextFunction) => { - - // extract auth mode - const { authMode, authTokenValue } = await extractAuthMode({ - headers: req.headers - }); - - // validate auth mode - if (!acceptedAuthModes.includes(authMode)) throw UnauthorizedRequestError({ - message: "Failed to authenticate unaccepted authentication mode" - }); - - // get auth data / payload - const authData: AuthData = await getAuthData({ - authMode, - authTokenValue, - ipAddress: req.realIP, - userAgent: req.headers["user-agent"] ?? "" - }); - - switch (authMode) { - case AuthMode.SERVICE_TOKEN: - req.serviceTokenData = authData.authPayload; - break; - case AuthMode.IDENTITY_ACCESS_TOKEN: - req.serviceTokenData = authData.authPayload; - break; - case AuthMode.API_KEY: - req.user = authData.authPayload; - break; - case AuthMode.API_KEY_V2: - req.user = authData.authPayload; - break; - case AuthMode.JWT: - req.user = authData.authPayload; - break; - } - - req.authData = authData; - - return next(); - } -} - -export default requireAuth; diff --git a/backend-mongo/src/middleware/requireBlindIndicesEnabled.ts b/backend-mongo/src/middleware/requireBlindIndicesEnabled.ts deleted file mode 100644 index b1288dd2b..000000000 --- a/backend-mongo/src/middleware/requireBlindIndicesEnabled.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { Types } from "mongoose"; -import { SecretBlindIndexData } from "../models"; -import { UnauthorizedRequestError } from "../utils/errors"; - -type req = "params" | "body" | "query"; - -/** - * Validate if workspace with [workspaceId] has blind indices enabled - * @param {Object} obj - * @param {String} obj.locationWorkspaceId - location of [workspaceId] on request (e.g. params, body) for parsing - * @returns - */ -const requireBlindIndicesEnabled = ({ - locationWorkspaceId -}: { - locationWorkspaceId: req; -}) => { - return async (req: Request, res: Response, next: NextFunction) => { - const workspaceId = req[locationWorkspaceId]?.workspaceId; - - const secretBlindIndexData = await SecretBlindIndexData.exists({ - workspace: new Types.ObjectId(workspaceId) - }); - - if (!secretBlindIndexData) throw UnauthorizedRequestError({ - message: "Failed workspace authorization due to blind indices not being enabled" - }); - - return next(); - } -} - -export default requireBlindIndicesEnabled; \ No newline at end of file diff --git a/backend-mongo/src/middleware/requireE2EEOff.ts b/backend-mongo/src/middleware/requireE2EEOff.ts deleted file mode 100644 index a9e5a735b..000000000 --- a/backend-mongo/src/middleware/requireE2EEOff.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { BadRequestError } from "../utils/errors"; -import { BotService } from "../services"; - -type req = "params" | "body" | "query"; - -/** - * Validate if workspace with [workspaceId] has E2EE off/disabled - * @param {Object} obj - * @param {String} obj.locationWorkspaceId - location of [workspaceId] on request (e.g. params, body) for parsing - * @returns - */ -const requireE2EEOff = ({ - locationWorkspaceId -}: { - locationWorkspaceId: req; -}) => { - return async (req: Request, _: Response, next: NextFunction) => { - const workspaceId = req[locationWorkspaceId]?.workspaceId; - - const isWorkspaceE2EE = await BotService.getIsWorkspaceE2EE(workspaceId); - - if (isWorkspaceE2EE) throw BadRequestError({ - message: "Failed workspace authorization due to end-to-end encryption not being disabled" - }); - - return next(); - } -} - -export default requireE2EEOff; \ No newline at end of file diff --git a/backend-mongo/src/middleware/requireMfaAuth.ts b/backend-mongo/src/middleware/requireMfaAuth.ts deleted file mode 100644 index 9c5313b05..000000000 --- a/backend-mongo/src/middleware/requireMfaAuth.ts +++ /dev/null @@ -1,46 +0,0 @@ -import jwt from "jsonwebtoken"; -import { NextFunction, Request, Response } from "express"; -import { User } from "../models"; -import { BadRequestError, UnauthorizedRequestError } from "../utils/errors"; -import { getAuthSecret } from "../config"; -import { AuthTokenType } from "../variables"; - -declare module "jsonwebtoken" { - export interface UserIDJwtPayload extends jwt.JwtPayload { - userId: string; - } -} - -/** - * Validate if (MFA) JWT temporary token on request is valid (e.g. not expired) - * and if there is an associated user. - */ -const requireMfaAuth = async ( - req: Request, - res: Response, - next: NextFunction -) => { - // JWT (temporary) authentication middleware for complete signup - const [ AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE ] = <[string, string]>req.headers["authorization"]?.split(" ", 2) ?? [null, null] - if(AUTH_TOKEN_TYPE === null) return next(BadRequestError({message: "Missing Authorization Header in the request header."})) - if(AUTH_TOKEN_TYPE.toLowerCase() !== "bearer") return next(BadRequestError({message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.`})) - if(AUTH_TOKEN_VALUE === null) return next(BadRequestError({message: "Missing Authorization Body in the request header"})) - - const decodedToken = ( - jwt.verify(AUTH_TOKEN_VALUE, await getAuthSecret()) - ); - - if (decodedToken.authTokenType !== AuthTokenType.MFA_TOKEN) throw UnauthorizedRequestError(); - - const user = await User.findOne({ - _id: decodedToken.userId, - }).select("+publicKey"); - - if (!user) - return next(UnauthorizedRequestError({message: "Unable to authenticate for User account completion. Try logging in again"})) - - req.user = user; - return next(); -}; - -export default requireMfaAuth; diff --git a/backend-mongo/src/middleware/requireSecretAuth.ts b/backend-mongo/src/middleware/requireSecretAuth.ts deleted file mode 100644 index 06ad6019e..000000000 --- a/backend-mongo/src/middleware/requireSecretAuth.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { Types } from "mongoose"; -import { validateClientForSecret } from "../validation"; - -// note: used for old /v1/secret and /v2/secret routes. -// newer /v2/secrets routes use [requireSecretsAuth] middleware with the exception -// of some /ee endpoints - -/** - * Validate if user on request has proper membership to modify secret. - * @param {Object} obj - * @param {String[]} obj.acceptedRoles - accepted workspace roles - * @param {String[]} obj.location - location of [workspaceId] on request (e.g. params, body) for parsing - */ -const requireSecretAuth = ({ - acceptedRoles, - requiredPermissions, -}: { - acceptedRoles: Array<"admin" | "member">; - requiredPermissions: string[]; -}) => { - return async (req: Request, res: Response, next: NextFunction) => { - const { secretId } = req.params; - - const secret = await validateClientForSecret({ - authData: req.authData, - secretId: new Types.ObjectId(secretId), - acceptedRoles, - requiredPermissions, - }); - - req._secret = secret; - - next(); - } -} - -export default requireSecretAuth; \ No newline at end of file diff --git a/backend-mongo/src/middleware/requireSecretsAuth.ts b/backend-mongo/src/middleware/requireSecretsAuth.ts deleted file mode 100644 index 3dabdb25c..000000000 --- a/backend-mongo/src/middleware/requireSecretsAuth.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { Types } from "mongoose"; -import { validateClientForSecrets } from "../validation"; - -const requireSecretsAuth = ({ - acceptedRoles, - requiredPermissions = [], -}: { - acceptedRoles: string[]; - requiredPermissions?: string[]; -}) => { - return async (req: Request, res: Response, next: NextFunction) => { - let secretIds = []; - if (Array.isArray(req.body.secrets)) { - secretIds = req.body.secrets.map((s: any) => s.id); - } else if (typeof req.body.secrets === "object") { - secretIds = [req.body.secrets.id]; - } else if (Array.isArray(req.body.secretIds)) { - secretIds = req.body.secretIds; - } else if (typeof req.body.secretIds === "string") { - secretIds = [req.body.secretIds]; - } - - req.secrets = await validateClientForSecrets({ - authData: req.authData, - secretIds: secretIds.map((secretId: string) => new Types.ObjectId(secretId)), - requiredPermissions, - }); - - return next(); - } -} - -export default requireSecretsAuth; \ No newline at end of file diff --git a/backend-mongo/src/middleware/requireServiceTokenAuth.ts b/backend-mongo/src/middleware/requireServiceTokenAuth.ts deleted file mode 100644 index 340f03cc0..000000000 --- a/backend-mongo/src/middleware/requireServiceTokenAuth.ts +++ /dev/null @@ -1,51 +0,0 @@ -import jwt from "jsonwebtoken"; -import { NextFunction, Request, Response } from "express"; -import { ServiceToken } from "../models"; -import { BadRequestError, UnauthorizedRequestError } from "../utils/errors"; -import { getJwtServiceSecret } from "../config"; - -// TODO: deprecate -declare module "jsonwebtoken" { - export interface UserIDJwtPayload extends jwt.JwtPayload { - userId: string; - } -} - -/** - * Validate if JWT (service) token on request is valid (e.g. not expired), - * and if there is an associated service token - * @param req - express request object - * @param res - express response object - * @param next - express next function - * @returns - */ -const requireServiceTokenAuth = async ( - req: Request, - res: Response, - next: NextFunction -) => { - // JWT service token middleware - - const [ AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE ] = <[string, string]>req.headers["authorization"]?.split(" ", 2) ?? [null, null] - if(AUTH_TOKEN_TYPE === null) return next(BadRequestError({message: "Missing Authorization Header in the request header."})) - //TODO: Determine what is the actual Token Type for Service Token Authentication (ex. Bearer) - //if(AUTH_TOKEN_TYPE.toLowerCase() !== 'bearer') return next(UnauthorizedRequestError({message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.`})) - if(AUTH_TOKEN_VALUE === null) return next(BadRequestError({message: "Missing Authorization Body in the request header"})) - - const decodedToken = ( - jwt.verify(AUTH_TOKEN_VALUE, await getJwtServiceSecret()) - ); - - const serviceToken = await ServiceToken.findOne({ - _id: decodedToken.serviceTokenId, - }) - .populate("user", "+publicKey") - .select("+encryptedKey +publicKey +nonce"); - - if (!serviceToken) return next(UnauthorizedRequestError({message: "The service token does not match the record in the database"})) - - req.serviceToken = serviceToken; - return next(); -}; - -export default requireServiceTokenAuth; diff --git a/backend-mongo/src/middleware/requireSignupAuth.ts b/backend-mongo/src/middleware/requireSignupAuth.ts deleted file mode 100644 index 510cb3d03..000000000 --- a/backend-mongo/src/middleware/requireSignupAuth.ts +++ /dev/null @@ -1,47 +0,0 @@ -import jwt from "jsonwebtoken"; -import { NextFunction, Request, Response } from "express"; -import { User } from "../models"; -import { BadRequestError, UnauthorizedRequestError } from "../utils/errors"; -import { getAuthSecret } from "../config"; -import { AuthTokenType } from "../variables"; - -declare module "jsonwebtoken" { - export interface UserIDJwtPayload extends jwt.JwtPayload { - userId: string; - } -} - -/** - * Validate if JWT temporary token on request is valid (e.g. not expired) - * and if there is an associated user. - */ -const requireSignupAuth = async ( - req: Request, - res: Response, - next: NextFunction -) => { - // JWT (temporary) authentication middleware for complete signup - - const [ AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE ] = <[string, string]>req.headers["authorization"]?.split(" ", 2) ?? [null, null] - if(AUTH_TOKEN_TYPE === null) return next(BadRequestError({message: "Missing Authorization Header in the request header."})) - if(AUTH_TOKEN_TYPE.toLowerCase() !== "bearer") return next(BadRequestError({message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.`})) - if(AUTH_TOKEN_VALUE === null) return next(BadRequestError({message: "Missing Authorization Body in the request header"})) - - const decodedToken = ( - jwt.verify(AUTH_TOKEN_VALUE, await getAuthSecret()) - ); - - if (decodedToken.authTokenType !== AuthTokenType.SIGNUP_TOKEN) throw UnauthorizedRequestError(); - - const user = await User.findOne({ - _id: decodedToken.userId, - }).select("+publicKey"); - - if (!user) - return next(UnauthorizedRequestError({message: "Unable to authenticate for User account completion. Try logging in again"})) - - req.user = user; - return next(); -}; - -export default requireSignupAuth; diff --git a/backend-mongo/src/middleware/requireSuperAdminAccess.ts b/backend-mongo/src/middleware/requireSuperAdminAccess.ts deleted file mode 100644 index 4445433ff..000000000 --- a/backend-mongo/src/middleware/requireSuperAdminAccess.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { UnauthorizedRequestError } from "../utils/errors"; - -export const requireSuperAdminAccess = (req: Request, _res: Response, next: NextFunction) => { - const isSuperAdmin = req.user.superAdmin; - if (!isSuperAdmin) throw UnauthorizedRequestError({ message: "Requires superadmin access" }); - return next(); -}; diff --git a/backend-mongo/src/middleware/requireWorkspaceAuth.ts b/backend-mongo/src/middleware/requireWorkspaceAuth.ts deleted file mode 100644 index bbf829565..000000000 --- a/backend-mongo/src/middleware/requireWorkspaceAuth.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { Types } from "mongoose"; -import { validateClientForWorkspace } from "../validation"; - -type req = "params" | "body" | "query"; - -/** - * Validate if user on request is a member with proper roles for workspace - * on request params. - * @param {Object} obj - * @param {String[]} obj.acceptedRoles - accepted workspace roles for JWT auth - * @param {String} obj.locationWorkspaceId - location of [workspaceId] on request (e.g. params, body) for parsing - */ -const requireWorkspaceAuth = ({ - acceptedRoles, - locationWorkspaceId, - locationEnvironment = undefined, - requiredPermissions = [], -}: { - acceptedRoles: Array<"admin" | "member">; - locationWorkspaceId: req; - locationEnvironment?: req | undefined; - requiredPermissions?: string[]; -}) => { - return async (req: Request, res: Response, next: NextFunction) => { - const workspaceId = req[locationWorkspaceId]?.workspaceId; - const environment = locationEnvironment ? req[locationEnvironment]?.environment : undefined; - - // validate clients - const { membership, workspace } = await validateClientForWorkspace({ - authData: req.authData, - workspaceId: new Types.ObjectId(workspaceId), - environment, - acceptedRoles, - requiredPermissions - }); - - if (membership) { - req.membership = membership; - } - - if (workspace) { - req.workspace = workspace; - } - - return next(); - }; -}; - -export default requireWorkspaceAuth; diff --git a/backend-mongo/src/middleware/serverAdmin.ts b/backend-mongo/src/middleware/serverAdmin.ts deleted file mode 100644 index d57dbf714..000000000 --- a/backend-mongo/src/middleware/serverAdmin.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { getServerConfig } from "../config/serverConfig"; -import { BadRequestError } from "../utils/errors"; - -export const disableSignUpByServerCfg = (_req: Request, _res: Response, next: NextFunction) => { - const cfg = getServerConfig(); - if (!cfg.allowSignUp) throw BadRequestError({ message: "Signup are disabled" }); - return next(); -}; diff --git a/backend-mongo/src/middleware/validateRequest.ts b/backend-mongo/src/middleware/validateRequest.ts deleted file mode 100644 index 56ea2653c..000000000 --- a/backend-mongo/src/middleware/validateRequest.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { NextFunction, Request, Response } from "express"; -import { validationResult } from "express-validator"; -import { UnauthorizedRequestError, ValidationError } from "../utils/errors"; - -/** - * Validate intended inputs on [req] via express-validator - * @param req - express request object - * @param res - express response object - * @param next - express next function - * @returns - */ -const validate = (req: Request, res: Response, next: NextFunction) => { - // express validator middleware - - try { - const errors = validationResult(req); - if (!errors.isEmpty()) { - return next(ValidationError({ context: { errors: `One or more of your parameters are invalid [error(s)=${(JSON.stringify(errors))}]` } })) - } - - return next(); - } catch (err) { - return next(UnauthorizedRequestError({ message: "Unauthenticated requests are not allowed. Try logging in" })) - } -}; - -export default validate; diff --git a/backend-mongo/src/models/apiKeyData.ts b/backend-mongo/src/models/apiKeyData.ts deleted file mode 100644 index 0b88c5ddb..000000000 --- a/backend-mongo/src/models/apiKeyData.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IAPIKeyData { - name: string; - user: Types.ObjectId; - lastUsed: Date; - expiresAt: Date; - secretHash: string; -} - -const apiKeyDataSchema = new Schema( - { - name: { - type: String, - required: true, - }, - user: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - lastUsed: { - type: Date, - }, - expiresAt: { - type: Date, - }, - secretHash: { - type: String, - required: true, - select: false, - }, - }, - { - timestamps: true, - } -); - -export const APIKeyData = model("APIKeyData", apiKeyDataSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/apiKeyDataV2.ts b/backend-mongo/src/models/apiKeyDataV2.ts deleted file mode 100644 index 6775a0878..000000000 --- a/backend-mongo/src/models/apiKeyDataV2.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; - -export interface IAPIKeyDataV2 extends Document { - _id: Types.ObjectId; - name: string; - user: Types.ObjectId; - lastUsed?: Date - usageCount: number; - expiresAt?: Date; -} - -const apiKeyDataV2Schema = new Schema( - { - name: { - type: String, - required: true - }, - user: { - type: Schema.Types.ObjectId, - ref: "User", - required: true - }, - lastUsed: { - type: Date, - required: false - }, - usageCount: { - type: Number, - default: 0, - required: true - } - }, - { - timestamps: true - } -); - -export const APIKeyDataV2 = model("APIKeyDataV2", apiKeyDataV2Schema); \ No newline at end of file diff --git a/backend-mongo/src/models/backupPrivateKey.ts b/backend-mongo/src/models/backupPrivateKey.ts deleted file mode 100644 index 09df1dda7..000000000 --- a/backend-mongo/src/models/backupPrivateKey.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, -} from "../variables"; - -export interface IBackupPrivateKey { - _id: Types.ObjectId; - user: Types.ObjectId; - encryptedPrivateKey: string; - iv: string; - tag: string; - salt: string; - algorithm: string; - keyEncoding: "base64" | "utf8"; - verifier: string; -} - -const backupPrivateKeySchema = new Schema( - { - user: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - encryptedPrivateKey: { - type: String, - select: false, - required: true, - }, - iv: { - type: String, - select: false, - required: true, - }, - tag: { - type: String, - select: false, - required: true, - }, - algorithm: { // the encryption algorithm used - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true, - }, - keyEncoding: { - type: String, - enum: [ - ENCODING_SCHEME_UTF8, - ENCODING_SCHEME_BASE64, - ], - required: true, - }, - salt: { - type: String, - select: false, - required: true, - }, - verifier: { - type: String, - select: false, - required: true, - }, - }, - { - timestamps: true, - } -); - -export const BackupPrivateKey = model( - "BackupPrivateKey", - backupPrivateKeySchema -); diff --git a/backend-mongo/src/models/bot.ts b/backend-mongo/src/models/bot.ts deleted file mode 100644 index 5a5c83b13..000000000 --- a/backend-mongo/src/models/bot.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, -} from "../variables"; - -export interface IBot { - _id: Types.ObjectId; - name: string; - workspace: Types.ObjectId; - isActive: boolean; - publicKey: string; - encryptedPrivateKey: string; - iv: string; - tag: string; - algorithm: "aes-256-gcm"; - keyEncoding: "base64" | "utf8"; -} - -const botSchema = new Schema( - { - name: { - type: String, - required: true, - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - }, - isActive: { - type: Boolean, - required: true, - default: false, - }, - publicKey: { - type: String, - required: true, - }, - encryptedPrivateKey: { - type: String, - required: true, - select: false, - }, - iv: { - type: String, - required: true, - select: false, - }, - tag: { - type: String, - required: true, - select: false, - }, - algorithm: { // the encryption algorithm used - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true, - select: false, - }, - keyEncoding: { - type: String, - enum: [ - ENCODING_SCHEME_UTF8, - ENCODING_SCHEME_BASE64, - ], - required: true, - select: false, - }, - }, - { - timestamps: true, - } -); - -export const Bot = model("Bot", botSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/botKey.ts b/backend-mongo/src/models/botKey.ts deleted file mode 100644 index 02a6d6ea9..000000000 --- a/backend-mongo/src/models/botKey.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IBotKey { - _id: Types.ObjectId; - encryptedKey: string; - nonce: string; - sender: Types.ObjectId; - bot: Types.ObjectId; - workspace: Types.ObjectId; -} - -const botKeySchema = new Schema( - { - encryptedKey: { - type: String, - required: true, - }, - nonce: { - type: String, - required: true, - }, - sender: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - bot: { - type: Schema.Types.ObjectId, - ref: "Bot", - required: true, - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - }, - }, - { - timestamps: true, - } -); - -export const BotKey = model("BotKey", botKeySchema); \ No newline at end of file diff --git a/backend-mongo/src/models/botOrg.ts b/backend-mongo/src/models/botOrg.ts deleted file mode 100644 index 177294ef9..000000000 --- a/backend-mongo/src/models/botOrg.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, -} from "../variables"; - -export interface IBotOrg { - _id: Types.ObjectId; - name: string; - organization: Types.ObjectId; - publicKey: string; - encryptedSymmetricKey: string; - symmetricKeyIV: string; - symmetricKeyTag: string; - symmetricKeyAlgorithm: "aes-256-gcm"; - symmetricKeyKeyEncoding: "base64" | "utf8"; - encryptedPrivateKey: string; - privateKeyIV: string; - privateKeyTag: string; - privateKeyAlgorithm: "aes-256-gcm"; - privateKeyKeyEncoding: "base64" | "utf8"; -} - -const botOrgSchema = new Schema( - { - name: { - type: String, - required: true, - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization", - required: true, - }, - publicKey: { - type: String, - required: true, - }, - encryptedSymmetricKey: { - type: String, - required: true - }, - symmetricKeyIV: { - type: String, - required: true - }, - symmetricKeyTag: { - type: String, - required: true - }, - symmetricKeyAlgorithm: { - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true - }, - symmetricKeyKeyEncoding: { - type: String, - enum: [ - ENCODING_SCHEME_UTF8, - ENCODING_SCHEME_BASE64, - ], - required: true - }, - encryptedPrivateKey: { - type: String, - required: true - }, - privateKeyIV: { - type: String, - required: true - }, - privateKeyTag: { - type: String, - required: true - }, - privateKeyAlgorithm: { - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true - }, - privateKeyKeyEncoding: { - type: String, - enum: [ - ENCODING_SCHEME_UTF8, - ENCODING_SCHEME_BASE64, - ], - required: true - }, - }, - { - timestamps: true, - } -); - -export const BotOrg = model("BotOrg", botOrgSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/folder.ts b/backend-mongo/src/models/folder.ts deleted file mode 100644 index b3016822d..000000000 --- a/backend-mongo/src/models/folder.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export type TFolderRootSchema = { - _id: Types.ObjectId; - workspace: Types.ObjectId; - environment: string; - nodes: TFolderSchema; -}; - -export type TFolderSchema = { - id: string; - name: string; - version: number; - children: TFolderSchema[]; -}; - -const folderSchema = new Schema({ - id: { - required: true, - type: String, - }, - version: { - required: true, - type: Number, - default: 1, - }, - name: { - required: true, - type: String, - default: "root", - }, -}); - -folderSchema.add({ children: [folderSchema] }); - -const folderRootSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - }, - environment: { - type: String, - required: true, - }, - nodes: folderSchema, - }, - { - timestamps: true, - } -); - -export const Folder = model("Folder", folderRootSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/identity.ts b/backend-mongo/src/models/identity.ts deleted file mode 100644 index ec4948e1b..000000000 --- a/backend-mongo/src/models/identity.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; -import { IPType } from "../ee/models"; - -export interface IIdentityTrustedIp { - ipAddress: string; - type: IPType; - prefix: number; -} - -export enum IdentityAuthMethod { - UNIVERSAL_AUTH = "universal-auth" -} - -export interface IIdentity extends Document { - _id: Types.ObjectId; - name: string; - authMethod?: IdentityAuthMethod; -} - -const identitySchema = new Schema( - { - name: { - type: String, - required: true - }, - authMethod: { - type: String, - enum: IdentityAuthMethod, - required: false, - }, - - }, - { - timestamps: true - } -); - -export const Identity = model("Identity", identitySchema); diff --git a/backend-mongo/src/models/identityAccessToken.ts b/backend-mongo/src/models/identityAccessToken.ts deleted file mode 100644 index 82b2e6778..000000000 --- a/backend-mongo/src/models/identityAccessToken.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; -import { IIdentityTrustedIp } from "./identity"; -import { IPType } from "../ee/models/trustedIp"; - -export interface IIdentityAccessToken extends Document { - _id: Types.ObjectId; - identity: Types.ObjectId; - identityUniversalAuthClientSecret?: Types.ObjectId; - accessTokenLastUsedAt?: Date; - accessTokenLastRenewedAt?: Date; - accessTokenNumUses: number; - accessTokenNumUsesLimit: number; - accessTokenTTL: number; - accessTokenMaxTTL: number; - accessTokenTrustedIps: Array; - isAccessTokenRevoked: boolean; - updatedAt: Date; - createdAt: Date; -} - -const identityAccessTokenSchema = new Schema( - { - identity: { - type: Schema.Types.ObjectId, - ref: "Identity", - required: false - }, - identityUniversalAuthClientSecret: { - type: Schema.Types.ObjectId, - ref: "IdentityUniversalAuthClientSecret", - required: false - }, - accessTokenLastUsedAt: { - type: Date, - required: false - }, - accessTokenLastRenewedAt: { - type: Date, - required: false - }, - accessTokenNumUses: { - // number of times access token has been used - type: Number, - default: 0, - required: true - }, - accessTokenNumUsesLimit: { - // number of times access token can be used for - type: Number, - default: 0, // default: used as many times as needed - required: true - }, - accessTokenTTL: { // seconds - // incremental lifetime - type: Number, - default: 2592000, // 30 days - required: true - }, - accessTokenMaxTTL: { // seconds - // max lifetime - type: Number, - default: 2592000, // 30 days - required: true - }, - accessTokenTrustedIps: { - type: [ - { - ipAddress: { - type: String, - required: true - }, - type: { - type: String, - enum: [ - IPType.IPV4, - IPType.IPV6 - ], - required: true - }, - prefix: { - type: Number, - required: false - } - } - ], - default: [{ - ipAddress: "0.0.0.0", - type: IPType.IPV4.toString(), - prefix: 0 - }], - required: true - }, - isAccessTokenRevoked: { - type: Boolean, - default: false, - required: true - }, - }, - { - timestamps: true - } -); - -export const IdentityAccessToken = model("IdentityAccessToken", identityAccessTokenSchema); diff --git a/backend-mongo/src/models/identityMembership.ts b/backend-mongo/src/models/identityMembership.ts deleted file mode 100644 index 4fedfe909..000000000 --- a/backend-mongo/src/models/identityMembership.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables"; - -export interface IIdentityMembership { - _id: Types.ObjectId; - identity: Types.ObjectId; - workspace: Types.ObjectId; - role: "admin" | "member" | "viewer" | "no-access" | "custom"; - customRole: Types.ObjectId; -} - -const identityMembershipSchema = new Schema( - { - identity: { - type: Schema.Types.ObjectId, - ref: "Identity" - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - index: true, - }, - role: { - type: String, - enum: [ADMIN, MEMBER, VIEWER, CUSTOM, NO_ACCESS], - required: true - }, - customRole: { - type: Schema.Types.ObjectId, - ref: "Role" - } - }, - { - timestamps: true - } -); - -export const IdentityMembership = model("IdentityMembership", identityMembershipSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/identityMembershipOrg.ts b/backend-mongo/src/models/identityMembershipOrg.ts deleted file mode 100644 index 8da8693c4..000000000 --- a/backend-mongo/src/models/identityMembershipOrg.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { ADMIN, CUSTOM, MEMBER, NO_ACCESS} from "../variables"; - -export interface IIdentityMembershipOrg { - _id: Types.ObjectId; - identity: Types.ObjectId; - organization: Types.ObjectId; - role: "admin" | "member" | "no-access" | "custom"; - customRole: Types.ObjectId; -} - -const identityMembershipOrgSchema = new Schema( - { - identity: { - type: Schema.Types.ObjectId, - ref: "Identity" - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization" - }, - role: { - type: String, - enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM], - required: true - }, - customRole: { - type: Schema.Types.ObjectId, - ref: "Role" - } - }, - { - timestamps: true - } -); - -export const IdentityMembershipOrg = model("IdentityMembershipOrg", identityMembershipOrgSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/identityUniversalAuth.ts b/backend-mongo/src/models/identityUniversalAuth.ts deleted file mode 100644 index 89fb46a95..000000000 --- a/backend-mongo/src/models/identityUniversalAuth.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; -import { IPType } from "../ee/models"; -import { IIdentityTrustedIp } from "./identity"; - -export interface IIdentityUniversalAuth extends Document { - _id: Types.ObjectId; - identity: Types.ObjectId; - clientId: string; - clientSecretTrustedIps: Array; - accessTokenTTL: number; - accessTokenMaxTTL: number; - accessTokenNumUsesLimit: number; - accessTokenTrustedIps: Array; -} - -const identityUniversalAuthSchema = new Schema( - { - identity: { - type: Schema.Types.ObjectId, - ref: "Identity", - required: true - }, - clientId: { - type: String, - required: true - }, - clientSecretTrustedIps: { - type: [ - { - ipAddress: { - type: String, - required: true - }, - type: { - type: String, - enum: [ - IPType.IPV4, - IPType.IPV6 - ], - required: true - }, - prefix: { - type: Number, - required: false - } - } - ], - default: [{ - ipAddress: "0.0.0.0", - type: IPType.IPV4.toString(), - prefix: 0 - }], - required: true - }, - accessTokenTTL: { // seconds - // incremental lifetime - type: Number, - default: 7200, - required: true - }, - accessTokenMaxTTL: { // seconds - // max lifetime - type: Number, - default: 7200, - required: true - }, - accessTokenNumUsesLimit: { - // number of times access token can be used for - type: Number, - default: 0, // default: used as many times as needed - required: true - }, - accessTokenTrustedIps: { - type: [ - { - ipAddress: { - type: String, - required: true - }, - type: { - type: String, - enum: [ - IPType.IPV4, - IPType.IPV6 - ], - required: true - }, - prefix: { - type: Number, - required: false - } - } - ], - default: [{ - ipAddress: "0.0.0.0", - type: IPType.IPV4.toString(), - prefix: 0 - }], - required: true - } - }, - { - timestamps: true - } -); - -export const IdentityUniversalAuth = model("IdentityUniversalAuth", identityUniversalAuthSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/identityUniversalAuthClientSecret.ts b/backend-mongo/src/models/identityUniversalAuthClientSecret.ts deleted file mode 100644 index af9cc08a4..000000000 --- a/backend-mongo/src/models/identityUniversalAuthClientSecret.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; - -export interface IIdentityUniversalAuthClientSecret extends Document { - _id: Types.ObjectId; - identity: Types.ObjectId; - identityUniversalAuth : Types.ObjectId; - description: string; - clientSecretPrefix: string; - clientSecretHash: string; - clientSecretLastUsedAt?: Date; - clientSecretNumUses: number; - clientSecretNumUsesLimit: number; - clientSecretTTL: number; - updatedAt: Date; - createdAt: Date; - isClientSecretRevoked: boolean; -} - -const identityUniversalAuthClientSecretSchema = new Schema( - { - identity: { - type: Schema.Types.ObjectId, - ref: "Identity", - required: true - }, - identityUniversalAuth: { - type: Schema.Types.ObjectId, - ref: "IdentityUniversalAuth", - required: true - }, - description: { - type: String, - required: true - }, - clientSecretPrefix: { - type: String, - required: true - }, - clientSecretHash: { - type: String, - required: true - }, - clientSecretLastUsedAt: { - type: Date, - required: false - }, - clientSecretNumUses: { - // number of times client secret has been used - // in login operation - type: Number, - default: 0, - required: true - }, - clientSecretNumUsesLimit: { - // number of times client secret can be used for - // a login operation - type: Number, - default: 0, // default: used as many times as needed - required: true - }, - clientSecretTTL: { - type: Number, - default: 0, // default: does not expire - required: true - }, - isClientSecretRevoked: { - type: Boolean, - default: false, - required: true - } - }, - { - timestamps: true - } -); - -identityUniversalAuthClientSecretSchema.index( - { identityUniversalAuth: 1, isClientSecretRevoked: 1 } -); - -export const IdentityUniversalAuthClientSecret = model("IdentityUniversalAuthClientSecret", identityUniversalAuthClientSecretSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/incidentContactOrg.ts b/backend-mongo/src/models/incidentContactOrg.ts deleted file mode 100644 index 905b9263f..000000000 --- a/backend-mongo/src/models/incidentContactOrg.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IIncidentContactOrg { - _id: Types.ObjectId; - email: string; - organization: Types.ObjectId; -} - -const incidentContactOrgSchema = new Schema( - { - email: { - type: String, - required: true, - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization", - required: true, - }, - }, - { - timestamps: true, - } -); - -export const IncidentContactOrg = model( - "IncidentContactOrg", - incidentContactOrgSchema -); \ No newline at end of file diff --git a/backend-mongo/src/models/index.ts b/backend-mongo/src/models/index.ts deleted file mode 100644 index 9d20ea67a..000000000 --- a/backend-mongo/src/models/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -export * from "./backupPrivateKey"; -export * from "./bot"; -export * from "./botOrg"; -export * from "./botKey"; -export * from "./incidentContactOrg"; -export * from "./integration/integration"; -export * from "./integrationAuth"; -export * from "./key"; -export * from "./membership"; -export * from "./membershipOrg"; -export * from "./organization"; -export * from "./secret"; -export * from "./tag"; -export * from "./folder"; -export * from "./secretImports"; -export * from "./secretBlindIndexData"; -export * from "./serviceToken"; // TODO: deprecate -export * from "./tokenData"; -export * from "./user"; -export * from "./userAction"; -export * from "./workspace"; -export * from "./serviceTokenData"; // TODO: deprecate - -// new -export * from "./identity"; -export * from "./identityMembership"; -export * from "./identityMembershipOrg"; -export * from "./identityUniversalAuth"; -export * from "./identityUniversalAuthClientSecret"; -export * from "./identityAccessToken"; - -export * from "./apiKeyData"; // TODO: deprecate -export * from "./apiKeyDataV2"; -export * from "./loginSRPDetail"; -export * from "./tokenVersion"; -export * from "./webhooks"; diff --git a/backend-mongo/src/models/integration/index.ts b/backend-mongo/src/models/integration/index.ts deleted file mode 100644 index 2ed44cd28..000000000 --- a/backend-mongo/src/models/integration/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./integration"; \ No newline at end of file diff --git a/backend-mongo/src/models/integration/integration.ts b/backend-mongo/src/models/integration/integration.ts deleted file mode 100644 index eaaadec92..000000000 --- a/backend-mongo/src/models/integration/integration.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_BITBUCKET, - INTEGRATION_CHECKLY, - INTEGRATION_CIRCLECI, - INTEGRATION_CLOUDFLARE_PAGES, - INTEGRATION_CLOUDFLARE_WORKERS, - INTEGRATION_CLOUD_66, - INTEGRATION_CODEFRESH, - INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, - INTEGRATION_FLYIO, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_HASHICORP_VAULT, - INTEGRATION_HASURA_CLOUD, - INTEGRATION_HEROKU, - INTEGRATION_LARAVELFORGE, - INTEGRATION_NETLIFY, - INTEGRATION_NORTHFLANK, - INTEGRATION_QOVERY, - INTEGRATION_RAILWAY, - INTEGRATION_RENDER, - INTEGRATION_SUPABASE, - INTEGRATION_TEAMCITY, - INTEGRATION_TERRAFORM_CLOUD, - INTEGRATION_TRAVISCI, - INTEGRATION_VERCEL, - INTEGRATION_WINDMILL -} from "../../variables"; -import { Schema, Types, model } from "mongoose"; -import { Metadata } from "./types"; - -export interface IIntegration { - _id: Types.ObjectId; - workspace: Types.ObjectId; - environment: string; - isActive: boolean; - url: string; - app: string; - appId: string; - owner: string; - targetEnvironment: string; - targetEnvironmentId: string; - targetService: string; - targetServiceId: string; - path: string; - region: string; - scope: string; - secretPath: string; - integration: - | "azure-key-vault" - | "aws-parameter-store" - | "aws-secret-manager" - | "heroku" - | "vercel" - | "netlify" - | "github" - | "gitlab" - | "render" - | "railway" - | "flyio" - | "circleci" - | "laravel-forge" - | "travisci" - | "supabase" - | "checkly" - | "qovery" - | "terraform-cloud" - | "teamcity" - | "hashicorp-vault" - | "cloudflare-pages" - | "cloudflare-workers" - | "bitbucket" - | "codefresh" - | "digital-ocean-app-platform" - | "cloud-66" - | "northflank" - | "windmill" - | "gcp-secret-manager" - | "hasura-cloud"; - integrationAuth: Types.ObjectId; - metadata: Metadata; -} - -const integrationSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - environment: { - type: String, - required: true - }, - isActive: { - type: Boolean, - required: true - }, - url: { - // for custom self-hosted integrations (e.g. self-hosted GitHub enterprise) - type: String, - default: null - }, - app: { - // name of app in provider - type: String, - default: null - }, - appId: { - // id of app in provider - type: String, - default: null - }, - targetEnvironment: { - // target environment - type: String, - default: null - }, - targetEnvironmentId: { - type: String, - default: null - }, - targetService: { - // railway-specific service - // qovery-specific project - type: String, - default: null - }, - targetServiceId: { - // railway-specific service - // qovery specific project - type: String, - default: null - }, - owner: { - // github-specific repo owner-login - type: String, - default: null - }, - path: { - // aws-parameter-store-specific path - // (also) vercel preview-branch - type: String, - default: null - }, - region: { - // aws-parameter-store-specific path - type: String, - default: null - }, - scope: { - // qovery-specific scope - type: String, - default: null - }, - integration: { - type: String, - enum: [ - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_HEROKU, - INTEGRATION_VERCEL, - INTEGRATION_NETLIFY, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_RENDER, - INTEGRATION_RAILWAY, - INTEGRATION_FLYIO, - INTEGRATION_CIRCLECI, - INTEGRATION_LARAVELFORGE, - INTEGRATION_TRAVISCI, - INTEGRATION_SUPABASE, - INTEGRATION_CHECKLY, - INTEGRATION_QOVERY, - INTEGRATION_TERRAFORM_CLOUD, - INTEGRATION_TEAMCITY, - INTEGRATION_HASHICORP_VAULT, - INTEGRATION_CLOUDFLARE_PAGES, - INTEGRATION_CLOUDFLARE_WORKERS, - INTEGRATION_CODEFRESH, - INTEGRATION_WINDMILL, - INTEGRATION_BITBUCKET, - INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, - INTEGRATION_CLOUD_66, - INTEGRATION_NORTHFLANK, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_HASURA_CLOUD - ], - required: true - }, - integrationAuth: { - type: Schema.Types.ObjectId, - ref: "IntegrationAuth", - required: true - }, - secretPath: { - type: String, - required: true, - default: "/" - }, - metadata: { - type: Schema.Types.Mixed, - default: {} - } - }, - { - timestamps: true - } -); - -export const Integration = model("Integration", integrationSchema); diff --git a/backend-mongo/src/models/integration/types.ts b/backend-mongo/src/models/integration/types.ts deleted file mode 100644 index 5c4387bba..000000000 --- a/backend-mongo/src/models/integration/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type Metadata = { - secretPrefix?: string; - secretSuffix?: string; - secretGCPLabel?: { - labelName: string; - labelValue: string; - } -} \ No newline at end of file diff --git a/backend-mongo/src/models/integrationAuth/index.ts b/backend-mongo/src/models/integrationAuth/index.ts deleted file mode 100644 index 157095bd2..000000000 --- a/backend-mongo/src/models/integrationAuth/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./integrationAuth"; \ No newline at end of file diff --git a/backend-mongo/src/models/integrationAuth/integrationAuth.ts b/backend-mongo/src/models/integrationAuth/integrationAuth.ts deleted file mode 100644 index da1e57268..000000000 --- a/backend-mongo/src/models/integrationAuth/integrationAuth.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_BITBUCKET, - INTEGRATION_CIRCLECI, - INTEGRATION_CLOUDFLARE_PAGES, - INTEGRATION_CLOUDFLARE_WORKERS, - INTEGRATION_CLOUD_66, - INTEGRATION_CODEFRESH, - INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, - INTEGRATION_FLYIO, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_HASHICORP_VAULT, - INTEGRATION_HASURA_CLOUD, - INTEGRATION_HEROKU, - INTEGRATION_LARAVELFORGE, - INTEGRATION_NETLIFY, - INTEGRATION_NORTHFLANK, - INTEGRATION_RAILWAY, - INTEGRATION_RENDER, - INTEGRATION_SUPABASE, - INTEGRATION_TEAMCITY, - INTEGRATION_TERRAFORM_CLOUD, - INTEGRATION_TRAVISCI, - INTEGRATION_VERCEL, - INTEGRATION_WINDMILL -} from "../../variables"; -import { Document, Schema, Types, model } from "mongoose"; -import { IntegrationAuthMetadata } from "./types"; - -export interface IIntegrationAuth extends Document { - _id: Types.ObjectId; - workspace: Types.ObjectId; - integration: - | "heroku" - | "vercel" - | "netlify" - | "github" - | "gitlab" - | "render" - | "railway" - | "flyio" - | "azure-key-vault" - | "laravel-forge" - | "circleci" - | "travisci" - | "supabase" - | "aws-parameter-store" - | "aws-secret-manager" - | "checkly" - | "qovery" - | "cloudflare-pages" - | "cloudflare-workers" - | "codefresh" - | "digital-ocean-app-platform" - | "bitbucket" - | "cloud-66" - | "terraform-cloud" - | "teamcity" - | "northflank" - | "windmill" - | "gcp-secret-manager" - | "hasura-cloud"; - teamId: string; - accountId: string; - url: string; - namespace: string; - refreshCiphertext?: string; - refreshIV?: string; - refreshTag?: string; - accessIdCiphertext?: string; - accessIdIV?: string; - accessIdTag?: string; - accessCiphertext?: string; - accessIV?: string; - accessTag?: string; - algorithm?: "aes-256-gcm"; - keyEncoding?: "utf8" | "base64"; - accessExpiresAt?: Date; - metadata?: IntegrationAuthMetadata; -} - -const integrationAuthSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - integration: { - type: String, - enum: [ - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_HEROKU, - INTEGRATION_VERCEL, - INTEGRATION_NETLIFY, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_RENDER, - INTEGRATION_RAILWAY, - INTEGRATION_FLYIO, - INTEGRATION_CIRCLECI, - INTEGRATION_LARAVELFORGE, - INTEGRATION_TRAVISCI, - INTEGRATION_TEAMCITY, - INTEGRATION_SUPABASE, - INTEGRATION_TERRAFORM_CLOUD, - INTEGRATION_HASHICORP_VAULT, - INTEGRATION_CLOUDFLARE_PAGES, - INTEGRATION_CLOUDFLARE_WORKERS, - INTEGRATION_CODEFRESH, - INTEGRATION_WINDMILL, - INTEGRATION_BITBUCKET, - INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, - INTEGRATION_CLOUD_66, - INTEGRATION_NORTHFLANK, - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_HASURA_CLOUD - ], - required: true - }, - teamId: { - // vercel-specific integration param - type: String - }, - url: { - // for any self-hosted integrations (e.g. self-hosted hashicorp-vault) - type: String - }, - namespace: { - // hashicorp-vault-specific integration param - type: String - }, - accountId: { - // netlify-specific integration param - type: String - }, - refreshCiphertext: { - type: String, - select: false - }, - refreshIV: { - type: String, - select: false - }, - refreshTag: { - type: String, - select: false - }, - accessIdCiphertext: { - type: String, - select: false - }, - accessIdIV: { - type: String, - select: false - }, - accessIdTag: { - type: String, - select: false - }, - accessCiphertext: { - type: String, - select: false - }, - accessIV: { - type: String, - select: false - }, - accessTag: { - type: String, - select: false - }, - accessExpiresAt: { - type: Date, - select: false - }, - algorithm: { - // the encryption algorithm used - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true - }, - keyEncoding: { - type: String, - enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64], - required: true - }, - metadata: { - type: Schema.Types.Mixed - } - }, - { - timestamps: true - } -); - -export const IntegrationAuth = model("IntegrationAuth", integrationAuthSchema); diff --git a/backend-mongo/src/models/integrationAuth/types.ts b/backend-mongo/src/models/integrationAuth/types.ts deleted file mode 100644 index d29869e3b..000000000 --- a/backend-mongo/src/models/integrationAuth/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -interface GCPIntegrationAuthMetadata { - authMethod: "oauth2" | "serviceAccount" -} - -export type IntegrationAuthMetadata = GCPIntegrationAuthMetadata; \ No newline at end of file diff --git a/backend-mongo/src/models/key.ts b/backend-mongo/src/models/key.ts deleted file mode 100644 index fcc6e6f60..000000000 --- a/backend-mongo/src/models/key.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IKey { - _id: Types.ObjectId; - encryptedKey: string; - nonce: string; - sender: Types.ObjectId; - receiver: Types.ObjectId; - workspace: Types.ObjectId; -} - -const keySchema = new Schema( - { - encryptedKey: { - type: String, - required: true, - }, - nonce: { - type: String, - required: true, - }, - sender: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - receiver: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - }, - }, - { - timestamps: true, - } -); - -export const Key = model("Key", keySchema); \ No newline at end of file diff --git a/backend-mongo/src/models/loginSRPDetail.ts b/backend-mongo/src/models/loginSRPDetail.ts deleted file mode 100644 index 26f897270..000000000 --- a/backend-mongo/src/models/loginSRPDetail.ts +++ /dev/null @@ -1,27 +0,0 @@ -import mongoose, { Schema, Types, model } from "mongoose"; - -export interface ILoginSRPDetail { - _id: Types.ObjectId; - clientPublicKey: string; - email: string; - serverBInt: mongoose.Schema.Types.Buffer; - userId: string; - expireAt: Date; -} - -const loginSRPDetailSchema = new Schema( - { - clientPublicKey: { - type: String, - required: true, - }, - email: { - type: String, - unique: true, - }, - serverBInt: { type: mongoose.Schema.Types.Buffer }, - expireAt: { type: Date }, - } -); - -export const LoginSRPDetail = model("LoginSRPDetail", loginSRPDetailSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/membership.ts b/backend-mongo/src/models/membership.ts deleted file mode 100644 index c09fa2779..000000000 --- a/backend-mongo/src/models/membership.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables"; - -export interface IMembershipPermission { - environmentSlug: string; - ability: string; -} - -export interface IMembership { - _id: Types.ObjectId; - user: Types.ObjectId; - inviteEmail?: string; - workspace: Types.ObjectId; - role: "admin" | "member" | "viewer" | "no-access" | "custom"; - customRole: Types.ObjectId; - deniedPermissions: IMembershipPermission[]; -} - -const membershipSchema = new Schema( - { - user: { - type: Schema.Types.ObjectId, - ref: "User" - }, - inviteEmail: { - type: String - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - deniedPermissions: { - type: [ - { - environmentSlug: String, - ability: { - type: String, - enum: ["read", "write"] - } - } - ], - default: [] - }, - role: { - type: String, - enum: [ADMIN, MEMBER, VIEWER, NO_ACCESS, CUSTOM], - required: true - }, - customRole: { - type: Schema.Types.ObjectId, - ref: "Role" - } - }, - { - timestamps: true - } -); - -export const Membership = model("Membership", membershipSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/membershipOrg.ts b/backend-mongo/src/models/membershipOrg.ts deleted file mode 100644 index 0d4a2f6b7..000000000 --- a/backend-mongo/src/models/membershipOrg.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; -import { ACCEPTED, ADMIN, CUSTOM, INVITED, MEMBER, NO_ACCESS } from "../variables"; - -export interface IMembershipOrg extends Document { - _id: Types.ObjectId; - user: Types.ObjectId; - inviteEmail: string; - organization: Types.ObjectId; - role: "admin" | "member" | "no-access" | "custom"; - customRole: Types.ObjectId; - status: "invited" | "accepted"; -} - -const membershipOrgSchema = new Schema( - { - user: { - type: Schema.Types.ObjectId, - ref: "User" - }, - inviteEmail: { - type: String - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization" - }, - role: { - type: String, - enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM], - required: true - }, - status: { - type: String, - enum: [INVITED, ACCEPTED], - required: true - }, - customRole: { - type: Schema.Types.ObjectId, - ref: "Role" - } - }, - { - timestamps: true - } -); - -export const MembershipOrg = model("MembershipOrg", membershipOrgSchema); diff --git a/backend-mongo/src/models/organization.ts b/backend-mongo/src/models/organization.ts deleted file mode 100644 index 1ae3bcb45..000000000 --- a/backend-mongo/src/models/organization.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IOrganization { - _id: Types.ObjectId; - name: string; - customerId?: string; -} - -const organizationSchema = new Schema( - { - name: { - type: String, - required: true, - }, - customerId: { - type: String, - }, - }, - { - timestamps: true, - } -); - -export const Organization = model("Organization", organizationSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/secret.ts b/backend-mongo/src/models/secret.ts deleted file mode 100644 index 4c1400fa8..000000000 --- a/backend-mongo/src/models/secret.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { Schema, Types, model } from "mongoose"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, - SECRET_PERSONAL, - SECRET_SHARED -} from "../variables"; - -export interface ISecret { - _id: Types.ObjectId; - version: number; - workspace: Types.ObjectId; - type: string; - user?: Types.ObjectId; - environment: string; - secretBlindIndex?: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretKeyHash: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretValueHash: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - secretCommentHash?: string; - - // ? NOTE: This works great for workspace-level reminders. - // ? If we want to do it on a user-basis, we should ideally have a seperate model for reminders. - secretReminderRepeatDays?: number | null; - secretReminderNote?: string | null; - - skipMultilineEncoding?: boolean; - algorithm: "aes-256-gcm"; - keyEncoding: "utf8" | "base64"; - tags?: string[]; - folder?: string; - metadata?: { - [key: string]: string; - }; -} - -const secretSchema = new Schema( - { - version: { - type: Number, - required: true, - default: 1 - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - type: { - type: String, - enum: [SECRET_SHARED, SECRET_PERSONAL], - required: true - }, - user: { - // user associated with the personal secret - type: Schema.Types.ObjectId, - ref: "User" - }, - tags: { - ref: "Tag", - type: [Schema.Types.ObjectId], - default: [] - }, - environment: { - type: String, - required: true - }, - secretBlindIndex: { - type: String, - select: false - }, - secretKeyCiphertext: { - type: String, - required: true - }, - secretKeyIV: { - type: String, // symmetric - required: true - }, - secretKeyTag: { - type: String, // symmetric - required: true - }, - secretKeyHash: { - type: String - }, - secretValueCiphertext: { - type: String, - required: true - }, - secretValueIV: { - type: String, // symmetric - required: true - }, - secretValueTag: { - type: String, // symmetric - required: true - }, - secretValueHash: { - type: String - }, - secretCommentCiphertext: { - type: String, - required: false - }, - secretCommentIV: { - type: String, // symmetric - required: false - }, - secretCommentTag: { - type: String, // symmetric - required: false - }, - secretCommentHash: { - type: String, - required: false - }, - - secretReminderRepeatDays: { - type: Number, - required: false, - default: null - }, - secretReminderNote: { - type: String, - required: false, - default: null - }, - - skipMultilineEncoding: { - type: Boolean, - required: false - }, - - algorithm: { - // the encryption algorithm used - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true, - default: ALGORITHM_AES_256_GCM - }, - keyEncoding: { - type: String, - enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64], - required: true, - default: ENCODING_SCHEME_UTF8 - }, - folder: { - type: String, - default: "root" - }, - metadata: { - type: Schema.Types.Mixed - } - }, - { - timestamps: true - } -); - -secretSchema.index({ tags: 1 }, { background: true }); - -export const Secret = model("Secret", secretSchema); diff --git a/backend-mongo/src/models/secretBlindIndexData.ts b/backend-mongo/src/models/secretBlindIndexData.ts deleted file mode 100644 index da397d2c1..000000000 --- a/backend-mongo/src/models/secretBlindIndexData.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, -} from "../variables"; - -export interface ISecretBlindIndexData extends Document { - _id: Types.ObjectId; - workspace: Types.ObjectId; - encryptedSaltCiphertext: string; - saltIV: string; - saltTag: string; - algorithm: "aes-256-gcm"; - keyEncoding: "base64" | "utf8" -} - -const secretBlindIndexDataSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - }, - encryptedSaltCiphertext: { // TODO: make these select: false - type: String, - required: true, - }, - saltIV: { - type: String, - required: true, - }, - saltTag: { - type: String, - required: true, - }, - algorithm: { - type: String, - enum: [ALGORITHM_AES_256_GCM], - required: true, - select: false, - }, - keyEncoding: { - type: String, - enum: [ - ENCODING_SCHEME_UTF8, - ENCODING_SCHEME_BASE64, - ], - required: true, - select: false, - }, - - } -); - -secretBlindIndexDataSchema.index({ workspace: 1 }); - -export const SecretBlindIndexData = model("SecretBlindIndexData", secretBlindIndexDataSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/secretImports.ts b/backend-mongo/src/models/secretImports.ts deleted file mode 100644 index 79046a489..000000000 --- a/backend-mongo/src/models/secretImports.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface ISecretImports { - _id: Types.ObjectId; - workspace: Types.ObjectId; - environment: string; - folderId: string; - imports: Array<{ - environment: string; - secretPath: string; - }>; -} - -const secretImportSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - environment: { - type: String, - required: true - }, - folderId: { - type: String, - required: true, - default: "root" - }, - imports: { - type: [ - { - environment: { - type: String, - required: true - }, - secretPath: { - type: String, - required: true - } - } - ], - default: [] - } - }, - { - timestamps: true - } -); - -export const SecretImport = model("SecretImports", secretImportSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/serverConfig.ts b/backend-mongo/src/models/serverConfig.ts deleted file mode 100644 index 13e469bd5..000000000 --- a/backend-mongo/src/models/serverConfig.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IServerConfig { - _id: Types.ObjectId; - initialized: boolean; - allowSignUp: boolean; -} - -const serverConfigSchema = new Schema( - { - initialized: { - type: Boolean, - default: false - }, - allowSignUp: { - type: Boolean, - default: true - } - }, - { - timestamps: true - } -); - -export const ServerConfig = model("ServerConfig", serverConfigSchema); diff --git a/backend-mongo/src/models/serviceToken.ts b/backend-mongo/src/models/serviceToken.ts deleted file mode 100644 index 0e943b177..000000000 --- a/backend-mongo/src/models/serviceToken.ts +++ /dev/null @@ -1,60 +0,0 @@ -// TODO: deprecate -import { Schema, Types, model } from "mongoose"; -export interface IServiceToken { - _id: Types.ObjectId; - name: string; - user: Types.ObjectId; - workspace: Types.ObjectId; - environment: string; - expiresAt: Date; - publicKey: string; - encryptedKey: string; - nonce: string; -} - -const serviceTokenSchema = new Schema( - { - name: { - type: String, - required: true, - }, - user: { - // token issuer - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true, - }, - environment: { - type: String, - required: true, - }, - expiresAt: { - type: Date, - }, - publicKey: { - type: String, - required: true, - select: true, - }, - encryptedKey: { - type: String, - required: true, - select: true, - }, - nonce: { - type: String, - required: true, - select: true, - }, - }, - { - timestamps: true, - } -); - -export const ServiceToken = model("ServiceToken", serviceTokenSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/serviceTokenData.ts b/backend-mongo/src/models/serviceTokenData.ts deleted file mode 100644 index 735131703..000000000 --- a/backend-mongo/src/models/serviceTokenData.ts +++ /dev/null @@ -1,93 +0,0 @@ -// TODO: deprecate -import { Document, Schema, Types, model } from "mongoose"; - -export interface IServiceTokenData extends Document { - _id: Types.ObjectId; - name: string; - workspace: Types.ObjectId; - scopes: Array<{ - environment: string; - secretPath: string; - }>; - user: Types.ObjectId; - serviceAccount: Types.ObjectId; - lastUsed: Date; - expiresAt: Date; - secretHash: string; - encryptedKey: string; - iv: string; - tag: string; - permissions: string[]; -} - -const serviceTokenDataSchema = new Schema( - { - name: { - type: String, - required: true - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - scopes: { - type: [ - { - environment: { - type: String, - required: true - }, - secretPath: { - type: String, - default: "/", - required: true - } - } - ], - required: true - }, - user: { - type: Schema.Types.ObjectId, - ref: "User", - required: true - }, - serviceAccount: { - type: Schema.Types.ObjectId, - ref: "ServiceAccount" - }, - lastUsed: { - type: Date - }, - expiresAt: { - type: Date - }, - secretHash: { - type: String, - required: true, - select: false - }, - encryptedKey: { - type: String, - select: false - }, - iv: { - type: String, - select: false - }, - tag: { - type: String, - select: false - }, - permissions: { - type: [String], - enum: ["read", "write"], - default: ["read"] - } - }, - { - timestamps: true - } -); - -export const ServiceTokenData = model("ServiceTokenData", serviceTokenDataSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/tag.ts b/backend-mongo/src/models/tag.ts deleted file mode 100644 index a5f0bd307..000000000 --- a/backend-mongo/src/models/tag.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface ITag { - _id: Types.ObjectId; - name: string; - tagColor: string; - slug: string; - user: Types.ObjectId; - workspace: Types.ObjectId; -} - -const tagSchema = new Schema( - { - name: { - type: String, - required: true, - trim: true, - }, - tagColor: { - type: String, - required: false, - trim: true, - }, - slug: { - type: String, - required: true, - trim: true, - lowercase: true, - validate: [ - function (value: any) { - return value.indexOf(" ") === -1; - }, - "slug cannot contain spaces", - ], - }, - user: { - type: Schema.Types.ObjectId, - ref: "User", - }, - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - }, - }, - { - timestamps: true, - } -); - -tagSchema.index({ slug: 1, workspace: 1 }, { unique: true }) -tagSchema.index({ workspace: 1 }) - -export const Tag = model("Tag", tagSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/token.ts b/backend-mongo/src/models/token.ts deleted file mode 100644 index 62d342b0a..000000000 --- a/backend-mongo/src/models/token.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Schema, model } from "mongoose"; - -export interface IToken { - email: string; - token: string; - createdAt: Date; - ttl: number; -} - -const tokenSchema = new Schema({ - email: { - type: String, - required: true, - }, - token: { - type: String, - required: true, - }, - createdAt: { - type: Date, - default: Date.now, - }, - ttl: { - type: Number, - }, -}); - -tokenSchema.index({ email: 1 }); - -export const Token = model("Token", tokenSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/tokenData.ts b/backend-mongo/src/models/tokenData.ts deleted file mode 100644 index 2544c05f1..000000000 --- a/backend-mongo/src/models/tokenData.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface ITokenData { - type: string; - email?: string; - phoneNumber?: string; - organization?: Types.ObjectId; - tokenHash: string; - triesLeft?: number; - expiresAt: Date; - createdAt: Date; - updatedAt: Date; -} - -const tokenDataSchema = new Schema({ - type: { - type: String, - enum: [ - "emailConfirmation", - "emailMfa", - "organizationInvitation", - "passwordReset", - ], - required: true, - }, - email: { - type: String, - }, - phoneNumber: { - type: String, - }, - organization: { // organizationInvitation-specific field - type: Schema.Types.ObjectId, - ref: "Organization", - }, - tokenHash: { - type: String, - select: false, - required: true, - }, - triesLeft: { - type: Number, - }, - expiresAt: { - type: Date, - expires: 0, - required: true, - }, -}, { - timestamps: true, -}); - -export const TokenData = model("TokenData", tokenDataSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/tokenVersion.ts b/backend-mongo/src/models/tokenVersion.ts deleted file mode 100644 index b162e019e..000000000 --- a/backend-mongo/src/models/tokenVersion.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; - -export interface ITokenVersion extends Document { - user: Types.ObjectId; - ip: string; - userAgent: string; - refreshVersion: number; - accessVersion: number; - lastUsed: Date; -} - -const tokenVersionSchema = new Schema( - { - user: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - ip: { - type: String, - required: true, - }, - userAgent: { - type: String, - required: true, - }, - refreshVersion: { - type: Number, - required: true, - }, - accessVersion: { - type: Number, - required: true, - }, - lastUsed: { - type: Date, - required: true, - }, - }, - { - timestamps: true, - } -); - -export const TokenVersion = model("TokenVersion", tokenVersionSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/user.ts b/backend-mongo/src/models/user.ts deleted file mode 100644 index a3d73b8a2..000000000 --- a/backend-mongo/src/models/user.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; - -export enum AuthMethod { - EMAIL = "email", - GOOGLE = "google", - GITHUB = "github", - GITLAB = "gitlab", - OKTA_SAML = "okta-saml", - AZURE_SAML = "azure-saml", - JUMPCLOUD_SAML = "jumpcloud-saml" -} - -export interface IUser extends Document { - _id: Types.ObjectId; - authProvider?: AuthMethod; - authMethods: AuthMethod[]; - email: string; - superAdmin?: boolean; - firstName?: string; - lastName?: string; - encryptionVersion: number; - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - publicKey?: string; - encryptedPrivateKey?: string; - iv?: string; - tag?: string; - salt?: string; - verifier?: string; - isMfaEnabled: boolean; - mfaMethods: boolean; - devices: { - ip: string; - userAgent: string; - }[]; -} - -const userSchema = new Schema( - { - authProvider: { - // TODO field: deprecate - type: String, - enum: AuthMethod - }, - authMethods: { - type: [ - { - type: String, - enum: AuthMethod - } - ], - default: [AuthMethod.EMAIL], - required: true - }, - email: { - type: String, - required: true, - unique: true - }, - firstName: { - type: String - }, - lastName: { - type: String - }, - encryptionVersion: { - type: Number, - select: false, - default: 1 // to resolve backward-compatibility issues - }, - protectedKey: { - // introduced as part of encryption version 2 - type: String, - select: false - }, - protectedKeyIV: { - // introduced as part of encryption version 2 - type: String, - select: false - }, - protectedKeyTag: { - // introduced as part of encryption version 2 - type: String, - select: false - }, - publicKey: { - type: String, - select: false - }, - encryptedPrivateKey: { - type: String, - select: false - }, - superAdmin: { - type: Boolean - }, - iv: { - // iv of [encryptedPrivateKey] - type: String, - select: false - }, - tag: { - // tag of [encryptedPrivateKey] - type: String, - select: false - }, - salt: { - type: String, - select: false - }, - verifier: { - type: String, - select: false - }, - isMfaEnabled: { - type: Boolean, - default: false - }, - mfaMethods: [ - { - type: String - } - ], - devices: { - type: [ - { - ip: String, - userAgent: String - } - ], - default: [], - select: false - } - }, - { - timestamps: true - } -); - -export const User = model("User", userSchema); diff --git a/backend-mongo/src/models/userAction.ts b/backend-mongo/src/models/userAction.ts deleted file mode 100644 index 68fae22be..000000000 --- a/backend-mongo/src/models/userAction.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IUserAction { - _id: Types.ObjectId; - user: Types.ObjectId; - action: string; -} - -const userActionSchema = new Schema( - { - user: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - action: { - type: String, - required: true, - }, - }, - { - timestamps: true, - } -); - -export const UserAction = model("UserAction", userActionSchema); \ No newline at end of file diff --git a/backend-mongo/src/models/webhooks.ts b/backend-mongo/src/models/webhooks.ts deleted file mode 100644 index bef5e795a..000000000 --- a/backend-mongo/src/models/webhooks.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Document, Schema, Types, model } from "mongoose"; -import { ALGORITHM_AES_256_GCM, ENCODING_SCHEME_BASE64, ENCODING_SCHEME_UTF8 } from "../variables"; - -export interface IWebhook extends Document { - _id: Types.ObjectId; - workspace: Types.ObjectId; - environment: string; - secretPath: string; - url: string; - lastStatus: "success" | "failed"; - lastRunErrorMessage?: string; - isDisabled: boolean; - encryptedSecretKey: string; - iv: string; - tag: string; - algorithm: "aes-256-gcm"; - keyEncoding: "base64" | "utf8"; -} - -const WebhookSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: "Workspace", - required: true - }, - environment: { - type: String, - required: true - }, - secretPath: { - type: String, - required: true, - default: "/" - }, - url: { - type: String, - required: true - }, - lastStatus: { - type: String, - enum: ["success", "failed"] - }, - lastRunErrorMessage: { - type: String - }, - isDisabled: { - type: Boolean, - default: false - }, - // used for webhook signature - encryptedSecretKey: { - type: String, - select: false - }, - iv: { - type: String, - select: false - }, - tag: { - type: String, - select: false - }, - algorithm: { - // the encryption algorithm used - type: String, - enum: [ALGORITHM_AES_256_GCM], - select: false - }, - keyEncoding: { - type: String, - enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64], - select: false - } - }, - { - timestamps: true - } -); - -export const Webhook = model("Webhook", WebhookSchema); diff --git a/backend-mongo/src/models/workspace.ts b/backend-mongo/src/models/workspace.ts deleted file mode 100644 index 9d7a19fcc..000000000 --- a/backend-mongo/src/models/workspace.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Schema, Types, model } from "mongoose"; - -export interface IWorkspace { - _id: Types.ObjectId; - name: string; - organization: Types.ObjectId; - environments: Array<{ - name: string; - slug: string; - }>; - autoCapitalization: boolean; -} - -const workspaceSchema = new Schema({ - name: { - type: String, - required: true, - }, - autoCapitalization: { - type: Boolean, - default: true, - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization", - required: true, - }, - environments: { - type: [ - { - name: String, - slug: String, - }, - ], - default: [ - { - name: "Development", - slug: "dev", - }, - { - name: "Staging", - slug: "staging", - }, - { - name: "Production", - slug: "prod", - }, - ], - }, -}); - -export const Workspace = model("Workspace", workspaceSchema); \ No newline at end of file diff --git a/backend-mongo/src/queues/integrations/syncSecretsToThirdPartyServices.ts b/backend-mongo/src/queues/integrations/syncSecretsToThirdPartyServices.ts deleted file mode 100644 index 490b31c10..000000000 --- a/backend-mongo/src/queues/integrations/syncSecretsToThirdPartyServices.ts +++ /dev/null @@ -1,86 +0,0 @@ -import Queue, { Job } from "bull"; -import { Integration, IntegrationAuth } from "../../models"; -import { BotService } from "../../services"; -import { getIntegrationAuthAccessHelper } from "../../helpers"; -import { syncSecrets } from "../../integrations/sync" - - -type TSyncSecretsToThirdPartyServices = { - workspaceId: string - environment?: string -} - -export const syncSecretsToThirdPartyServices = new Queue("sync-secrets-to-third-party-services", process.env.REDIS_URL as string); - -syncSecretsToThirdPartyServices.process(async (job: Job) => { - const { workspaceId, environment }: TSyncSecretsToThirdPartyServices = job.data - const integrations = await Integration.find({ - workspace: workspaceId, - ...(environment - ? { - environment - } - : {}), - isActive: true, - }); - - // for each workspace integration, sync/push secrets - // to that integration - for (const integration of integrations) { - // get workspace, environment (shared) secrets - const secrets = await BotService.getSecrets({ - workspaceId: integration.workspace, - environment: integration.environment, - secretPath: integration.secretPath - }); - - const suffixedSecrets: any = {}; - if (integration.metadata) { - for (const key in secrets) { - const prefix = (integration.metadata?.secretPrefix || ""); - const suffix = (integration.metadata?.secretSuffix || ""); - const newKey = prefix + key + suffix; - - suffixedSecrets[newKey] = secrets[key]; - } - } - - const integrationAuth = await IntegrationAuth.findById(integration.integrationAuth); - - if (!integrationAuth) throw new Error("Failed to find integration auth"); - - // get integration auth access token - const access = await getIntegrationAuthAccessHelper({ - integrationAuthId: integration.integrationAuth - }); - - // sync secrets to integration - await syncSecrets({ - integration, - integrationAuth, - secrets: Object.keys(suffixedSecrets).length !== 0 ? suffixedSecrets : secrets, - accessId: access.accessId === undefined ? null : access.accessId, - accessToken: access.accessToken, - appendices: { prefix: integration.metadata?.secretPrefix || "", suffix: integration.metadata?.secretSuffix || "" } - }); - } -}) - -syncSecretsToThirdPartyServices.on("error", (error) => { - // console.log("QUEUE ERROR:", error) // eslint-disable-line -}) - -export const syncSecretsToActiveIntegrationsQueue = (jobDetails: TSyncSecretsToThirdPartyServices) => { - syncSecretsToThirdPartyServices.add(jobDetails, { - attempts: 5, - backoff: { - type: "exponential", - delay: 3000 - }, - removeOnComplete: true, - removeOnFail: { - count: 20 // keep the most recent 20 jobs - } - }) -} - diff --git a/backend-mongo/src/queues/reminders/sendSecretReminders.ts b/backend-mongo/src/queues/reminders/sendSecretReminders.ts deleted file mode 100644 index 0cf4a79a4..000000000 --- a/backend-mongo/src/queues/reminders/sendSecretReminders.ts +++ /dev/null @@ -1,83 +0,0 @@ -import Queue, { Job } from "bull"; -import { IUser, Membership, Organization, Workspace } from "../../models"; -import { Types } from "mongoose"; -import { sendMail } from "../../helpers"; - -type TSendSecretReminders = { - workspaceId: string; - secretId: string; - repeatDays: number; - note: string | undefined | null; -}; - -type TDeleteSecretReminder = { - secretId: string; - repeatDays: number; -}; - -const DAY_IN_MS = 86400000; - -export const sendSecretReminders = new Queue( - "send-secret-reminders", - process.env.REDIS_URL as string -); - -sendSecretReminders.process(async (job: Job) => { - const { workspaceId }: TSendSecretReminders = job.data; - - const workspace = await Workspace.findById(new Types.ObjectId(workspaceId)); - const organization = await Organization.findById(new Types.ObjectId(workspace?.organization)); - - if (!workspace) { - throw new Error("Workspace for reminder not found"); - } - if (!organization) { - throw new Error("Organization for reminder not found"); - } - - const memberships = await Membership.find({ - workspace: workspaceId - }).populate<{ user: IUser }>("user"); - - await sendMail({ - template: "secretReminder.handlebars", - subjectLine: "Infisical secret reminder", - recipients: [...memberships.map((membership) => membership.user.email)], - substitutions: { - reminderNote: job.data.note, // May not be present. - workspaceName: workspace.name, - organizationName: organization.name - } - }); -}); - -export const createRecurringSecretReminder = (jobDetails: TSendSecretReminders) => { - const repeat = jobDetails.repeatDays * DAY_IN_MS; - - return sendSecretReminders.add(jobDetails, { - delay: repeat, - repeat: { - every: repeat - }, - jobId: `reminder-${jobDetails.secretId}`, - removeOnComplete: true, - removeOnFail: { - count: 20 - } - }); -}; - -export const deleteRecurringSecretReminder = (jobDetails: TDeleteSecretReminder) => { - const repeat = jobDetails.repeatDays * DAY_IN_MS; - - return sendSecretReminders.removeRepeatable({ - every: repeat, - jobId: `reminder-${jobDetails.secretId}` - }); -}; - -export const updateRecurringSecretReminder = async (jobDetails: TSendSecretReminders) => { - // We need to delete the potentially existing reminder job first, or the new one won't be created. - await deleteRecurringSecretReminder(jobDetails); - await createRecurringSecretReminder(jobDetails); -}; diff --git a/backend-mongo/src/queues/secret-scanning/githubScanFullRepository.ts b/backend-mongo/src/queues/secret-scanning/githubScanFullRepository.ts deleted file mode 100644 index ece43bd97..000000000 --- a/backend-mongo/src/queues/secret-scanning/githubScanFullRepository.ts +++ /dev/null @@ -1,101 +0,0 @@ -import Queue, { Job } from "bull"; -import { ProbotOctokit } from "probot" -import TelemetryService from "../../services/TelemetryService"; -import { sendMail } from "../../helpers"; -import { GitRisks } from "../../ee/models"; -import { MembershipOrg, User } from "../../models"; -import { ADMIN } from "../../variables"; -import { convertKeysToLowercase, scanFullRepoContentAndGetFindings } from "../../ee/services/GithubSecretScanning/helper"; -import { getSecretScanningGitAppId, getSecretScanningPrivateKey } from "../../config"; -import { SecretMatch } from "../../ee/services/GithubSecretScanning/types"; - -export const githubFullRepositorySecretScan = new Queue("github-full-repository-secret-scanning", "redis://redis:6379"); - -type TScanPushEventQueueDetails = { - organizationId: string, - installationId: string, - repository: { - id: number, - fullName: string, - }, -} - -githubFullRepositorySecretScan.process(async (job: Job, done: Queue.DoneCallback) => { - const { organizationId, repository, installationId }: TScanPushEventQueueDetails = job.data - try { - const octokit = new ProbotOctokit({ - auth: { - appId: await getSecretScanningGitAppId(), - privateKey: await getSecretScanningPrivateKey(), - installationId: installationId - }, - }); - - const findings: SecretMatch[] = await scanFullRepoContentAndGetFindings(octokit, installationId as any, repository.fullName) - for (const finding of findings) { - await GitRisks.findOneAndUpdate({ fingerprint: finding.Fingerprint }, - { - ...convertKeysToLowercase(finding), - installationId: installationId, - organization: organizationId, - repositoryFullName: repository.fullName, - repositoryId: repository.id - }, { - upsert: true - }).lean() - } - - // get emails of admins - const adminsOfWork = await MembershipOrg.find({ - organization: organizationId, - role: ADMIN, - }).lean() - - const userEmails = await User.find({ - _id: { - $in: [adminsOfWork.map(orgMembership => orgMembership.user)] - } - }).select("email").lean() - - const usersToNotify = userEmails.map(userObject => userObject.email) - - if (findings.length) { - await sendMail({ - template: "historicalSecretLeakIncident.handlebars", - subjectLine: `Incident alert: leaked secrets found in Github repository ${repository.fullName}`, - recipients: usersToNotify, - substitutions: { - numberOfSecrets: findings.length, - } - }); - } - - const postHogClient = await TelemetryService.getPostHogClient(); - if (postHogClient) { - postHogClient.capture({ - event: "historical cloud secret scan", - distinctId: repository.fullName, - properties: { - numberOfRisksFound: findings.length, - } - }); - } - done(null, findings) - } catch (error) { - done(new Error(`gitHubHistoricalScanning.process: an error occurred ${error}`), null) - } -}) - -export const scanGithubFullRepoForSecretLeaks = (pushEventPayload: TScanPushEventQueueDetails) => { - githubFullRepositorySecretScan.add(pushEventPayload, { - attempts: 3, - backoff: { - type: "exponential", - delay: 5000 - }, - removeOnComplete: true, - removeOnFail: { - count: 20 // keep the most recent 20 jobs - } - }) -} \ No newline at end of file diff --git a/backend-mongo/src/queues/secret-scanning/githubScanPushEvent.ts b/backend-mongo/src/queues/secret-scanning/githubScanPushEvent.ts deleted file mode 100644 index af2d88f1f..000000000 --- a/backend-mongo/src/queues/secret-scanning/githubScanPushEvent.ts +++ /dev/null @@ -1,145 +0,0 @@ -import Queue, { Job } from "bull"; -import { ProbotOctokit } from "probot" -import { Commit } from "@octokit/webhooks-types"; -import TelemetryService from "../../services/TelemetryService"; -import { sendMail } from "../../helpers"; -import { GitRisks } from "../../ee/models"; -import { MembershipOrg, User } from "../../models"; -import { ADMIN } from "../../variables"; -import { convertKeysToLowercase, scanContentAndGetFindings } from "../../ee/services/GithubSecretScanning/helper"; -import { getSecretScanningGitAppId, getSecretScanningPrivateKey } from "../../config"; -import { SecretMatch } from "../../ee/services/GithubSecretScanning/types"; - -export const githubPushEventSecretScan = new Queue("github-push-event-secret-scanning", "redis://redis:6379"); - -type TScanPushEventQueueDetails = { - organizationId: string, - commits: Commit[] - pusher: { - name: string, - email: string | null - }, - repository: { - id: number, - fullName: string, - }, - installationId: number -} - -githubPushEventSecretScan.process(async (job: Job, done: Queue.DoneCallback) => { - const { organizationId, commits, pusher, repository, installationId }: TScanPushEventQueueDetails = job.data - const [owner, repo] = repository.fullName.split("/"); - const octokit = new ProbotOctokit({ - auth: { - appId: await getSecretScanningGitAppId(), - privateKey: await getSecretScanningPrivateKey(), - installationId: installationId - }, - }); - - const allFindingsByFingerprint: { [key: string]: SecretMatch; } = {} - - for (const commit of commits) { - for (const filepath of [...commit.added, ...commit.modified]) { - try { - const fileContentsResponse = await octokit.repos.getContent({ - owner, - repo, - path: filepath, - }); - - const data: any = fileContentsResponse.data; - const fileContent = Buffer.from(data.content, "base64").toString(); - - const findings = await scanContentAndGetFindings(`\n${fileContent}`) // extra line to count lines correctly - - for (const finding of findings) { - const fingerPrintWithCommitId = `${commit.id}:${filepath}:${finding.RuleID}:${finding.StartLine}` - const fingerPrintWithoutCommitId = `${filepath}:${finding.RuleID}:${finding.StartLine}` - finding.Fingerprint = fingerPrintWithCommitId - finding.FingerPrintWithoutCommitId = fingerPrintWithoutCommitId - finding.Commit = commit.id - finding.File = filepath - finding.Author = commit.author.name - finding.Email = commit?.author?.email ? commit?.author?.email : "" - - allFindingsByFingerprint[fingerPrintWithCommitId] = finding - } - - } catch (error) { - done(new Error(`gitHubHistoricalScanning.process: unable to fetch content for [filepath=${filepath}] because [error=${error}]`), null) - } - } - } - - // change to update - for (const key in allFindingsByFingerprint) { - await GitRisks.findOneAndUpdate({ fingerprint: allFindingsByFingerprint[key].Fingerprint }, - { - ...convertKeysToLowercase(allFindingsByFingerprint[key]), - installationId: installationId, - organization: organizationId, - repositoryFullName: repository.fullName, - repositoryId: repository.id - }, { - upsert: true - }).lean() - } - // get emails of admins - const adminsOfWork = await MembershipOrg.find({ - organization: organizationId, - role: ADMIN - }).lean() - - const userEmails = await User.find({ - _id: { - $in: [adminsOfWork.map(orgMembership => orgMembership.user)] - } - }).select("email").lean() - - const adminOrOwnerEmails = userEmails.map(userObject => userObject.email) - - const usersToNotify = pusher?.email ? [pusher.email, ...adminOrOwnerEmails] : [...adminOrOwnerEmails] - if (Object.keys(allFindingsByFingerprint).length) { - await sendMail({ - template: "secretLeakIncident.handlebars", - subjectLine: `Incident alert: leaked secrets found in Github repository ${repository.fullName}`, - recipients: usersToNotify, - substitutions: { - numberOfSecrets: Object.keys(allFindingsByFingerprint).length, - pusher_email: pusher.email, - pusher_name: pusher.name - } - }); - } - - const postHogClient = await TelemetryService.getPostHogClient(); - if (postHogClient) { - postHogClient.capture({ - event: "cloud secret scan", - distinctId: pusher.email, - properties: { - numberOfCommitsScanned: commits.length, - numberOfRisksFound: Object.keys(allFindingsByFingerprint).length, - } - }); - } - - done(null, allFindingsByFingerprint) - -}) - -export const scanGithubPushEventForSecretLeaks = (pushEventPayload: TScanPushEventQueueDetails) => { - githubPushEventSecretScan.add(pushEventPayload, { - attempts: 3, - backoff: { - type: "exponential", - delay: 5000 - }, - removeOnComplete: true, - removeOnFail: { - count: 20 // keep the most recent 20 jobs - } - }) -} - diff --git a/backend-mongo/src/routes/status/index.ts b/backend-mongo/src/routes/status/index.ts deleted file mode 100644 index 6f3be6271..000000000 --- a/backend-mongo/src/routes/status/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import healthCheck from "./status"; - -export { - healthCheck, -} \ No newline at end of file diff --git a/backend-mongo/src/routes/status/status.ts b/backend-mongo/src/routes/status/status.ts deleted file mode 100644 index fc35f7edb..000000000 --- a/backend-mongo/src/routes/status/status.ts +++ /dev/null @@ -1,28 +0,0 @@ -import express, { Request, Response } from "express"; -import { getInviteOnlySignup, getRedisUrl, getSecretScanningGitAppId, getSecretScanningPrivateKey, getSecretScanningWebhookSecret, getSmtpConfigured } from "../../config"; - -const router = express.Router(); - -router.get( - "/status", - async (req: Request, res: Response) => { - const gitAppId = await getSecretScanningGitAppId() - const gitSecretScanningWebhookSecret = await getSecretScanningWebhookSecret() - const gitSecretScanningPrivateKey = await getSecretScanningPrivateKey() - let secretScanningConfigured = false - if (gitAppId && gitSecretScanningPrivateKey && gitSecretScanningWebhookSecret) { - secretScanningConfigured = true - } - - res.status(200).json({ - date: new Date(), - message: "Ok", - emailConfigured: await getSmtpConfigured(), - inviteOnlySignup: await getInviteOnlySignup(), - redisConfigured: await getRedisUrl() !== "" && await getRedisUrl() !== undefined, - secretScanningConfigured: secretScanningConfigured, - }) - } -); - -export default router \ No newline at end of file diff --git a/backend-mongo/src/routes/v1/admin.ts b/backend-mongo/src/routes/v1/admin.ts deleted file mode 100644 index 5e7989ce0..000000000 --- a/backend-mongo/src/routes/v1/admin.ts +++ /dev/null @@ -1,20 +0,0 @@ -import express from "express"; -import { adminController } from "../../controllers/v1"; -const router = express.Router(); -import { requireAuth, requireSuperAdminAccess } from "../../middleware"; -import { AuthMode } from "../../variables"; - -router.get("/config", adminController.getServerConfigInfo); - -router.post("/signup", adminController.adminSignUp); - -router.patch( - "/config", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - requireSuperAdminAccess, - adminController.updateServerConfig -); - -export default router; diff --git a/backend-mongo/src/routes/v1/auth.ts b/backend-mongo/src/routes/v1/auth.ts deleted file mode 100644 index a3037f311..000000000 --- a/backend-mongo/src/routes/v1/auth.ts +++ /dev/null @@ -1,51 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth, validateRequest } from "../../middleware"; -import { authController } from "../../controllers/v1"; -import { authLimiter } from "../../helpers/rateLimiter"; -import { AuthMode } from "../../variables"; - -router.post("/token", validateRequest, authController.getNewToken); - -router.post( - // TODO endpoint: deprecate (moved to api/v3/auth/login1) - "/login1", - authLimiter, - authController.login1 -); - -router.post( - // TODO endpoint: deprecate (moved to api/v3/auth/login2) - "/login2", - authLimiter, - authController.login2 -); - -router.post( - "/logout", - authLimiter, - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - authController.logout -); - -router.post( - "/checkAuth", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - authController.checkAuth -); - -router.delete( - // TODO endpoint: deprecate (moved to DELETE v2/users/me/sessions) - "/sessions", - authLimiter, - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - authController.revokeAllSessions -); - -export default router; diff --git a/backend-mongo/src/routes/v1/bot.ts b/backend-mongo/src/routes/v1/bot.ts deleted file mode 100644 index 5e76288cd..000000000 --- a/backend-mongo/src/routes/v1/bot.ts +++ /dev/null @@ -1,25 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { - requireAuth -} from "../../middleware"; -import { botController } from "../../controllers/v1"; -import { AuthMode } from "../../variables"; - -router.get( - "/:workspaceId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - botController.getBotByWorkspaceId -); - -router.patch( - "/:botId/active", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - botController.setBotActiveState -); - -export default router; diff --git a/backend-mongo/src/routes/v1/index.ts b/backend-mongo/src/routes/v1/index.ts deleted file mode 100644 index 8bc4642af..000000000 --- a/backend-mongo/src/routes/v1/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -import signup from "./signup"; -import bot from "./bot"; -import auth from "./auth"; -import universalAuth from "./universalAuth"; -import user from "./user"; -import userAction from "./userAction"; -import organization from "./organization"; -import workspace from "./workspace"; -import membershipOrg from "./membershipOrg"; -import membership from "./membership"; -import key from "./key"; -import inviteOrg from "./inviteOrg"; -import secret from "./secret"; -import serviceToken from "./serviceToken"; -import sso from "./sso"; -import password from "./password"; -import integration from "./integration"; -import integrationAuth from "./integrationAuth"; -import secretsFolder from "./secretsFolder"; -import webhooks from "./webhook"; -import secretImps from "./secretImps"; -import admin from "./admin"; - -export { - signup, - auth, - universalAuth, - bot, - user, - userAction, - organization, - workspace, - membershipOrg, - membership, - key, - inviteOrg, - secret, - serviceToken, - password, - integration, - integrationAuth, - secretsFolder, - webhooks, - secretImps, - sso, - admin -}; diff --git a/backend-mongo/src/routes/v1/integration.ts b/backend-mongo/src/routes/v1/integration.ts deleted file mode 100644 index 6dda7527b..000000000 --- a/backend-mongo/src/routes/v1/integration.ts +++ /dev/null @@ -1,39 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; -import { integrationController } from "../../controllers/v1"; - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - integrationController.createIntegration -); - -router.patch( - "/:integrationId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationController.updateIntegration -); - -router.delete( - "/:integrationId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationController.deleteIntegration -); - -router.post( - "/manual-sync", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationController.manualSync -); - -export default router; \ No newline at end of file diff --git a/backend-mongo/src/routes/v1/integrationAuth.ts b/backend-mongo/src/routes/v1/integrationAuth.ts deleted file mode 100644 index 9e4236dbc..000000000 --- a/backend-mongo/src/routes/v1/integrationAuth.ts +++ /dev/null @@ -1,175 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; -import { integrationAuthController } from "../../controllers/v1"; - -router.get( - "/integration-options", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationOptions -); - -router.get( - "/:integrationAuthId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuth -); - -router.post( - "/oauth-token", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.oAuthExchange -); - -router.post( - "/access-token", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - integrationAuthController.saveIntegrationToken -); - -router.get( - "/:integrationAuthId/apps", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthApps -); - -router.get( - "/:integrationAuthId/teams", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthTeams -); - -router.get( - "/:integrationAuthId/vercel/branches", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthVercelBranches -); - -router.get( - "/:integrationAuthId/checkly/groups", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthChecklyGroups -); - -router.get( - "/:integrationAuthId/qovery/orgs", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthQoveryOrgs -); - -router.get( - "/:integrationAuthId/qovery/projects", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthQoveryProjects -); - -router.get( - "/:integrationAuthId/qovery/environments", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthQoveryEnvironments -); - -router.get( - "/:integrationAuthId/qovery/apps", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthQoveryApps -); - -router.get( - "/:integrationAuthId/qovery/containers", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthQoveryContainers -); - -router.get( - "/:integrationAuthId/qovery/jobs", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthQoveryJobs -); - -router.get( - "/:integrationAuthId/railway/environments", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthRailwayEnvironments -); - -router.get( - "/:integrationAuthId/railway/services", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthRailwayServices -); - -router.get( - "/:integrationAuthId/bitbucket/workspaces", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthBitBucketWorkspaces -); - -router.get( - "/:integrationAuthId/northflank/secret-groups", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthNorthflankSecretGroups -); - -router.get( - "/:integrationAuthId/teamcity/build-configs", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.getIntegrationAuthTeamCityBuildConfigs -); - -router.delete( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.deleteIntegrationAuths -); - -router.delete( - "/:integrationAuthId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - integrationAuthController.deleteIntegrationAuthById -); - -export default router; diff --git a/backend-mongo/src/routes/v1/inviteOrg.ts b/backend-mongo/src/routes/v1/inviteOrg.ts deleted file mode 100644 index 0fa4ffbfe..000000000 --- a/backend-mongo/src/routes/v1/inviteOrg.ts +++ /dev/null @@ -1,27 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { body } from "express-validator"; -import { requireAuth, validateRequest } from "../../middleware"; -import { membershipOrgController } from "../../controllers/v1"; -import { AuthMode } from "../../variables"; - -// TODO endpoint: consider moving these endpoints to be under /organization to be more RESTful - -router.post( - "/signup", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - membershipOrgController.inviteUserToOrganization -); - -router.post( - "/verify", - body("email").exists().trim().notEmpty(), - body("organizationId").exists().trim().notEmpty(), - body("code").exists().trim().notEmpty(), - validateRequest, - membershipOrgController.verifyUserToOrganization -); - -export default router; diff --git a/backend-mongo/src/routes/v1/key.ts b/backend-mongo/src/routes/v1/key.ts deleted file mode 100644 index be2c8d929..000000000 --- a/backend-mongo/src/routes/v1/key.ts +++ /dev/null @@ -1,26 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; -import { keyController } from "../../controllers/v1"; - -// TODO endpoint: consider moving these endpoints to be under /workspaces to be more RESTful - -router.post( - "/:workspaceId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - keyController.uploadKey -); - -router.get( - // TODO endpoint: deprecate (note: move frontend to v2/workspace/key or something) - "/:workspaceId/latest", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - keyController.getLatestKey -); - -export default router; diff --git a/backend-mongo/src/routes/v1/membership.ts b/backend-mongo/src/routes/v1/membership.ts deleted file mode 100644 index 54b3b7c9e..000000000 --- a/backend-mongo/src/routes/v1/membership.ts +++ /dev/null @@ -1,37 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { membershipController } from "../../controllers/v1"; -import { AuthMode } from "../../variables"; - -// note: ALL DEPRECIATED (moved to api/v2/workspace/:workspaceId/memberships/:membershipId) -// TODO endpoint: consider moving these endpoints to be under /workspace to be more RESTful - -router.get( - // TODO endpoint: deprecate - used for old CLI (deprecate) - "/:workspaceId/connect", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - membershipController.validateMembership -); - -router.delete( - // TODO endpoint: check dashboard - "/:membershipId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - membershipController.deleteMembership -); - -router.post( - // TODO endpoint: check dashboard - "/:membershipId/change-role", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - membershipController.changeMembershipRole -); - -export default router; diff --git a/backend-mongo/src/routes/v1/membershipOrg.ts b/backend-mongo/src/routes/v1/membershipOrg.ts deleted file mode 100644 index d841f0c4b..000000000 --- a/backend-mongo/src/routes/v1/membershipOrg.ts +++ /dev/null @@ -1,29 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { param } from "express-validator"; -import { requireAuth, validateRequest } from "../../middleware"; -import { membershipOrgController } from "../../controllers/v1"; -import { AuthMode } from "../../variables"; - -// depreciated completely -// ignored for new codebase -router.post( - // TODO endpoint: check dashboard - "/membershipOrg/:membershipOrgId/change-role", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - param("membershipOrgId"), - validateRequest, - membershipOrgController.changeMembershipOrgRole -); - -router.delete( - "/:membershipOrgId", // TODO endpoint: check dashboard - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - membershipOrgController.deleteMembershipOrg -); - -export default router; diff --git a/backend-mongo/src/routes/v1/organization.ts b/backend-mongo/src/routes/v1/organization.ts deleted file mode 100644 index 3dfe2689b..000000000 --- a/backend-mongo/src/routes/v1/organization.ts +++ /dev/null @@ -1,90 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; -import { organizationController } from "../../controllers/v1"; - -router.get( - // TODO endpoint: deprecate (moved to api/v2/users/me/organizations) - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.getOrganizations -); - -router.get( - "/:organizationId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.getOrganization -); - -router.get( - // TODO endpoint: deprecate (moved to api/v2/organizations/:organizationId/memberships) - "/:organizationId/users", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.getOrganizationMembers -); - -router.get( - // TODO endpoint: move to /v2/users/me/organizations/:organizationId/workspaces - "/:organizationId/my-workspaces", // deprecated (moved to api/v2/organizations/:organizationId/workspaces) - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.getOrganizationWorkspaces -); - -router.patch( - "/:organizationId/name", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.changeOrganizationName -); - -router.get( - "/:organizationId/incidentContactOrg", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.getOrganizationIncidentContacts -); - -router.post( - "/:organizationId/incidentContactOrg", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.addOrganizationIncidentContact -); - -router.delete( - "/:organizationId/incidentContactOrg", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.deleteOrganizationIncidentContact -); - -router.post( - "/:organizationId/customer-portal-session", // TODO endpoint: move to EE - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.createOrganizationPortalSession -); - -router.get( - "/:organizationId/workspace-memberships", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationController.getOrganizationMembersAndTheirWorkspaces -); - -export default router; diff --git a/backend-mongo/src/routes/v1/password.ts b/backend-mongo/src/routes/v1/password.ts deleted file mode 100644 index aec995cee..000000000 --- a/backend-mongo/src/routes/v1/password.ts +++ /dev/null @@ -1,51 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth, requireSignupAuth } from "../../middleware"; -import { passwordController } from "../../controllers/v1"; -import { passwordLimiter } from "../../helpers/rateLimiter"; -import { AuthMode } from "../../variables"; - -router.post( - "/srp1", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - passwordController.srp1 -); - -router.post( - "/change-password", - passwordLimiter, - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - passwordController.changePassword -); - -router.post("/email/password-reset", passwordLimiter, passwordController.emailPasswordReset); - -router.post( - "/email/password-reset-verify", - passwordLimiter, - passwordController.emailPasswordResetVerify -); - -router.get( - "/backup-private-key", - passwordLimiter, - requireSignupAuth, - passwordController.getBackupPrivateKey -); - -router.post( - "/backup-private-key", - passwordLimiter, - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - passwordController.createBackupPrivateKey -); - -router.post("/password-reset", requireSignupAuth, passwordController.resetPassword); - -export default router; diff --git a/backend-mongo/src/routes/v1/secret.ts b/backend-mongo/src/routes/v1/secret.ts deleted file mode 100644 index e2b63e9ef..000000000 --- a/backend-mongo/src/routes/v1/secret.ts +++ /dev/null @@ -1,63 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { - requireAuth, - requireServiceTokenAuth, - requireWorkspaceAuth, - validateRequest, -} from "../../middleware"; -import { body, param, query } from "express-validator"; -import { secretController } from "../../controllers/v1"; -import { - ADMIN, - AuthMode, - MEMBER -} from "../../variables"; - -// note: endpoints deprecated in favor of v3/secrets - -router.post( // TODO endpoint: deprecate (moved to POST api/v3/secrets) - "/:workspaceId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params", - }), - body("secrets").exists(), - body("keys").exists(), - body("environment").exists().trim().notEmpty(), - body("channel"), - param("workspaceId").exists().trim(), - validateRequest, - secretController.pushSecrets -); - -router.get( // TODO endpoint: deprecate (moved to GET api/v3/secrets) - "/:workspaceId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params", - }), - query("environment").exists().trim(), - query("channel"), - param("workspaceId").exists().trim(), - validateRequest, - secretController.pullSecrets -); - -router.get( // TODO endpoint: deprecate (moved to GET api/v3/secrets) - "/:workspaceId/service-token", - requireServiceTokenAuth, - query("environment").exists().trim(), - query("channel"), - param("workspaceId").exists().trim(), - validateRequest, - secretController.pullSecretsServiceToken -); - -export default router; diff --git a/backend-mongo/src/routes/v1/secretImps.ts b/backend-mongo/src/routes/v1/secretImps.ts deleted file mode 100644 index 478714e54..000000000 --- a/backend-mongo/src/routes/v1/secretImps.ts +++ /dev/null @@ -1,47 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { secretImpsController } from "../../controllers/v1"; -import { AuthMode } from "../../variables"; - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - secretImpsController.createSecretImp -); - -router.put( - "/:id", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - secretImpsController.updateSecretImport -); - -router.delete( - "/:id", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - secretImpsController.deleteSecretImport -); - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - secretImpsController.getSecretImports -); - -router.get( - "/secrets", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY] - }), - secretImpsController.getAllSecretsFromImport -); - -export default router; diff --git a/backend-mongo/src/routes/v1/secretsFolder.ts b/backend-mongo/src/routes/v1/secretsFolder.ts deleted file mode 100644 index e7bfc8987..000000000 --- a/backend-mongo/src/routes/v1/secretsFolder.ts +++ /dev/null @@ -1,44 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { - createFolder, - deleteFolder, - getFolders, - updateFolderById -} from "../../controllers/v1/secretsFolderController"; -import { AuthMode } from "../../variables"; - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - createFolder -); - -router.patch( - "/:folderName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - updateFolderById -); - -router.delete( - "/:folderName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - deleteFolder -); - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - getFolders -); - -export default router; diff --git a/backend-mongo/src/routes/v1/serviceToken.ts b/backend-mongo/src/routes/v1/serviceToken.ts deleted file mode 100644 index e79d24ffa..000000000 --- a/backend-mongo/src/routes/v1/serviceToken.ts +++ /dev/null @@ -1,45 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { - requireAuth, - requireServiceTokenAuth, - requireWorkspaceAuth, - validateRequest, -} from "../../middleware"; -import { body } from "express-validator"; -import { - ADMIN, - AuthMode, - MEMBER -} from "../../variables"; -import { serviceTokenController } from "../../controllers/v1"; - -// note: deprecate service-token routes in favor of service-token data routes/structure - -router.get( // TODO endpoint: deprecate - "/", - requireServiceTokenAuth, - serviceTokenController.getServiceToken -); - -router.post( // TODO endpoint: deprecate - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "body", - }), - body("name").exists().trim().notEmpty(), - body("workspaceId").exists().trim().notEmpty(), - body("environment").exists().trim().notEmpty(), - body("expiresIn"), // measured in ms - body("publicKey").exists().trim().notEmpty(), - body("encryptedKey").exists().trim().notEmpty(), - body("nonce").exists().trim().notEmpty(), - validateRequest, - serviceTokenController.createServiceToken -); - -export default router; diff --git a/backend-mongo/src/routes/v1/signup.ts b/backend-mongo/src/routes/v1/signup.ts deleted file mode 100644 index e7b92f643..000000000 --- a/backend-mongo/src/routes/v1/signup.ts +++ /dev/null @@ -1,24 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { signupController } from "../../controllers/v1"; -import { authLimiter } from "../../helpers/rateLimiter"; -import { disableSignUpByServerCfg } from "../../middleware"; - -// TODO: consider moving to users/v3/signup - -router.post( - // TODO endpoint: consider moving to v3/users/signup/mail - "/email/signup", - disableSignUpByServerCfg, - authLimiter, - signupController.beginEmailSignup -); - -router.post( - "/email/verify", // TODO endpoint: consider moving to v3/users/signup/verify - disableSignUpByServerCfg, - authLimiter, - signupController.verifyEmailSignup -); - -export default router; diff --git a/backend-mongo/src/routes/v1/sso.ts b/backend-mongo/src/routes/v1/sso.ts deleted file mode 100644 index b06ba9986..000000000 --- a/backend-mongo/src/routes/v1/sso.ts +++ /dev/null @@ -1,72 +0,0 @@ -import express from "express"; -const router = express.Router(); -import passport from "passport"; -import { authLimiter } from "../../helpers/rateLimiter"; -import { ssoController } from "../../ee/controllers/v1"; - -router.get("/redirect/google", authLimiter, (req, res, next) => { - passport.authenticate("google", { - scope: ["profile", "email"], - session: false, - ...(req.query.callback_port - ? { - state: req.query.callback_port as string - } - : {}) - })(req, res, next); -}); - -router.get( - "/google", - passport.authenticate("google", { - failureRedirect: "/login/provider/error", - session: false - }), - ssoController.redirectSSO -); - -router.get("/redirect/github", authLimiter, (req, res, next) => { - passport.authenticate("github", { - session: false, - ...(req.query.callback_port - ? { - state: req.query.callback_port as string - } - : {}) - })(req, res, next); -}); - -router.get( - "/github", - authLimiter, - passport.authenticate("github", { - failureRedirect: "/login/provider/error", - session: false - }), - ssoController.redirectSSO -); - -router.get( - "/redirect/gitlab", - authLimiter, - (req, res, next) => { - passport.authenticate("gitlab", { - session: false, - ...(req.query.callback_port ? { - state: req.query.callback_port as string - } : {}) - })(req, res, next); - } -); - -router.get( - "/gitlab", - authLimiter, - passport.authenticate("gitlab", { - failureRedirect: "/login/provider/error", - session: false - }), - ssoController.redirectSSO -); - -export default router; \ No newline at end of file diff --git a/backend-mongo/src/routes/v1/universalAuth.ts b/backend-mongo/src/routes/v1/universalAuth.ts deleted file mode 100644 index b9d180040..000000000 --- a/backend-mongo/src/routes/v1/universalAuth.ts +++ /dev/null @@ -1,66 +0,0 @@ - -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { universalAuthController } from "../../controllers/v1"; -import { AuthMode } from "../../variables"; - -router.post( - "/token/renew", - universalAuthController.renewAccessToken -); - -router.post( - "/universal-auth/login", - universalAuthController.loginIdentityUniversalAuth -); - -router.post( - "/universal-auth/identities/:identityId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - universalAuthController.attachIdentityUniversalAuth -); - -router.patch( - "/universal-auth/identities/:identityId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - universalAuthController.updateIdentityUniversalAuth -); - -router.get( - "/universal-auth/identities/:identityId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - universalAuthController.getIdentityUniversalAuth -); - -router.post( - "/universal-auth/identities/:identityId/client-secrets", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - universalAuthController.createUniversalAuthClientSecret -); - -router.get( - "/universal-auth/identities/:identityId/client-secrets", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - universalAuthController.getUniversalAuthClientSecretsDetails -); - -router.post( - "/universal-auth/identities/:identityId/client-secrets/:clientSecretId/revoke", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - universalAuthController.revokeUniversalAuthClientSecret -); - -export default router; \ No newline at end of file diff --git a/backend-mongo/src/routes/v1/user.ts b/backend-mongo/src/routes/v1/user.ts deleted file mode 100644 index 85333db9b..000000000 --- a/backend-mongo/src/routes/v1/user.ts +++ /dev/null @@ -1,15 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { userController } from "../../controllers/v1"; -import { AuthMode } from "../../variables"; - -router.get( // TODO endpoint: deprecate (moved to v2/users/me) - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - userController.getUser -); - -export default router; diff --git a/backend-mongo/src/routes/v1/userAction.ts b/backend-mongo/src/routes/v1/userAction.ts deleted file mode 100644 index 762e1cde3..000000000 --- a/backend-mongo/src/routes/v1/userAction.ts +++ /dev/null @@ -1,25 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { userActionController } from "../../controllers/v1"; -import { AuthMode } from "../../variables"; - -// note: [userAction] will be deprecated in /v2 in favor of [action] -router.post( - // TODO endpoint: move this into /users/me - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - userActionController.addUserAction -); - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - userActionController.getUserAction -); - -export default router; diff --git a/backend-mongo/src/routes/v1/webhook.ts b/backend-mongo/src/routes/v1/webhook.ts deleted file mode 100644 index 30c59a15b..000000000 --- a/backend-mongo/src/routes/v1/webhook.ts +++ /dev/null @@ -1,47 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; -import { webhookController } from "../../controllers/v1"; - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - webhookController.createWebhook -); - -router.patch( - "/:webhookId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - webhookController.updateWebhook -); - -router.post( - "/:webhookId/test", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - webhookController.testWebhook -); - -router.delete( - "/:webhookId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - webhookController.deleteWebhook -); - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - webhookController.listWebhooks -); - -export default router; diff --git a/backend-mongo/src/routes/v1/workspace.ts b/backend-mongo/src/routes/v1/workspace.ts deleted file mode 100644 index 4dbc121b9..000000000 --- a/backend-mongo/src/routes/v1/workspace.ts +++ /dev/null @@ -1,95 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; -import { membershipController, workspaceController } from "../../controllers/v1"; - -router.get( - "/:workspaceId/keys", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspacePublicKeys -); - -router.get( - "/:workspaceId/users", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspaceMemberships -); - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - workspaceController.getWorkspaces -); - -router.get( - "/:workspaceId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspace -); - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.createWorkspace -); - -router.delete( - "/:workspaceId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.deleteWorkspace -); - -router.post( - "/:workspaceId/name", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.changeWorkspaceName -); - -router.post( - "/:workspaceId/invite-signup", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - membershipController.inviteUserToWorkspace -); - -router.get( - "/:workspaceId/integrations", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspaceIntegrations -); - -router.get( - "/:workspaceId/authorizations", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspaceIntegrationAuthorizations -); - -router.get( - "/:workspaceId/service-tokens", // TODO endpoint: deprecate - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspaceServiceTokens -); - -export default router; diff --git a/backend-mongo/src/routes/v2/auth.ts b/backend-mongo/src/routes/v2/auth.ts deleted file mode 100644 index c24324e3f..000000000 --- a/backend-mongo/src/routes/v2/auth.ts +++ /dev/null @@ -1,33 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { body } from "express-validator"; -import { requireMfaAuth, validateRequest } from "../../middleware"; -import { authController } from "../../controllers/v2"; -import { authLimiter } from "../../helpers/rateLimiter"; - -router.post( - // TODO: deprecate (moved to api/v3/auth/login1) - "/login1", - authLimiter, - body("email").isString().trim().notEmpty().toLowerCase(), - body("clientPublicKey").isString().trim().notEmpty(), - validateRequest, - authController.login1 -); - -router.post( - // TODO: deprecate (moved to api/v3/auth/login1) - "/login2", - authLimiter, - body("email").isString().trim().notEmpty().toLowerCase(), - body("clientProof").isString().trim().notEmpty(), - validateRequest, - authController.login2 -); - -//remove above ones after depreciation -router.post("/mfa/send", authLimiter, requireMfaAuth, authController.sendMfaToken); - -router.post("/mfa/verify", authLimiter, requireMfaAuth, authController.verifyMfaToken); - -export default router; diff --git a/backend-mongo/src/routes/v2/environment.ts b/backend-mongo/src/routes/v2/environment.ts deleted file mode 100644 index e5143e6fe..000000000 --- a/backend-mongo/src/routes/v2/environment.ts +++ /dev/null @@ -1,39 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { environmentController } from "../../controllers/v2"; -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; - -router.post( - "/:workspaceId/environments", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - environmentController.createWorkspaceEnvironment -); - -router.put( - "/:workspaceId/environments", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - environmentController.renameWorkspaceEnvironment -); - -router.patch( - "/:workspaceId/environments", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - environmentController.reorderWorkspaceEnvironments -); - -router.delete( - "/:workspaceId/environments", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - environmentController.deleteWorkspaceEnvironment -); - -export default router; diff --git a/backend-mongo/src/routes/v2/index.ts b/backend-mongo/src/routes/v2/index.ts deleted file mode 100644 index 99ad9c01a..000000000 --- a/backend-mongo/src/routes/v2/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import auth from "./auth"; -import environment from "./environment"; -import membership from "./membership"; -import organizations from "./organizations"; -import secret from "./secret"; // deprecated -import secrets from "./secrets"; -import serviceTokenData from "./serviceTokenData"; -import signup from "./signup"; -import tags from "./tags"; -import users from "./users"; -import workspace from "./workspace"; - -export { - auth, - signup, - users, - organizations, - workspace, - secret, - secrets, - serviceTokenData, - environment, - tags, - membership -}; diff --git a/backend-mongo/src/routes/v2/membership.ts b/backend-mongo/src/routes/v2/membership.ts deleted file mode 100644 index a91af00f2..000000000 --- a/backend-mongo/src/routes/v2/membership.ts +++ /dev/null @@ -1,15 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { membershipController } from "../../controllers/v2"; -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; - -router.post( - "/:workspaceId/memberships", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - membershipController.addUserToWorkspace -); - -export default router; diff --git a/backend-mongo/src/routes/v2/organizations.ts b/backend-mongo/src/routes/v2/organizations.ts deleted file mode 100644 index c66223750..000000000 --- a/backend-mongo/src/routes/v2/organizations.ts +++ /dev/null @@ -1,65 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; -import { organizationsController } from "../../controllers/v2"; - -// TODO: /POST to create membership - -router.get( - "/:organizationId/memberships", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - organizationsController.getOrganizationMemberships -); - -router.patch( - "/:organizationId/memberships/:membershipId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - organizationsController.updateOrganizationMembership -); - -router.delete( - "/:organizationId/memberships/:membershipId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - organizationsController.deleteOrganizationMembership -); - -router.get( - "/:organizationId/workspaces", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - organizationsController.getOrganizationWorkspaces -); - -router.post( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.createOrganization -); - -router.delete( - "/:organizationId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - organizationsController.deleteOrganizationById -); - -router.get( - "/:organizationId/identity-memberships", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - organizationsController.getOrganizationIdentityMemberships -); - -export default router; diff --git a/backend-mongo/src/routes/v2/secret.ts b/backend-mongo/src/routes/v2/secret.ts deleted file mode 100644 index 1707a927f..000000000 --- a/backend-mongo/src/routes/v2/secret.ts +++ /dev/null @@ -1,147 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { - requireAuth, - requireSecretAuth, - requireWorkspaceAuth, - validateRequest, -} from "../../middleware"; -import { body, param, query } from "express-validator"; -import { - ADMIN, - AuthMode, - MEMBER, - PERMISSION_READ_SECRETS, - PERMISSION_WRITE_SECRETS, -} from "../../variables"; -import { CreateSecretRequestBody, ModifySecretRequestBody } from "../../types/secret"; -import { secretController } from "../../controllers/v2"; - -// note: endpoints deprecated in favor of v3/secrets - -router.post( // TODO endpoint: deprecate (moved to POST api/v3/secrets) - "/batch-create/workspace/:workspaceId/environment/:environment", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params", - }), - param("workspaceId").exists().isMongoId().trim(), - param("environment").exists().trim(), - body("secrets").exists().isArray().custom((value) => value.every((item: CreateSecretRequestBody) => typeof item === "object")), - body("channel"), - validateRequest, - secretController.createSecrets -); - -router.post( - "/workspace/:workspaceId/environment/:environment", // TODO endpoint: deprecate (moved to POST api/v3/secrets) - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params", - }), - param("workspaceId").exists().isMongoId().trim(), - param("environment").exists().trim(), - body("secret").exists().isObject(), - body("channel"), - validateRequest, - secretController.createSecret -); - -router.get( // TODO endpoint: deprecate (moved to GET api/v3/secrets) - "/workspace/:workspaceId", - param("workspaceId").exists().trim(), - query("environment").exists(), - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN], - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params", - }), - query("channel"), - validateRequest, - secretController.getSecrets -); - -router.get( // TODO endpoint: deprecate (moved to POST api/v3/secrets) - "/:secretId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN], - }), - requireSecretAuth({ - acceptedRoles: [ADMIN, MEMBER], - requiredPermissions: [PERMISSION_READ_SECRETS], - }), - validateRequest, - secretController.getSecret -); - -router.delete( // TODO endpoint: deprecate (moved to DELETE api/v3/secrets) - "/batch/workspace/:workspaceId/environment/:environmentName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - param("workspaceId").exists().isMongoId().trim(), - param("environmentName").exists().trim(), - body("secretIds").exists().isArray().custom(array => array.length > 0), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params", - }), - validateRequest, - secretController.deleteSecrets -); - -router.delete( // TODO endpoint: deprecate (moved to DELETE api/v3/secrets) - "/:secretId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - requireSecretAuth({ - acceptedRoles: [ADMIN, MEMBER], - requiredPermissions: [PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS], - }), - param("secretId").isMongoId(), - validateRequest, - secretController.deleteSecret -); - -router.patch( // TODO endpoint: deprecate (moved to PATCH api/v3/secrets) - "/batch-modify/workspace/:workspaceId/environment/:environmentName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - body("secrets").exists().isArray().custom((secrets: ModifySecretRequestBody[]) => secrets.length > 0), - param("workspaceId").exists().isMongoId().trim(), - param("environmentName").exists().trim(), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params", - }), - validateRequest, - secretController.updateSecrets -); - -router.patch( // TODO endpoint: deprecate (moved to PATCH api/v3/secrets) - "/workspace/:workspaceId/environment/:environmentName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT], - }), - body("secret").isObject(), - param("workspaceId").exists().isMongoId().trim(), - param("environmentName").exists().trim(), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params", - }), - validateRequest, - secretController.updateSecret -); - -export default router; diff --git a/backend-mongo/src/routes/v2/secrets.ts b/backend-mongo/src/routes/v2/secrets.ts deleted file mode 100644 index c175335ff..000000000 --- a/backend-mongo/src/routes/v2/secrets.ts +++ /dev/null @@ -1,173 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { - requireAuth, - requireSecretsAuth, - requireWorkspaceAuth, - validateRequest -} from "../../middleware"; -import { body } from "express-validator"; -import { secretsController } from "../../controllers/v2"; -import { - ADMIN, - AuthMode, - MEMBER, - PERMISSION_READ_SECRETS, - PERMISSION_WRITE_SECRETS, - SECRET_PERSONAL, - SECRET_SHARED -} from "../../variables"; - -router.post( - // TODO endpoint: strongly consider deprecation in favor of a single operation experience on dashboard - "/batch", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN] - }), - secretsController.batchSecrets -); - -router.post( - // TODO endpoint: deprecate (moved to POST api/v3/secrets) - "/", - body("workspaceId").exists().isString().trim(), - body("environment").exists().isString().trim(), - body("folderId").default("root").isString().trim(), - body("secretPath").optional().isString().trim(), - body("secrets") - .exists() - .custom((value) => { - if (Array.isArray(value)) { - // case: create multiple secrets - if (value.length === 0) throw new Error("secrets cannot be an empty array"); - for (const secret of value) { - if ( - !secret.type || - !(secret.type === SECRET_PERSONAL || secret.type === SECRET_SHARED) || - !secret.secretKeyCiphertext || - !secret.secretKeyIV || - !secret.secretKeyTag || - typeof secret.secretValueCiphertext !== "string" || - !secret.secretValueIV || - !secret.secretValueTag - ) { - throw new Error( - "secrets array must contain objects that have required secret properties" - ); - } - } - } else if (typeof value === "object") { - // case: update 1 secret - if ( - !value.type || - !(value.type === SECRET_PERSONAL || value.type === SECRET_SHARED) || - !value.secretKeyCiphertext || - !value.secretKeyIV || - !value.secretKeyTag || - !value.secretValueCiphertext || - !value.secretValueIV || - !value.secretValueTag - ) { - throw new Error("secrets object is missing required secret properties"); - } - } else { - throw new Error("secrets must be an object or an array of objects"); - } - - return true; - }), - validateRequest, - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "body", - locationEnvironment: "body", - requiredPermissions: [PERMISSION_WRITE_SECRETS] - }), - secretsController.createSecrets -); - -router.get( - // TODO endpoint: deprecate (moved to GET api/v3/secrets) - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "query", - locationEnvironment: "query", - requiredPermissions: [PERMISSION_READ_SECRETS] - }), - secretsController.getSecrets -); - -router.patch( - // TODO endpoint: deprecate (moved to PATCH api/v3/secrets) - "/", - body("secrets") - .exists() - .custom((value) => { - if (Array.isArray(value)) { - // case: update multiple secrets - if (value.length === 0) throw new Error("secrets cannot be an empty array"); - for (const secret of value) { - if (!secret.id) { - throw new Error("Each secret must contain a ID property"); - } - } - } else if (typeof value === "object") { - // case: update 1 secret - if (!value.id) { - throw new Error("secret must contain a ID property"); - } - } else { - throw new Error("secrets must be an object or an array of objects"); - } - - return true; - }), - validateRequest, - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN] - }), - requireSecretsAuth({ - acceptedRoles: [ADMIN, MEMBER], - requiredPermissions: [PERMISSION_WRITE_SECRETS] - }), - secretsController.updateSecrets -); - -router.delete( - // TODO endpoint: deprecate (moved to DELETE api/v3/secrets) - "/", - body("secretIds") - .exists() - .custom((value) => { - // case: delete 1 secret - if (typeof value === "string") return true; - - if (Array.isArray(value)) { - // case: delete multiple secrets - if (value.length === 0) throw new Error("secrets cannot be an empty array"); - return value.every((id: string) => typeof id === "string"); - } - - throw new Error("secretIds must be a string or an array of strings"); - }) - .not() - .isEmpty(), - validateRequest, - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN] - }), - requireSecretsAuth({ - acceptedRoles: [ADMIN, MEMBER], - requiredPermissions: [PERMISSION_WRITE_SECRETS] - }), - secretsController.deleteSecrets -); - -export default router; diff --git a/backend-mongo/src/routes/v2/serviceTokenData.ts b/backend-mongo/src/routes/v2/serviceTokenData.ts deleted file mode 100644 index 2a0760f50..000000000 --- a/backend-mongo/src/routes/v2/serviceTokenData.ts +++ /dev/null @@ -1,33 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { - requireAuth -} from "../../middleware"; -import { AuthMode } from "../../variables"; -import { serviceTokenDataController } from "../../controllers/v2"; - -router.get( // TODO: deprecate (moving to identity) - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.SERVICE_TOKEN] - }), - serviceTokenDataController.getServiceTokenData -); - -router.post( // TODO: deprecate (moving to identity) - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - serviceTokenDataController.createServiceTokenData -); - -router.delete( // TODO: deprecate (moving to identity) - "/:serviceTokenDataId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - serviceTokenDataController.deleteServiceTokenData -); - -export default router; \ No newline at end of file diff --git a/backend-mongo/src/routes/v2/signup.ts b/backend-mongo/src/routes/v2/signup.ts deleted file mode 100644 index 8a404cfc2..000000000 --- a/backend-mongo/src/routes/v2/signup.ts +++ /dev/null @@ -1,51 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { body } from "express-validator"; -import { disableSignUpByServerCfg, requireSignupAuth, validateRequest } from "../../middleware"; -import { signupController } from "../../controllers/v2"; -import { authLimiter } from "../../helpers/rateLimiter"; - -router.post( - "/complete-account/signup", // TODO endpoint: deprecate (moved to v3/signup/complete/account-signup), - disableSignUpByServerCfg, - authLimiter, - requireSignupAuth, - body("email").exists().isString().trim().notEmpty().isEmail(), - body("firstName").exists().isString().trim().notEmpty(), - body("lastName").exists().isString().trim().notEmpty(), - body("protectedKey").exists().isString().trim().notEmpty(), - body("protectedKeyIV").exists().isString().trim().notEmpty(), - body("protectedKeyTag").exists().isString().trim().notEmpty(), - body("publicKey").exists().isString().trim().notEmpty(), - body("encryptedPrivateKey").exists().isString().trim().notEmpty(), - body("encryptedPrivateKeyIV").exists().isString().trim().notEmpty(), - body("encryptedPrivateKeyTag").exists().isString().trim().notEmpty(), - body("salt").exists().isString().trim().notEmpty(), - body("verifier").exists().isString().trim().notEmpty(), - body("organizationName").exists().isString().trim().notEmpty(), - validateRequest, - signupController.completeAccountSignup -); - -router.post( - "/complete-account/invite", // TODO: consider moving to v3/users/new/complete-account/invite - disableSignUpByServerCfg, - authLimiter, - requireSignupAuth, - body("email").exists().isString().trim().notEmpty().isEmail(), - body("firstName").exists().isString().trim().notEmpty(), - body("lastName").exists().isString().trim().notEmpty(), - body("protectedKey").exists().isString().trim().notEmpty(), - body("protectedKeyIV").exists().isString().trim().notEmpty(), - body("protectedKeyTag").exists().isString().trim().notEmpty(), - body("publicKey").exists().trim().notEmpty(), - body("encryptedPrivateKey").exists().isString().trim().notEmpty(), - body("encryptedPrivateKeyIV").exists().isString().trim().notEmpty(), - body("encryptedPrivateKeyTag").exists().isString().trim().notEmpty(), - body("salt").exists().isString().trim().notEmpty(), - body("verifier").exists().isString().trim().notEmpty(), - validateRequest, - signupController.completeAccountInvite -); - -export default router; diff --git a/backend-mongo/src/routes/v2/tags.ts b/backend-mongo/src/routes/v2/tags.ts deleted file mode 100644 index 7926e9452..000000000 --- a/backend-mongo/src/routes/v2/tags.ts +++ /dev/null @@ -1,31 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { tagController } from "../../controllers/v2"; -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; - -router.get( - "/:workspaceId/tags", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - tagController.getWorkspaceTags -); - -router.delete( - "/tags/:tagId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - tagController.deleteWorkspaceTag -); - -router.post( - "/:workspaceId/tags", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - tagController.createWorkspaceTag -); - -export default router; diff --git a/backend-mongo/src/routes/v2/users.ts b/backend-mongo/src/routes/v2/users.ts deleted file mode 100644 index 54c16898f..000000000 --- a/backend-mongo/src/routes/v2/users.ts +++ /dev/null @@ -1,95 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { usersController } from "../../controllers/v2"; -import { AuthMode } from "../../variables"; - -router.patch( - "/me/mfa", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - usersController.updateMyMfaEnabled -); - -router.patch( - "/me/name", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - usersController.updateName -); - -router.put( - "/me/auth-methods", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY], - }), - usersController.updateAuthMethods, -); - -router.get( - "/me/organizations", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - usersController.getMyOrganizations -); - -router.get( // TODO: deprecate (moving to API Key V2) - "/me/api-keys", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - usersController.getMyAPIKeys -); - -router.post( - "/me/api-keys", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - usersController.createAPIKey -); - -router.delete( - "/me/api-keys/:apiKeyDataId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - usersController.deleteAPIKey -); - -router.get( - "/me/sessions", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - usersController.getMySessions -); - -router.delete( - "/me/sessions", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - usersController.deleteMySessions -); - -router.get( - "/me", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - usersController.getMe -); - -router.delete( - "/me", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - usersController.deleteMe -); - -export default router; diff --git a/backend-mongo/src/routes/v2/workspace.ts b/backend-mongo/src/routes/v2/workspace.ts deleted file mode 100644 index f45c38f0c..000000000 --- a/backend-mongo/src/routes/v2/workspace.ts +++ /dev/null @@ -1,129 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { body, param, query } from "express-validator"; -import { requireAuth, requireWorkspaceAuth, validateRequest } from "../../middleware"; -import { ADMIN, AuthMode, MEMBER } from "../../variables"; -import { workspaceController } from "../../controllers/v2"; - -router.post( - // TODO endpoint: deprecate (moved to POST v3/secrets) - "/:workspaceId/secrets", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params" - }), - body("secrets").exists(), - body("keys").exists(), - body("environment").exists().trim().notEmpty(), - body("channel"), - param("workspaceId").exists().trim(), - validateRequest, - workspaceController.pushWorkspaceSecrets -); - -router.get( - // TODO endpoint: deprecate (moved to GET v3/secrets) - "/:workspaceId/secrets", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "params" - }), - query("environment").exists().trim(), - query("channel"), - param("workspaceId").exists().trim(), - validateRequest, - workspaceController.pullSecrets -); - -router.get( - // TODO endpoint: consider moving to v3/users/me/workspaces/:workspaceId/key - "/:workspaceId/encrypted-key", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] - }), - workspaceController.getWorkspaceKey -); - -router.get( - "/:workspaceId/service-token-data", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.getWorkspaceServiceTokenData -); - -router.get( - // new - TODO: rewire dashboard to this route - "/:workspaceId/memberships", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.getWorkspaceMemberships -); - -router.patch( - // TODO - rewire dashboard to this route - "/:workspaceId/memberships/:membershipId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.updateWorkspaceMembership -); - -router.delete( - // TODO - rewire dashboard to this route - "/:workspaceId/memberships/:membershipId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.deleteWorkspaceMembership -); - -router.patch( - "/:workspaceId/auto-capitalization", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspaceController.toggleAutoCapitalization -); - -router.post( - "/:workspaceId/identity-memberships/:identityId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.addIdentityToWorkspace -); - -router.patch( - "/:workspaceId/identity-memberships/:identityId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.updateIdentityWorkspaceRole -); - -router.delete( - "/:workspaceId/identity-memberships/:identityId", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.deleteIdentityFromWorkspace -); - -router.get( - "/:workspaceId/identity-memberships", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - workspaceController.getWorkspaceIdentityMemberships -); - - -export default router; diff --git a/backend-mongo/src/routes/v3/auth.ts b/backend-mongo/src/routes/v3/auth.ts deleted file mode 100644 index 44fdaef4b..000000000 --- a/backend-mongo/src/routes/v3/auth.ts +++ /dev/null @@ -1,11 +0,0 @@ -import express from "express"; -import { authController } from "../../controllers/v3"; -import { authLimiter } from "../../helpers/rateLimiter"; - -const router = express.Router(); - -router.post("/login1", authLimiter, authController.login1); - -router.post("/login2", authLimiter, authController.login2); - -export default router; diff --git a/backend-mongo/src/routes/v3/index.ts b/backend-mongo/src/routes/v3/index.ts deleted file mode 100644 index a2b64294c..000000000 --- a/backend-mongo/src/routes/v3/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import auth from "./auth"; -import users from "./users"; -import secrets from "./secrets"; -import workspaces from "./workspaces"; -import signup from "./signup"; - -export { - auth, - users, - secrets, - signup, - workspaces -} diff --git a/backend-mongo/src/routes/v3/secrets.ts b/backend-mongo/src/routes/v3/secrets.ts deleted file mode 100644 index be6daba2c..000000000 --- a/backend-mongo/src/routes/v3/secrets.ts +++ /dev/null @@ -1,160 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth, requireBlindIndicesEnabled, requireE2EEOff } from "../../middleware"; -import { secretsController } from "../../controllers/v3"; -import { AuthMode } from "../../variables"; - -router.get( - "/raw", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - secretsController.getSecretsRaw -); - -router.get( - "/raw/:secretName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "query" - }), - requireE2EEOff({ - locationWorkspaceId: "query" - }), - secretsController.getSecretByNameRaw -); - -router.post( - "/raw/:secretName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - requireE2EEOff({ - locationWorkspaceId: "body" - }), - secretsController.createSecretRaw -); - -router.patch( - "/raw/:secretName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - requireE2EEOff({ - locationWorkspaceId: "body" - }), - secretsController.updateSecretByNameRaw -); - -router.delete( - "/raw/:secretName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - requireE2EEOff({ - locationWorkspaceId: "body" - }), - secretsController.deleteSecretByNameRaw -); - -router.get( - "/", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "query" - }), - secretsController.getSecrets -); - -// akhilmhdh: dont put batch router below the individual operation as those have arbitory name as params -router.post( - "/batch", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - secretsController.createSecretByNameBatch -); - -router.patch( - "/batch", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - secretsController.updateSecretByNameBatch -); - -router.delete( - "/batch", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - secretsController.deleteSecretByNameBatch -); - -router.post( - "/:secretName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - secretsController.createSecret -); - -router.get( - "/:secretName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "query" - }), - secretsController.getSecretByName -); - -router.patch( - "/:secretName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - secretsController.updateSecretByName -); - -router.delete( - "/:secretName", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY, AuthMode.API_KEY_V2, AuthMode.SERVICE_TOKEN] - }), - requireBlindIndicesEnabled({ - locationWorkspaceId: "body" - }), - secretsController.deleteSecretByName -); - -export default router; diff --git a/backend-mongo/src/routes/v3/signup.ts b/backend-mongo/src/routes/v3/signup.ts deleted file mode 100644 index e2b13a0a2..000000000 --- a/backend-mongo/src/routes/v3/signup.ts +++ /dev/null @@ -1,15 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { signupController } from "../../controllers/v3"; -import { authLimiter } from "../../helpers/rateLimiter"; -import { disableSignUpByServerCfg, validateRequest } from "../../middleware"; - -router.post( - "/complete-account/signup", // TODO: consider moving endpoint to v3/users/new/complete-account/signup - disableSignUpByServerCfg, - authLimiter, - validateRequest, - signupController.completeAccountSignup -); - -export default router; diff --git a/backend-mongo/src/routes/v3/users.ts b/backend-mongo/src/routes/v3/users.ts deleted file mode 100644 index f465791f8..000000000 --- a/backend-mongo/src/routes/v3/users.ts +++ /dev/null @@ -1,15 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { AuthMode } from "../../variables"; -import { usersController } from "../../controllers/v3"; - -router.get( - "/me/api-keys", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - usersController.getMyAPIKeys -); - -export default router; \ No newline at end of file diff --git a/backend-mongo/src/routes/v3/workspaces.ts b/backend-mongo/src/routes/v3/workspaces.ts deleted file mode 100644 index 834d54cd1..000000000 --- a/backend-mongo/src/routes/v3/workspaces.ts +++ /dev/null @@ -1,37 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { requireAuth } from "../../middleware"; -import { workspacesController } from "../../controllers/v3"; -import { AuthMode } from "../../variables"; - -// -- migration to blind indices endpoints - -router.get( - "/:workspaceId/secrets/blind-index-status", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspacesController.getWorkspaceBlindIndexStatus -); - -router.get( - // allow admins to get all workspace secrets (part of blind indices migration) - "/:workspaceId/secrets", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspacesController.getWorkspaceSecrets -); - -router.post( - // allow admins to name all workspace secrets (part of blind indices migration) - "/:workspaceId/secrets/names", - requireAuth({ - acceptedAuthModes: [AuthMode.JWT] - }), - workspacesController.nameWorkspaceSecrets -); - -// -- - -export default router; diff --git a/backend-mongo/src/services/BotOrgService.ts b/backend-mongo/src/services/BotOrgService.ts deleted file mode 100644 index 070a44058..000000000 --- a/backend-mongo/src/services/BotOrgService.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Types } from "mongoose"; -import { getSymmetricKeyHelper } from "../helpers/botOrg"; - -// TODO: DOCstrings - -class BotOrgService { - static async getSymmetricKey(organizationId: Types.ObjectId) { - return await getSymmetricKeyHelper(organizationId); - } -} - -export default BotOrgService; \ No newline at end of file diff --git a/backend-mongo/src/services/BotService.ts b/backend-mongo/src/services/BotService.ts deleted file mode 100644 index ca75985d2..000000000 --- a/backend-mongo/src/services/BotService.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { Types } from "mongoose"; -import { - decryptSymmetricHelper, - encryptSymmetricHelper, - getIsWorkspaceE2EEHelper, - getKey, - getSecretsBotHelper, - getSecretsCommentBotHelper, -} from "../helpers/bot"; - -/** - * Class to handle bot actions - */ -class BotService { - /** - * Return whether or not workspace with id [workspaceId] is end-to-end encrypted - * @param workspaceId - id of workspace - * @returns {Boolean} - */ - static async getIsWorkspaceE2EE(workspaceId: Types.ObjectId) { - return await getIsWorkspaceE2EEHelper(workspaceId); - } - - /** - * Get workspace key for workspace with id [workspaceId] shared to bot. - * @param {Object} obj - * @param {Types.ObjectId} obj.workspaceId - id of workspace to get workspace key for - * @returns - */ - static async getWorkspaceKeyWithBot({ - workspaceId, - }: { - workspaceId: Types.ObjectId; - }) { - return await getKey({ - workspaceId, - }); - } - - /** - * Return decrypted secrets for workspace with id [workspaceId] and - * environment [environmen] shared to bot. - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace of secrets - * @param {String} obj.environment - environment for secrets - * @returns {Object} secretObj - object where keys are secret keys and values are secret values - */ - static async getSecrets({ - workspaceId, - environment, - secretPath, - }: { - workspaceId: Types.ObjectId; - environment: string; - secretPath: string; - }) { - return await getSecretsBotHelper({ - workspaceId, - environment, - secretPath, - }); - } - - /** - * Return symmetrically encrypted [plaintext] using the - * bot's copy of the workspace key for workspace with id [workspaceId] - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace - * @param {String} obj.plaintext - plaintext to encrypt - */ - static async encryptSymmetric({ - workspaceId, - plaintext, - }: { - workspaceId: Types.ObjectId; - plaintext: string; - }) { - return await encryptSymmetricHelper({ - workspaceId, - plaintext, - }); - } - - /** - * Return symmetrically decrypted [ciphertext] using the - * bot's copy of the workspace key for workspace with id [workspaceId] - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace - * @param {String} obj.ciphertext - ciphertext to decrypt - * @param {String} obj.iv - iv - * @param {String} obj.tag - tag - */ - static async decryptSymmetric({ - workspaceId, - ciphertext, - iv, - tag, - }: { - workspaceId: Types.ObjectId; - ciphertext: string; - iv: string; - tag: string; - }) { - return await decryptSymmetricHelper({ - workspaceId, - ciphertext, - iv, - tag, - }); - } - - /** - * Return decrypted secret comments for workspace with id [worskpaceId] and - * environment [environment] shared to bot. - * @param {Object} obj - * @param {String} obj.workspaceId - id of workspace of secrets - * @param {String} obj.environment - environment for secrets - * @returns {Object} secretObj - object where keys are secret keys and values are comments - */ - static async getSecretComments({ - workspaceId, - environment, - secretPath - }: { - workspaceId: Types.ObjectId; - environment: string; - secretPath: string; - }) { - return await getSecretsCommentBotHelper({ - workspaceId, - environment, - secretPath - }); - } -} - -export default BotService; diff --git a/backend-mongo/src/services/DatabaseService.ts b/backend-mongo/src/services/DatabaseService.ts deleted file mode 100644 index 4b40863d0..000000000 --- a/backend-mongo/src/services/DatabaseService.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { - closeDatabaseHelper, - initDatabaseHelper, -} from "../helpers/database"; - -/** - * Class to handle database actions - */ -class DatabaseService { - /** - * Initialize database connection - * @param {Object} obj - * @param {String} obj.mongoURL - mongo connection string - * @returns - */ - static async initDatabase(MONGO_URL: string) { - return await initDatabaseHelper({ - mongoURL: MONGO_URL, - }); - } - - /** - * Close database conection - */ - static async closeDatabase() { - return await closeDatabaseHelper(); - } -} - -export default DatabaseService; \ No newline at end of file diff --git a/backend-mongo/src/services/EventService.ts b/backend-mongo/src/services/EventService.ts deleted file mode 100644 index 7abc7c1b1..000000000 --- a/backend-mongo/src/services/EventService.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Types } from "mongoose"; -import { handleEventHelper } from "../helpers/event"; - -interface Event { - name: string; - workspaceId: Types.ObjectId; - environment?: string; - payload: any; -} - -/** - * Class to handle events. - */ -class EventService { - /** - * Handle event [event] - * @param {Object} obj - * @param {Event} obj.event - an event - * @param {String} obj.event.name - name of event - * @param {String} obj.event.workspaceId - id of workspace that event is part of - * @param {Object} obj.event.payload - payload of event (depends on event) - */ - static async handleEvent({ event }: { event: Event }): Promise { - await handleEventHelper({ - event, - }); - } -} - -export default EventService; \ No newline at end of file diff --git a/backend-mongo/src/services/FolderService.ts b/backend-mongo/src/services/FolderService.ts deleted file mode 100644 index 65aa5b0f3..000000000 --- a/backend-mongo/src/services/FolderService.ts +++ /dev/null @@ -1,233 +0,0 @@ -import { nanoid } from "nanoid"; -import { Types } from "mongoose"; -import { Folder, TFolderSchema } from "../models"; -import path from "path"; - -type TAppendFolderDTO = { - folderName: string; - directory: string; -}; - -type TRenameFolderDTO = { - folderName: string; - folderId: string; -}; - -export const validateFolderName = (folderName: string) => { - const validNameRegex = /^[a-zA-Z0-9-_]+$/; - return validNameRegex.test(folderName); -}; - -export const generateFolderId = (): string => nanoid(12); - -// simple bfs search -export const searchByFolderId = ( - root: TFolderSchema, - folderId: string -): TFolderSchema | undefined => { - const queue = [root]; - while (queue.length) { - const folder = queue.pop() as TFolderSchema; - if (folder.id === folderId) { - return folder; - } - queue.push(...folder.children); - } -}; - -export const folderBfsTraversal = async ( - root: TFolderSchema, - callback: (data: TFolderSchema) => void | Promise -) => { - const queue = [root]; - while (queue.length) { - const folder = queue.pop() as TFolderSchema; - await callback(folder); - queue.push(...folder.children); - } -}; - -// bfs and then append to the folder -const appendChild = (folders: TFolderSchema, folderName: string) => { - const folder = folders.children.find(({ name }) => name === folderName); - if (folder) return { folder, hasCreated: false }; - - const id = generateFolderId(); - folders.version += 1; - folders.children.push({ - id, - name: folderName, - children: [], - version: 1 - }); - // last element that is the new one - return { folder: folders.children[folders.children.length - 1], hasCreated: true }; -}; - -// root of append child wrapper -export const appendFolder = ( - folders: TFolderSchema, - { folderName, directory }: TAppendFolderDTO -): { parent: TFolderSchema; child: TFolderSchema; hasCreated?: boolean } => { - if (directory === "/") { - const newFolder = appendChild(folders, folderName); - return { parent: folders, child: newFolder.folder, hasCreated: newFolder.hasCreated }; - } - - const segments = directory.split("/").filter(Boolean); - const segment = segments.shift(); - if (segment) { - const nestedFolders = appendChild(folders, segment); - return appendFolder(nestedFolders.folder, { - folderName, - directory: path.join("/", ...segments) - }); - } - - const newFolder = appendChild(folders, folderName); - return { parent: folders, child: newFolder.folder, hasCreated: newFolder.hasCreated }; -}; - -export const renameFolder = ( - folders: TFolderSchema, - { folderName, folderId }: TRenameFolderDTO -) => { - const folder = searchByFolderId(folders, folderId); - if (!folder) { - throw new Error("Folder doesn't exist"); - } - - folder.name = folderName; -}; - -// bfs but stops on parent folder -// Then unmount the required child and then return both -export const deleteFolderById = (folders: TFolderSchema, folderId: string) => { - const queue = [folders]; - while (queue.length) { - const folder = queue.pop() as TFolderSchema; - const index = folder.children.findIndex(({ id }) => folderId === id); - if (index !== -1) { - const deletedFolder = folder.children.splice(index, 1); - return { deletedNode: deletedFolder[0], parent: folder }; - } - queue.push(...folder.children); - } -}; - -// bfs but return parent of the folderID -export const getParentFromFolderId = (folders: TFolderSchema, folderId: string) => { - const queue = [folders]; - while (queue.length) { - const folder = queue.pop() as TFolderSchema; - const index = folder.children.findIndex(({ id }) => folderId === id); - if (index !== -1) return folder; - - queue.push(...folder.children); - } -}; - -// to get all folders ids from everything from below nodes -export const getAllFolderIds = (folders: TFolderSchema) => { - const folderIds: Array<{ id: string; name: string }> = []; - const queue = [folders]; - while (queue.length) { - const folder = queue.pop() as TFolderSchema; - folderIds.push({ id: folder.id, name: folder.name }); - queue.push(...folder.children); - } - return folderIds; -}; - -// To get the path of a folder from the root. Used for breadcrumbs -// LOGIC: We do dfs instead if bfs -// Each time we go down we record the current node -// We then record the number of childs of each root node -// When we reach leaf node or when all childs of a root node are visited -// We remove it from path recorded by using the total child record -export const searchByFolderIdWithDir = (folders: TFolderSchema, folderId: string) => { - const stack = [folders]; - const dir: Array<{ id: string; name: string }> = []; - const hits: Record = {}; - - while (stack.length) { - const folder = stack.shift() as TFolderSchema; - // score the hit - hits[folder.id] = folder.children.length; - const parent = dir[dir.length - 1]; - if (parent) hits[parent.id] -= 1; - - if (folder.id === folderId) { - dir.push({ name: folder.name, id: folder.id }); - return { folder, dir }; - } - - if (folder.children.length) { - dir.push({ name: folder.name, id: folder.id }); - stack.unshift(...folder.children); - } else { - if (!hits[parent.id]) { - dir.pop(); - } - } - } - return; -}; - -// used for get folder path from id -export const getFolderWithPathFromId = (folders: TFolderSchema, parentFolderId: string) => { - const search = searchByFolderIdWithDir(folders, parentFolderId); - if (!search) { - throw { message: "Folder permission denied" }; - } - const { folder, dir } = search; - const folderPath = path.join( - "/", - ...dir.filter(({ name }) => name !== "root").map(({ name }) => name) - ); - return { folder, folderPath, dir }; -}; - -// to get folder of a path given -// Like /frontend/folder#1 -export const getFolderByPath = (folders: TFolderSchema, searchPath: string) => { - // corner case when its just / return root - if (searchPath === "/") { - return folders.id === "root" ? folders : undefined; - } - - const path = searchPath.split("/").filter(Boolean); - const queue = [folders]; - let segment: TFolderSchema | undefined; - while (queue.length && path.length) { - const folder = queue.pop(); - const segmentPath = path.shift(); - segment = folder?.children.find(({ name }) => name === segmentPath); - if (!segment) return; - - queue.push(segment); - } - return segment; -}; - -export const getFolderIdFromServiceToken = async ( - workspaceId: Types.ObjectId | string, - environment: string, - secretPath: string -) => { - const folders = await Folder.findOne({ - workspace: workspaceId, - environment - }); - - if (!folders) { - if (secretPath !== "/") throw new Error("Invalid path. Folders not found"); - } else { - const folder = getFolderByPath(folders.nodes, secretPath); - if (!folder) { - throw new Error("Folder not found"); - } - return folder.id; - } - return "root"; -}; diff --git a/backend-mongo/src/services/IntegrationService.ts b/backend-mongo/src/services/IntegrationService.ts deleted file mode 100644 index 06d0426f3..000000000 --- a/backend-mongo/src/services/IntegrationService.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { Types } from "mongoose"; -import { - getIntegrationAuthAccessHelper, - getIntegrationAuthRefreshHelper, - handleOAuthExchangeHelper, - setIntegrationAuthAccessHelper, - setIntegrationAuthRefreshHelper, -} from "../helpers/integration"; -import { syncSecretsToActiveIntegrationsQueue } from "../queues/integrations/syncSecretsToThirdPartyServices"; -import { IIntegrationAuth } from "../models"; - -/** - * Class to handle integrations - */ -class IntegrationService { - - /** - * Perform OAuth2 code-token exchange for workspace with id [workspaceId] and integration - * named [integration] - * - Store integration access and refresh tokens returned from the OAuth2 code-token exchange - * - Add placeholder inactive integration - * - Create bot sequence for integration - * @param {Object} obj1 - * @param {String} obj1.workspaceId - id of workspace - * @param {String} obj1.environment - workspace environment - * @param {String} obj1.integration - name of integration - * @param {String} obj1.code - code - * @returns {IntegrationAuth} integrationAuth - integration authorization after OAuth2 code-token exchange - */ - static async handleOAuthExchange({ - workspaceId, - integration, - code, - environment, - url - }: { - workspaceId: string; - integration: string; - code: string; - environment: string; - url?: string; - }) { - return await handleOAuthExchangeHelper({ - workspaceId, - integration, - code, - environment, - url - }); - } - - /** - * Sync/push environment variables in workspace with id [workspaceId] to - * all associated integrations - * @param {Object} obj - * @param {Object} obj.workspaceId - id of workspace - */ - static syncIntegrations({ - workspaceId, - environment, - }: { - workspaceId: Types.ObjectId; - environment?: string; - }) { - syncSecretsToActiveIntegrationsQueue({ workspaceId: workspaceId.toString(), environment: environment }) - } - - /** - * Return decrypted refresh token for integration auth - * with id [integrationAuthId] - * @param {Object} obj - * @param {String} obj.integrationAuthId - id of integration auth - * @param {String} refreshToken - decrypted refresh token - */ - static async getIntegrationAuthRefresh({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) { - return await getIntegrationAuthRefreshHelper({ - integrationAuthId, - }); - } - - /** - * Return decrypted access token for integration auth - * with id [integrationAuthId] - * @param {Object} obj - * @param {String} obj.integrationAuthId - id of integration auth - * @param {String} accessToken - decrypted access token - */ - static async getIntegrationAuthAccess({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) { - return await getIntegrationAuthAccessHelper({ - integrationAuthId, - }); - } - - /** - * Encrypt refresh token [refreshToken] using the bot's copy - * of the workspace key for workspace belonging to integration auth - * with id [integrationAuthId] - * @param {Object} obj - * @param {String} obj.integrationAuthId - id of integration auth - * @param {String} obj.refreshToken - refresh token - * @returns {IntegrationAuth} integrationAuth - updated integration auth - */ - static async setIntegrationAuthRefresh({ - integrationAuthId, - refreshToken, - }: { - integrationAuthId: string; - refreshToken: string; - }): Promise { - return await setIntegrationAuthRefreshHelper({ - integrationAuthId, - refreshToken, - }); - } - - /** - * Encrypt access token [accessToken] and (optionally) access id using the - * bot's copy of the workspace key for workspace belonging to integration auth - * with id [integrationAuthId] - * @param {Object} obj - * @param {String} obj.integrationAuthId - id of integration auth - * @param {String} obj.accessId - access id - * @param {String} obj.accessToken - access token - * @param {Date} obj.accessExpiresAt - expiration date of access token - * @returns {IntegrationAuth} - updated integration auth - */ - static async setIntegrationAuthAccess({ - integrationAuthId, - accessId, - accessToken, - accessExpiresAt, - }: { - integrationAuthId: string; - accessId?: string; - accessToken?: string; - accessExpiresAt: Date | undefined; - }) { - return await setIntegrationAuthAccessHelper({ - integrationAuthId, - accessId, - accessToken, - accessExpiresAt, - }); - } -} - -export default IntegrationService; \ No newline at end of file diff --git a/backend-mongo/src/services/RedisService.ts b/backend-mongo/src/services/RedisService.ts deleted file mode 100644 index e439ffb40..000000000 --- a/backend-mongo/src/services/RedisService.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Redis, { Redis as TRedis } from "ioredis"; -import { logger } from "../utils/logging"; - -let redisClient: TRedis | null; - -export const initRedis = async () => { - if (process.env.REDIS_URL) { - redisClient = new Redis(process.env.REDIS_URL as string); - } else { - logger.warn("Redis URL not set, skipping Redis initialization."); - redisClient = null; - } -} - - -export { redisClient }; diff --git a/backend-mongo/src/services/SecretImportService.ts b/backend-mongo/src/services/SecretImportService.ts deleted file mode 100644 index b8d622d30..000000000 --- a/backend-mongo/src/services/SecretImportService.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { Types } from "mongoose"; -import { generateSecretBlindIndexHelper } from "../helpers"; -import { SecretVersion } from "../ee/models"; -import { Folder, ISecret, Secret, SecretImport } from "../models"; -import { getFolderByPath } from "./FolderService"; - -type TSecretImportFid = { environment: string; folderId: string; secretPath: string }; - -export const getAnImportedSecret = async ( - secretName: string, - workspaceId: string, - environment: string, - folderId = "root", - version?: number -) => { - const secretBlindIndex = await generateSecretBlindIndexHelper({ - secretName, - workspaceId: new Types.ObjectId(workspaceId) - }); - - const secImports = await SecretImport.findOne({ - workspace: workspaceId, - environment, - folderId - }); - if (!secImports) return; - if (secImports.imports.length === 0) return; - const folders = await Folder.find({ - workspace: workspaceId, - environment: { $in: secImports.imports.map((el) => el.environment) } - }); - - const importedSecByFid: TSecretImportFid[] = []; - secImports.imports.forEach((el) => { - const folder = folders.find((fl) => fl.environment === el.environment); - if (folder) { - const secPathFolder = getFolderByPath(folder.nodes, el.secretPath); - if (secPathFolder) - importedSecByFid.push({ - environment: el.environment, - folderId: secPathFolder.id, - secretPath: el.secretPath - }); - } else { - if (el.secretPath === "/") { - // this happens when importing with a fresh env without any folders - importedSecByFid.push({ environment: el.environment, folderId: "root", secretPath: "/" }); - } - } - }); - if (importedSecByFid.length === 0) return; - - let secret; - if (version === undefined) { - secret = await Secret.findOne({ - workspace: workspaceId, - secretBlindIndex - }).or(importedSecByFid.map(({ environment, folderId }) => ({ environment, folder: folderId }))).lean() - } else { - const secretVersion = await SecretVersion.findOne({ - workspace: workspaceId, - secretBlindIndex, - version - }).or(importedSecByFid.map(({ environment, folderId }) => ({ environment, folder: folderId }))).lean(); - - if (secretVersion) { - secret = await new Secret({ - ...secretVersion, - _id: secretVersion.secret, - }); - } - } - - return secret; -}; - -export const getAllImportedSecrets = async ( - workspaceId: string, - environment: string, - folderId = "root", - permissionCheckCB: (env: string, secPath: string) => boolean -) => { - const secImports = await SecretImport.findOne({ - workspace: workspaceId, - environment, - folderId - }); - if (!secImports) return []; - if (secImports.imports.length === 0) return []; - - const importedEnv: Record = {}; // to get folders from all environment - const allowedSecretImports = secImports.imports.filter((el) => - permissionCheckCB(el.environment, el.secretPath) - ); - allowedSecretImports.forEach((el) => (importedEnv[el.environment] = true)); - - const folders = await Folder.find({ - workspace: workspaceId, - environment: { $in: Object.keys(importedEnv) } - }); - - const importedSecByFid: TSecretImportFid[] = []; - allowedSecretImports.forEach((el) => { - const folder = folders.find((fl) => fl.environment === el.environment); - if (folder) { - const secPathFolder = getFolderByPath(folder.nodes, el.secretPath); - if (secPathFolder) - importedSecByFid.push({ - environment: el.environment, - folderId: secPathFolder.id, - secretPath: el.secretPath - }); - } else { - if (el.secretPath === "/") { - // this happens when importing with a fresh env without any folders - importedSecByFid.push({ environment: el.environment, folderId: "root", secretPath: "/" }); - } - } - }); - if (importedSecByFid.length === 0) return []; - - const secsGroupedByRef = await Secret.aggregate([ - { - $match: { - workspace: new Types.ObjectId(workspaceId), - type: "shared" - } - }, - { - $group: { - _id: { - environment: "$environment", - folderId: "$folder" - }, - secrets: { $push: "$$ROOT" } - } - }, - { - $match: { - $or: importedSecByFid.map(({ environment, folderId: fid }) => ({ - "_id.environment": environment, - "_id.folderId": fid - })) - } - } - ]); - - // now let stitch together secrets. - const importedSecrets: Array = []; - importedSecByFid.forEach(({ environment, folderId, secretPath }) => { - const secretsGrouped = secsGroupedByRef.find( - (el) => el._id.environment === environment && el._id.folderId === folderId - ); - if (secretsGrouped) { - importedSecrets.push({ secretPath, folderId, environment, secrets: secretsGrouped.secrets }); - } - }); - return importedSecrets; -}; diff --git a/backend-mongo/src/services/SecretService.ts b/backend-mongo/src/services/SecretService.ts deleted file mode 100644 index 109fe1507..000000000 --- a/backend-mongo/src/services/SecretService.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { Types } from "mongoose"; -import { - CreateSecretBatchParams, - CreateSecretParams, - DeleteSecretBatchParams, - DeleteSecretParams, - GetSecretParams, - GetSecretsParams, - UpdateSecretBatchParams, - UpdateSecretParams -} from "../interfaces/services/SecretService"; -import { - createSecretBatchHelper, - createSecretBlindIndexDataHelper, - createSecretHelper, - deleteSecretBatchHelper, - deleteSecretHelper, - generateSecretBlindIndexHelper, - generateSecretBlindIndexWithSaltHelper, - getSecretBlindIndexSaltHelper, - getSecretHelper, - getSecretsHelper, - updateSecretBatchHelper, - updateSecretHelper -} from "../helpers/secrets"; - -class SecretService { - /** - * Create secret blind index data containing encrypted blind index salt - * for workspace with id [workspaceId] - * @param {Object} obj - * @param {Buffer} obj.salt - 16-byte random salt - * @param {Types.ObjectId} obj.workspaceId - */ - static async createSecretBlindIndexData({ workspaceId }: { workspaceId: Types.ObjectId }) { - return await createSecretBlindIndexDataHelper({ - workspaceId - }); - } - - /** - * Get secret blind index salt for workspace with id [workspaceId] - * @param {Object} obj - * @param {Types.ObjectId} obj.workspaceId - id of workspace to get salt for - * @returns - */ - static async getSecretBlindIndexSalt({ workspaceId }: { workspaceId: Types.ObjectId }) { - return await getSecretBlindIndexSaltHelper({ - workspaceId - }); - } - - /** - * Generate blind index for secret with name [secretName] - * and salt [salt] - * @param {Object} obj - * @param {Object} obj.secretName - name of secret to generate blind index for - * @param {String} obj.salt - base64-salt - */ - static async generateSecretBlindIndexWithSalt({ - secretName, - salt - }: { - secretName: string; - salt: string; - }) { - return await generateSecretBlindIndexWithSaltHelper({ - secretName, - salt - }); - } - - /** - * Create and return blind index for secret with - * name [secretName] part of workspace with id [workspaceId] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to generate blind index for - * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to - */ - static async generateSecretBlindIndex({ - secretName, - workspaceId - }: { - secretName: string; - workspaceId: Types.ObjectId; - }) { - return await generateSecretBlindIndexHelper({ - secretName, - workspaceId - }); - } - - /** - * Create secret with name [secretName] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to create - * @param {Types.ObjectId} obj.workspaceId - id of workspace to create secret for - * @param {String} obj.environment - environment in workspace to create secret for - * @param {'shared' | 'personal'} obj.type - type of secret - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ - static async createSecret(createSecretParams: CreateSecretParams) { - return await createSecretHelper(createSecretParams); - } - - /** - * Get secrets for workspace with id [workspaceId] and environment [environment] - * @param {Object} obj - * @param {Types.ObjectId} obj.workspaceId - id of workspace - * @param {String} obj.environment - environment in workspace - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ - static async getSecrets(getSecretsParams: GetSecretsParams) { - return await getSecretsHelper(getSecretsParams); - } - - /** - * Get secret with name [secretName] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to get - * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to - * @param {String} obj.environment - environment in workspace that secret belongs to - * @param {'shared' | 'personal'} obj.type - type of secret - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ - static async getSecret(getSecretParams: GetSecretParams) { - // TODO(akhilmhdh) The one above is diff. Change this to some other name - return await getSecretHelper(getSecretParams); - } - - /** - * Update secret with name [secretName] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to update - * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to - * @param {String} obj.environment - environment in workspace that secret belongs to - * @param {'shared' | 'personal'} obj.type - type of secret - * @param {String} obj.secretValueCiphertext - ciphertext of secret value - * @param {String} obj.secretValueIV - IV of secret value - * @param {String} obj.secretValueTag - tag of secret value - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ - static async updateSecret(updateSecretParams: UpdateSecretParams) { - return await updateSecretHelper(updateSecretParams); - } - - /** - * Delete secret with name [secretName] - * @param {Object} obj - * @param {String} obj.secretName - name of secret to delete - * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to - * @param {String} obj.environment - environment in workspace that secret belongs to - * @param {'shared' | 'personal'} obj.type - type of secret - * @param {AuthData} obj.authData - authentication data on request - * @returns - */ - static async deleteSecret(deleteSecretParams: DeleteSecretParams) { - return await deleteSecretHelper(deleteSecretParams); - } - - static async createSecretBatch(createSecretParams: CreateSecretBatchParams) { - return await createSecretBatchHelper(createSecretParams); - } - - static async updateSecretBatch(updateSecretParams: UpdateSecretBatchParams) { - return await updateSecretBatchHelper(updateSecretParams); - } - - static async deleteSecretBatch(deleteSecretParams: DeleteSecretBatchParams) { - return await deleteSecretBatchHelper(deleteSecretParams); - } -} - -export default SecretService; diff --git a/backend-mongo/src/services/TelemetryService.ts b/backend-mongo/src/services/TelemetryService.ts deleted file mode 100644 index 60cb93216..000000000 --- a/backend-mongo/src/services/TelemetryService.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { PostHog } from "posthog-node"; -import { logger } from "../utils/logging"; -import { AuthData } from "../interfaces/middleware"; -import { - getNodeEnv, - getPostHogHost, - getPostHogProjectApiKey, - getTelemetryEnabled, -} from "../config"; -import { - Identity, - ServiceTokenData, - User -} from "../models"; -import { - AccountNotFoundError, -} from "../utils/errors"; - -class Telemetry { - /** - * Logs telemetry enable/disable notice. - */ - static logTelemetryMessage = async () => { - - if (!(await getTelemetryEnabled())) { - [ - "To improve, Infisical collects telemetry data about general usage.", - "This helps us understand how the product is doing and guide our product development to create the best possible platform; it also helps us demonstrate growth as we support Infisical as open-source software.", - "To opt into telemetry, you can set `TELEMETRY_ENABLED=true` within the environment variables.", - ].forEach(line => logger.info(line)); - } - } - - /** - * Return an instance of the PostHog client initialized. - * @returns - */ - static getPostHogClient = async () => { - let postHogClient: any; - if ((await getNodeEnv()) === "production" && (await getTelemetryEnabled())) { - // case: enable opt-out telemetry in production - postHogClient = new PostHog(await getPostHogProjectApiKey(), { - host: await getPostHogHost(), - }); - } - - return postHogClient; - } - - static getDistinctId = async ({ - authData, - }: { - authData: AuthData; - }) => { - - let distinctId = ""; - if (authData.authPayload instanceof User) { - distinctId = authData.authPayload.email; - } else if (authData.authPayload instanceof ServiceTokenData) { - if (authData.authPayload.user) { - const user = await User.findById(authData.authPayload.user, "email"); - if (!user) throw AccountNotFoundError(); - distinctId = user.email; - } - } else if (authData.authPayload instanceof Identity) { - distinctId = `identity-${authData.authPayload._id.toString()}` - } else { - distinctId = "unknown-auth-data" - } - - return distinctId; - } -} - -export default Telemetry; \ No newline at end of file diff --git a/backend-mongo/src/services/TokenService.ts b/backend-mongo/src/services/TokenService.ts deleted file mode 100644 index 7d0ff881d..000000000 --- a/backend-mongo/src/services/TokenService.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Types } from "mongoose"; -import { createTokenHelper, validateTokenHelper } from "../helpers/token"; - -/** - * Class to handle token actions - * TODO: elaborate more on this class - */ -class TokenService { - /** - * Create a token [token] for type [type] with associated details - * @param {Object} obj - * @param {String} obj.type - type or context of token (e.g. emailConfirmation) - * @param {String} obj.email - email associated with the token - * @param {String} obj.phoneNumber - phone number associated with the token - * @param {Types.ObjectId} obj.organizationId - id of organization associated with the token - * @returns {String} token - the token to create - */ - static async createToken({ - type, - email, - phoneNumber, - organizationId, - }: { - type: "emailConfirmation" | "emailMfa" | "organizationInvitation" | "passwordReset"; - email?: string; - phoneNumber?: string; - organizationId?: Types.ObjectId; - }) { - return await createTokenHelper({ - type, - email, - phoneNumber, - organizationId, - }); - } - - /** - * Validate whether or not token [token] and its associated details match a token in the DB - * @param {Object} obj - * @param {String} obj.type - type or context of token (e.g. emailConfirmation) - * @param {String} obj.email - email associated with the token - * @param {String} obj.phoneNumber - phone number associated with the token - * @param {Types.ObjectId} obj.organizationId - id of organization associated with the token - * @param {String} obj.token - the token to validate - */ - static async validateToken({ - type, - email, - phoneNumber, - organizationId, - token, - }: { - type: "emailConfirmation" | "emailMfa" | "organizationInvitation" | "passwordReset"; - email?: string; - phoneNumber?: string; - organizationId?: Types.ObjectId; - token: string; - }) { - return await validateTokenHelper({ - type, - email, - phoneNumber, - organizationId, - token, - }); - } -} - -export default TokenService; \ No newline at end of file diff --git a/backend-mongo/src/services/WebhookService.ts b/backend-mongo/src/services/WebhookService.ts deleted file mode 100644 index cc2106a1c..000000000 --- a/backend-mongo/src/services/WebhookService.ts +++ /dev/null @@ -1,109 +0,0 @@ -import axios from "axios"; -import crypto from "crypto"; -import { Types } from "mongoose"; -import picomatch from "picomatch"; -import { client, getEncryptionKey, getRootEncryptionKey } from "../config"; -import { IWebhook, Webhook } from "../models"; -import { decryptSymmetric128BitHexKeyUTF8 } from "../utils/crypto"; -import { ENCODING_SCHEME_BASE64, ENCODING_SCHEME_UTF8 } from "../variables"; - -export const triggerWebhookRequest = async ( - { url, encryptedSecretKey, iv, tag, keyEncoding }: IWebhook, - payload: Record -) => { - const headers: Record = {}; - payload["timestamp"] = Date.now(); - - if (encryptedSecretKey) { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - let secretKey; - if (rootEncryptionKey && keyEncoding === ENCODING_SCHEME_BASE64) { - // case: encoding scheme is base64 - secretKey = client.decryptSymmetric(encryptedSecretKey, rootEncryptionKey, iv, tag); - } else if (encryptionKey && keyEncoding === ENCODING_SCHEME_UTF8) { - // case: encoding scheme is utf8 - secretKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: encryptedSecretKey, - iv: iv, - tag: tag, - key: encryptionKey - }); - } - if (secretKey) { - const webhookSign = crypto - .createHmac("sha256", secretKey) - .update(JSON.stringify(payload)) - .digest("hex"); - headers["x-infisical-signature"] = `t=${payload["timestamp"]};${webhookSign}`; - } - } - const req = await axios.post(url, payload, { headers }); - return req; -}; - -export const getWebhookPayload = ( - eventName: string, - workspaceId: string, - environment: string, - secretPath?: string -) => ({ - event: eventName, - project: { - workspaceId, - environment, - secretPath - } -}); - -export const triggerWebhook = async ( - workspaceId: string, - environment: string, - secretPath: string -) => { - const webhooks = await Webhook.find({ workspace: workspaceId, environment, isDisabled: false }); - // TODO(akhilmhdh): implement retry policy later, for that a cron job based approach is needed - // for exponential backoff - const toBeTriggeredHooks = webhooks.filter(({ secretPath: hookSecretPath }) => - picomatch.isMatch(secretPath, hookSecretPath, { strictSlashes: false }) - ); - const webhooksTriggered = await Promise.allSettled( - toBeTriggeredHooks.map((hook) => - triggerWebhookRequest( - hook, - getWebhookPayload("secrets.modified", workspaceId, environment, secretPath) - ) - ) - ); - const successWebhooks: Types.ObjectId[] = []; - const failedWebhooks: Array<{ id: Types.ObjectId; error: string }> = []; - webhooksTriggered.forEach((data, index) => { - if (data.status === "rejected") { - failedWebhooks.push({ id: toBeTriggeredHooks[index]._id, error: data.reason.message }); - return; - } - successWebhooks.push(toBeTriggeredHooks[index]._id); - }); - // dont remove the workspaceid and environment filter. its used to reduce the dataset before $in check - await Webhook.bulkWrite([ - { - updateMany: { - filter: { workspace: workspaceId, environment, _id: { $in: successWebhooks } }, - update: { lastStatus: "success", lastRunErrorMessage: null } - } - }, - ...failedWebhooks.map(({ id, error }) => ({ - updateOne: { - filter: { - workspace: workspaceId, - environment, - _id: id - }, - update: { - lastStatus: "failed", - lastRunErrorMessage: error - } - } - })) - ]); -}; diff --git a/backend-mongo/src/services/health.ts b/backend-mongo/src/services/health.ts deleted file mode 100644 index b9cb90fa2..000000000 --- a/backend-mongo/src/services/health.ts +++ /dev/null @@ -1,32 +0,0 @@ -import mongoose from "mongoose"; -import { createTerminus } from "@godaddy/terminus"; -import { logger } from "../utils/logging"; - -export const setUpHealthEndpoint = (server: T) => { - const onSignal = async () => { - logger.info("Server is starting clean-up"); - return Promise.all([ - new Promise((resolve) => { - if (mongoose.connection && mongoose.connection.readyState == 1) { - mongoose.connection.close() - .then(() => resolve("Database connection closed")); - } else { - resolve("Database connection already closed"); - } - }), - ]); - }; - - const healthCheck = () => { - // `state.isShuttingDown` (boolean) shows whether the server is shutting down or not - // optionally include a resolve value to be included as info in the health check response - return Promise.resolve(); - }; - - createTerminus(server, { - healthChecks: { - "/healthcheck": healthCheck, - onSignal, - }, - }); -}; diff --git a/backend-mongo/src/services/index.ts b/backend-mongo/src/services/index.ts deleted file mode 100644 index 781fb435c..000000000 --- a/backend-mongo/src/services/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import DatabaseService from "./DatabaseService"; -// import { logTelemetryMessage, getPostHogClient } from './TelemetryService'; -import TelemetryService from "./TelemetryService"; -import BotService from "./BotService"; -import BotOrgService from "./BotOrgService"; -import EventService from "./EventService"; -import IntegrationService from "./IntegrationService"; -import TokenService from "./TokenService"; -import SecretService from "./SecretService"; - -export { - TelemetryService, - DatabaseService, - BotService, - BotOrgService, - EventService, - IntegrationService, - TokenService, - SecretService, -} diff --git a/backend-mongo/src/services/smtp.ts b/backend-mongo/src/services/smtp.ts deleted file mode 100644 index 027b81295..000000000 --- a/backend-mongo/src/services/smtp.ts +++ /dev/null @@ -1,82 +0,0 @@ -import nodemailer from "nodemailer"; -import { - SMTP_HOST_GMAIL, - SMTP_HOST_MAILGUN, - SMTP_HOST_OFFICE365, - SMTP_HOST_SENDGRID, - SMTP_HOST_SOCKETLABS, - SMTP_HOST_ZOHOMAIL -} from "../variables"; -import SMTPConnection from "nodemailer/lib/smtp-connection"; -import { - getSmtpHost, - getSmtpPassword, - getSmtpPort, - getSmtpSecure, - getSmtpUsername -} from "../config"; - -export const initSmtp = async () => { - const mailOpts: SMTPConnection.Options = { - host: await getSmtpHost(), - port: await getSmtpPort() - }; - - if ((await getSmtpUsername()) && (await getSmtpPassword())) { - mailOpts.auth = { - user: await getSmtpUsername(), - pass: await getSmtpPassword() - }; - } - - if ((await getSmtpSecure()) ? await getSmtpSecure() : false) { - switch (await getSmtpHost()) { - case SMTP_HOST_SENDGRID: - mailOpts.requireTLS = true; - break; - case SMTP_HOST_MAILGUN: - mailOpts.requireTLS = true; - mailOpts.tls = { - ciphers: "TLSv1.2" - }; - break; - case SMTP_HOST_SOCKETLABS: - mailOpts.requireTLS = true; - mailOpts.tls = { - ciphers: "TLSv1.2" - }; - break; - case SMTP_HOST_ZOHOMAIL: - mailOpts.requireTLS = true; - mailOpts.tls = { - ciphers: "TLSv1.2" - }; - break; - case SMTP_HOST_GMAIL: - mailOpts.requireTLS = true; - mailOpts.tls = { - ciphers: "TLSv1.2" - }; - break; - case SMTP_HOST_OFFICE365: - mailOpts.requireTLS = true; - mailOpts.tls = { - ciphers: "TLSv1.2" - }; - break; - default: - if ((await getSmtpHost()).includes("amazonaws.com")) { - mailOpts.tls = { - ciphers: "TLSv1.2" - }; - } else { - mailOpts.secure = true; - } - break; - } - } - - const transporter = nodemailer.createTransport(mailOpts); - - return transporter; -}; diff --git a/backend-mongo/src/templates/emailMfa.handlebars b/backend-mongo/src/templates/emailMfa.handlebars deleted file mode 100644 index 489c9dd30..000000000 --- a/backend-mongo/src/templates/emailMfa.handlebars +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - MFA Code - - - -

Infisical

-

Sign in attempt requires further verification

-

Your MFA code is below — enter it where you started signing in to Infisical.

-

{{code}}

-

The MFA code will be valid for 2 minutes.

-

Not you? Contact Infisical or your administrator immediately.

- - - \ No newline at end of file diff --git a/backend-mongo/src/templates/emailVerification.handlebars b/backend-mongo/src/templates/emailVerification.handlebars deleted file mode 100644 index fc738d202..000000000 --- a/backend-mongo/src/templates/emailVerification.handlebars +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - Code - - - -

Confirm your email address

-

Your confirmation code is below — enter it in the browser window where you've started signing up for Infisical.

-

{{code}}

-

Questions about setting up Infisical? Email us at support@infisical.com

- - - \ No newline at end of file diff --git a/backend-mongo/src/templates/historicalSecretLeakIncident.handlebars b/backend-mongo/src/templates/historicalSecretLeakIncident.handlebars deleted file mode 100644 index 3cb517a57..000000000 --- a/backend-mongo/src/templates/historicalSecretLeakIncident.handlebars +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - Incident alert: secrets potentially leaked - - - -

Infisical has uncovered {{numberOfSecrets}} secret(s) from historical commits to your repo

-

View leaked secrets

- -

If these are production secrets, please rotate them immediately.

- -

Once you have taken action, be sure to update the status of the risk in your Infisical - dashboard.

- - - \ No newline at end of file diff --git a/backend-mongo/src/templates/newDevice.handlebars b/backend-mongo/src/templates/newDevice.handlebars deleted file mode 100644 index 654bb1ba3..000000000 --- a/backend-mongo/src/templates/newDevice.handlebars +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - Successful login for {{email}} from new device - - - -

Infisical

-

We're verifying a recent login for {{email}}:

-

Timestamp: {{timestamp}}

-

IP address: {{ip}}

-

User agent: {{userAgent}}

-

If you believe that this login is suspicious, please contact Infisical or reset your password immediately.

- - - \ No newline at end of file diff --git a/backend-mongo/src/templates/organizationInvitation.handlebars b/backend-mongo/src/templates/organizationInvitation.handlebars deleted file mode 100644 index b281786f4..000000000 --- a/backend-mongo/src/templates/organizationInvitation.handlebars +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Organization Invitation - - -

Join your organization on Infisical

-

{{inviterFirstName}} ({{inviterEmail}}) has invited you to their Infisical organization — {{organizationName}}

- Join now -

What is Infisical?

-

Infisical is an easy-to-use end-to-end encrypted tool that enables developers to sync and manage their secrets and configs.

- - \ No newline at end of file diff --git a/backend-mongo/src/templates/passwordReset.handlebars b/backend-mongo/src/templates/passwordReset.handlebars deleted file mode 100644 index 3b136e859..000000000 --- a/backend-mongo/src/templates/passwordReset.handlebars +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Account Recovery - - -

Reset your password

-

Someone requested a password reset.

- Reset password -

If you didn't initiate this request, please contact us immediately at team@infisical.com

- - \ No newline at end of file diff --git a/backend-mongo/src/templates/secretLeakIncident.handlebars b/backend-mongo/src/templates/secretLeakIncident.handlebars deleted file mode 100644 index 1bf2d3175..000000000 --- a/backend-mongo/src/templates/secretLeakIncident.handlebars +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - Incident alert: secret leaked - - - -

Infisical has uncovered {{numberOfSecrets}} secret(s) from your recent push

-

View leaked secrets

-

You are receiving this notification because one or more secret leaks have been detected in a recent commit pushed - by {{pusher_name}} ({{pusher_email}}). If - these are test secrets, please add `infisical-scan:ignore` at the end of the line containing the secret as comment - in the given programming. This will prevent future notifications from being sent out for those secret(s).

- -

If these are production secrets, please rotate them immediately.

- -

Once you have taken action, be sure to update the status of the risk in your Infisical - dashboard.

- - - \ No newline at end of file diff --git a/backend-mongo/src/templates/secretReminder.handlebars b/backend-mongo/src/templates/secretReminder.handlebars deleted file mode 100644 index 58f738534..000000000 --- a/backend-mongo/src/templates/secretReminder.handlebars +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - Secret Reminder - - - -

Infisical

-

You have a new secret reminder!

-

You have a new secret reminder from workspace "{{workspaceName}}", in {{organizationName}}

- {{#if reminderNote}} -

Here's the note included with the reminder: {{reminderNote}}

- {{/if}} - - - \ No newline at end of file diff --git a/backend-mongo/src/templates/workspaceInvitation.handlebars b/backend-mongo/src/templates/workspaceInvitation.handlebars deleted file mode 100644 index 60556555c..000000000 --- a/backend-mongo/src/templates/workspaceInvitation.handlebars +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Project Invitation - - -

Join your team on Infisical

-

{{inviterFirstName}} ({{inviterEmail}}) has invited you to their Infisical project — {{workspaceName}}

- Join now -

What is Infisical?

-

Infisical is an easy-to-use end-to-end encrypted tool that enables developers to sync and manage their secrets and configs.

- - \ No newline at end of file diff --git a/backend-mongo/src/types/express/index.d.ts b/backend-mongo/src/types/express/index.d.ts deleted file mode 100644 index 654a24f1d..000000000 --- a/backend-mongo/src/types/express/index.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Types } from "mongoose"; -import { - AuthData -} from "../../interfaces/middleware"; - -declare module "express" { - interface Request { - user?: any; - } -} - -// TODO: fix (any) types -declare global { - namespace Express { - interface Request { - clientIp: any; - user: any; - workspace: any; - membership: any; - targetMembership: any; - isUserCompleted: boolean; - providerAuthToken: any; - organization: any; - membershipOrg: any; - integration: any; - integrationAuth: any; - bot: any; - _secret: any; - secrets: any; - secretSnapshot: any; - serviceToken: any; - accessToken: any; - accessId: any; - serviceTokenData: any; - apiKeyData: any; - query?: any; - tokenVersionId?: Types.ObjectId; - authData: AuthData; - realIP: string; - requestData: { - [key: string]: string - }; - } - } -} diff --git a/backend-mongo/src/types/secret/index.d.ts b/backend-mongo/src/types/secret/index.d.ts deleted file mode 100644 index 05016b38e..000000000 --- a/backend-mongo/src/types/secret/index.d.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Assign, Omit } from "utility-types"; -import { ISecret } from "../../models"; - -// Everything is required, except the omitted types -export type CreateSecretRequestBody = Omit< - ISecret, - "user" | "version" | "environment" | "workspace" ->; - -// Omit the listed properties, then make everything optional and then make _id required -export type ModifySecretRequestBody = Assign< - Partial>, - { _id: string } ->; - -// Used for modeling sanitized secrets before uplaod. To be used for converting user input for uploading -export type SanitizedSecretModify = Partial< - Omit ->; - -// Everything is required, except the omitted types -export type SanitizedSecretForCreate = Omit; - -export interface BatchSecretRequest { - id: string; - method: "POST" | "PATCH" | "DELETE"; - secret: Secret; -} - -export interface BatchSecret { - version?: number; - _id?: string; - user?: string; - environment: string; - workspace?: string; - algorithm?: string; - keyEncoding?: string; - type: "shared" | "personal"; - secretName: string; - secretBlindIndex: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - tags: string[]; - folder: string; -} diff --git a/backend-mongo/src/utils/addDevelopmentUser.ts b/backend-mongo/src/utils/addDevelopmentUser.ts deleted file mode 100644 index b5b0f3495..000000000 --- a/backend-mongo/src/utils/addDevelopmentUser.ts +++ /dev/null @@ -1,147 +0,0 @@ -/************************************************************************************************ -* -* Attention: The credentials below are only for development purposes, it should never be used for production -* -************************************************************************************************/ - -import { Key, Membership, MembershipOrg, Organization, User, Workspace } from "../models"; -import { SecretService } from "../services"; -import { Types } from "mongoose"; -import { getNodeEnv } from "../config"; - -export const testUserEmail = "test@localhost.local" -export const testUserPassword = "testInfisical1" -export const testUserId = "63cefa6ec8d3175601cfa980" -export const testWorkspaceId = "63cefb15c8d3175601cfa989" -export const testOrgId = "63cefb15c8d3175601cfa985" -export const testMembershipId = "63cefb159185d9aa3ef0cf35" -export const testMembershipOrgId = "63cefb159185d9aa3ef0cf31" -export const testWorkspaceKeyId = "63cf48f0225e6955acec5eff" -export const plainTextWorkspaceKey = "543fef8224813a46230b0a50a46c5fb2" - -export const createTestUserForDevelopment = async () => { - if ((await getNodeEnv()) === "development" || (await getNodeEnv()) === "test") { - const testUser = { - _id: testUserId, - email: testUserEmail, - refreshVersion: 0, - encryptedPrivateKey: "ITMdDXtLoxib4+53U/qzvIV/T/UalRwimogFCXv/UsulzEoiKM+aK2aqOb0=", - firstName: "Jake", - iv: "9fp0dZHI+UuHeKkWMDvD6w==", - lastName: "Moni", - publicKey: "cf44BhkybbBfsE0fZHe2jvqtCj6KLXvSq4hVjV0svzk=", - salt: "d8099dc70958090346910fb9639262b83cf526fc9b4555a171b36a9e1bcd0240", - tag: "bQ/UTghqcQHRoSMpLQD33g==", - verifier: "12271fcd50937ca4512e1e3166adaf9d9fc7a5cd0e4c4cb3eda89f35572ede4d9eef23f64aef9220367abff9437b0b6fa55792c442f177201d87051cf77dadade254ff667170440327355fb7d6ac4745d4db302f4843632c2ed5919ebdcff343287a4cd552255d9e3ce81177edefe089617b7616683901475d393405f554634b9bf9230c041ac85624f37a60401be20b78044932580ae0868323be3749fbf856df1518153ba375fec628275f0c445f237446ea4aa7f12c1aa1d6b5fd74b7f2e88d062845a19819ec63f2d2ed9e9f37c055149649461d997d2ae1482f53b04f9de7493efbb9686fb19b2d559b9aa2b502c22dec83f9fc43290dfea89a1dc6f03580b3642b3824513853e81a441be9a0b2fde2231bac60f3287872617a36884697805eeea673cf1a351697834484ada0f282e4745015c9c2928d61e6d092f1b9c3a27eda8413175d23bb2edae62f82ccaf52bf5a6a90344a766c7e4ebf65dae9ae90b2ad4ae65dbf16e3a6948e429771cc50307ae86d454f71a746939ed061f080dd3ae369c1a0739819aca17af46a085bac1f2a5d936d198e7951a8ac3bb38b893665fe7312835abd3f61811f81efa2a8761af5070085f9b6adcca80bf9b0d81899c3d41487fba90728bb24eceb98bd69770360a232624133700ceb4d153f2ad702e0a5b7dfaf97d20bc8aa71dc8c20024a58c06a8fecdad18cb5a2f89c51eaf7", - } - - const testWorkspaceKey = { - _id: new Types.ObjectId(testWorkspaceKeyId), - workspace: testWorkspaceId, - encryptedKey: "96ZIRSU21CjVzIQ4Yp994FGWQvDdyK3gq+z+NCaJLK0ByTlvUePmf+AYGFJjkAdz", - nonce: "1jhCGqg9Wx3n0OtVxbDgiYYGq4S3EdgO", - sender: "63cefa6ec8d3175601cfa980", - receiver: "63cefa6ec8d3175601cfa980", - } - - const testWorkspace = { - _id: new Types.ObjectId(testWorkspaceId), - name: "Example Project", - organization: testOrgId, - environments: [ - { - _id: "63cefb15c8d3175601cfa98a", - name: "Development", - slug: "dev", - }, - { - _id: "63cefb15c8d3175601cfa98b", - name: "Test", - slug: "test", - }, - { - _id: "63cefb15c8d3175601cfa98c", - name: "Staging", - slug: "staging", - }, - { - _id: "63cefb15c8d3175601cfa98d", - name: "Production", - slug: "prod", - }, - ], - } - - const testOrg = { - _id: testOrgId, - name: "Jake's organization", - } - - const testMembershipOrg = { - _id: testMembershipOrgId, - organization: testOrgId, - role: "admin", - status: "accepted", - user: testUserId, - } - - const testMembership = { - _id: testMembershipId, - role: "admin", - user: testUserId, - workspace: testWorkspaceId, - } - - try { - // create user if not exist - const userInDB = await User.findById(testUserId) - if (!userInDB) { - await User.create(testUser) - } - - // create org if not exist - const orgInDB = await Organization.findById(testOrgId) - if (!orgInDB) { - await Organization.create(testOrg) - } - - // create membership org if not exist - const membershipOrgInDB = await MembershipOrg.findById(testMembershipOrgId) - if (!membershipOrgInDB) { - await MembershipOrg.create(testMembershipOrg) - } - - // create membership - const membershipInDB = await Membership.findById(testMembershipId) - if (!membershipInDB) { - await Membership.create(testMembership) - } - - // create workspace if not exist - const workspaceInDB = await Workspace.findById(testWorkspaceId) - if (!workspaceInDB) { - const workspace = await Workspace.create(testWorkspace) - - // initialize blind index salt for workspace - await SecretService.createSecretBlindIndexData({ - workspaceId: workspace._id, - }); - } - - // create workspace key if not exist - const workspaceKeyInDB = await Key.findById(testWorkspaceKeyId) - if (!workspaceKeyInDB) { - await Key.create(testWorkspaceKey) - } - - /* eslint-disable no-console */ - console.info(`DEVELOPMENT MODE DETECTED: You may login with test user with email: ${testUserEmail} and password: ${testUserPassword}`) - /* eslint-enable no-console */ - - } catch (e) { - /* eslint-disable no-console */ - console.error(`Unable to create test user while booting up [err=${e}]`) - /* eslint-enable no-console */ - } - } -} \ No newline at end of file diff --git a/backend-mongo/src/utils/aes-gcm.ts b/backend-mongo/src/utils/aes-gcm.ts deleted file mode 100644 index 21734611b..000000000 --- a/backend-mongo/src/utils/aes-gcm.ts +++ /dev/null @@ -1,41 +0,0 @@ -import crypto = require("crypto"); - -const ALGORITHM = "aes-256-gcm"; -const BLOCK_SIZE_BYTES = 16; - -export default class AesGCM { - static encrypt( - text: string, - secret: string - ): { ciphertext: string; iv: string; tag: string } { - const iv = crypto.randomBytes(BLOCK_SIZE_BYTES); - const cipher = crypto.createCipheriv(ALGORITHM, secret, iv); - - let ciphertext = cipher.update(text, "utf8", "base64"); - ciphertext += cipher.final("base64"); - return { - ciphertext, - iv: iv.toString("base64"), - tag: cipher.getAuthTag().toString("base64"), - }; - } - - static decrypt( - ciphertext: string, - iv: string, - tag: string, - secret: string - ): string { - const decipher = crypto.createDecipheriv( - ALGORITHM, - secret, - Buffer.from(iv, "base64") - ); - decipher.setAuthTag(Buffer.from(tag, "base64")); - - let cleartext = decipher.update(ciphertext, "base64", "utf8"); - cleartext += decipher.final("utf8"); - - return cleartext; - } -} diff --git a/backend-mongo/src/utils/authn/authModeValidators/apiKey.ts b/backend-mongo/src/utils/authn/authModeValidators/apiKey.ts deleted file mode 100644 index a1bfd28b8..000000000 --- a/backend-mongo/src/utils/authn/authModeValidators/apiKey.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Types } from "mongoose"; -import { - APIKeyData, - IUser, - User -} from "../../../models"; -import { AccountNotFoundError, UnauthorizedRequestError } from "../../errors"; -import bcrypt from "bcrypt"; - -interface ValidateAPIKeyParams { - authTokenValue: string; -} - -export const validateAPIKey = async ({ - authTokenValue -}: ValidateAPIKeyParams) => { - - const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split(".", 3); - - let apiKeyData = await APIKeyData - .findById(TOKEN_IDENTIFIER, "+secretHash +expiresAt") - .populate<{ user: IUser }>("user", "+publicKey"); - - if (!apiKeyData) { - throw UnauthorizedRequestError(); - } else if (apiKeyData?.expiresAt && new Date(apiKeyData.expiresAt) < new Date()) { - // case: API key expired - await APIKeyData.findByIdAndDelete(apiKeyData._id); - throw UnauthorizedRequestError(); - } - - const isMatch = await bcrypt.compare(TOKEN_SECRET, apiKeyData.secretHash); - if (!isMatch) throw UnauthorizedRequestError(); - - apiKeyData = await APIKeyData.findOneAndUpdate({ - _id: new Types.ObjectId(TOKEN_IDENTIFIER), - }, { - lastUsed: new Date(), - }, { - new: true, - }); - - if (!apiKeyData) throw UnauthorizedRequestError(); - - const user = await User.findById(apiKeyData.user).select("+publicKey"); - - if (!user) throw AccountNotFoundError(); - - return user; -} \ No newline at end of file diff --git a/backend-mongo/src/utils/authn/authModeValidators/apiKeyV2.ts b/backend-mongo/src/utils/authn/authModeValidators/apiKeyV2.ts deleted file mode 100644 index 2b57542b9..000000000 --- a/backend-mongo/src/utils/authn/authModeValidators/apiKeyV2.ts +++ /dev/null @@ -1,39 +0,0 @@ -import jwt from "jsonwebtoken"; -import { APIKeyDataV2, User } from "../../../models"; -import { getAuthSecret } from "../../../config"; -import { AuthTokenType } from "../../../variables"; -import { AccountNotFoundError, UnauthorizedRequestError } from "../../errors"; - -interface ValidateAPIKeyV2Params { - authTokenValue: string; -} - -export const validateAPIKeyV2 = async ({ - authTokenValue -}: ValidateAPIKeyV2Params) => { - - const decodedToken = ( - jwt.verify(authTokenValue, await getAuthSecret()) - ); - - if (decodedToken.authTokenType !== AuthTokenType.API_KEY) throw UnauthorizedRequestError(); - - const apiKeyData = await APIKeyDataV2.findByIdAndUpdate( - decodedToken.apiKeyDataId, - { - lastUsed: new Date(), - $inc: { usageCount: 1 } - }, - { - new: true - } - ); - - if (!apiKeyData) throw UnauthorizedRequestError(); - - const user = await User.findById(apiKeyData.user).select("+publicKey"); - - if (!user) throw AccountNotFoundError(); - - return user; -} diff --git a/backend-mongo/src/utils/authn/authModeValidators/identity.ts b/backend-mongo/src/utils/authn/authModeValidators/identity.ts deleted file mode 100644 index c85227e32..000000000 --- a/backend-mongo/src/utils/authn/authModeValidators/identity.ts +++ /dev/null @@ -1,104 +0,0 @@ -import jwt from "jsonwebtoken"; -import { IIdentity, IdentityAccessToken } from "../../../models"; -import { getAuthSecret } from "../../../config"; -import { AuthTokenType } from "../../../variables"; -import { UnauthorizedRequestError } from "../../errors"; -import { checkIPAgainstBlocklist } from "../../../utils/ip"; - -interface ValidateIdentityParams { - authTokenValue: string; - ipAddress: string; -} - -export const validateIdentity = async ({ - authTokenValue, - ipAddress -}: ValidateIdentityParams) => { - const decodedToken = ( - jwt.verify(authTokenValue, await getAuthSecret()) - ); - - if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) throw UnauthorizedRequestError(); - - const identityAccessToken = await IdentityAccessToken - .findOne({ - _id: decodedToken.identityAccessTokenId, - isAccessTokenRevoked: false - }) - .populate<{ identity: IIdentity }>("identity"); - - if (!identityAccessToken || !identityAccessToken?.identity) throw UnauthorizedRequestError(); - - const { - accessTokenNumUsesLimit, - accessTokenNumUses, - accessTokenTTL, - accessTokenLastRenewedAt, - accessTokenMaxTTL, - createdAt: accessTokenCreatedAt - } = identityAccessToken; - - checkIPAgainstBlocklist({ - ipAddress, - trustedIps: identityAccessToken.accessTokenTrustedIps - }); - - // ttl check - if (accessTokenTTL > 0) { - const currentDate = new Date(); - if (accessTokenLastRenewedAt) { - // access token has been renewed - const accessTokenRenewed = new Date(accessTokenLastRenewedAt); - const ttlInMilliseconds = accessTokenTTL * 1000; - const expirationDate = new Date(accessTokenRenewed.getTime() + ttlInMilliseconds); - - if (currentDate > expirationDate) throw UnauthorizedRequestError({ - message: "Failed to authenticate identity access token due to TTL expiration" - }); - } else { - // access token has never been renewed - const accessTokenCreated = new Date(accessTokenCreatedAt); - const ttlInMilliseconds = accessTokenTTL * 1000; - const expirationDate = new Date(accessTokenCreated.getTime() + ttlInMilliseconds); - - if (currentDate > expirationDate) throw UnauthorizedRequestError({ - message: "Failed to authenticate identity access token due to TTL expiration" - }); - } - } - - // max ttl check - if (accessTokenMaxTTL > 0) { - const accessTokenCreated = new Date(accessTokenCreatedAt); - const ttlInMilliseconds = accessTokenMaxTTL * 1000; - const currentDate = new Date(); - const expirationDate = new Date(accessTokenCreated.getTime() + ttlInMilliseconds); - - if (currentDate > expirationDate) throw UnauthorizedRequestError({ - message: "Failed to authenticate identity access token due to Max TTL expiration" - }); - } - - // num uses check - if ( - accessTokenNumUsesLimit > 0 - && accessTokenNumUses === accessTokenNumUsesLimit - ) { - throw UnauthorizedRequestError({ - message: "Failed to authenticate MI access token due to access token number of uses limit reached" - }); - } - - await IdentityAccessToken.findByIdAndUpdate( - identityAccessToken._id, - { - accessTokenLastUsedAt: new Date(), - $inc: { accessTokenNumUses: 1 } - }, - { - new: true - } - ); - - return identityAccessToken.identity; -} \ No newline at end of file diff --git a/backend-mongo/src/utils/authn/authModeValidators/index.ts b/backend-mongo/src/utils/authn/authModeValidators/index.ts deleted file mode 100644 index 170a8ce59..000000000 --- a/backend-mongo/src/utils/authn/authModeValidators/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./apiKey"; -export * from "./apiKeyV2"; -export * from "./jwt"; -export * from "./serviceTokenV2"; -export * from "./identity"; \ No newline at end of file diff --git a/backend-mongo/src/utils/authn/authModeValidators/jwt.ts b/backend-mongo/src/utils/authn/authModeValidators/jwt.ts deleted file mode 100644 index f9f0971fc..000000000 --- a/backend-mongo/src/utils/authn/authModeValidators/jwt.ts +++ /dev/null @@ -1,41 +0,0 @@ -import jwt from "jsonwebtoken"; -import { Types } from "mongoose"; -import { TokenVersion, User } from "../../../models"; -import { getAuthSecret } from "../../../config"; -import { AuthTokenType } from "../../../variables"; -import { AccountNotFoundError, UnauthorizedRequestError } from "../../errors"; - -interface ValidateJWTParams { - authTokenValue: string; -} - -export const validateJWT = async ({ - authTokenValue -}: ValidateJWTParams) => { - - const decodedToken = ( - jwt.verify(authTokenValue, await getAuthSecret()) - ); - - if (decodedToken.authTokenType !== AuthTokenType.ACCESS_TOKEN) throw UnauthorizedRequestError(); - - const tokenVersion = await TokenVersion.findOneAndUpdate({ - _id: new Types.ObjectId(decodedToken.tokenVersionId), - user: decodedToken.userId - }, { - lastUsed: new Date(), - }); - - if (!tokenVersion) throw UnauthorizedRequestError(); - if (decodedToken.accessVersion !== tokenVersion.accessVersion) throw UnauthorizedRequestError(); - - const user = await User.findOne({ - _id: new Types.ObjectId(decodedToken.userId), - }).select("+publicKey"); - - if (!user) throw AccountNotFoundError({ message: "Failed to find user" }); - - if (!user?.publicKey) throw UnauthorizedRequestError({ message: "Failed to authenticate user with partially set up account" }); - - return user; -} diff --git a/backend-mongo/src/utils/authn/authModeValidators/serviceTokenV2.ts b/backend-mongo/src/utils/authn/authModeValidators/serviceTokenV2.ts deleted file mode 100644 index 0ebed5963..000000000 --- a/backend-mongo/src/utils/authn/authModeValidators/serviceTokenV2.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Types } from "mongoose"; -import { ServiceTokenData } from "../../../models"; -import { ResourceNotFoundError, UnauthorizedRequestError } from "../../errors"; -import bcrypt from "bcrypt"; - -interface ValidateServiceTokenV2Params { - authTokenValue: string; -} - -export const validateServiceTokenV2 = async ({ - authTokenValue -}: ValidateServiceTokenV2Params) => { - const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split(".", 3); - - const serviceTokenData = await ServiceTokenData - .findById(TOKEN_IDENTIFIER, "+secretHash +expiresAt") - - if (!serviceTokenData) { - throw UnauthorizedRequestError(); - } else if (serviceTokenData?.expiresAt && new Date(serviceTokenData.expiresAt) < new Date()) { - // case: service token expired - await ServiceTokenData.findByIdAndDelete(serviceTokenData._id); - throw UnauthorizedRequestError({ - message: "Failed to authenticate expired service token", - }); - } - - const isMatch = await bcrypt.compare(TOKEN_SECRET, serviceTokenData.secretHash); - if (!isMatch) throw UnauthorizedRequestError(); - - const serviceTokenDataToReturn = await ServiceTokenData - .findOneAndUpdate({ - _id: new Types.ObjectId(TOKEN_IDENTIFIER), - }, { - lastUsed: new Date(), - }, { - new: true, - }) - .select("+encryptedKey +iv +tag") - - if (!serviceTokenDataToReturn) throw ResourceNotFoundError(); - - return serviceTokenDataToReturn; -} \ No newline at end of file diff --git a/backend-mongo/src/utils/authn/helpers/authDataExtractors.ts b/backend-mongo/src/utils/authn/helpers/authDataExtractors.ts deleted file mode 100644 index e928108c3..000000000 --- a/backend-mongo/src/utils/authn/helpers/authDataExtractors.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { AuthData } from "../../../interfaces/middleware"; -import { - Identity, - ServiceTokenData, - User -} from "../../../models"; - -/** - * Returns an object containing the id of the authentication data payload - * @param {AuthData} authData - authentication data object - * @returns - */ - export const getAuthDataPayloadIdObj = (authData: AuthData) => { - if (authData.authPayload instanceof User) { - return { userId: authData.authPayload._id }; - } - - if (authData.authPayload instanceof ServiceTokenData) { - return { serviceTokenDataId: authData.authPayload._id }; - } - - if (authData.authPayload instanceof Identity) { - return { serviceTokenDataId: authData.authPayload._id }; - } -}; - -/** - * Returns an object containing the user associated with the authentication data payload - * @param {AuthData} authData - authentication data object - * @returns - */ -export const getAuthDataPayloadUserObj = (authData: AuthData) => { - if (authData.authPayload instanceof User) { - return { user: authData.authPayload._id }; - } - - if (authData.authPayload instanceof ServiceTokenData) { - return { user: authData.authPayload.user }; - } - - if (authData.authPayload instanceof Identity) { - return {}; - } -} \ No newline at end of file diff --git a/backend-mongo/src/utils/authn/helpers/index.ts b/backend-mongo/src/utils/authn/helpers/index.ts deleted file mode 100644 index d3df5ffa5..000000000 --- a/backend-mongo/src/utils/authn/helpers/index.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { AuthData } from "../../../interfaces/middleware"; -import jwt from "jsonwebtoken"; -import { getAuthSecret } from "../../../config"; -import { ActorType } from "../../../ee/models"; -import { AuthMode, AuthTokenType } from "../../../variables"; -import { UnauthorizedRequestError } from "../../errors"; -import { - validateAPIKey, - validateAPIKeyV2, - validateIdentity, - validateJWT, - validateServiceTokenV2 -} from "../authModeValidators"; -import { getUserAgentType } from "../../posthog"; - -export * from "./authDataExtractors"; - -interface ExtractAuthModeParams { - headers: { [key: string]: string | string[] | undefined }; -} - -interface ExtractAuthModeReturn { - authMode: AuthMode; - authTokenValue: string; -} - -interface GetAuthDataParams { - authMode: AuthMode; - authTokenValue: string; - ipAddress: string; - userAgent: string; -} - -/** - * Returns the recognized authentication mode based on token in [headers]; accepted token types include: - * - SERVICE_TOKEN - * - API_KEY - * - JWT - * - IDENTITY_ACCESS_TOKEN (from identity) - * - API_KEY_V2 - * @param {Object} params - * @param {Object.} params.headers - The HTTP request headers, usually from Express's `req.headers`. - * @returns {Promise} The derived authentication mode based on the headers. - * @throws {UnauthorizedError} Throws an error if no applicable authMode is found. - */ -export const extractAuthMode = async ({ - headers -}: ExtractAuthModeParams): Promise => { - const apiKey = headers["x-api-key"] as string; - const authHeader = headers["authorization"] as string; - - if (apiKey) { - return { authMode: AuthMode.API_KEY, authTokenValue: apiKey }; - } - - if (!authHeader) - throw UnauthorizedRequestError({ - message: "Failed to authenticate unknown authentication method" - }); - - if (!authHeader.startsWith("Bearer ")) - throw UnauthorizedRequestError({ - message: "Failed to authenticate unknown authentication method" - }); - - const authTokenValue = authHeader.slice(7); - - if (authTokenValue.startsWith("st.")) { - return { authMode: AuthMode.SERVICE_TOKEN, authTokenValue }; - } - - const decodedToken = jwt.verify(authTokenValue, await getAuthSecret()); - - switch (decodedToken.authTokenType) { - case AuthTokenType.ACCESS_TOKEN: - return { authMode: AuthMode.JWT, authTokenValue }; - case AuthTokenType.API_KEY: - return { authMode: AuthMode.API_KEY_V2, authTokenValue }; - case AuthTokenType.IDENTITY_ACCESS_TOKEN: - return { authMode: AuthMode.IDENTITY_ACCESS_TOKEN, authTokenValue }; - default: - throw UnauthorizedRequestError({ - message: "Failed to authenticate unknown authentication method" - }); - } -}; - -export const getAuthData = async ({ - authMode, - authTokenValue, - ipAddress, - userAgent -}: GetAuthDataParams): Promise => { - const userAgentType = getUserAgentType(userAgent); - - switch (authMode) { - case AuthMode.SERVICE_TOKEN: { - const serviceTokenData = await validateServiceTokenV2({ - authTokenValue - }); - - return { - actor: { - type: ActorType.SERVICE, - metadata: { - serviceId: serviceTokenData._id.toString(), - name: serviceTokenData.name - } - }, - authPayload: serviceTokenData, - ipAddress, - userAgent, - userAgentType - }; - } - case AuthMode.IDENTITY_ACCESS_TOKEN: { - const identity = await validateIdentity({ - authTokenValue, - ipAddress - }); - - return { - actor: { - type: ActorType.IDENTITY, - metadata: { - identityId: identity._id.toString(), - name: identity.name - } - }, - authPayload: identity, - ipAddress, - userAgent, - userAgentType - }; - } - case AuthMode.API_KEY: { - const user = await validateAPIKey({ - authTokenValue - }); - - return { - actor: { - type: ActorType.USER, - metadata: { - userId: user._id.toString(), - email: user.email - } - }, - authPayload: user, - ipAddress, - userAgent, - userAgentType - }; - } - case AuthMode.API_KEY_V2: { - const user = await validateAPIKeyV2({ - authTokenValue - }); - - return { - actor: { - type: ActorType.USER, - metadata: { - userId: user._id.toString(), - email: user.email - } - }, - authPayload: user, - ipAddress, - userAgent, - userAgentType - }; - } - case AuthMode.JWT: { - const user = await validateJWT({ - authTokenValue - }); - - return { - actor: { - type: ActorType.USER, - metadata: { - userId: user._id.toString(), - email: user.email - } - }, - authPayload: user, - ipAddress, - userAgent, - userAgentType - }; - } - } -}; diff --git a/backend-mongo/src/utils/authn/passport/github.ts b/backend-mongo/src/utils/authn/passport/github.ts deleted file mode 100644 index 2f0a9b1ab..000000000 --- a/backend-mongo/src/utils/authn/passport/github.ts +++ /dev/null @@ -1,60 +0,0 @@ -import express from "express"; -import passport from "passport"; -import { - getClientIdGitHubLogin, - getClientSecretGitHubLogin, -} from "../../../config"; -import { standardRequest } from "../../../config/request"; -import { AuthMethod } from "../../../models"; -import { INTEGRATION_GITHUB_API_URL } from "../../../variables"; -import { handleSSOUserTokenFlow } from "./helpers"; - -// eslint-disable-next-line @typescript-eslint/no-var-requires -const GitHubStrategy = require("passport-github").Strategy; - -export const initializeGitHubStrategy = async () => { - const clientIdGitHubLogin = await getClientIdGitHubLogin(); - const clientSecretGitHubLogin = await getClientSecretGitHubLogin(); - if (clientIdGitHubLogin && clientSecretGitHubLogin) { - passport.use( - new GitHubStrategy({ - passReqToCallback: true, - clientID: clientIdGitHubLogin, - clientSecret: clientSecretGitHubLogin, - callbackURL: "/api/v1/sso/github", - scope: ["user:email"] - }, async (req : express.Request, accessToken : any, refreshToken : any, profile : any, done : any) => { - interface GitHubEmail { - email: string; - primary: boolean; - verified: boolean; - visibility: null | string; - } - - const { data }: { data: GitHubEmail[] } = await standardRequest.get( - `${INTEGRATION_GITHUB_API_URL}/user/emails`, - { - headers: { - Authorization: `Bearer ${accessToken}` - } - } - ); - - const primaryEmail = data.filter((gitHubEmail: GitHubEmail) => gitHubEmail.primary)[0]; - const email = primaryEmail.email; - - const { isUserCompleted, providerAuthToken } = await handleSSOUserTokenFlow({ - email, - firstName: profile.displayName, - lastName: "", - authMethod: AuthMethod.GITHUB, - callbackPort: req.query.state as string - }); - - req.isUserCompleted = isUserCompleted; - req.providerAuthToken = providerAuthToken; - return done(null, profile); - }) - ); - } -} \ No newline at end of file diff --git a/backend-mongo/src/utils/authn/passport/gitlab.ts b/backend-mongo/src/utils/authn/passport/gitlab.ts deleted file mode 100644 index 22851a450..000000000 --- a/backend-mongo/src/utils/authn/passport/gitlab.ts +++ /dev/null @@ -1,44 +0,0 @@ -import express from "express"; -import passport from "passport"; -import { - getClientIdGitLabLogin, - getClientSecretGitLabLogin, - getUrlGitLabLogin -} from "../../../config"; -import { AuthMethod } from "../../../models"; -import { handleSSOUserTokenFlow } from "./helpers"; - -// eslint-disable-next-line @typescript-eslint/no-var-requires -const GitLabStrategy = require("passport-gitlab2").Strategy; - -export const initializeGitLabStrategy = async () => { - const urlGitLab = await getUrlGitLabLogin(); - const clientIdGitLabLogin = await getClientIdGitLabLogin(); - const clientSecretGitLabLogin = await getClientSecretGitLabLogin(); - - if (urlGitLab && clientIdGitLabLogin && clientSecretGitLabLogin) { - passport.use( - new GitLabStrategy({ - passReqToCallback: true, - clientID: clientIdGitLabLogin, - clientSecret: clientSecretGitLabLogin, - callbackURL: "/api/v1/sso/gitlab", - baseURL: urlGitLab - }, async (req : express.Request, accessToken : any, refreshToken : any, profile : any, done : any) => { - const email = profile.emails[0].value; - - const { isUserCompleted, providerAuthToken } = await handleSSOUserTokenFlow({ - email, - firstName: profile.displayName, - lastName: "", - authMethod: AuthMethod.GITLAB, - callbackPort: req.query.state as string - }); - - req.isUserCompleted = isUserCompleted; - req.providerAuthToken = providerAuthToken; - return done(null, profile); - }) - ); - } -} \ No newline at end of file diff --git a/backend-mongo/src/utils/authn/passport/google.ts b/backend-mongo/src/utils/authn/passport/google.ts deleted file mode 100644 index 126f2f9fb..000000000 --- a/backend-mongo/src/utils/authn/passport/google.ts +++ /dev/null @@ -1,48 +0,0 @@ -import express from "express"; -import passport from "passport"; -import { getClientIdGoogleLogin, getClientSecretGoogleLogin } from "../../../config"; -import { AuthMethod } from "../../../models"; - -import { handleSSOUserTokenFlow } from "./helpers"; - -// eslint-disable-next-line @typescript-eslint/no-var-requires -const GoogleStrategy = require("passport-google-oauth20").Strategy; - -export const initializeGoogleStrategy = async () => { - const clientIdGoogleLogin = await getClientIdGoogleLogin(); - const clientSecretGoogleLogin = await getClientSecretGoogleLogin(); - - if (clientIdGoogleLogin && clientSecretGoogleLogin) { - passport.use(new GoogleStrategy({ - passReqToCallback: true, - clientID: clientIdGoogleLogin, - clientSecret: clientSecretGoogleLogin, - callbackURL: "/api/v1/sso/google", - scope: ["profile", " email"], - }, async ( - req: express.Request, - accessToken: string, - refreshToken: string, - profile: any, - done: any - ) => { - try { - const email = profile.emails[0].value; - - const { isUserCompleted, providerAuthToken } = await handleSSOUserTokenFlow({ - email, - firstName: profile.name.givenName, - lastName: profile.name.familyName, - authMethod: AuthMethod.GOOGLE, - callbackPort: req.query.state as string - }); - - req.isUserCompleted = isUserCompleted; - req.providerAuthToken = providerAuthToken; - done(null, profile); - } catch (err) { - done(null, false); - } - })); - } -} \ No newline at end of file diff --git a/backend-mongo/src/utils/authn/passport/helpers.ts b/backend-mongo/src/utils/authn/passport/helpers.ts deleted file mode 100644 index b6e672caa..000000000 --- a/backend-mongo/src/utils/authn/passport/helpers.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { AuthMethod, User } from "../../../models"; -import { createToken } from "../../../helpers/auth"; -import { AuthTokenType } from "../../../variables"; -import { getAuthSecret, getJwtProviderAuthLifetime } from "../../../config"; -import { getServerConfig } from "../../../config/serverConfig"; - -interface SSOUserTokenFlowParams { - email: string; - firstName: string; - lastName: string; - authMethod: AuthMethod; - callbackPort?: string; -} - -export const handleSSOUserTokenFlow = async ({ - email, - firstName, - lastName, - authMethod, - callbackPort -}: SSOUserTokenFlowParams) => { - let user = await User.findOne({ - email - }).select("+publicKey"); - - const serverCfg = getServerConfig(); - if (!user && !serverCfg.allowSignUp) throw new Error("User signup disabled"); - - if (!user) { - user = await new User({ - email, - authMethods: [authMethod], - firstName, - lastName - }).save(); - } - - let isLinkingRequired = false; - if (!user.authMethods.includes(authMethod)) { - isLinkingRequired = true; - } - - const isUserCompleted = !!user.publicKey; - const providerAuthToken = createToken({ - payload: { - authTokenType: AuthTokenType.PROVIDER_TOKEN, - userId: user._id.toString(), - email: user.email, - firstName: user.firstName, - lastName: user.lastName, - authMethod, - isUserCompleted, - isLinkingRequired, - ...(callbackPort - ? { - callbackPort - } - : {}) - }, - expiresIn: await getJwtProviderAuthLifetime(), - secret: await getAuthSecret() - }); - - return { isUserCompleted, providerAuthToken }; -}; diff --git a/backend-mongo/src/utils/authn/passport/index.ts b/backend-mongo/src/utils/authn/passport/index.ts deleted file mode 100644 index 4346c7d67..000000000 --- a/backend-mongo/src/utils/authn/passport/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { initializeGoogleStrategy } from "./google"; -export { initializeGitHubStrategy } from "./github"; -export { initializeGitLabStrategy } from "./gitlab"; -export { initializeSamlStrategy } from "./saml"; diff --git a/backend-mongo/src/utils/authn/passport/saml.ts b/backend-mongo/src/utils/authn/passport/saml.ts deleted file mode 100644 index 74a2242e2..000000000 --- a/backend-mongo/src/utils/authn/passport/saml.ts +++ /dev/null @@ -1,174 +0,0 @@ -import passport from "passport"; -import { - getAuthSecret, - getJwtProviderAuthLifetime, - getSiteURL -} from "../../../config"; -import { - AuthMethod, - MembershipOrg, - Organization, - User -} from "../../../models"; -import { - createToken -} from "../../../helpers/auth"; -import { - ACCEPTED, - AuthTokenType, - INVITED, - MEMBER -} from "../../../variables"; -import { Types } from "mongoose"; -import { getSSOConfigHelper } from "../../../ee/helpers/organizations"; -import { InternalServerError, OrganizationNotFoundError } from "../../errors"; - -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { MultiSamlStrategy } = require("@node-saml/passport-saml"); - -export const initializeSamlStrategy = async () => { - passport.use("saml", new MultiSamlStrategy( - { - passReqToCallback: true, - getSamlOptions: async (req: any, done: any) => { - const { ssoIdentifier } = req.params; - - const ssoConfig = await getSSOConfigHelper({ - ssoConfigId: new Types.ObjectId(ssoIdentifier) - }); - - interface ISAMLConfig { - callbackUrl: string; - entryPoint: string; - issuer: string; - cert: string; - audience: string; - wantAuthnResponseSigned?: boolean; - } - - const samlConfig: ISAMLConfig = ({ - callbackUrl: `${await getSiteURL()}/api/v1/sso/saml2/${ssoIdentifier}`, - entryPoint: ssoConfig.entryPoint, - issuer: ssoConfig.issuer, - cert: ssoConfig.cert, - audience: await getSiteURL() - }); - - if (ssoConfig.authProvider.toString() === AuthMethod.JUMPCLOUD_SAML.toString()) { - samlConfig.wantAuthnResponseSigned = false; - } - - if (ssoConfig.authProvider.toString() === AuthMethod.AZURE_SAML.toString()) { - if (req.body.RelayState && JSON.parse(req.body.RelayState).spInitiated) { - samlConfig.audience = `spn:${ssoConfig.issuer}`; - } - } - - req.ssoConfig = ssoConfig; - - done(null, samlConfig); - }, - }, - async (req: any, profile: any, done: any) => { - if (!req.ssoConfig.isActive) return done(InternalServerError()); - - const organization = await Organization.findById(req.ssoConfig.organization); - - if (!organization) return done(OrganizationNotFoundError()); - - const email = profile?.email ?? profile?.emailAddress // emailRippling is added because in Rippling the field `email` reserved - const firstName = profile.firstName; - const lastName = profile.lastName; - - let user = await User.findOne({ - email - }).select("+publicKey"); - - if (user) { - // if user does not have SAML enabled then update - const hasSamlEnabled = user.authMethods - .some( - (authMethod: AuthMethod) => [ - AuthMethod.OKTA_SAML, - AuthMethod.AZURE_SAML, - AuthMethod.JUMPCLOUD_SAML - ].includes(authMethod) - ); - - if (!hasSamlEnabled) { - await User.findByIdAndUpdate( - user._id, - { - authMethods: [req.ssoConfig.authProvider] - }, - { - new: true - } - ); - } - - let membershipOrg = await MembershipOrg.findOne( - { - user: user._id, - organization: organization._id - } - ); - - if (!membershipOrg) { - membershipOrg = await new MembershipOrg({ - inviteEmail: email, - user: user._id, - organization: organization._id, - role: MEMBER, - status: ACCEPTED - }).save(); - } - - if (membershipOrg.status === INVITED) { - membershipOrg.status = ACCEPTED; - await membershipOrg.save(); - } - } else { - user = await new User({ - email, - authMethods: [req.ssoConfig.authProvider], - firstName, - lastName - }).save(); - - await new MembershipOrg({ - inviteEmail: email, - user: user._id, - organization: organization._id, - role: MEMBER, - status: INVITED - }).save(); - } - - const isUserCompleted = !!user.publicKey; - const providerAuthToken = createToken({ - payload: { - authTokenType: AuthTokenType.PROVIDER_TOKEN, - userId: user._id.toString(), - email: user.email, - firstName, - lastName, - organizationName: organization?.name, - organizationId: organization?._id, - authMethod: req.ssoConfig.authProvider, - isUserCompleted, - ...(req.body.RelayState ? { - callbackPort: JSON.parse(req.body.RelayState).callbackPort as string - } : {}) - }, - expiresIn: await getJwtProviderAuthLifetime(), - secret: await getAuthSecret(), - }); - - req.isUserCompleted = isUserCompleted; - req.providerAuthToken = providerAuthToken; - - done(null, profile); - } - )); -} \ No newline at end of file diff --git a/backend-mongo/src/utils/crypto/index.ts b/backend-mongo/src/utils/crypto/index.ts deleted file mode 100644 index 9194bd7e8..000000000 --- a/backend-mongo/src/utils/crypto/index.ts +++ /dev/null @@ -1,165 +0,0 @@ -import crypto from "crypto"; -import nacl from "tweetnacl"; -import util from "tweetnacl-util"; -import { - IDecryptAsymmetricInput, - IDecryptSymmetricInput, - IEncryptAsymmetricInput, - IEncryptAsymmetricOutput, - IEncryptSymmetricInput, - IGenerateKeyPairOutput, -} from "../../interfaces/utils"; -import { BadRequestError } from "../errors"; -import { - ALGORITHM_AES_256_GCM, - BLOCK_SIZE_BYTES_16, -} from "../../variables"; - -/** - * Return new base64, NaCl, public-private key pair. - * @returns {Object} obj - * @returns {String} obj.publicKey - (base64) NaCl, public key - * @returns {String} obj.privateKey - (base64), NaCl, private key - */ -const generateKeyPair = (): IGenerateKeyPairOutput => { - const pair = nacl.box.keyPair(); - - return ({ - publicKey: util.encodeBase64(pair.publicKey), - privateKey: util.encodeBase64(pair.secretKey), - }); -} - -/** - * Return assymmetrically encrypted [plaintext] using [publicKey] where - * [publicKey] likely belongs to the recipient. - * @param {Object} obj - * @param {String} obj.plaintext - plaintext to encrypt - * @param {String} obj.publicKey - (base64) Nacl public key of the recipient - * @param {String} obj.privateKey - (base64) Nacl private key of the sender (current user) - * @returns {Object} obj - * @returns {String} obj.ciphertext - (base64) ciphertext - * @returns {String} obj.nonce - (base64) nonce - */ -const encryptAsymmetric = ({ - plaintext, - publicKey, - privateKey, -}: IEncryptAsymmetricInput): IEncryptAsymmetricOutput => { - const nonce = nacl.randomBytes(24); - const ciphertext = nacl.box( - util.decodeUTF8(plaintext), - nonce, - util.decodeBase64(publicKey), - util.decodeBase64(privateKey) - ); - - return { - ciphertext: util.encodeBase64(ciphertext), - nonce: util.encodeBase64(nonce), - }; -}; - -/** - * Return assymmetrically decrypted [ciphertext] using [privateKey] where - * [privateKey] likely belongs to the recipient. - * @param {Object} obj - * @param {String} obj.ciphertext - ciphertext to decrypt - * @param {String} obj.nonce - (base64) nonce - * @param {String} obj.publicKey - (base64) public key of the sender - * @param {String} obj.privateKey - (base64) private key of the receiver (current user) - * @returns {String} plaintext - (utf8) plaintext - */ -const decryptAsymmetric = ({ - ciphertext, - nonce, - publicKey, - privateKey, -}: IDecryptAsymmetricInput): string => { - const plaintext: Uint8Array | null = nacl.box.open( - util.decodeBase64(ciphertext), - util.decodeBase64(nonce), - util.decodeBase64(publicKey), - util.decodeBase64(privateKey) - ); - - if (plaintext == null) throw BadRequestError({ - message: "Invalid ciphertext or keys", - }); - - return util.encodeUTF8(plaintext); -}; - -/** - * Return symmetrically encrypted [plaintext] using [key]. - * - * NOTE: THIS FUNCTION SHOULD NOT BE USED FOR ALL FUTURE - * ENCRYPTION OPERATIONS UNLESS IT TOUCHES OLD FUNCTIONALITY - * THAT USES IT. USE encryptSymmetric() instead - * - * @param {Object} obj - * @param {String} obj.plaintext - (utf8) plaintext to encrypt - * @param {String} obj.key - (hex) 128-bit key - * @returns {Object} obj - * @returns {String} obj.ciphertext (base64) ciphertext - * @returns {String} obj.iv (base64) iv - * @returns {String} obj.tag (base64) tag - */ -const encryptSymmetric128BitHexKeyUTF8 = ({ - plaintext, - key, -}: IEncryptSymmetricInput) => { - const iv = crypto.randomBytes(BLOCK_SIZE_BYTES_16); - const cipher = crypto.createCipheriv(ALGORITHM_AES_256_GCM, key, iv); - - let ciphertext = cipher.update(plaintext, "utf8", "base64"); - ciphertext += cipher.final("base64"); - - return { - ciphertext, - iv: iv.toString("base64"), - tag: cipher.getAuthTag().toString("base64"), - }; -} -/** - * Return symmetrically decrypted [ciphertext] using [iv], [tag], - * and [key]. - * - * NOTE: THIS FUNCTION SHOULD NOT BE USED FOR ALL FUTURE - * DECRYPTION OPERATIONS UNLESS IT TOUCHES OLD FUNCTIONALITY - * THAT USES IT. USE decryptSymmetric() instead - * - * @param {Object} obj - * @param {String} obj.ciphertext - ciphertext to decrypt - * @param {String} obj.iv - (base64) 256-bit iv - * @param {String} obj.tag - (base64) tag - * @param {String} obj.key - (hex) 128-bit key - * @returns {String} cleartext - the deciphered ciphertext - */ -const decryptSymmetric128BitHexKeyUTF8 = ({ - ciphertext, - iv, - tag, - key, -}: IDecryptSymmetricInput) => { - const decipher = crypto.createDecipheriv( - ALGORITHM_AES_256_GCM, - key, - Buffer.from(iv, "base64") - ); - - decipher.setAuthTag(Buffer.from(tag, "base64")); - - let cleartext = decipher.update(ciphertext, "base64", "utf8"); - cleartext += decipher.final("utf8"); - - return cleartext; -} - -export { - generateKeyPair, - encryptAsymmetric, - decryptAsymmetric, - encryptSymmetric128BitHexKeyUTF8, - decryptSymmetric128BitHexKeyUTF8, -}; diff --git a/backend-mongo/src/utils/errors.ts b/backend-mongo/src/utils/errors.ts deleted file mode 100644 index 105069c2a..000000000 --- a/backend-mongo/src/utils/errors.ts +++ /dev/null @@ -1,214 +0,0 @@ -import RequestError, { LogLevel, RequestErrorContext } from "./requestError" - -//* ----->[GENERAL HTTP ERRORS]<----- -export const RouteNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.INFO, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "route_not_found", - message: error?.message ?? "The requested source was not found", - context: error?.context, - stack: error?.stack, -}); - -export const MethodNotAllowedError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.INFO, - statusCode: error?.statusCode ?? 405, - type: error?.type ?? "method_not_allowed", - message: error?.message ?? "The requested method is not allowed for the resource", - context: error?.context, - stack: error?.stack, -}); - -export const UnauthorizedRequestError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.INFO, - statusCode: error?.statusCode ?? 401, - type: error?.type ?? "unauthorized", - message: error?.message ?? "You are not authorized to access this resource", - context: error?.context, - stack: error?.stack, -}); - -export const ForbiddenRequestError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.WARN, - statusCode: error?.statusCode ?? 403, - type: error?.type ?? "forbidden", - message: error?.message ?? "You are not allowed to access this resource", - context: error?.context, - stack: error?.stack, -}); - -export const BadRequestError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.INFO, - statusCode: error?.statusCode ?? 400, - type: error?.type ?? "bad_request", - message: error?.message ?? "The request is invalid or cannot be served", - context: error?.context, - stack: error?.stack, -}); - -export const ResourceNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.INFO, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "resource_not_found", - message: error?.message ?? "The requested resource is not found", - context: error?.context, - stack: error?.stack, -}); - -export const InternalServerError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 500, - type: error?.type ?? "internal_server_error", - message: error?.message ?? "The server encountered an error while processing the request", - context: error?.context, - stack: error?.stack, -}); - -export const ServiceUnavailableError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 503, - type: error?.type ?? "service_unavailable", - message: error?.message ?? "The service is currently unavailable. Please try again later.", - context: error?.context, - stack: error?.stack, -}); - -export const ValidationError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 400, - type: error?.type ?? "validation_error", - message: error?.message ?? "The request failed validation", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[INTEGRATION AUTH ERRORS]<----- -export const IntegrationAuthNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "integration_auth_not_found_error", - message: error?.message ?? "The requested integration authorization was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[INTEGRATION ERRORS]<----- -export const IntegrationNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "integration_not_found_error", - message: error?.message ?? "The requested integration was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[WORKSPACE ERRORS]<----- -export const WorkspaceNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "workspace_not_found_error", - message: error?.message ?? "The requested workspace was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[WORKSPACE MEMBERSHIP ERRORS]<----- -export const MembershipNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "workspace_membership_not_found_error", - message: error?.message ?? "The requested membership was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[ORGANIZATION ERRORS]<----- -export const OrganizationNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "organization_not_found_error", - message: error?.message ?? "The requested organization was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[MEMBERSHIP ORGANIZATION ERRORS]<----- -export const MembershipOrgNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "organization_membership_not_found_error", - message: error?.message ?? "The requested organization membership was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[ACCOUNT ERRORS]<----- -export const AccountNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "account_not_found_error", - message: error?.message ?? "The requested account was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[SECRET ERRORS]<----- -export const SecretNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "secret_not_found_error", - message: error?.message ?? "The requested secret was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[SECRET BLIND INDEX DATA ERRORS]<----- -export const SecretBlindIndexDataNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "secret_blind_index_data_not_found_error", - message: error?.message ?? "The requested secret was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[SECRET SNAPSHOT ERRORS]<----- -export const SecretSnapshotNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "secret_snapshot_not_found_error", - message: error?.message ?? "The requested secret snapshot was not found", - context: error?.context, - stack: error?.stack, -}); - -//* ----->[SERVICE TOKEN DATA ERRORS]<----- -export const ServiceTokenDataNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "service_token_data_not_found_error", - message: error?.message ?? "The requested service token data was not found", - context: error?.context, - stack: error?.stack, -}) - -//* ----->[API KEY DATA ERRORS]<----- -export const APIKeyDataNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "api_key_data_not_found_error", - message: error?.message ?? "The requested service token data was not found", - context: error?.context, - stack: error?.stack, -}); - -export const BotNotFoundError = (error?: Partial) => new RequestError({ - logLevel: error?.logLevel ?? LogLevel.ERROR, - statusCode: error?.statusCode ?? 404, - type: error?.type ?? "bot_not_found_error", - message: error?.message ?? "The requested bot was not found", - context: error?.context, - stack: error?.stack, -}) - -//* ----->[MISC ERRORS]<----- diff --git a/backend-mongo/src/utils/folder.ts b/backend-mongo/src/utils/folder.ts deleted file mode 100644 index 45a8b94d6..000000000 --- a/backend-mongo/src/utils/folder.ts +++ /dev/null @@ -1,87 +0,0 @@ -// import Folder from "../models/folder"; - -// export const ROOT_FOLDER_PATH = "/" - -// export const getFolderPath = async (folderId: string) => { -// let currentFolder = await Folder.findById(folderId); -// const pathSegments = []; - -// while (currentFolder) { -// pathSegments.unshift(currentFolder.name); -// currentFolder = currentFolder.parent ? await Folder.findById(currentFolder.parent) : null; -// } - -// return '/' + pathSegments.join('/'); -// }; - -// /** -// Returns the folder ID associated with the specified secret path in the given workspace and environment. -// @param workspaceId - The ID of the workspace to search in. -// @param environment - The environment to search in. -// @param secretPath - The secret path to search for. -// @returns The folder ID associated with the specified secret path, or undefined if the path is at the root folder level. -// @throws Error if the specified secret path is not found. -// */ -// export const getFolderIdFromPath = async (workspaceId: string, environment: string, secretPath: string) => { -// const secretPathParts = secretPath.split("/").filter(path => path != "") -// if (secretPathParts.length <= 1) { -// return undefined // root folder, so no folder id -// } - -// const folderId = await Folder.find({ path: secretPath, workspace: workspaceId, environment: environment }) -// if (!folderId) { -// throw Error("Secret path not found") -// } - -// return folderId -// } - -// /** -// * Cleans up a path by removing empty parts, duplicate slashes, -// * and ensuring it starts with ROOT_FOLDER_PATH. -// * @param path - The input path to clean up. -// * @returns The cleaned-up path string. -// */ -// export const normalizePath = (path: string) => { -// if (path == undefined || path == "" || path == ROOT_FOLDER_PATH) { -// return ROOT_FOLDER_PATH -// } - -// const pathParts = path.split("/").filter(part => part != "") -// const cleanPathString = ROOT_FOLDER_PATH + pathParts.join("/") - -// return cleanPathString -// } - -// export const getFoldersInDirectory = async (workspaceId: string, environment: string, pathString: string) => { -// const normalizedPath = normalizePath(pathString) -// const foldersInDirectory = await Folder.find({ -// workspace: workspaceId, -// environment: environment, -// parentPath: normalizedPath, -// }); - -// return foldersInDirectory; -// } - -// /** -// * Returns the parent path of the given path. -// * @param path - The input path. -// * @returns The parent path string. -// */ -// export const getParentPath = (path: string) => { -// const normalizedPath = normalizePath(path); -// const folderParts = normalizedPath.split('/').filter(part => part !== ''); - -// let folderParent = ROOT_FOLDER_PATH; -// if (folderParts.length > 1) { -// folderParent = ROOT_FOLDER_PATH + folderParts.slice(0, folderParts.length - 1).join('/'); -// } - -// return folderParent; -// } - -// export const validateFolderName = (folderName: string) => { -// const validNameRegex = /^[a-zA-Z0-9-_]+$/; -// return validNameRegex.test(folderName); -// } diff --git a/backend-mongo/src/utils/ip/index.ts b/backend-mongo/src/utils/ip/index.ts deleted file mode 100644 index 17c8ce5a6..000000000 --- a/backend-mongo/src/utils/ip/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./ip"; \ No newline at end of file diff --git a/backend-mongo/src/utils/ip/ip.ts b/backend-mongo/src/utils/ip/ip.ts deleted file mode 100644 index bc314fa9a..000000000 --- a/backend-mongo/src/utils/ip/ip.ts +++ /dev/null @@ -1,136 +0,0 @@ -import net from "net"; -import { IPType } from "../../ee/models"; -import { InternalServerError, UnauthorizedRequestError } from "../errors"; - -/** - * Return details of IP [ip]: - * - If [ip] is a specific IP address then return the IPv4/IPv6 address - * - If [ip] is a subnet then return the network IPv4/IPv6 address and prefix - * @param {String} ip - ip whose details to return - * @returns - */ -export const extractIPDetails = (ip: string) => { - if (net.isIPv4(ip)) return ({ - ipAddress: ip, - type: IPType.IPV4 - }); - - if (net.isIPv6(ip)) return ({ - ipAddress: ip, - type: IPType.IPV6 - }); - - const [ipNet, prefix] = ip.split("/"); - - let type; - switch (net.isIP(ipNet)) { - case 4: - type = IPType.IPV4; - break; - case 6: - type = IPType.IPV6; - break; - default: - throw InternalServerError({ - message: "Failed to extract IP details" - }); - } - - return ({ - ipAddress: ipNet, - type, - prefix: parseInt(prefix, 10) - }); -} - -/** - * Checks if a given string is a valid CIDR block. - * - * The function checks if the input string is a valid IPv4 or IPv6 address in CIDR notation. - * - * CIDR notation includes a network address followed by a slash ('/') and a prefix length. - * For IPv4, the prefix length must be between 0 and 32. For IPv6, it must be between 0 and 128. - * If the input string is not a valid CIDR block, the function returns `false`. - * - * @param {string} cidr - string in CIDR notation - * @returns {boolean} Returns `true` if the string is a valid CIDR block, `false` otherwise. - * -*/ -export const isValidCidr = (cidr: string): boolean => { - const [ip, prefix] = cidr.split("/"); - - const prefixNum = parseInt(prefix, 10); - - // ensure prefix exists and is a number within the appropriate range for each IP version - if (!prefix || isNaN(prefixNum) || - (net.isIPv4(ip) && (prefixNum < 0 || prefixNum > 32)) || - (net.isIPv6(ip) && (prefixNum < 0 || prefixNum > 128))) { - return false; - } - - // ensure the IP portion of the CIDR block is a valid IPv4 or IPv6 address - if (!net.isIPv4(ip) && !net.isIPv6(ip)) { - return false; - } - - return true; -} - -/** - * Checks if a given string is a valid IPv4/IPv6 address or a valid CIDR block. - * - * If the string contains a slash ('/'), it treats the input as a CIDR block and checks its validity. - * Otherwise, it treats the string as a standalone IP address (either IPv4 or IPv6) and checks its validity. - * - * @param {string} input - The string to be checked. It could be an IP address or a CIDR block. - * @returns {boolean} Returns `true` if the string is a valid IP address (either IPv4 or IPv6) or a valid CIDR block, `false` otherwise. - * -*/ -export const isValidIpOrCidr = (ip: string): boolean => { - // if the string contains a slash, treat it as a CIDR block - if (ip.includes("/")) { - return isValidCidr(ip); - } - - // otherwise, treat it as a standalone IP address - if (net.isIPv4(ip) || net.isIPv6(ip)) { - return true; - } - - return false; -} - -/** - * Validates the IP address [ipAddress] against the trusted IPs [trustedIps]. - * @param {Object} obj - * @param {String} obj.ipAddress - IP address to check - * @param {Object[]} obj.trustedIps - IPs to trust in blocklist - */ -export const checkIPAgainstBlocklist = ({ - ipAddress, - trustedIps -}: { - ipAddress: string; - trustedIps: { - ipAddress: string; - type: IPType; - prefix: number; - }[] -}) => { - const blockList = new net.BlockList(); - - for (const trustedIp of trustedIps) { - if (trustedIp.prefix !== undefined) { - blockList.addSubnet(trustedIp.ipAddress, trustedIp.prefix, trustedIp.type); - } else { - blockList.addAddress(trustedIp.ipAddress, trustedIp.type); - } - } - - const { type } = extractIPDetails(ipAddress); - const check = blockList.check(ipAddress, type); - - if (!check) throw UnauthorizedRequestError({ - message: "Failed to authenticate" - }); -} diff --git a/backend-mongo/src/utils/logging/index.ts b/backend-mongo/src/utils/logging/index.ts deleted file mode 100644 index 5d5654efc..000000000 --- a/backend-mongo/src/utils/logging/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { logger, initLogger } from "./logger"; diff --git a/backend-mongo/src/utils/logging/logger.ts b/backend-mongo/src/utils/logging/logger.ts deleted file mode 100644 index 70ba77570..000000000 --- a/backend-mongo/src/utils/logging/logger.ts +++ /dev/null @@ -1,69 +0,0 @@ -import pino, { Logger } from "pino"; -import { getAwsCloudWatchLog, getNodeEnv } from "../../config"; - -export let logger: Logger; - -// https://github.com/pinojs/pino/blob/master/lib/levels.js#L13-L20 -const logLevelToSeverityLookup: Record = { - "10": "TRACE", - "20": "DEBUG", - "30": "INFO", - "40": "WARNING", - "50": "ERROR", - "60": "CRITICAL" -} - -export const initLogger = async () => { - const awsCloudWatchLogCfg = await getAwsCloudWatchLog(); - const nodeEnv = await getNodeEnv(); - const isProduction = nodeEnv === "production"; - const targets: pino.TransportMultiOptions["targets"][number][] = [ - isProduction - ? { level: "info", target: "pino/file", options: {} } - : { - level: "info", - target: "pino-pretty", // must be installed separately - options: { - colorize: true - } - } - ]; - - if (awsCloudWatchLogCfg) { - targets.push({ - target: "@serdnam/pino-cloudwatch-transport", - level: "info", - options: { - logGroupName: awsCloudWatchLogCfg.logGroupName, - logStreamName: awsCloudWatchLogCfg.logGroupName, - awsRegion: awsCloudWatchLogCfg.region, - awsAccessKeyId: awsCloudWatchLogCfg.accessKeyId, - awsSecretAccessKey: awsCloudWatchLogCfg.accessKeySecret, - interval: awsCloudWatchLogCfg.interval - } - }); - } - - const transport = pino.transport({ - targets - }); - - logger = pino( - { - mixin(_context, level) { - return { "severity": logLevelToSeverityLookup[level] || logLevelToSeverityLookup["30"] } - }, - level: process.env.PINO_LOG_LEVEL || "info", - formatters: { - bindings: (bindings) => { - return { - pid: bindings.pid, - hostname: bindings.hostname - // node_version: process.version - }; - } - } - }, - transport - ); -}; diff --git a/backend-mongo/src/utils/posthog.ts b/backend-mongo/src/utils/posthog.ts deleted file mode 100644 index 5ee2eef13..000000000 --- a/backend-mongo/src/utils/posthog.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UserAgentType } from "../ee/models" - -export const getUserAgentType = function (userAgent: string | undefined) { - if (userAgent == undefined) { - return UserAgentType.OTHER; - } else if (userAgent == UserAgentType.CLI) { - return UserAgentType.CLI; - } else if (userAgent == UserAgentType.K8_OPERATOR) { - return UserAgentType.K8_OPERATOR; - } else if (userAgent == UserAgentType.TERRAFORM) { - return UserAgentType.TERRAFORM; - } else if (userAgent.toLowerCase().includes("mozilla")) { - return UserAgentType.WEB; - } else if (userAgent.includes(UserAgentType.NODE_SDK)) { - return UserAgentType.NODE_SDK; - } else if (userAgent.includes(UserAgentType.PYTHON_SDK)) { - return UserAgentType.PYTHON_SDK; - } else { - return UserAgentType.OTHER; - } -} \ No newline at end of file diff --git a/backend-mongo/src/utils/requestError.ts b/backend-mongo/src/utils/requestError.ts deleted file mode 100644 index 7e4625e30..000000000 --- a/backend-mongo/src/utils/requestError.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { Request } from "express" -import { getVerboseErrorOutput } from "../config"; - -export enum LogLevel { - TRACE = 10, - DEBUG = 20, - INFO = 30, - WARN = 40, - ERROR = 50, - FATAL = 60 -} - -type PinoLogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal"; - -export const mapToPinoLogLevel = (customLogLevel: LogLevel): PinoLogLevel => { - switch (customLogLevel) { - case LogLevel.TRACE: - return "trace"; - case LogLevel.DEBUG: - return "debug"; - case LogLevel.INFO: - return "info"; - case LogLevel.WARN: - return "warn"; - case LogLevel.ERROR: - return "error"; - case LogLevel.FATAL: - return "fatal"; - } -} - -export type RequestErrorContext = { - logLevel?: LogLevel, - statusCode: number, - type: string, - message: string, - context?: Record, - stack?: string|undefined -} - -export default class RequestError extends Error { - - private _logLevel: LogLevel - private _logName: string; - statusCode: number - type: string - context: Record - extra: Record[] - private stacktrace: string|undefined|string[] - - constructor( - {logLevel, statusCode, type, message, context, stack} : RequestErrorContext - ){ - - super(message) - this._logLevel = logLevel || LogLevel.INFO; - this._logName = LogLevel[this._logLevel]; - this.statusCode = statusCode; - this.message = message; - this.type = type - this.context = context || {} - this.extra = [] - - if(stack) this.stack = stack - else Error.captureStackTrace(this, this.constructor) - this.stacktrace = this.stack?.split("\n") - } - - static convertFrom(error: Error) { - //This error was not handled by error handler. Please report this incident to the staff. - return new RequestError({ - logLevel: LogLevel.ERROR, - statusCode: 500, - type: "internal_server_error", - message: "This error was not handled by error handler. Please report this incident to the staff", - context: { - message: error.message, - name: error.name, - }, - stack: error.stack, - }) - } - - get level(){ - return this._logLevel - } - get levelName(){ - return this._logName - } - - withTags(...tags: string[]|number[]){ - this.context["tags"] = Object.assign(tags, this.context["tags"]) - return this - } - - withExtras(...extras: Record[]){ - this.extra = Object.assign(extras, this.extra) - return this - } - - private _omit(obj: any, keys: string[]): typeof obj{ - const exclude = new Set(keys) - obj = Object.fromEntries(Object.entries(obj).filter(e => !exclude.has(e[0]))) - return obj - } - - public async format(req: Request){ - let _context = Object.assign({ - stacktrace: this.stacktrace, - }, this.context) - - //* Omit sensitive information from context that can leak internal workings of this program if user is not developer - const verboseErrorOutput = await getVerboseErrorOutput(); - if (verboseErrorOutput !== undefined) { - _context = this._omit(_context, [ - "stacktrace", - "exception", - ]) - } - - const formatObject = { - type: this.type, - message: this.message, - context: _context, - level: this.level, - level_name: this.levelName, - status_code: this.statusCode, - datetime_iso: new Date().toISOString(), - application: process.env.npm_package_name || "unknown", - request_id: req.headers["Request-Id"], - extra: this.extra, - } - - return formatObject - - } -} diff --git a/backend-mongo/src/utils/setup/backfillData.ts b/backend-mongo/src/utils/setup/backfillData.ts deleted file mode 100644 index 21b2a95df..000000000 --- a/backend-mongo/src/utils/setup/backfillData.ts +++ /dev/null @@ -1,879 +0,0 @@ -import crypto from "crypto"; -import { Types } from "mongoose"; -import { encryptSymmetric128BitHexKeyUTF8 } from "../crypto"; -import { EESecretService } from "../../ee/services"; -import { redisClient } from "../../services/RedisService"; -import { - IPType, - ISecretVersion, - Role, - SecretSnapshot, - SecretVersion, - TrustedIP -} from "../../ee/models"; -import { - AuthMethod, - BackupPrivateKey, - Bot, - BotOrg, - ISecret, - IWorkspace, - Integration, - IntegrationAuth, - Membership, - MembershipOrg, - Organization, - Secret, - SecretBlindIndexData, - ServiceTokenData, - User, - Workspace -} from "../../models"; -import { generateKeyPair } from "../../utils/crypto"; -import { client, getEncryptionKey, getIsInfisicalCloud, getRootEncryptionKey } from "../../config"; -import { - ADMIN, - ALGORITHM_AES_256_GCM, - CUSTOM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, - MEMBER, - OWNER -} from "../../variables"; -import { InternalServerError } from "../errors"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - memberProjectPermissions -} from "../../ee/services/ProjectRoleService"; -import { logger } from "../logging"; -import { getServerConfig, updateServerConfig } from "../../config/serverConfig"; - -/** - * Backfill secrets to ensure that they're all versioned and have - * corresponding secret versions - */ -export const backfillSecretVersions = async () => { - await Secret.updateMany({ version: { $exists: false } }, { $set: { version: 1 } }); - - const unversionedSecrets: ISecret[] = await Secret.aggregate([ - { - $lookup: { - from: "secretversions", - localField: "_id", - foreignField: "secret", - as: "versions" - } - }, - { - $match: { - versions: { $size: 0 } - } - } - ]); - - if (unversionedSecrets.length > 0) { - await EESecretService.addSecretVersions({ - secretVersions: unversionedSecrets.map( - (s, idx) => - new SecretVersion({ - ...s, - secret: s._id, - version: s.version ? s.version : 1, - isDeleted: false, - workspace: s.workspace, - environment: s.environment, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }) - ) - }); - } - logger.info("Migration: Secret version migration v1 complete"); -}; - -/** - * Backfill workspace bots to ensure that every workspace has a bot - */ -export const backfillBots = async () => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - const workspaceIdsWithBot = await Bot.distinct("workspace"); - const workspaceIdsToAddBot = await Workspace.distinct("_id", { - _id: { - $nin: workspaceIdsWithBot - } - }); - - if (workspaceIdsToAddBot.length === 0) return; - - const botsToInsert = await Promise.all( - workspaceIdsToAddBot.map(async (workspaceToAddBot) => { - const { publicKey, privateKey } = generateKeyPair(); - - if (rootEncryptionKey) { - const { - ciphertext: encryptedPrivateKey, - iv, - tag - } = client.encryptSymmetric(privateKey, rootEncryptionKey); - - return new Bot({ - name: "Infisical Bot", - workspace: workspaceToAddBot, - isActive: false, - publicKey, - encryptedPrivateKey, - iv, - tag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_BASE64 - }); - } else if (encryptionKey) { - const { - ciphertext: encryptedPrivateKey, - iv, - tag - } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: privateKey, - key: encryptionKey - }); - - return new Bot({ - name: "Infisical Bot", - workspace: workspaceToAddBot, - isActive: false, - publicKey, - encryptedPrivateKey, - iv, - tag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }); - } - - throw InternalServerError({ - message: "Failed to backfill workspace bots due to missing encryption key" - }); - }) - ); - - await Bot.insertMany(botsToInsert); -}; - -/** - * Backfill organization bots to ensure that every organization has a bot - */ -export const backfillBotOrgs = async () => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - const organizationIdsWithBot = await BotOrg.distinct("organization"); - const organizationIdsToAddBot = await Organization.distinct("_id", { - _id: { - $nin: organizationIdsWithBot - } - }); - - if (organizationIdsToAddBot.length === 0) return; - - const botsToInsert = await Promise.all( - organizationIdsToAddBot.map(async (organizationToAddBot) => { - const { publicKey, privateKey } = generateKeyPair(); - - const key = client.createSymmetricKey(); - - if (rootEncryptionKey) { - const { - ciphertext: encryptedPrivateKey, - iv: privateKeyIV, - tag: privateKeyTag - } = client.encryptSymmetric(privateKey, rootEncryptionKey); - - const { - ciphertext: encryptedSymmetricKey, - iv: symmetricKeyIV, - tag: symmetricKeyTag - } = client.encryptSymmetric(key, rootEncryptionKey); - - return new BotOrg({ - name: "Infisical Bot", - organization: organizationToAddBot, - publicKey, - encryptedSymmetricKey, - symmetricKeyIV, - symmetricKeyTag, - symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, - symmetricKeyKeyEncoding: ENCODING_SCHEME_BASE64, - encryptedPrivateKey, - privateKeyIV, - privateKeyTag, - privateKeyAlgorithm: ALGORITHM_AES_256_GCM, - privateKeyKeyEncoding: ENCODING_SCHEME_BASE64 - }); - } else if (encryptionKey) { - const { - ciphertext: encryptedPrivateKey, - iv: privateKeyIV, - tag: privateKeyTag - } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: privateKey, - key: encryptionKey - }); - - const { - ciphertext: encryptedSymmetricKey, - iv: symmetricKeyIV, - tag: symmetricKeyTag - } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: key, - key: encryptionKey - }); - - return new BotOrg({ - name: "Infisical Bot", - organization: organizationToAddBot, - publicKey, - encryptedSymmetricKey, - symmetricKeyIV, - symmetricKeyTag, - symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, - symmetricKeyKeyEncoding: ENCODING_SCHEME_UTF8, - encryptedPrivateKey, - privateKeyIV, - privateKeyTag, - privateKeyAlgorithm: ALGORITHM_AES_256_GCM, - privateKeyKeyEncoding: ENCODING_SCHEME_UTF8 - }); - } - - throw InternalServerError({ - message: "Failed to backfill organization bots due to missing encryption key" - }); - }) - ); - - await BotOrg.insertMany(botsToInsert); -}; - -/** - * Backfill secret blind index data to ensure that every workspace - * has a secret blind index data - */ -export const backfillSecretBlindIndexData = async () => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - const workspaceIdsBlindIndexed = await SecretBlindIndexData.distinct("workspace"); - const workspaceIdsToBlindIndex = await Workspace.distinct("_id", { - _id: { - $nin: workspaceIdsBlindIndexed - } - }); - - if (workspaceIdsToBlindIndex.length === 0) return; - - const secretBlindIndexDataToInsert = await Promise.all( - workspaceIdsToBlindIndex.map(async (workspaceToBlindIndex) => { - const salt = crypto.randomBytes(16).toString("base64"); - - if (rootEncryptionKey) { - const { - ciphertext: encryptedSaltCiphertext, - iv: saltIV, - tag: saltTag - } = client.encryptSymmetric(salt, rootEncryptionKey); - - return new SecretBlindIndexData({ - workspace: workspaceToBlindIndex, - encryptedSaltCiphertext, - saltIV, - saltTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_BASE64 - }); - } else if (encryptionKey) { - const { - ciphertext: encryptedSaltCiphertext, - iv: saltIV, - tag: saltTag - } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: salt, - key: encryptionKey - }); - - return new SecretBlindIndexData({ - workspace: workspaceToBlindIndex, - encryptedSaltCiphertext, - saltIV, - saltTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - }); - } - - throw InternalServerError({ - message: "Failed to backfill secret blind index data due to missing encryption key" - }); - }) - ); - - SecretBlindIndexData.insertMany(secretBlindIndexDataToInsert); -}; - -/** - * Backfill Secret, SecretVersion, SecretBlindIndexData, Bot, - * BackupPrivateKey, IntegrationAuth collections to ensure that - * they all have encryption metadata documented - */ -export const backfillEncryptionMetadata = async () => { - // backfill secret encryption metadata - await Secret.updateMany( - { - algorithm: { - $exists: false - }, - keyEncoding: { - $exists: false - } - }, - { - $set: { - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - } - } - ); - - // backfill secret version encryption metadata - await SecretVersion.updateMany( - { - algorithm: { - $exists: false - }, - keyEncoding: { - $exists: false - } - }, - { - $set: { - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - } - } - ); - - // backfill secret blind index encryption metadata - await SecretBlindIndexData.updateMany( - { - algorithm: { - $exists: false - }, - keyEncoding: { - $exists: false - } - }, - { - $set: { - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - } - } - ); - - // backfill bot encryption metadata - await Bot.updateMany( - { - algorithm: { - $exists: false - }, - keyEncoding: { - $exists: false - } - }, - { - $set: { - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - } - } - ); - - // backfill backup private key encryption metadata - await BackupPrivateKey.updateMany( - { - algorithm: { - $exists: false - }, - keyEncoding: { - $exists: false - } - }, - { - $set: { - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - } - } - ); - - // backfill integration auth encryption metadata - await IntegrationAuth.updateMany( - { - algorithm: { - $exists: false - }, - keyEncoding: { - $exists: false - } - }, - { - $set: { - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8 - } - } - ); -}; - -export const backfillSecretFolders = async () => { - await Secret.updateMany( - { - folder: { - $exists: false - } - }, - { - $set: { - folder: "root" - } - } - ); - - await SecretVersion.updateMany( - { - folder: { - $exists: false - } - }, - { - $set: { - folder: "root" - } - } - ); - - // Back fill because tags were missing in secret versions - await SecretVersion.updateMany( - { - tags: { - $exists: false - } - }, - { - $set: { - tags: [] - } - } - ); - - let secretSnapshots = await SecretSnapshot.find({ - environment: { - $exists: false - } - }) - .populate<{ secretVersions: ISecretVersion[] }>("secretVersions") - .limit(50); - - while (secretSnapshots.length > 0) { - for (const secSnapshot of secretSnapshots) { - const groupSnapByEnv: Record> = {}; - secSnapshot.secretVersions.forEach((secVer) => { - if (!groupSnapByEnv?.[secVer.environment]) groupSnapByEnv[secVer.environment] = []; - groupSnapByEnv[secVer.environment].push(secVer); - }); - - const newSnapshots = Object.keys(groupSnapByEnv).map((snapEnv) => { - const secretIdsOfEnvGroup = groupSnapByEnv[snapEnv] - ? groupSnapByEnv[snapEnv].map((secretVersion) => secretVersion._id) - : []; - return { - ...secSnapshot.toObject({ virtuals: false }), - _id: new Types.ObjectId(), - environment: snapEnv, - secretVersions: secretIdsOfEnvGroup - }; - }); - - await SecretSnapshot.insertMany(newSnapshots); - await secSnapshot.deleteOne(); - } - - secretSnapshots = await SecretSnapshot.find({ - environment: { - $exists: false - } - }) - .populate<{ secretVersions: ISecretVersion[] }>("secretVersions") - .limit(50); - } - - logger.info("Migration: Folder migration v1 complete"); -}; - -export const backfillServiceToken = async () => { - await ServiceTokenData.updateMany( - { - secretPath: { - $exists: false - } - }, - { - $set: { - secretPath: "/" - } - } - ); - logger.info("Migration: Service token migration v1 complete"); -}; - -export const backfillIntegration = async () => { - await Integration.updateMany( - { - secretPath: { - $exists: false - } - }, - { - $set: { - secretPath: "/" - } - } - ); - logger.info("Migration: Integration migration v1 complete"); -}; - -export const backfillServiceTokenMultiScope = async () => { - const documentsToUpdate = await ServiceTokenData.find({ scopes: { $exists: false } }); - - for (const doc of documentsToUpdate) { - // Cast doc to any to bypass TypeScript's type checks - const anyDoc = doc as any; - - const environment = anyDoc.environment; - const secretPath = anyDoc.secretPath; - - if (environment && secretPath) { - const updatedScopes = [ - { - environment: environment, - secretPath: secretPath - } - ]; - - await ServiceTokenData.updateOne({ _id: doc._id }, { $set: { scopes: updatedScopes } }); - } - } - - logger.info("Migration: Service token migration v2 complete"); -}; - -/** - * Backfill each workspace without any registered trusted IPs to - * have default trusted ip of 0.0.0.0/0 - */ -export const backfillTrustedIps = async () => { - const workspaceIdsWithTrustedIps = await TrustedIP.distinct("workspace"); - const workspaceIdsToAddTrustedIp = await Workspace.distinct("_id", { - _id: { - $nin: workspaceIdsWithTrustedIps - } - }); - - if (workspaceIdsToAddTrustedIp.length > 0) { - const operations: { - updateOne: { - filter: { - workspace: Types.ObjectId; - ipAddress: string; - }; - update: { - workspace: Types.ObjectId; - ipAddress: string; - type: string; - prefix: number; - isActive: boolean; - comment: string; - }; - upsert: boolean; - }; - }[] = []; - - workspaceIdsToAddTrustedIp.forEach((workspaceId) => { - // default IPv4 trusted CIDR - operations.push({ - updateOne: { - filter: { - workspace: workspaceId, - ipAddress: "0.0.0.0" - }, - update: { - workspace: workspaceId, - ipAddress: "0.0.0.0", - type: IPType.IPV4.toString(), - prefix: 0, - isActive: true, - comment: "" - }, - upsert: true - } - }); - - // default IPv6 trusted CIDR - operations.push({ - updateOne: { - filter: { - workspace: workspaceId, - ipAddress: "::" - }, - update: { - workspace: workspaceId, - ipAddress: "::", - type: IPType.IPV6.toString(), - prefix: 0, - isActive: true, - comment: "" - }, - upsert: true - } - }); - }); - - await TrustedIP.bulkWrite(operations); - logger.info("Backfill: Trusted IPs complete"); - } -}; - -export const backfillUserAuthMethods = async () => { - await User.updateMany( - { - authProvider: { - $exists: false - }, - authMethods: { - $exists: false - } - }, - { - authMethods: [AuthMethod.EMAIL] - } - ); - - const documentsToUpdate = await User.find({ - authProvider: { $exists: true }, - authMethods: { $exists: false } - }); - - for (const doc of documentsToUpdate) { - // Cast doc to any to bypass TypeScript's type checks - const anyDoc = doc as any; - - const authProvider = anyDoc.authProvider; - const authMethods = [authProvider]; - - await User.updateOne( - { _id: doc._id }, - { - $set: { authMethods: authMethods }, - $unset: { authProvider: 1, authId: 1 } - } - ); - } -}; - -export const backfillPermission = async () => { - const lockKey = "backfill_permission_lock"; - const timeout = 900000; // 15 min lock timeout in milliseconds - const lock = await redisClient?.set(lockKey, 1, "PX", timeout, "NX"); - - if (lock) { - try { - logger.info("Lock acquired for script [backfillPermission]"); - - const memberships = await Membership.find({ - deniedPermissions: { - $exists: true, - $ne: [] - }, - role: MEMBER - }) - .populate<{ workspace: IWorkspace }>("workspace") - .lean(); - - // group memberships that need the same permission set - const roleMap = new Map< - string, - { membershipIds: string[]; permissions: any[]; organizationId: string; workspaceId: string } - >(); - - for (const membership of memberships) { - // get permissions of members except secret permission - const customPermissions = memberProjectPermissions.rules.filter( - ({ subject }) => subject !== ProjectPermissionSub.Secrets - ); - const secretAccessRule: Record = {}; - - // iterate and record true and false ones - membership.deniedPermissions.forEach(({ ability, environmentSlug }) => { - if (!secretAccessRule?.[environmentSlug]) - secretAccessRule[environmentSlug] = { read: true, write: true }; - if (ability === "write") secretAccessRule[environmentSlug].write = false; - if (ability === "read") secretAccessRule[environmentSlug].read = false; - }); - - // environments that are not listed in deniedPermissions should be set to allowed for both read & and write - membership.workspace.environments.forEach((env) => { - if (!secretAccessRule?.[env.slug]) { - secretAccessRule[env.slug] = { read: true, write: true }; - } - }); - - const secretPermissions: any = []; - Object.entries(secretAccessRule).forEach(([envSlug, { read, write }]) => { - if (read) { - secretPermissions.push({ - subject: ProjectPermissionSub.Secrets, - action: ProjectPermissionActions.Read, - conditions: { environment: envSlug } - }); - } - if (write) { - secretPermissions.push( - { - subject: ProjectPermissionSub.Secrets, - action: ProjectPermissionActions.Edit, - conditions: { environment: envSlug } - }, - { - subject: ProjectPermissionSub.Secrets, - action: ProjectPermissionActions.Delete, - conditions: { environment: envSlug } - }, - { - subject: ProjectPermissionSub.Secrets, - action: ProjectPermissionActions.Create, - conditions: { environment: envSlug } - } - ); - } - }); - - const key = `${JSON.stringify(secretPermissions)}-${membership.workspace._id.toString()}`; // group roles that have same permission with in the same workspace - const value = roleMap.get(key); - if (value) { - value.membershipIds.push(membership._id.toString()); - value.organizationId = membership.workspace.organization.toString(); - value.workspaceId = membership.workspace._id.toString(); - } else { - roleMap.set(key, { - membershipIds: [membership._id.toString()], - permissions: [...customPermissions, ...secretPermissions], - organizationId: membership.workspace.organization.toString(), - workspaceId: membership.workspace._id.toString() - }); - } - } - - for (const [key, value] of roleMap.entries()) { - const { membershipIds, permissions, workspaceId, organizationId } = value; - const membership_identity = crypto.randomBytes(3).toString("hex"); - const role = new Role({ - name: `Limited [${membership_identity.toUpperCase()}]`, - organization: organizationId, - workspace: workspaceId, - description: - "This role was auto generated by Infisical in effort to migrate your project members to our new permission system", - isOrgRole: false, - slug: `custom-role-${membership_identity}`, - permissions: permissions - }); - - await role.save(); - - for (const id of membershipIds) { - await Membership.findByIdAndUpdate(id, { - // document db doesn't support update many so we must loop - $set: { - role: CUSTOM, - customRole: role - } - }); - } - } - - logger.info("Backfill: Finished converting old denied permission in workspace to viewers"); - - await MembershipOrg.updateMany( - { - role: OWNER - }, - { - $set: { - role: ADMIN - } - } - ); - - logger.info("Backfill: Finished converting owner role to member"); - } catch (error) { - logger.error(error, "An error occurred when running script [backfillPermission]"); - } - } else { - logger.info("Could not acquire lock for script [backfillPermission], skipping"); - } -}; - -export const migrateRoleFromOwnerToAdmin = async () => { - await MembershipOrg.updateMany( - { - role: OWNER - }, - { - $set: { - role: ADMIN - } - } - ); - - logger.info("Backfill: Finished converting owner role to member"); -}; - -export const migrationAssignSuperadmin = async () => { - const users = await User.find({}).sort({ createdAt: 1 }).limit(2); - const serverCfg = getServerConfig(); - if (serverCfg.initialized) return; - - if (await getIsInfisicalCloud()) { - await updateServerConfig({ initialized: true }); - logger.info("Backfill: Infisical Cloud(initialized)"); - return; - } - - if (users.length) { - let superAdminUserId = ""; - const firstAccount = users?.[0]; - if (firstAccount.email === "test@localhost.local" && users.length === 2) { - superAdminUserId = users?.[1]?._id.toString(); - } else { - superAdminUserId = firstAccount._id.toString(); - } - - if (superAdminUserId) { - const user = await User.findByIdAndUpdate(superAdminUserId, { superAdmin: true }); - await updateServerConfig({ initialized: true }); - logger.info(`Migrated ${user?.email} to superuser`); - } - logger.info("Backfill: Migrated first infisical user to super admin"); - } -}; diff --git a/backend-mongo/src/utils/setup/index.ts b/backend-mongo/src/utils/setup/index.ts deleted file mode 100644 index e6bdd88a0..000000000 --- a/backend-mongo/src/utils/setup/index.ts +++ /dev/null @@ -1,116 +0,0 @@ -import * as Sentry from "@sentry/node"; -import { TelemetryService } from "../../services"; -import { setTransporter } from "../../helpers/nodemailer"; -import { EELicenseService } from "../../ee/services"; -import { initSmtp } from "../../services/smtp"; -// eslint-disable-next-line @typescript-eslint/no-var-requires -import { validateEncryptionKeysConfig } from "./validateConfig"; -import { - backfillBotOrgs, - backfillBots, - backfillEncryptionMetadata, - backfillIntegration, - backfillSecretBlindIndexData, - backfillSecretFolders, - backfillSecretVersions, - backfillServiceToken, - backfillServiceTokenMultiScope, - backfillTrustedIps, - backfillUserAuthMethods, - migrateRoleFromOwnerToAdmin, - migrationAssignSuperadmin -} from "./backfillData"; -import { - reencryptBotOrgKeys, - reencryptBotPrivateKeys, - reencryptSecretBlindIndexDataSalts -} from "./reencryptData"; -import { getNodeEnv, getRedisUrl, getSentryDSN } from "../../config"; -import { - initializeGitHubStrategy, - initializeGitLabStrategy, - initializeGoogleStrategy, - initializeSamlStrategy -} from "../authn/passport"; -import { logger } from "../logging"; -import { bootstrap } from "../../bootstrap"; - -/** - * Prepare Infisical upon startup. This includes tasks like: - * - Log initial telemetry message - * - Initializing SMTP configuration - * - Initializing the instance global feature set (if applicable) - * - Initializing the database connection - * - Initializing Sentry - * - Backfilling data - * - Re-encrypting data - */ -export const setup = async () => { - if ((await getRedisUrl()) === undefined || (await getRedisUrl()) === "") { - logger.error( - "WARNING: Redis is not yet configured. Infisical may not function as expected without it." - ); - } - - await validateEncryptionKeysConfig(); - await TelemetryService.logTelemetryMessage(); - - // initializing SMTP configuration - const transporter = await initSmtp(); - setTransporter(transporter); - - // initializing global feature set - await EELicenseService.initGlobalFeatureSet(); - - // initializing auth strategies - await initializeGoogleStrategy(); - await initializeGitHubStrategy(); - await initializeGitLabStrategy(); - await initializeSamlStrategy(); - - // re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY - // to base64 256-bit ROOT_ENCRYPTION_KEY - // await reencryptBotPrivateKeys(); - // await reencryptSecretBlindIndexDataSalts(); - - await bootstrap({ transporter }); - - /** - * NOTE: the order in this setup function is critical. - * It is important to backfill data before performing any re-encryption functionality. - */ - - // backfilling data to catch up with new collections and updated fields - await backfillSecretVersions(); - await backfillBots(); - await backfillBotOrgs(); - await backfillSecretBlindIndexData(); - await backfillEncryptionMetadata(); - await backfillSecretFolders(); - await backfillServiceToken(); - await backfillIntegration(); - await backfillServiceTokenMultiScope(); - await backfillTrustedIps(); - await backfillUserAuthMethods(); - // await backfillPermission(); - await migrateRoleFromOwnerToAdmin(); - await migrationAssignSuperadmin(); - - // re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY - // to base64 256-bit ROOT_ENCRYPTION_KEY - await reencryptBotPrivateKeys(); - await reencryptBotOrgKeys(); - await reencryptSecretBlindIndexDataSalts(); - - // initializing Sentry - Sentry.init({ - dsn: await getSentryDSN(), - tracesSampleRate: 1.0, - debug: (await getNodeEnv()) === "production" ? false : true, - environment: await getNodeEnv() - }); - - // akhilmhdh: removed dev account as we have now admin account onboarding flow - // That will be user's first account going forward - // await createTestUserForDevelopment(); -}; diff --git a/backend-mongo/src/utils/setup/reencryptData.ts b/backend-mongo/src/utils/setup/reencryptData.ts deleted file mode 100644 index 1a782ab8f..000000000 --- a/backend-mongo/src/utils/setup/reencryptData.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { - Bot, - BotOrg, - IBot, - IBotOrg, - ISecretBlindIndexData, - SecretBlindIndexData, -} from "../../models"; -import { decryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; -import { - client, - getEncryptionKey, - getRootEncryptionKey, -} from "../../config"; -import { - ALGORITHM_AES_256_GCM, - ENCODING_SCHEME_BASE64, - ENCODING_SCHEME_UTF8, -} from "../../variables"; - -/** - * Re-encrypt bot private keys from under hex 128-bit ENCRYPTION_KEY - * to base64 256-bit ROOT_ENCRYPTION_KEY - */ -export const reencryptBotPrivateKeys = async () => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - if (encryptionKey && rootEncryptionKey) { - // 1: re-encrypt bot private keys under ROOT_ENCRYPTION_KEY - const bots = await Bot.find({ - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - }).select("+encryptedPrivateKey iv tag algorithm keyEncoding"); - - if (bots.length === 0) return; - - const operationsBot = await Promise.all( - bots.map(async (bot: IBot) => { - - const privateKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: bot.encryptedPrivateKey, - iv: bot.iv, - tag: bot.tag, - key: encryptionKey, - }); - - const { - ciphertext: encryptedPrivateKey, - iv, - tag, - } = client.encryptSymmetric(privateKey, rootEncryptionKey); - - return ({ - updateOne: { - filter: { - _id: bot._id, - }, - update: { - encryptedPrivateKey, - iv, - tag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_BASE64, - }, - }, - }) - }) - ); - - await Bot.bulkWrite(operationsBot); - } -} - -/** - * Re-encrypt organization bot keys (symmetric and private) from under hex 128-bit ENCRYPTION_KEY - * to base64 256-bit ROOT_ENCRYPTION_KEY - */ -export const reencryptBotOrgKeys = async () => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - if (encryptionKey && rootEncryptionKey) { - // 1: re-encrypt organization bot keys under ROOT_ENCRYPTION_KEY - const botOrgs = await BotOrg.find({ - symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, - symmetricKeyKeyEncoding: ENCODING_SCHEME_UTF8, - privateKeyAlgorithm: ALGORITHM_AES_256_GCM, - privateKeyKeyEncoding: ENCODING_SCHEME_UTF8 - }).select("+encryptedPrivateKey iv tag algorithm keyEncoding"); - - if (botOrgs.length === 0) return; - - const operationsBotOrg = await Promise.all( - botOrgs.map(async (botOrg: IBotOrg) => { - const privateKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: botOrg.encryptedPrivateKey, - iv: botOrg.privateKeyIV, - tag: botOrg.privateKeyTag, - key: encryptionKey - }); - - const { - ciphertext: encryptedPrivateKey, - iv: privateKeyIV, - tag: privateKeyTag, - } = client.encryptSymmetric(privateKey, rootEncryptionKey); - - const symmetricKey = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: botOrg.encryptedSymmetricKey, - iv: botOrg.symmetricKeyIV, - tag: botOrg.symmetricKeyTag, - key: encryptionKey - }); - - const { - ciphertext: encryptedSymmetricKey, - iv: symmetricKeyIV, - tag: symmetricKeyTag, - } = client.encryptSymmetric(symmetricKey, rootEncryptionKey); - - return ({ - updateOne: { - filter: { - _id: botOrg._id, - }, - update: { - encryptedSymmetricKey, - symmetricKeyIV, - symmetricKeyTag, - symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, - symmetricKeyKeyEncoding: ENCODING_SCHEME_BASE64, - encryptedPrivateKey, - privateKeyIV, - privateKeyTag, - privateKeyAlgorithm: ALGORITHM_AES_256_GCM, - privateKeyKeyEncoding: ENCODING_SCHEME_BASE64, - }, - }, - }) - }) - ); - - await BotOrg.bulkWrite(operationsBotOrg); - } -} - -/** - * Re-encrypt secret blind index data salts from hex 128-bit ENCRYPTION_KEY - * to base64 256-bit ROOT_ENCRYPTION_KEY - */ -export const reencryptSecretBlindIndexDataSalts = async () => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - if (encryptionKey && rootEncryptionKey) { - const secretBlindIndexData = await SecretBlindIndexData.find({ - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_UTF8, - }).select("+encryptedSaltCiphertext +saltIV +saltTag +algorithm +keyEncoding"); - - if (secretBlindIndexData.length == 0) return; - - const operationsSecretBlindIndexData = await Promise.all( - secretBlindIndexData.map(async (secretBlindIndexDatum: ISecretBlindIndexData) => { - - const salt = decryptSymmetric128BitHexKeyUTF8({ - ciphertext: secretBlindIndexDatum.encryptedSaltCiphertext, - iv: secretBlindIndexDatum.saltIV, - tag: secretBlindIndexDatum.saltTag, - key: encryptionKey, - }); - - const { - ciphertext: encryptedSaltCiphertext, - iv: saltIV, - tag: saltTag, - } = client.encryptSymmetric(salt, rootEncryptionKey); - - return ({ - updateOne: { - filter: { - _id: secretBlindIndexDatum._id, - }, - update: { - encryptedSaltCiphertext, - saltIV, - saltTag, - algorithm: ALGORITHM_AES_256_GCM, - keyEncoding: ENCODING_SCHEME_BASE64, - }, - }, - }) - }) - ); - - await SecretBlindIndexData.bulkWrite(operationsSecretBlindIndexData); - } -} \ No newline at end of file diff --git a/backend-mongo/src/utils/setup/validateConfig.ts b/backend-mongo/src/utils/setup/validateConfig.ts deleted file mode 100644 index 3a3974791..000000000 --- a/backend-mongo/src/utils/setup/validateConfig.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { - getEncryptionKey, - getRootEncryptionKey, -} from "../../config"; -import { - InternalServerError, -} from "../../utils/errors"; - -/** - * Validate ENCRYPTION_KEY and ROOT_ENCRYPTION_KEY. Specifically: - * - ENCRYPTION_KEY is a hex, 128-bit string - * - ROOT_ENCRYPTION_KEY is a base64, 128-bit string - * - Either ENCRYPTION_KEY or ROOT_ENCRYPTION_KEY are present - * - * - Encrypted data is consistent with the passed in encryption keys - * - * NOTE 1: ENCRYPTION_KEY is being transitioned to ROOT_ENCRYPTION_KEY - * NOTE 2: In the future, we will have a superior validation function - * built into the SDK. - */ -export const validateEncryptionKeysConfig = async () => { - const encryptionKey = await getEncryptionKey(); - const rootEncryptionKey = await getRootEncryptionKey(); - - if ( - (encryptionKey === undefined || encryptionKey === "") && - (rootEncryptionKey === undefined || rootEncryptionKey === "") - ) throw InternalServerError({ - message: "Failed to find required root encryption key environment variable. Please make sure that you're passing in a ROOT_ENCRYPTION_KEY environment variable.", - }); - - // if (encryptionKey && encryptionKey !== '') { - // // validate [encryptionKey] - - // const keyBuffer = Buffer.from(encryptionKey, 'hex'); - // const decoded = keyBuffer.toString('hex'); - - // if (decoded !== encryptionKey) throw InternalServerError({ - // message: 'Failed to validate that the encryption key is correctly encoded in hex.' - // }); - - // if (keyBuffer.length !== 16) throw InternalServerError({ - // message: 'Failed to validate that the encryption key is a 128-bit hex string.' - // }); - // } - - if (rootEncryptionKey && rootEncryptionKey !== "") { - // validate [rootEncryptionKey] - - const keyBuffer = Buffer.from(rootEncryptionKey, "base64") - const decoded = keyBuffer.toString("base64"); - - if (decoded !== rootEncryptionKey) throw InternalServerError({ - message: "Failed to validate that the root encryption key is correctly encoded in base64", - }); - - if (keyBuffer.length !== 32) throw InternalServerError({ - message: "Failed to validate that the encryption key is a 256-bit base64 string", - }); - } -} \ No newline at end of file diff --git a/backend-mongo/src/validation/action.ts b/backend-mongo/src/validation/action.ts deleted file mode 100644 index 7c76a5365..000000000 --- a/backend-mongo/src/validation/action.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { z } from "zod"; - -export const GetActionV1 = z.object({ - params: z.object({ - actionId: z.string().trim() - }) -}); - -export const AddUserActionV1 = z.object({ - body: z.object({ - action: z.string().trim() - }) -}); - -export const GetUserActionV1 = z.object({ - query: z.object({ - action: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/admin.ts b/backend-mongo/src/validation/admin.ts deleted file mode 100644 index aee6c88cc..000000000 --- a/backend-mongo/src/validation/admin.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { z } from "zod"; - -export const UpdateServerConfigV1 = z.object({ - body: z.object({ - allowSignUp: z.boolean().optional() - }) -}); - -export const SignupV1 = z.object({ - body: z.object({ - email: z.string().email().trim(), - firstName: z.string().trim(), - lastName: z.string().trim().optional(), - protectedKey: z.string().trim(), - protectedKeyIV: z.string().trim(), - protectedKeyTag: z.string().trim(), - publicKey: z.string().trim(), - encryptedPrivateKey: z.string().trim(), - encryptedPrivateKeyIV: z.string().trim(), - encryptedPrivateKeyTag: z.string().trim(), - salt: z.string().trim(), - verifier: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/apiKeyDataV3.ts b/backend-mongo/src/validation/apiKeyDataV3.ts deleted file mode 100644 index c92ce468c..000000000 --- a/backend-mongo/src/validation/apiKeyDataV3.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { z } from "zod"; - -export const CreateAPIKeyV3 = z.object({ - body: z.object({ - name: z.string().trim() - }) -}); - -export const UpdateAPIKeyV3 = z.object({ - params: z.object({ - apiKeyDataId: z.string().trim() - }), - body: z.object({ - name: z.string().trim() - }) -}); - -export const DeleteAPIKeyV3 = z.object({ - params: z.object({ - apiKeyDataId: z.string().trim() - }) -}); \ No newline at end of file diff --git a/backend-mongo/src/validation/auth.ts b/backend-mongo/src/validation/auth.ts deleted file mode 100644 index 6e494a66b..000000000 --- a/backend-mongo/src/validation/auth.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { z } from "zod"; - -export const BeginEmailSignUpV1 = z.object({ - body: z.object({ - email: z.string().email().trim() - }) -}); - -export const VerifyEmailSignUpV1 = z.object({ - body: z.object({ - email: z.string().email().trim(), - code: z.string().trim() - }) -}); - -export const Login1V1 = z.object({ - body: z.object({ - email: z.string().email().trim(), - clientPublicKey: z.string().trim() - }) -}); - -export const Login2V1 = z.object({ - body: z.object({ - email: z.string().email().trim(), - clientProof: z.string().trim() - }) -}); - -export const Srp1V1 = z.object({ - body: z.object({ - clientPublicKey: z.string().trim() - }) -}); - -export const ChangePasswordV1 = z.object({ - body: z.object({ - clientProof: z.string().trim(), - protectedKey: z.string().trim(), - protectedKeyIV: z.string().trim(), - protectedKeyTag: z.string().trim(), - encryptedPrivateKey: z.string().trim(), - encryptedPrivateKeyIV: z.string().trim(), - encryptedPrivateKeyTag: z.string().trim(), - salt: z.string().trim(), - verifier: z.string().trim() - }) -}); - -export const EmailPasswordResetV1 = z.object({ - body: z.object({ - email: z.string().email().trim() - }) -}); - -export const EmailPasswordResetVerifyV1 = z.object({ - body: z.object({ - email: z.string().email().trim(), - code: z.string().trim() - }) -}); - -export const CreateBackupPrivateKeyV1 = z.object({ - body: z.object({ - clientProof: z.string().trim(), - encryptedPrivateKey: z.string().trim(), - iv: z.string().trim(), - tag: z.string().trim(), - salt: z.string().trim(), - verifier: z.string().trim() - }) -}); - -export const ResetPasswordV1 = z.object({ - body: z.object({ - protectedKey: z.string().trim(), - protectedKeyIV: z.string().trim(), - protectedKeyTag: z.string().trim(), - encryptedPrivateKey: z.string().trim(), - encryptedPrivateKeyIV: z.string().trim(), - encryptedPrivateKeyTag: z.string().trim(), - salt: z.string().trim(), - verifier: z.string().trim() - }) -}); - -export const RenewAccessTokenV1 = z.object({ - body: z.object({ - accessToken: z.string().trim(), - }) -}); - -export const LoginUniversalAuthV1 = z.object({ - body: z.object({ - clientId: z.string().trim(), - clientSecret: z.string().trim() - }) -}); - -export const AddUniversalAuthToIdentityV1 = z.object({ - params: z.object({ - identityId: z.string().trim() - }), - body: z.object({ - clientSecretTrustedIps: z - .object({ - ipAddress: z.string().trim(), - }) - .array() - .min(1) - .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]), - accessTokenTrustedIps: z - .object({ - ipAddress: z.string().trim(), - }) - .array() - .min(1) - .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]), - accessTokenTTL: z.number().int().min(1).refine(value => value !== 0, { - message: "accessTokenTTL must have a non zero number", - }).default(2592000), - accessTokenMaxTTL: z.number().int().refine(value => value !== 0, { - message: "accessTokenMaxTTL must have a non zero number", - }).default(2592000), // 30 days - accessTokenNumUsesLimit: z.number().int().min(0).default(0) - }) -}); - -export const UpdateUniversalAuthToIdentityV1 = z.object({ - params: z.object({ - identityId: z.string() - }), - body: z.object({ - clientSecretTrustedIps: z - .object({ - ipAddress: z.string().trim() - }) - .array() - .min(1) - .optional(), - accessTokenTrustedIps: z - .object({ - ipAddress: z.string().trim(), - }) - .array() - .min(1) - .optional(), - accessTokenTTL: z.number().int().min(0).optional(), - accessTokenNumUsesLimit: z.number().int().min(0).optional(), - accessTokenMaxTTL: z.number().int().refine(value => value !== 0, { - message: "accessTokenMaxTTL must have a non zero number", - }).optional(), - }), -}); - -export const GetUniversalAuthForIdentityV1 = z.object({ - params: z.object({ - identityId: z.string().trim() - }) -}); - -export const CreateUniversalAuthClientSecretV1 = z.object({ - params: z.object({ - identityId: z.string() - }), - body: z.object({ - description: z.string().trim().default(""), - numUsesLimit: z.number().min(0).default(0), - ttl: z.number().min(0).default(0), - }), -}); - -export const GetUniversalAuthClientSecretsV1 = z.object({ - params: z.object({ - identityId: z.string() - }) -}); - -export const RevokeUniversalAuthClientSecretV1 = z.object({ - params: z.object({ - identityId: z.string(), - clientSecretId: z.string() - }) -}); - -export const VerifyMfaTokenV2 = z.object({ - body: z.object({ - mfaToken: z.string().trim() - }) -}); - -export const Login1V3 = z.object({ - body: z.object({ - email: z.string().email().trim(), - providerAuthToken: z.string().trim().optional(), - clientPublicKey: z.string().trim() - }) -}); - -export const Login2V3 = z.object({ - body: z.object({ - email: z.string().email().trim(), - providerAuthToken: z.string().trim().optional(), - clientProof: z.string().trim() - }) -}); - -export const CompletedAccountSignupV3 = z.object({ - body: z.object({ - email: z.string().email().trim(), - firstName: z.string().trim(), - lastName: z.string().trim().optional(), - protectedKey: z.string().trim(), - protectedKeyIV: z.string().trim(), - protectedKeyTag: z.string().trim(), - publicKey: z.string().trim(), - encryptedPrivateKey: z.string().trim(), - encryptedPrivateKeyIV: z.string().trim(), - encryptedPrivateKeyTag: z.string().trim(), - salt: z.string().trim(), - verifier: z.string().trim(), - organizationName: z.string().trim(), - providerAuthToken: z.string().trim().optional().nullish(), - attributionSource: z.string().trim().optional() - }) -}); diff --git a/backend-mongo/src/validation/bot.ts b/backend-mongo/src/validation/bot.ts deleted file mode 100644 index a5fa5b52f..000000000 --- a/backend-mongo/src/validation/bot.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { z } from "zod"; - -export const GetBotByWorkspaceIdV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const SetBotActiveStateV1 = z.object({ - body: z.object({ - isActive: z.boolean(), - botKey: z - .object({ - nonce: z.string().trim().optional(), - encryptedKey: z.string().trim().optional() - }) - .optional() - }), - params: z.object({ - botId: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/cloudProducts.ts b/backend-mongo/src/validation/cloudProducts.ts deleted file mode 100644 index 1cfd361b3..000000000 --- a/backend-mongo/src/validation/cloudProducts.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { z } from "zod"; - -export const GetCloudProductsV1 = z.object({ - query: z.object({ - "billing-cycle": z.enum(["monthly", "yearly"]) - }) -}); diff --git a/backend-mongo/src/validation/environments.ts b/backend-mongo/src/validation/environments.ts deleted file mode 100644 index 6cf7cf68a..000000000 --- a/backend-mongo/src/validation/environments.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { z } from "zod"; - -export const CreateWorkspaceEnvironmentV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - environmentSlug: z.string().trim(), - environmentName: z.string().trim() - }) -}); - -export const UpdateWorkspaceEnvironmentV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - environmentSlug: z.string().trim(), - environmentName: z.string().trim(), - oldEnvironmentSlug: z.string().trim() - }) -}); - -export const DeleteWorkspaceEnvironmentV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - environmentSlug: z.string().trim() - }) -}); - -export const GetAllAccessibileEnvironmentsOfWorkspaceV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const ReorderWorkspaceEnvironmentsV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - environmentSlug: z.string().trim(), - environmentName: z.string().trim(), - otherEnvironmentSlug: z.string().trim(), - otherEnvironmentName: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/folders.ts b/backend-mongo/src/validation/folders.ts deleted file mode 100644 index deda48b03..000000000 --- a/backend-mongo/src/validation/folders.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { z } from "zod"; - -export const CreateFolderV1 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - folderName: z.string().trim(), - directory: z.string().trim().default("/") - }) -}); - -export const UpdateFolderV1 = z.object({ - params: z.object({ - folderName: z.string().trim() - }), - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - name: z.string().trim(), - directory: z.string().trim().default("/") - }) -}); - -export const DeleteFolderV1 = z.object({ - params: z.object({ - folderName: z.string().trim() - }), - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - directory: z.string().trim().default("/") - }) -}); - -export const GetFoldersV1 = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - directory: z.string().trim().default("/") - }) -}); diff --git a/backend-mongo/src/validation/hasuraCloudIntegration.ts b/backend-mongo/src/validation/hasuraCloudIntegration.ts deleted file mode 100644 index 63b037370..000000000 --- a/backend-mongo/src/validation/hasuraCloudIntegration.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as z from "zod"; - -export const ZGetTenantEnv = z.object({ - data: z.object({ - getTenantEnv: z.object({ - hash: z.string(), - envVars: z.object({ - environment: z.record(z.any()).optional() - }) - }) - }) -}); - -export const ZUpdateTenantEnv = z.object({ - data: z.object({ - updateTenantEnv: z.object({ - hash: z.string(), - envVars: z.record(z.any()) - }) - }) -}); diff --git a/backend-mongo/src/validation/identities.ts b/backend-mongo/src/validation/identities.ts deleted file mode 100644 index fa22fde34..000000000 --- a/backend-mongo/src/validation/identities.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { z } from "zod"; -import { NO_ACCESS } from "../variables"; - -export const CreateIdentityV1 = z.object({ - body: z.object({ - name: z.string().trim(), - organizationId: z.string().trim(), - role: z.string().trim().min(1).default(NO_ACCESS) - }) -}); - -export const UpdateIdentityV1 = z.object({ - params: z.object({ - identityId: z.string() - }), - body: z.object({ - name: z.string().trim().optional(), - role: z.string().trim().min(1).optional() - }), -}); - -export const DeleteIdentityV1 = z.object({ - params: z.object({ - identityId: z.string() - }), -}); diff --git a/backend-mongo/src/validation/index.ts b/backend-mongo/src/validation/index.ts deleted file mode 100644 index e2027d41b..000000000 --- a/backend-mongo/src/validation/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from "./user"; -export * from "./workspace"; -export * from "./bot"; -export * from "./integration"; -export * from "./integrationAuth"; -export * from "./membership"; -export * from "./membershipOrg"; -export * from "./organization"; -export * from "./secrets"; -export * from "./serviceTokenData"; -export * from "./identities"; -export * from "./apiKeyDataV3"; diff --git a/backend-mongo/src/validation/integration.ts b/backend-mongo/src/validation/integration.ts deleted file mode 100644 index b5a02b164..000000000 --- a/backend-mongo/src/validation/integration.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { z } from "zod"; - -export const CreateIntegrationV1 = z.object({ - body: z.object({ - integrationAuthId: z.string().trim(), - app: z.string().trim().optional(), - isActive: z.boolean(), - appId: z.string().trim().optional(), - secretPath: z.string().trim().default("/"), - sourceEnvironment: z.string().trim(), - targetEnvironment: z.string().trim().optional(), - targetEnvironmentId: z.string().trim().optional(), - targetService: z.string().trim().optional(), - targetServiceId: z.string().trim().optional(), - owner: z.string().trim().optional(), - path: z.string().trim().optional(), - region: z.string().trim().optional(), - scope: z.string().trim().optional(), - metadata: z.object({ - secretPrefix: z.string().optional(), - secretSuffix: z.string().optional(), - secretGCPLabel: z.object({ - labelName: z.string(), - labelValue: z.string() - }).optional(), - }).optional() - }) -}); - -export const UpdateIntegrationV1 = z.object({ - params: z.object({ - integrationId: z.string().trim() - }), - body: z.object({ - app: z.string().trim(), - appId: z.string().trim(), - isActive: z.boolean(), - secretPath: z.string().trim().default("/"), - targetEnvironment: z.string().trim(), - owner: z.string().trim(), - environment: z.string().trim() - }) -}); - -export const DeleteIntegrationV1 = z.object({ - params: z.object({ - integrationId: z.string().trim() - }) -}); - -export const ManualSyncV1 = z.object({ - body: z.object({ - environment: z.string().trim(), - workspaceId: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/integrationAuth.ts b/backend-mongo/src/validation/integrationAuth.ts deleted file mode 100644 index 928e7f233..000000000 --- a/backend-mongo/src/validation/integrationAuth.ts +++ /dev/null @@ -1,217 +0,0 @@ -import { Types } from "mongoose"; -import { IUser, IWorkspace, IntegrationAuth } from "../models"; -import { IntegrationAuthNotFoundError, UnauthorizedRequestError } from "../utils/errors"; -import { IntegrationService } from "../services"; -import { validateUserClientForWorkspace } from "./user"; -import { AuthData } from "../interfaces/middleware"; -import { ActorType } from "../ee/models"; -import { z } from "zod"; - -/** - * Validate authenticated clients for integration authorization with id [integrationAuthId] based - * on any known permissions. - * @param {Object} obj - * @param {Object} obj.authData - authenticated client details - * @param {Types.ObjectId} obj.integrationAuthId - id of integration authorization to validate against - * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles - * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint - */ -const validateClientForIntegrationAuth = async ({ - authData, - integrationAuthId, - acceptedRoles, - attachAccessToken -}: { - authData: AuthData; - integrationAuthId: Types.ObjectId; - acceptedRoles: Array<"admin" | "member">; - attachAccessToken?: boolean; -}) => { - const integrationAuth = await IntegrationAuth.findById(integrationAuthId) - .populate<{ workspace: IWorkspace }>("workspace") - .select( - "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt metadata" - ); - - if (!integrationAuth) throw IntegrationAuthNotFoundError(); - - let accessToken, accessId; - if (attachAccessToken) { - const access = await IntegrationService.getIntegrationAuthAccess({ - integrationAuthId: integrationAuth._id - }); - - accessToken = access.accessToken; - accessId = access.accessId; - } - - switch (authData.actor.type) { - case ActorType.USER: - await validateUserClientForWorkspace({ - user: authData.authPayload as IUser, - workspaceId: integrationAuth.workspace._id, - acceptedRoles - }); - - return { integrationAuth, accessToken, accessId }; - case ActorType.SERVICE: - throw UnauthorizedRequestError({ - message: "Failed service token authorization for integration authorization" - }); - case ActorType.IDENTITY: - throw UnauthorizedRequestError({ - message: "Failed identity authorization for integration authorization" - }); - } -}; - -export const GetIntegrationAuthV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }) -}); - -export const OauthExchangeV1 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - code: z.string().trim(), - integration: z.string().trim(), - url: z.string().trim().url().optional(), - }) -}); - -export const SaveIntegrationAccessTokenV1 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - integration: z.string().trim(), - accessId: z.string().trim().optional(), - accessToken: z.string().trim().optional(), - url: z.string().url().trim().optional(), - namespace: z.string().trim().optional(), - refreshToken:z.string().trim().optional() - }) -}); - -export const GetIntegrationAuthAppsV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - teamId: z.string().trim().optional(), - workspaceSlug: z.string().trim().optional() - }) -}); - -export const GetIntegrationAuthTeamsV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }) -}); - -export const GetIntegrationAuthVercelBranchesV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - appId: z.string().trim() - }) -}); - -export const GetIntegrationAuthChecklyGroupsV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - accountId: z.string().trim() - }) -}); - -export const GetIntegrationAuthQoveryOrgsV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }) -}); - -export const GetIntegrationAuthQoveryProjectsV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - orgId: z.string().trim() - }) -}); - -export const GetIntegrationAuthQoveryEnvironmentsV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - projectId: z.string().trim() - }) -}); - -export const GetIntegrationAuthQoveryScopesV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - environmentId: z.string().trim() - }) -}); - -export const GetIntegrationAuthRailwayEnvironmentsV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - appId: z.string().trim() - }) -}); - -export const GetIntegrationAuthRailwayServicesV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - appId: z.string().trim() - }) -}); - -export const GetIntegrationAuthBitbucketWorkspacesV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }) -}); - -export const GetIntegrationAuthNorthflankSecretGroupsV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }), - query: z.object({ - appId: z.string().trim() - }) -}); - -export const DeleteIntegrationAuthsV1 = z.object({ - query: z.object({ - integration: z.string().trim(), - workspaceId: z.string().trim() - }) -}); - -export const DeleteIntegrationAuthV1 = z.object({ - params: z.object({ - integrationAuthId: z.string().trim() - }) -}); - -export const GetIntegrationAuthTeamCityBuildConfigsV1 = z.object({ - params: z.object({ - integrationAuthId:z.string().trim() - }), - query: z.object({ - appId:z.string().trim() - }) -}) - -export { validateClientForIntegrationAuth }; diff --git a/backend-mongo/src/validation/key.ts b/backend-mongo/src/validation/key.ts deleted file mode 100644 index a2d4ab92d..000000000 --- a/backend-mongo/src/validation/key.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { z } from "zod"; - -export const UploadKeyV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - key: z.object({ - encryptedKey: z.string().trim(), - nonce: z.string().trim(), - userId: z.string().trim() - }) - }) -}); - -export const GetLatestKeyV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/membership.ts b/backend-mongo/src/validation/membership.ts deleted file mode 100644 index 373a09aa0..000000000 --- a/backend-mongo/src/validation/membership.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Types } from "mongoose"; -import { IServiceTokenData, IUser, Membership } from "../models"; -import { validateUserClientForWorkspace } from "./user"; -import { validateServiceTokenDataClientForWorkspace } from "./serviceTokenData"; -import { MembershipNotFoundError } from "../utils/errors"; -import { AuthData } from "../interfaces/middleware"; -import { ActorType } from "../ee/models"; -import { z } from "zod"; - -/** - * Validate authenticated clients for membership with id [membershipId] based - * on any known permissions. - * @param {Object} obj - * @param {Object} obj.authData - authenticated client details - * @param {Types.ObjectId} obj.membershipId - id of membership to validate against - * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspaceRoles - * @returns {Membership} - validated membership - */ -export const validateClientForMembership = async ({ - authData, - membershipId, - acceptedRoles -}: { - authData: AuthData; - membershipId: Types.ObjectId; - acceptedRoles: Array<"admin" | "member">; -}) => { - const membership = await Membership.findById(membershipId); - - if (!membership) - throw MembershipNotFoundError({ - message: "Failed to find membership" - }); - - switch (authData.actor.type) { - case ActorType.USER: - await validateUserClientForWorkspace({ - user: authData.authPayload as IUser, - workspaceId: membership.workspace, - acceptedRoles - }); - - return membership; - case ActorType.SERVICE: - await validateServiceTokenDataClientForWorkspace({ - serviceTokenData: authData.authPayload as IServiceTokenData, - workspaceId: new Types.ObjectId(membership.workspace) - }); - - return membership; - } -}; - -export const ValidateMembershipV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const DeleteMembershipV1 = z.object({ - params: z.object({ - membershipId: z.string().trim() - }) -}); - -export const ChangeMembershipRoleV1 = z.object({ - body: z.object({ - role: z.string().trim() - }), - params: z.object({ membershipId: z.string().trim() }) -}); - -export const DenyMembershipPermissionV1 = z.object({ - params: z.object({ - membershipId: z.string().trim() - }), - body: z.object({ - permissions: z.object({}).array() - }) -}); - -export const AddUserToWorkspaceV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - members: z - .object({ - orgMembershipId: z.string().trim(), - workspaceEncryptedKey: z.string().trim(), - workspaceEncryptedNonce: z.string().trim() - }) - .array() - .min(1) - }) -}); diff --git a/backend-mongo/src/validation/membershipOrg.ts b/backend-mongo/src/validation/membershipOrg.ts deleted file mode 100644 index 4656d42fe..000000000 --- a/backend-mongo/src/validation/membershipOrg.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { z } from "zod"; - -export const DelOrgMembershipv1 = z.object({ - params: z.object({ - membershipOrgId: z.string().trim() - }) -}); - -export const InviteUserToOrgv1 = z.object({ - body: z.object({ - inviteeEmail: z.string().trim().email(), - organizationId: z.string().trim() - }) -}); - -export const VerifyUserToOrgv1 = z.object({ - body: z.object({ - email: z.string().trim().email(), - organizationId: z.string().trim(), - code: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/organization.ts b/backend-mongo/src/validation/organization.ts deleted file mode 100644 index d0ab37057..000000000 --- a/backend-mongo/src/validation/organization.ts +++ /dev/null @@ -1,223 +0,0 @@ -import { Types } from "mongoose"; -import { z } from "zod"; -import { IUser, Organization } from "../models"; -import { OrganizationNotFoundError, UnauthorizedRequestError } from "../utils/errors"; -import { validateUserClientForOrganization } from "./user"; -import { AuthData } from "../interfaces/middleware"; -import { ActorType } from "../ee/models"; - -/** - * Validate accepted clients for organization with id [organizationId] - * @param {Object} obj - * @param {Object} obj.authData - authenticated client details - * @param {Types.ObjectId} obj.organizationId - id of organization to validate against - */ -export const validateClientForOrganization = async ({ - authData, - organizationId, - acceptedRoles, - acceptedStatuses -}: { - authData: AuthData; - organizationId: Types.ObjectId; - acceptedRoles: Array<"owner" | "admin" | "member">; - acceptedStatuses: Array<"invited" | "accepted">; -}) => { - const organization = await Organization.findById(organizationId); - - if (!organization) { - throw OrganizationNotFoundError({ - message: "Failed to find organization" - }); - } - - let membershipOrg; - switch (authData.actor.type) { - case ActorType.USER: - membershipOrg = await validateUserClientForOrganization({ - user: authData.authPayload as IUser, - organization, - acceptedRoles, - acceptedStatuses - }); - - return { organization, membershipOrg }; - case ActorType.SERVICE: - throw UnauthorizedRequestError({ - message: "Failed service token authorization for organization" - }); - case ActorType.IDENTITY: - throw UnauthorizedRequestError({ - message: "Failed identity authorization for organization" - }); - } -}; - -export const GetOrgPlansTablev1 = z.object({ - query: z.object({ billingCycle: z.enum(["monthly", "yearly"]) }), - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgPlanv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }), - query: z.object({ workspaceId: z.string().trim().optional() }) -}); - -export const StartOrgTrailv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }), - body: z.object({ success_url: z.string().trim() }) -}); - -export const GetOrgPlanBillingInfov1 = z.object({ - params: z.object({ organizationId: z.string().trim() }), - query: z.object({ workspaceId: z.string().trim().optional() }) -}); - -export const GetOrgPlanTablev1 = z.object({ - params: z.object({ organizationId: z.string().trim() }), - query: z.object({ workspaceId: z.string().trim().optional() }) -}); - -export const GetOrgBillingDetailsv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const UpdateOrgBillingDetailsv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }), - body: z.object({ - email: z.string().trim().email().optional(), - name: z.string().trim().optional() - }) -}); - -export const GetOrgPmtMethodsv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const CreateOrgPmtMethodv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }), - body: z.object({ - success_url: z.string().trim(), - cancel_url: z.string().trim() - }) -}); - -export const DelOrgPmtMethodv1 = z.object({ - params: z.object({ - organizationId: z.string().trim(), - pmtMethodId: z.string().trim() - }) -}); - -export const GetOrgTaxIdsv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const CreateOrgTaxId = z.object({ - params: z.object({ organizationId: z.string().trim() }), - body: z.object({ - type: z.string().trim(), - value: z.string().trim() - }) -}); - -export const DelOrgTaxIdv1 = z.object({ - params: z.object({ - organizationId: z.string().trim(), - taxId: z.string().trim() - }) -}); - -export const GetOrgInvoicesv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgLicencesv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgv1 = z.object({ - params: z.object({ - organizationId: z.string().trim() - }) -}); - -export const GetOrgMembersv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgWorkspacesv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const ChangeOrgNamev1 = z.object({ - params: z.object({ organizationId: z.string().trim() }), - body: z.object({ name: z.string().trim() }) -}); - -export const GetOrgIncidentContactv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const CreateOrgIncideContact = z.object({ - params: z.object({ organizationId: z.string().trim() }), - body: z.object({ email: z.string().email().trim() }) -}); - -export const DelOrgIncideContact = z.object({ - params: z.object({ organizationId: z.string().trim() }), - body: z.object({ email: z.string().email().trim() }) -}); - -export const CreateOrgPortalSessionv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgMembersAndWsv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgMembersv2 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const UpdateOrgMemberv2 = z.object({ - params: z.object({ organizationId: z.string().trim(), membershipId: z.string().trim() }), - body: z.object({ - role: z.string().trim() - }) -}); - -export const DeleteOrgMemberv2 = z.object({ - params: z.object({ organizationId: z.string().trim(), membershipId: z.string().trim() }) -}); - -export const GetOrgWorkspacesv2 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const VerfiyUserToOrganizationV1 = z.object({ - body: z.object({ - email: z.string().trim().email(), - organizationId: z.string().trim(), - code: z.string().trim() - }) -}); - -export const CreateOrgv2 = z.object({ - body: z.object({ - name: z.string().trim() - }) -}); - -export const DeleteOrgv2 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgServiceMembersV2 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgIdentityMembershipsV2 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); \ No newline at end of file diff --git a/backend-mongo/src/validation/secretImports.ts b/backend-mongo/src/validation/secretImports.ts deleted file mode 100644 index a899a8346..000000000 --- a/backend-mongo/src/validation/secretImports.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { z } from "zod"; - -export const CreateSecretImportV1 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - directory: z.string().trim().default("/"), - secretImport: z.object({ - environment: z.string().trim(), - secretPath: z.string().trim() - }) - }) -}); - -export const UpdateSecretImportV1 = z.object({ - params: z.object({ - id: z.string().trim() - }), - body: z.object({ - secretImports: z - .object({ - environment: z.string().trim(), - secretPath: z.string().trim() - }) - .array() - }) -}); - -export const DeleteSecretImportV1 = z.object({ - params: z.object({ - id: z.string().trim() - }), - body: z.object({ - secretImportPath: z.string().trim(), - secretImportEnv: z.string().trim() - }) -}); - -export const GetSecretImportsV1 = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - directory: z.string().trim().default("/") - }) -}); - -export const GetAllSecretsFromImportV1 = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - directory: z.string().trim().default("/") - }) -}); diff --git a/backend-mongo/src/validation/secretScanning.ts b/backend-mongo/src/validation/secretScanning.ts deleted file mode 100644 index 2a883f8f8..000000000 --- a/backend-mongo/src/validation/secretScanning.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { z } from "zod"; - -export const CreateInstalLSessionv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const LinkInstallationToOrgv1 = z.object({ - body: z.object({ - installationId: z.string(), - sessionId: z.string().trim() - }) -}); - -export const GetOrgInstallStatusv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const GetOrgRisksv1 = z.object({ - params: z.object({ organizationId: z.string().trim() }) -}); - -export const UpdateRiskStatusv1 = z.object({ - params: z.object({ organizationId: z.string().trim(), riskId: z.string().trim() }), - body: z.object({ status: z.string().trim() }) -}); diff --git a/backend-mongo/src/validation/secretSnapshot.ts b/backend-mongo/src/validation/secretSnapshot.ts deleted file mode 100644 index b431547e8..000000000 --- a/backend-mongo/src/validation/secretSnapshot.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { z } from "zod"; - -export const GetSecretSnapshotV1 = z.object({ - params: z.object({ - secretSnapshotId: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/secrets.ts b/backend-mongo/src/validation/secrets.ts deleted file mode 100644 index 016fe750f..000000000 --- a/backend-mongo/src/validation/secrets.ts +++ /dev/null @@ -1,475 +0,0 @@ -import { Types } from "mongoose"; -import { ISecret, IServiceTokenData, IUser, Secret } from "../models"; -import { validateUserClientForSecret, validateUserClientForSecrets } from "./user"; -import { - validateServiceTokenDataClientForSecrets, - validateServiceTokenDataClientForWorkspace -} from "./serviceTokenData"; -import { BadRequestError, SecretNotFoundError } from "../utils/errors"; -import { AuthData } from "../interfaces/middleware"; -import { ActorType } from "../ee/models"; -import { z } from "zod"; -import { SECRET_PERSONAL, SECRET_SHARED } from "../variables"; -/** - * Validate authenticated clients for secrets with id [secretId] based - * on any known permissions. - * @param {Object} obj - * @param {Object} obj.authData - authenticated client details - * @param {Types.ObjectId} obj.secretId - id of secret to validate against - * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles - * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint - */ -export const validateClientForSecret = async ({ - authData, - secretId, - acceptedRoles, - requiredPermissions -}: { - authData: AuthData; - secretId: Types.ObjectId; - acceptedRoles: Array<"admin" | "member">; - requiredPermissions: string[]; -}) => { - const secret = await Secret.findById(secretId); - - if (!secret) - throw SecretNotFoundError({ - message: "Failed to find secret" - }); - - switch (authData.actor.type) { - case ActorType.USER: - await validateUserClientForSecret({ - user: authData.authPayload as IUser, - secret, - acceptedRoles, - requiredPermissions - }); - - return secret; - case ActorType.SERVICE: - await validateServiceTokenDataClientForWorkspace({ - serviceTokenData: authData.authPayload as IServiceTokenData, - workspaceId: secret.workspace, - environment: secret.environment - }); - - return secret; - } -}; - -/** - * Validate authenticated clients for secrets with ids [secretIds] based - * on any known permissions. - * @param {Object} obj - * @param {Object} obj.authData - authenticated client details - * @param {Types.ObjectId[]} obj.secretIds - id of workspace to validate against - * @param {String} obj.environment - (optional) environment in workspace to validate against - * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles - * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint - */ -export const validateClientForSecrets = async ({ - authData, - secretIds, - requiredPermissions -}: { - authData: AuthData; - secretIds: Types.ObjectId[]; - requiredPermissions: string[]; -}) => { - let secrets: ISecret[] = []; - - secrets = await Secret.find({ - _id: { - $in: secretIds - } - }); - - if (secrets.length != secretIds.length) { - throw BadRequestError({ message: "Failed to validate non-existent secrets" }); - } - - switch (authData.actor.type) { - case ActorType.USER: - await validateUserClientForSecrets({ - user: authData.authPayload as IUser, - secrets, - requiredPermissions - }); - - return secrets; - case ActorType.SERVICE: - await validateServiceTokenDataClientForSecrets({ - serviceTokenData: authData.authPayload as IServiceTokenData, - secrets, - requiredPermissions - }); - - return secrets; - } -}; - -export const GetSecretVersionsV1 = z.object({ - params: z.object({ - secretId: z.string().trim() - }), - query: z.object({ - offset: z.coerce.number(), - limit: z.coerce.number() - }) -}); - -export const RollbackSecretVersionV1 = z.object({ - params: z.object({ - secretId: z.string().trim() - }), - body: z.object({ - version: z.number() - }) -}); - -export const PushSecretsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - secrets: z.object({}).array(), - keys: z.object({}).array(), - environment: z.string().trim(), - channel: z.string().trim() - }) -}); - -export const PullSecretsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - query: z.object({ - channel: z.string().optional(), - environment: z.string().trim() - }) -}); - -export const PullSecretsServiceTokenV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - query: z.object({ - channel: z.string().optional(), - environment: z.string().trim() - }) -}); - -const batchUpdateRequestV2 = z.object({ - _id: z.string(), - folderId: z.string().trim().optional(), - type: z.enum(["shared", "personal"]), - secretName: z.string().trim(), - secretKeyCiphertext: z.string().trim(), - secretKeyIV: z.string().trim(), - secretKeyTag: z.string().trim(), - secretValueCiphertext: z.string().trim(), - secretValueIV: z.string().trim(), - secretValueTag: z.string().trim(), - secretCommentCiphertext: z.string().trim().optional(), - secretCommentIV: z.string().trim().optional(), - secretCommentTag: z.string().trim().optional(), - tags: z - .object({ - _id: z.string().trim(), - name: z.string().trim(), - slug: z.string().trim() - }) - .array() -}); - -export const BatchSecretsV2 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - folderId: z.string().trim().default("root"), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - requests: z - .discriminatedUnion("method", [ - z.object({ - method: z.literal("POST"), - secret: batchUpdateRequestV2.omit({ _id: true }) - }), - z.object({ - method: z.literal("PATCH"), - secret: batchUpdateRequestV2 - }), - z.object({ - method: z.literal("DELETE"), - secret: z.object({ _id: z.string().trim(), secretName: z.string().trim() }) - }) - ]) - .array() - }) -}); - -export const GetSecretsV2 = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - tagSlugs: z.string().trim().optional(), - folderId: z.string().trim().default("root"), - secretPath: z.string().trim().optional(), - include_imports: z - .enum(["true", "false"]) - .default("false") - .transform((value) => value === "true") - }) -}); - -export const GetSecretsRawV3 = z.object({ - query: z.object({ - workspaceId: z.string().trim().optional(), - environment: z.string().trim().optional(), - secretPath: z.string().trim().default("/"), - include_imports: z - .enum(["true", "false"]) - .default("false") - .transform((value) => value === "true") - }) -}); - -export const GetSecretByNameRawV3 = z.object({ - params: z.object({ - secretName: z.string().trim() - }), - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).optional(), - include_imports: z - .enum(["true", "false"]) - .default("true") - .transform((value) => value === "true"), - version: z - .string() - .trim() - .optional() - .transform((value) => value === undefined ? undefined : parseInt(value, 10)) - .refine((value) => value === undefined || !isNaN(value), { - message: "Version must be a number", - }) - }) -}); - -export const CreateSecretRawV3 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - secretValue: z - .string() - .transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())), - secretComment: z.string().trim().optional().default(""), - - skipMultilineEncoding: z.boolean().optional(), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]) - }), - params: z.object({ - secretName: z.string().trim() - }) -}); - -export const UpdateSecretByNameRawV3 = z.object({ - params: z.object({ - secretName: z.string().trim() - }), - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - - secretValue: z - .string() - .transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())), - secretPath: z.string().trim().default("/"), - skipMultilineEncoding: z.boolean().optional(), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).default(SECRET_SHARED) - }) -}); - -export const DeleteSecretByNameRawV3 = z.object({ - params: z.object({ - secretName: z.string().trim() - }), - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).default(SECRET_SHARED) - }) -}); - -export const GetSecretsV3 = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - include_imports: z - .enum(["true", "false"]) - .default("false") - .transform((value) => value === "true") - }) -}); - -export const GetSecretByNameV3 = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).optional(), - include_imports: z - .enum(["true", "false"]) - .default("true") - .transform((value) => value === "true"), - version: z - .string() - .trim() - .optional() - .transform((value) => value === undefined ? undefined : parseInt(value, 10)) - .refine((value) => value === undefined || !isNaN(value), { - message: "Version must be a number", - }) - }), - params: z.object({ - secretName: z.string().trim() - }) -}); - -export const CreateSecretV3 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]), - secretPath: z.string().trim().default("/"), - secretKeyCiphertext: z.string().trim(), - secretKeyIV: z.string().trim(), - secretKeyTag: z.string().trim(), - secretValueCiphertext: z.string().trim(), - secretValueIV: z.string().trim(), - secretValueTag: z.string().trim(), - secretCommentCiphertext: z.string().trim().optional(), - secretCommentIV: z.string().trim().optional(), - secretCommentTag: z.string().trim().optional(), - metadata: z.record(z.string()).optional(), - skipMultilineEncoding: z.boolean().optional() - }), - params: z.object({ - secretName: z.string().trim() - }) -}); - -export const UpdateSecretByNameV3 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretId: z.string().trim().optional(), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]), - secretPath: z.string().trim().default("/"), - secretValueCiphertext: z.string().trim(), - secretValueIV: z.string().trim(), - secretValueTag: z.string().trim(), - secretCommentCiphertext: z.string().trim().optional(), - secretCommentIV: z.string().trim().optional(), - secretCommentTag: z.string().trim().optional(), - - secretReminderRepeatDays: z.number().min(1).max(365).optional().nullable(), - secretReminderNote: z.string().trim().nullable().optional(), - - tags: z.string().array().optional(), - skipMultilineEncoding: z.boolean().optional(), - // to update secret name - secretName: z.string().trim().optional(), - secretKeyIV: z.string().trim().optional(), - secretKeyTag: z.string().trim().optional(), - secretKeyCiphertext: z.string().trim().optional() - }), - params: z.object({ - secretName: z.string() - }) -}); - -export const DeleteSecretByNameV3 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]), - secretPath: z.string().trim().default("/"), - secretId: z.string().trim().optional() - }), - params: z.object({ - secretName: z.string() - }) -}); - -export const CreateSecretByNameBatchV3 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - secrets: z - .object({ - secretName: z.string().trim(), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]), - secretKeyCiphertext: z.string().trim(), - secretKeyIV: z.string().trim(), - secretKeyTag: z.string().trim(), - secretValueCiphertext: z.string().trim(), - secretValueIV: z.string().trim(), - secretValueTag: z.string().trim(), - secretCommentCiphertext: z.string().trim().optional(), - secretCommentIV: z.string().trim().optional(), - secretCommentTag: z.string().trim().optional(), - metadata: z.record(z.string()).optional(), - skipMultilineEncoding: z.boolean().optional() - }) - .array() - .min(1) - }) -}); - -export const UpdateSecretByNameBatchV3 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - secrets: z - .object({ - secretName: z.string().trim(), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]), - secretValueCiphertext: z.string().trim(), - secretValueIV: z.string().trim(), - secretValueTag: z.string().trim(), - secretKeyCiphertext: z.string().trim(), - secretKeyIV: z.string().trim(), - secretKeyTag: z.string().trim(), - secretCommentCiphertext: z.string().trim().optional(), - secretCommentIV: z.string().trim().optional(), - secretCommentTag: z.string().trim().optional(), - skipMultilineEncoding: z.boolean().optional(), - tags: z.string().array().optional() - }) - .array() - .min(1) - }) -}); - -export const DeleteSecretByNameBatchV3 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - secretPath: z.string().trim().default("/"), - secrets: z - .object({ - secretName: z.string().trim(), - type: z.enum([SECRET_SHARED, SECRET_PERSONAL]) - }) - .array() - .min(1) - }) -}); diff --git a/backend-mongo/src/validation/serviceTokenData.ts b/backend-mongo/src/validation/serviceTokenData.ts deleted file mode 100644 index 49ee6d23f..000000000 --- a/backend-mongo/src/validation/serviceTokenData.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { Types } from "mongoose"; -import { ISecret, IServiceTokenData, IUser, ServiceTokenData } from "../models"; -import { ServiceTokenDataNotFoundError, UnauthorizedRequestError } from "../utils/errors"; -import { validateUserClientForWorkspace } from "./user"; -import { ActorType } from "../ee/models"; -import { AuthData } from "../interfaces/middleware"; -import { z } from "zod"; -import { isValidScope } from "../helpers"; - -/** - * Validate authenticated clients for service token with id [serviceTokenId] based - * on any known permissions. - * @param {Object} obj - * @param {Object} obj.authData - authenticated client details - * @param {Types.ObjectId} obj.serviceTokenData - id of service token to validate against - * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles - */ -export const validateClientForServiceTokenData = async ({ - authData, - serviceTokenDataId, - acceptedRoles -}: { - authData: AuthData; - serviceTokenDataId: Types.ObjectId; - acceptedRoles: Array<"admin" | "member">; -}) => { - const serviceTokenData = await ServiceTokenData.findById(serviceTokenDataId) - .select("+encryptedKey +iv +tag") - .populate<{ user: IUser }>("user"); - - if (!serviceTokenData) - throw ServiceTokenDataNotFoundError({ - message: "Failed to find service token data" - }); - - switch (authData.actor.type) { - case ActorType.USER: - await validateUserClientForWorkspace({ - user: authData.authPayload as IUser, - workspaceId: serviceTokenData.workspace, - acceptedRoles - }); - - return serviceTokenData; - case ActorType.SERVICE: - throw UnauthorizedRequestError({ - message: "Failed service token authorization for service token data" - }); - } -}; - -/** - * Validate that service token (client) can access workspace - * with id [workspaceId] and its environment [environment] with required permissions - * [requiredPermissions] - * @param {Object} obj - * @param {ServiceTokenData} obj.serviceTokenData - service token client - * @param {Types.ObjectId} obj.workspaceId - id of workspace to validate against - * @param {String} environment - (optional) environment in workspace to validate against - * @param {String[]} requiredPermissions - required permissions as part of the endpoint - */ -export const validateServiceTokenDataClientForWorkspace = async ({ - serviceTokenData, - workspaceId, - environment, - secretPath = "/", - requiredPermissions -}: { - serviceTokenData: IServiceTokenData; - workspaceId: Types.ObjectId; - environment?: string; - secretPath?: string; - requiredPermissions?: string[]; -}) => { - if (!serviceTokenData.workspace.equals(workspaceId)) { - // case: invalid workspaceId passed - throw UnauthorizedRequestError({ - message: "Failed service token authorization for the given workspace" - }); - } - - if (environment) { - // case: environment is specified - if (!serviceTokenData.scopes.find(({ environment: tkEnv }) => tkEnv === environment)) { - // case: invalid environment passed - throw UnauthorizedRequestError({ - message: "Failed service token authorization for the given workspace environment" - }); - } - - if (!isValidScope(serviceTokenData, environment, secretPath)) { - throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); - } - - requiredPermissions?.forEach((permission) => { - if (!serviceTokenData.permissions.includes(permission)) { - throw UnauthorizedRequestError({ - message: `Failed service token authorization for the given workspace environment action: ${permission}` - }); - } - }); - } -}; - -/** - * Validate that service token (client) can access secrets - * with required permissions [requiredPermissions] - * @param {Object} obj - * @param {ServiceTokenData} obj.serviceTokenData - service token client - * @param {Secret[]} secrets - secrets to validate against - * @param {string[]} requiredPermissions - required permissions as part of the endpoint - */ -export const validateServiceTokenDataClientForSecrets = async ({ - serviceTokenData, - secrets, - requiredPermissions -}: { - serviceTokenData: IServiceTokenData; - secrets: ISecret[]; - requiredPermissions?: string[]; -}) => { - secrets.forEach((secret: ISecret) => { - if (!serviceTokenData.workspace.equals(secret.workspace)) { - // case: invalid workspaceId passed - throw UnauthorizedRequestError({ - message: "Failed service token authorization for the given workspace" - }); - } - - if (!serviceTokenData.scopes.find(({ environment: tkEnv }) => tkEnv === secret.environment)) { - // case: invalid environment passed - throw UnauthorizedRequestError({ - message: "Failed service token authorization for the given workspace environment" - }); - } - - requiredPermissions?.forEach((permission) => { - if (!serviceTokenData.permissions.includes(permission)) { - throw UnauthorizedRequestError({ - message: `Failed service token authorization for the given workspace environment action: ${permission}` - }); - } - }); - }); -}; - -export const CreateServiceTokenV2 = z.object({ - body: z.object({ - name: z.string().trim(), - workspaceId: z.string().trim(), - scopes: z - .object({ - environment: z.string().trim(), - secretPath: z.string().trim() - }) - .array() - .min(1), - encryptedKey: z.string().trim(), - iv: z.string().trim(), - tag: z.string().trim(), - expiresIn: z.number().nullable().optional(), - permissions: z.enum(["read", "write"]).array() - }) -}); - -export const DeleteServiceTokenV2 = z.object({ - params: z.object({ - serviceTokenDataId: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/sso.ts b/backend-mongo/src/validation/sso.ts deleted file mode 100644 index 275ae611e..000000000 --- a/backend-mongo/src/validation/sso.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { z } from "zod"; -import { AuthProvider } from "../ee/models"; - -export const GetSsoConfigv1 = z.object({ - query: z.object({ organizationId: z.string().trim() }) -}); - -export const CreateSsoConfigv1 = z.object({ - body: z.object({ - organizationId: z.string().trim(), - authProvider: z.nativeEnum(AuthProvider), - isActive: z.boolean(), - entryPoint: z.string().trim(), - issuer: z.string().trim(), - cert: z.string().trim() - }) -}); - -export const UpdateSsoConfigv1 = z.object({ - body: z.object({ - organizationId: z.string().trim(), - authProvider: z.nativeEnum(AuthProvider).optional(), - isActive: z.boolean().optional(), - entryPoint: z.string().trim().optional(), - issuer: z.string().trim().optional(), - cert: z.string().trim().optional() - }) -}); diff --git a/backend-mongo/src/validation/tags.ts b/backend-mongo/src/validation/tags.ts deleted file mode 100644 index 0631e9a9a..000000000 --- a/backend-mongo/src/validation/tags.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { z } from "zod"; - -export const GetWorkspaceTagsV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const DeleteWorkspaceTagsV2 = z.object({ - params: z.object({ - tagId: z.string().trim() - }) -}); - -export const CreateWorkspaceTagsV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - name: z.string().trim(), - slug: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/user.ts b/backend-mongo/src/validation/user.ts deleted file mode 100644 index 1f356ec11..000000000 --- a/backend-mongo/src/validation/user.ts +++ /dev/null @@ -1,232 +0,0 @@ -import fs from "fs"; -import path from "path"; -import { Types } from "mongoose"; -import { IOrganization, ISecret, IUser, Membership } from "../models"; -import { validateMembership } from "../helpers/membership"; -import _ from "lodash"; -import { BadRequestError, UnauthorizedRequestError, ValidationError } from "../utils/errors"; -import { validateMembershipOrg } from "../helpers/membershipOrg"; -import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from "../variables"; -import { AuthMethod } from "../models"; -import { z } from "zod"; - -/** - * Validate that email [email] is not disposable - * @param email - email to validate - */ -export const validateUserEmail = (email: string) => { - const emailDomain = email.split("@")[1]; - const disposableEmails = fs - .readFileSync(path.resolve(__dirname, "../data/" + "disposable_emails.txt"), "utf8") - .split("\n"); - - if (disposableEmails.includes(emailDomain)) - throw ValidationError({ - message: "Failed to validate email as non-disposable" - }); -}; - -/** - * Validate that user (client) can access workspace - * with id [workspaceId] and its environment [environment] with required permissions - * [requiredPermissions] - * @param {Object} obj - * @param {User} obj.user - user client - * @param {Types.ObjectId} obj.workspaceId - id of workspace to validate against - * @param {String} environment - (optional) environment in workspace to validate against - * @param {String[]} requiredPermissions - required permissions as part of the endpoint - */ -export const validateUserClientForWorkspace = async ({ - user, - workspaceId, - environment, - acceptedRoles, - requiredPermissions -}: { - user: IUser; - workspaceId: Types.ObjectId; - environment?: string; - acceptedRoles: Array<"admin" | "member">; - requiredPermissions?: string[]; -}) => { - // validate user membership in workspace - const membership = await validateMembership({ - userId: user._id, - workspaceId, - acceptedRoles - }); - - let runningIsDisallowed = false; - requiredPermissions?.forEach((requiredPermission: string) => { - switch (requiredPermission) { - case PERMISSION_READ_SECRETS: - runningIsDisallowed = _.some(membership.deniedPermissions, { - environmentSlug: environment, - ability: PERMISSION_READ_SECRETS - }); - break; - case PERMISSION_WRITE_SECRETS: - runningIsDisallowed = _.some(membership.deniedPermissions, { - environmentSlug: environment, - ability: PERMISSION_WRITE_SECRETS - }); - break; - default: - break; - } - - if (runningIsDisallowed) { - throw UnauthorizedRequestError({ - message: `Failed permissions authorization for workspace environment action : ${requiredPermission}` - }); - } - }); - - return membership; -}; - -/** - * Validate that user (client) can access secret [secret] - * with required permissions [requiredPermissions] - * @param {Object} obj - * @param {User} obj.user - user client - * @param {Secret[]} obj.secrets - secrets to validate against - * @param {String[]} requiredPermissions - required permissions as part of the endpoint - */ -export const validateUserClientForSecret = async ({ - user, - secret, - acceptedRoles, - requiredPermissions -}: { - user: IUser; - secret: ISecret; - acceptedRoles?: Array<"admin" | "member">; - requiredPermissions?: string[]; -}) => { - const membership = await validateMembership({ - userId: user._id, - workspaceId: secret.workspace, - acceptedRoles - }); - - if (requiredPermissions?.includes(PERMISSION_WRITE_SECRETS)) { - const isDisallowed = _.some(membership.deniedPermissions, { - environmentSlug: secret.environment, - ability: PERMISSION_WRITE_SECRETS - }); - - if (isDisallowed) { - throw UnauthorizedRequestError({ - message: "You do not have the required permissions to perform this action" - }); - } - } -}; - -/** - * Validate that user (client) can access secrets [secrets] - * with required permissions [requiredPermissions] - * @param {Object} obj - * @param {User} obj.user - user client - * @param {Secret[]} obj.secrets - secrets to validate against - * @param {String[]} requiredPermissions - required permissions as part of the endpoint - */ -export const validateUserClientForSecrets = async ({ - user, - secrets, - requiredPermissions -}: { - user: IUser; - secrets: ISecret[]; - requiredPermissions?: string[]; -}) => { - // TODO: add acceptedRoles? - - const userMemberships = await Membership.find({ user: user._id }); - const userMembershipById = _.keyBy(userMemberships, "workspace"); - const workspaceIdsSet = new Set(userMemberships.map((m) => m.workspace.toString())); - - // for each secret check if the secret belongs to a workspace the user is a member of - secrets.forEach((secret: ISecret) => { - if (!workspaceIdsSet.has(secret.workspace.toString())) { - throw BadRequestError({ - message: "Failed authorization for the secret" - }); - } - - if (requiredPermissions?.includes(PERMISSION_WRITE_SECRETS)) { - const deniedMembershipPermissions = - userMembershipById[secret.workspace.toString()].deniedPermissions; - const isDisallowed = _.some(deniedMembershipPermissions, { - environmentSlug: secret.environment, - ability: PERMISSION_WRITE_SECRETS - }); - - if (isDisallowed) { - throw UnauthorizedRequestError({ - message: "You do not have the required permissions to perform this action" - }); - } - } - }); -}; - -/** - * Validate that user (client) can access organization [organization] - * @param {Object} obj - * @param {User} obj.user - user client - * @param {Organization} obj.organization - organization to validate against - */ -export const validateUserClientForOrganization = async ({ - user, - organization, - acceptedRoles, - acceptedStatuses -}: { - user: IUser; - organization: IOrganization; - acceptedRoles: Array<"owner" | "admin" | "member">; - acceptedStatuses: Array<"invited" | "accepted">; -}) => { - const membershipOrg = await validateMembershipOrg({ - userId: user._id, - organizationId: organization._id, - acceptedRoles, - acceptedStatuses - }); - - return membershipOrg; -}; - -export const UpdateMyMfaEnabledV2 = z.object({ - body: z.object({ - isMfaEnabled: z.boolean() - }) -}); - -export const UpdateNameV2 = z.object({ - body: z.object({ - firstName: z.string().trim(), - lastName: z.string().trim() - }) -}); - -export const UpdateAuthMethodsV2 = z.object({ - body: z.object({ - authMethods: z.nativeEnum(AuthMethod).array().min(1) - }) -}); - -export const CreateApiKeyV2 = z.object({ - body: z.object({ - name: z.string().trim(), - expiresIn: z.number() - }) -}); - -export const DeleteApiKeyV2 = z.object({ - params: z.object({ - apiKeyDataId: z.string().trim() - }) -}); diff --git a/backend-mongo/src/validation/webhooks.ts b/backend-mongo/src/validation/webhooks.ts deleted file mode 100644 index 907f90633..000000000 --- a/backend-mongo/src/validation/webhooks.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { z } from "zod"; - -export const CreateWebhookV1 = z.object({ - body: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), - webhookUrl: z.string().url().trim(), - webhookSecretKey: z.string().trim().optional(), - secretPath: z.string().trim().default("/") - }) -}); - -export const UpdateWebhookV1 = z.object({ - params: z.object({ - webhookId: z.string().trim() - }), - body: z.object({ - isDisabled: z.boolean().default(false) - }) -}); - -export const TestWebhookV1 = z.object({ - params: z.object({ - webhookId: z.string().trim() - }) -}); - -export const DeleteWebhookV1 = z.object({ - params: z.object({ - webhookId: z.string().trim() - }) -}); - -export const ListWebhooksV1 = z.object({ - query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim().optional(), - secretPath: z.string().trim().optional() - }) -}); diff --git a/backend-mongo/src/validation/workspace.ts b/backend-mongo/src/validation/workspace.ts deleted file mode 100644 index 4c9a2183d..000000000 --- a/backend-mongo/src/validation/workspace.ts +++ /dev/null @@ -1,340 +0,0 @@ -import { Types } from "mongoose"; -import { IServiceTokenData, IUser, Workspace } from "../models"; -import { ActorType } from "../ee/models"; -import { validateUserClientForWorkspace } from "./user"; -import { validateServiceTokenDataClientForWorkspace } from "./serviceTokenData"; -import { WorkspaceNotFoundError } from "../utils/errors"; -import { AuthData } from "../interfaces/middleware"; -import { z } from "zod"; -import { EventType, UserAgentType } from "../ee/models"; -import { UnauthorizedRequestError } from "../utils/errors"; -import { NO_ACCESS } from "../variables"; - -/** - * Validate authenticated clients for workspace with id [workspaceId] based - * on any known permissions. - * @param {Object} obj - * @param {Object} obj.authData - authenticated client details - * @param {Types.ObjectId} obj.workspaceId - id of workspace to validate against - * @param {String} obj.environment - (optional) environment in workspace to validate against - * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles - * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint - */ -export const validateClientForWorkspace = async ({ - authData, - workspaceId, - environment, - acceptedRoles, - requiredPermissions -}: { - authData: AuthData; - workspaceId: Types.ObjectId; - environment?: string; - acceptedRoles: Array<"admin" | "member">; - requiredPermissions?: string[]; -}) => { - const workspace = await Workspace.findById(workspaceId); - - if (!workspace) - throw WorkspaceNotFoundError({ - message: "Failed to find workspace" - }); - - let membership; - switch (authData.actor.type) { - case ActorType.USER: - membership = await validateUserClientForWorkspace({ - user: authData.authPayload as IUser, - workspaceId, - environment, - acceptedRoles, - requiredPermissions - }); - - return { membership, workspace }; - case ActorType.SERVICE: - await validateServiceTokenDataClientForWorkspace({ - serviceTokenData: authData.authPayload as IServiceTokenData, - workspaceId, - environment, - requiredPermissions - }); - return { membership, workspace }; - case ActorType.IDENTITY: - throw UnauthorizedRequestError({ - message: "Failed identity authorization for organization" - }); - } -}; - -export const GetWorkspaceSecretSnapshotsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - query: z.object({ - environment: z.string().trim(), - directory: z.string().trim().default("/"), - offset: z.coerce.number(), - limit: z.coerce.number() - }) -}); - -export const GetWorkspaceSecretSnapshotsCountV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - query: z.object({ - environment: z.string().trim(), - directory: z.string().trim().default("/") - }) -}); - -export const RollbackWorkspaceSecretSnapshotV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - environment: z.string().trim(), - directory: z.string().trim().default("/"), - version: z.number() - }) -}); - -export const GetWorkspaceLogsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - query: z.object({ - offset: z.coerce.number(), - limit: z.coerce.number(), - sortBy: z.string().trim().optional(), - userId: z.string().trim().optional(), - actionNames: z.string().trim().optional() - }) -}); - -export const GetWorkspaceAuditLogsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - query: z.object({ - eventType: z.nativeEnum(EventType).nullable().optional(), - userAgentType: z.nativeEnum(UserAgentType).nullable().optional(), - startDate: z.string().datetime().nullable().optional(), - endDate: z.string().datetime().nullable().optional(), - offset: z.coerce.number().default(0), - limit: z.coerce.number().default(20), - actor: z.string().nullish().optional() - }) -}); - -export const GetWorkspaceAuditLogActorFilterOptsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceTrustedIpsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const AddWorkspaceTrustedIpV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - ipAddress: z.string().trim(), - comment: z.string().trim().default(""), - isActive: z.boolean() - }) -}); - -export const UpdateWorkspaceTrustedIpV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim(), - trustedIpId: z.string().trim() - }), - body: z.object({ - ipAddress: z.string().trim(), - comment: z.string().trim().default("") - }) -}); - -export const DeleteWorkspaceTrustedIpV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim(), - trustedIpId: z.string().trim() - }) -}); - -export const GetWorkspacePublicKeysV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceMembershipsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const CreateWorkspaceV1 = z.object({ - body: z.object({ - workspaceName: z.string().trim(), - organizationId: z.string().trim() - }) -}); - -export const DeleteWorkspaceV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const ChangeWorkspaceNameV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - name: z.string().trim() - }) -}); - -export const InviteUserToWorkspaceV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - email: z.string().trim() - }) -}); - -export const GetWorkspaceIntegrationsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceIntegrationAuthorizationsV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceServiceTokensV1 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceServiceTokenDataV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceKeyV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceMembershipsV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const UpdateWorkspaceMembershipsV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim(), - membershipId: z.string().trim() - }), - body: z.object({ - role: z.string().trim() - }) -}); - -export const DeleteWorkspaceMembershipsV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim(), - membershipId: z.string().trim() - }) -}); - -export const ToggleAutoCapitalizationV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - autoCapitalization: z.boolean() - }) -}); - -export const AddIdentityToWorkspaceV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim(), - identityId: z.string().trim() - }), - body: z.object({ - role: z.string().trim().min(1).default(NO_ACCESS), - }) -}); - -export const UpdateIdentityWorkspaceRoleV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim(), - identityId: z.string().trim() - }), - body: z.object({ - role: z.string().trim().min(1).default(NO_ACCESS), - }) -}); - -export const DeleteIdentityFromWorkspaceV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim(), - identityId: z.string().trim() - }) -}); - -export const GetWorkspaceIdentityMembersV2 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), -}); - -export const GetWorkspaceBlinkIndexStatusV3 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const GetWorkspaceSecretsV3 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }) -}); - -export const NameWorkspaceSecretsV3 = z.object({ - params: z.object({ - workspaceId: z.string().trim() - }), - body: z.object({ - secretsToUpdate: z - .object({ - secretName: z.string().trim(), - _id: z.string().trim() - }) - .array() - }) -}); diff --git a/backend-mongo/src/variables/authentication.ts b/backend-mongo/src/variables/authentication.ts deleted file mode 100644 index 5eec0ba22..000000000 --- a/backend-mongo/src/variables/authentication.ts +++ /dev/null @@ -1,21 +0,0 @@ -// TODO: merge [AuthTokenType] and [AuthMode] - -export enum AuthTokenType { - ACCESS_TOKEN = "accessToken", - REFRESH_TOKEN = "refreshToken", - SIGNUP_TOKEN = "signupToken", // TODO: remove in favor of claim - MFA_TOKEN = "mfaToken", // TODO: remove in favor of claim - PROVIDER_TOKEN = "providerToken", // TODO: remove in favor of claim - API_KEY = "apiKey", - IDENTITY_ACCESS_TOKEN = "identityAccessToken", -} - -export enum AuthMode { - JWT = "jwt", - SERVICE_TOKEN = "serviceToken", - IDENTITY_ACCESS_TOKEN = "identityAccessToken", - API_KEY = "apiKey", - API_KEY_V2 = "apiKeyV2" -} - -export const K8_USER_AGENT_NAME = "k8-operator" \ No newline at end of file diff --git a/backend-mongo/src/variables/crypto.ts b/backend-mongo/src/variables/crypto.ts deleted file mode 100644 index 64dde2c22..000000000 --- a/backend-mongo/src/variables/crypto.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const ALGORITHM_AES_256_GCM = "aes-256-gcm"; -export const NONCE_BYTES_SIZE = 12; -export const BLOCK_SIZE_BYTES_16 = 16; - -export const ENCODING_SCHEME_UTF8 = "utf8"; -export const ENCODING_SCHEME_HEX = "hex"; -export const ENCODING_SCHEME_BASE64 = "base64"; \ No newline at end of file diff --git a/backend-mongo/src/variables/environment.ts b/backend-mongo/src/variables/environment.ts deleted file mode 100644 index d0c8220ef..000000000 --- a/backend-mongo/src/variables/environment.ts +++ /dev/null @@ -1,6 +0,0 @@ -// environments -export const ENV_DEV = "dev"; -export const ENV_TESTING = "test"; -export const ENV_STAGING = "staging"; -export const ENV_PROD = "prod"; -export const ENV_SET = new Set([ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD]); \ No newline at end of file diff --git a/backend-mongo/src/variables/event.ts b/backend-mongo/src/variables/event.ts deleted file mode 100644 index 126ede040..000000000 --- a/backend-mongo/src/variables/event.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const EVENT_PUSH_SECRETS = "pushSecrets"; -export const EVENT_PULL_SECRETS = "pullSecrets"; -export const EVENT_START_INTEGRATION = "startIntegration"; diff --git a/backend-mongo/src/variables/index.ts b/backend-mongo/src/variables/index.ts deleted file mode 100644 index ec9f14212..000000000 --- a/backend-mongo/src/variables/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export * from "./authentication"; -export * from "./crypto"; -export * from "./environment"; -export * from "./event"; -export * from "./integration"; -export * from "./organization"; -export * from "./permission"; -export * from "./secret"; -export * from "./smtp"; -export * from "./token"; -export * from "./user"; diff --git a/backend-mongo/src/variables/integration.ts b/backend-mongo/src/variables/integration.ts deleted file mode 100644 index 28848dbb6..000000000 --- a/backend-mongo/src/variables/integration.ts +++ /dev/null @@ -1,397 +0,0 @@ -import { - getClientIdAzure, - getClientIdBitBucket, - getClientIdGCPSecretManager, - getClientIdGitHub, - getClientIdGitLab, - getClientIdHeroku, - getClientIdNetlify, - getClientSlugVercel -} from "../config"; - -// integrations -export const INTEGRATION_AZURE_KEY_VAULT = "azure-key-vault"; -export const INTEGRATION_AWS_PARAMETER_STORE = "aws-parameter-store"; -export const INTEGRATION_AWS_SECRET_MANAGER = "aws-secret-manager"; -export const INTEGRATION_GCP_SECRET_MANAGER = "gcp-secret-manager"; -export const INTEGRATION_HEROKU = "heroku"; -export const INTEGRATION_VERCEL = "vercel"; -export const INTEGRATION_NETLIFY = "netlify"; -export const INTEGRATION_GITHUB = "github"; -export const INTEGRATION_GITLAB = "gitlab"; -export const INTEGRATION_RENDER = "render"; -export const INTEGRATION_RAILWAY = "railway"; -export const INTEGRATION_FLYIO = "flyio"; -export const INTEGRATION_LARAVELFORGE = "laravel-forge"; -export const INTEGRATION_CIRCLECI = "circleci"; -export const INTEGRATION_TRAVISCI = "travisci"; -export const INTEGRATION_TEAMCITY = "teamcity"; -export const INTEGRATION_SUPABASE = "supabase"; -export const INTEGRATION_CHECKLY = "checkly"; -export const INTEGRATION_QOVERY = "qovery"; -export const INTEGRATION_TERRAFORM_CLOUD = "terraform-cloud"; -export const INTEGRATION_HASHICORP_VAULT = "hashicorp-vault"; -export const INTEGRATION_CLOUDFLARE_PAGES = "cloudflare-pages"; -export const INTEGRATION_CLOUDFLARE_WORKERS = "cloudflare-workers"; -export const INTEGRATION_BITBUCKET = "bitbucket"; -export const INTEGRATION_CODEFRESH = "codefresh"; -export const INTEGRATION_WINDMILL = "windmill"; -export const INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM = "digital-ocean-app-platform"; -export const INTEGRATION_CLOUD_66 = "cloud-66"; -export const INTEGRATION_NORTHFLANK = "northflank"; -export const INTEGRATION_HASURA_CLOUD = "hasura-cloud"; -export const INTEGRATION_SET = new Set([ - INTEGRATION_GCP_SECRET_MANAGER, - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_HEROKU, - INTEGRATION_VERCEL, - INTEGRATION_NETLIFY, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_RENDER, - INTEGRATION_FLYIO, - INTEGRATION_CIRCLECI, - INTEGRATION_LARAVELFORGE, - INTEGRATION_TRAVISCI, - INTEGRATION_TEAMCITY, - INTEGRATION_SUPABASE, - INTEGRATION_CHECKLY, - INTEGRATION_QOVERY, - INTEGRATION_TERRAFORM_CLOUD, - INTEGRATION_HASHICORP_VAULT, - INTEGRATION_CLOUDFLARE_PAGES, - INTEGRATION_CLOUDFLARE_WORKERS, - INTEGRATION_CODEFRESH, - INTEGRATION_WINDMILL, - INTEGRATION_BITBUCKET, - INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, - INTEGRATION_CLOUD_66, - INTEGRATION_NORTHFLANK, - INTEGRATION_HASURA_CLOUD -]); - -// integration types -export const INTEGRATION_OAUTH2 = "oauth2"; - -// integration oauth endpoints -export const INTEGRATION_GCP_TOKEN_URL = "https://oauth2.googleapis.com/token"; -export const INTEGRATION_AZURE_TOKEN_URL = - "https://login.microsoftonline.com/common/oauth2/v2.0/token"; -export const INTEGRATION_HEROKU_TOKEN_URL = "https://id.heroku.com/oauth/token"; -export const INTEGRATION_VERCEL_TOKEN_URL = "https://api.vercel.com/v2/oauth/access_token"; -export const INTEGRATION_NETLIFY_TOKEN_URL = "https://api.netlify.com/oauth/token"; -export const INTEGRATION_GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token"; -export const INTEGRATION_GITLAB_TOKEN_URL = "https://gitlab.com/oauth/token"; -export const INTEGRATION_BITBUCKET_TOKEN_URL = "https://bitbucket.org/site/oauth2/access_token"; - -// integration apps endpoints -export const INTEGRATION_GCP_API_URL = "https://cloudresourcemanager.googleapis.com"; -export const INTEGRATION_HEROKU_API_URL = "https://api.heroku.com"; -export const GITLAB_URL = "https://gitlab.com"; -export const INTEGRATION_GITLAB_API_URL = `${GITLAB_URL}/api`; -export const INTEGRATION_GITHUB_API_URL = "https://api.github.com"; -export const INTEGRATION_VERCEL_API_URL = "https://api.vercel.com"; -export const INTEGRATION_NETLIFY_API_URL = "https://api.netlify.com"; -export const INTEGRATION_RENDER_API_URL = "https://api.render.com"; -export const INTEGRATION_RAILWAY_API_URL = "https://backboard.railway.app/graphql/v2"; -export const INTEGRATION_FLYIO_API_URL = "https://api.fly.io/graphql"; -export const INTEGRATION_CIRCLECI_API_URL = "https://circleci.com/api"; -export const INTEGRATION_TRAVISCI_API_URL = "https://api.travis-ci.com"; -export const INTEGRATION_SUPABASE_API_URL = "https://api.supabase.com"; -export const INTEGRATION_LARAVELFORGE_API_URL = "https://forge.laravel.com"; -export const INTEGRATION_CHECKLY_API_URL = "https://api.checklyhq.com"; -export const INTEGRATION_QOVERY_API_URL = "https://api.qovery.com"; -export const INTEGRATION_TERRAFORM_CLOUD_API_URL = "https://app.terraform.io"; -export const INTEGRATION_CLOUDFLARE_PAGES_API_URL = "https://api.cloudflare.com"; -export const INTEGRATION_CLOUDFLARE_WORKERS_API_URL = "https://api.cloudflare.com"; -export const INTEGRATION_BITBUCKET_API_URL = "https://api.bitbucket.org"; -export const INTEGRATION_CODEFRESH_API_URL = "https://g.codefresh.io/api"; -export const INTEGRATION_WINDMILL_API_URL = "https://app.windmill.dev/api"; -export const INTEGRATION_DIGITAL_OCEAN_API_URL = "https://api.digitalocean.com"; -export const INTEGRATION_CLOUD_66_API_URL = "https://app.cloud66.com/api"; -export const INTEGRATION_NORTHFLANK_API_URL = "https://api.northflank.com"; -export const INTEGRATION_HASURA_CLOUD_API_URL = "https://data.pro.hasura.io/v1/graphql"; - -export const INTEGRATION_GCP_SECRET_MANAGER_SERVICE_NAME = "secretmanager.googleapis.com"; -export const INTEGRATION_GCP_SECRET_MANAGER_URL = `https://${INTEGRATION_GCP_SECRET_MANAGER_SERVICE_NAME}`; -export const INTEGRATION_GCP_SERVICE_USAGE_URL = "https://serviceusage.googleapis.com"; -export const INTEGRATION_GCP_CLOUD_PLATFORM_SCOPE = - "https://www.googleapis.com/auth/cloud-platform"; - -export const getIntegrationOptions = async () => { - const INTEGRATION_OPTIONS = [ - { - name: "Heroku", - slug: "heroku", - image: "Heroku.png", - isAvailable: true, - type: "oauth", - clientId: await getClientIdHeroku(), - docsLink: "" - }, - { - name: "Vercel", - slug: "vercel", - image: "Vercel.png", - isAvailable: true, - type: "oauth", - clientId: "", - clientSlug: await getClientSlugVercel(), - docsLink: "" - }, - { - name: "Netlify", - slug: "netlify", - image: "Netlify.png", - isAvailable: true, - type: "oauth", - clientId: await getClientIdNetlify(), - docsLink: "" - }, - { - name: "GitHub", - slug: "github", - image: "GitHub.png", - isAvailable: true, - type: "oauth", - clientId: await getClientIdGitHub(), - docsLink: "" - }, - { - name: "Render", - slug: "render", - image: "Render.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Railway", - slug: "railway", - image: "Railway.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Fly.io", - slug: "flyio", - image: "Flyio.svg", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "AWS Parameter Store", - slug: "aws-parameter-store", - image: "Amazon Web Services.png", - isAvailable: true, - type: "custom", - clientId: "", - docsLink: "" - }, - { - name: "Laravel Forge", - slug: "laravel-forge", - image: "Laravel Forge.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "AWS Secrets Manager", - slug: "aws-secret-manager", - image: "Amazon Web Services.png", - isAvailable: true, - type: "custom", - clientId: "", - docsLink: "" - }, - { - name: "Azure Key Vault", - slug: "azure-key-vault", - image: "Microsoft Azure.png", - isAvailable: true, - type: "oauth", - clientId: await getClientIdAzure(), - docsLink: "" - }, - { - name: "Circle CI", - slug: "circleci", - image: "Circle CI.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "GitLab", - slug: "gitlab", - image: "GitLab.png", - isAvailable: true, - type: "custom", - clientId: await getClientIdGitLab(), - docsLink: "" - }, - { - name: "Terraform Cloud", - slug: "terraform-cloud", - image: "Terraform Cloud.png", - isAvailable: true, - type: "pat", - cliendId: "", - docsLink: "" - }, - { - name: "Travis CI", - slug: "travisci", - image: "Travis CI.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "TeamCity", - slug: "teamcity", - image: "TeamCity.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Supabase", - slug: "supabase", - image: "Supabase.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Checkly", - slug: "checkly", - image: "Checkly.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Qovery", - slug: "qovery", - image: "Qovery.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "HashiCorp Vault", - slug: "hashicorp-vault", - image: "Vault.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "GCP Secret Manager", - slug: "gcp-secret-manager", - image: "Google Cloud Platform.png", - isAvailable: true, - type: "oauth", - clientId: await getClientIdGCPSecretManager(), - docsLink: "" - }, - { - name: "Cloudflare Pages", - slug: "cloudflare-pages", - image: "Cloudflare.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Cloudflare Workers", - slug: "cloudflare-workers", - image: "Cloudflare.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "BitBucket", - slug: "bitbucket", - image: "BitBucket.png", - isAvailable: true, - type: "oauth", - clientId: await getClientIdBitBucket(), - docsLink: "" - }, - { - name: "Codefresh", - slug: "codefresh", - image: "Codefresh.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Windmill", - slug: "windmill", - image: "Windmill.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Digital Ocean App Platform", - slug: "digital-ocean-app-platform", - image: "Digital Ocean.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Cloud 66", - slug: "cloud-66", - image: "Cloud 66.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Northflank", - slug: "northflank", - image: "Northflank.png", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - }, - { - name: "Hasura Cloud", - slug: "hasura-cloud", - image: "Hasura.svg", - isAvailable: true, - type: "pat", - clientId: "", - docsLink: "" - } - ]; - - return INTEGRATION_OPTIONS; -}; diff --git a/backend-mongo/src/variables/organization.ts b/backend-mongo/src/variables/organization.ts deleted file mode 100644 index c8eb52863..000000000 --- a/backend-mongo/src/variables/organization.ts +++ /dev/null @@ -1,13 +0,0 @@ -// membership roles -export const OWNER = "owner"; // depreciated -export const ADMIN = "admin"; -export const MEMBER = "member"; -export const VIEWER = "viewer"; -export const NO_ACCESS = "no-access"; -export const CUSTOM = "custom"; - -// membership statuses -export const INVITED = "invited"; - -// -- organization -export const ACCEPTED = "accepted"; diff --git a/backend-mongo/src/variables/permission.ts b/backend-mongo/src/variables/permission.ts deleted file mode 100644 index 9dc4c61a3..000000000 --- a/backend-mongo/src/variables/permission.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const PERMISSION_READ_SECRETS = "read"; -export const PERMISSION_WRITE_SECRETS = "write"; \ No newline at end of file diff --git a/backend-mongo/src/variables/secret.ts b/backend-mongo/src/variables/secret.ts deleted file mode 100644 index b24d8a101..000000000 --- a/backend-mongo/src/variables/secret.ts +++ /dev/null @@ -1,3 +0,0 @@ -// secrets -export const SECRET_SHARED = "shared"; -export const SECRET_PERSONAL = "personal"; diff --git a/backend-mongo/src/variables/smtp.ts b/backend-mongo/src/variables/smtp.ts deleted file mode 100644 index 4ad68c356..000000000 --- a/backend-mongo/src/variables/smtp.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const SMTP_HOST_SENDGRID = "smtp.sendgrid.net"; -export const SMTP_HOST_MAILGUN = "smtp.mailgun.org"; -export const SMTP_HOST_SOCKETLABS = "smtp.socketlabs.com"; -export const SMTP_HOST_ZOHOMAIL = "smtp.zoho.com"; -export const SMTP_HOST_GMAIL = "smtp.gmail.com"; -export const SMTP_HOST_OFFICE365 = "smtp.office365.com"; \ No newline at end of file diff --git a/backend-mongo/src/variables/token.ts b/backend-mongo/src/variables/token.ts deleted file mode 100644 index 187e2534b..000000000 --- a/backend-mongo/src/variables/token.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const TOKEN_EMAIL_CONFIRMATION = "emailConfirmation"; -export const TOKEN_EMAIL_MFA = "emailMfa"; -export const TOKEN_EMAIL_ORG_INVITATION = "organizationInvitation"; -export const TOKEN_EMAIL_PASSWORD_RESET = "passwordReset"; \ No newline at end of file diff --git a/backend-mongo/src/variables/user.ts b/backend-mongo/src/variables/user.ts deleted file mode 100644 index a688b115d..000000000 --- a/backend-mongo/src/variables/user.ts +++ /dev/null @@ -1 +0,0 @@ -export const MFA_METHOD_EMAIL = "email"; \ No newline at end of file diff --git a/backend-mongo/swagger/index.ts b/backend-mongo/swagger/index.ts deleted file mode 100644 index 6f3a426fb..000000000 --- a/backend-mongo/swagger/index.ts +++ /dev/null @@ -1,318 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -const swaggerAutogen = require("swagger-autogen")({ openapi: "3.0.0" }); -const fs = require("fs").promises; -const yaml = require("js-yaml"); - -/** - * Generates OpenAPI specs for all Infisical API endpoints: - * - spec.json in /backend for api-serving - * - spec.yaml in /docs for API reference - */ -const generateOpenAPISpec = async () => { - const doc = { - info: { - title: "Infisical API", - description: "List of all available APIs that can be consumed" - }, - host: ["https://infisical.com"], - servers: [ - { - url: "https://app.infisical.com", - description: "Production server" - }, - { - url: "http://localhost:8080", - description: "Local server" - } - ], - securityDefinitions: { - bearerAuth: { - type: "http", - scheme: "bearer", - bearerFormat: "JWT", - description: "An access token in Infisical" - }, - apiKeyAuth: { - type: "apiKey", - in: "header", - name: "X-API-Key", - description: "An API Key in Infisical" - } - }, - definitions: { - CurrentUser: { - _id: "", - email: "johndoe@gmail.com", - firstName: "John", - lastName: "Doe", - publicKey: "johns_nacl_public_key", - encryptedPrivateKey: "johns_enc_nacl_private_key", - iv: "iv_of_enc_nacl_private_key", - tag: "tag_of_enc_nacl_private_key", - updatedAt: "2023-01-13T14:16:12.210Z", - createdAt: "2023-01-13T14:16:12.210Z" - }, - Identity: { - _id: "", - name: "Machine 1", - authMethod: "universal-auth" - }, - IdentityUniversalAuth: { - _id: "", - identity: "", - clientId: "...", - clientSecretTrustedIps: [{ - ipAddress: "0.0.0.0", - type: "ipv4", - prefix: "0" - }], - accessTokenTTL: 7200, - accessTokenMaxTTL: 2592000, - accessTokenNumUsesLimit: 0, - accessTokenTrustedIps: [{ - ipAddress: "0.0.0.0", - type: "ipv4", - prefix: "0" - }] - }, - IdentityUniversalAuthClientSecretData: { - _id: "", - identityUniversalAuth: "", - isClientSecretRevoked: false, - description: "", - clientSecretPrefix: "abc", - clientSecretNumUses: 0, - clientSecretNumUsesLimit: 0, - clientSecretTTL: 0, - createdAt: "2023-01-13T14:16:12.210Z", - updatedAt: "2023-01-13T14:16:12.210Z" - }, - Membership: { - user: { - _id: "", - email: "johndoe@gmail.com", - firstName: "John", - lastName: "Doe", - publicKey: "johns_nacl_public_key", - updatedAt: "2023-01-13T14:16:12.210Z", - createdAt: "2023-01-13T14:16:12.210Z" - }, - workspace: "", - role: "admin" - }, - MembershipOrg: { - user: { - _id: "", - email: "johndoe@gmail.com", - firstName: "John", - lastName: "Doe", - publicKey: "johns_nacl_public_key", - updatedAt: "2023-01-13T14:16:12.210Z", - createdAt: "2023-01-13T14:16:12.210Z" - }, - organization: "", - role: "owner", - status: "accepted" - }, - IdentityMembership: { - identity: { - _id: "", - name: "Machine 1", - authMethod: "universal-auth" - }, - workspace: "", - role: "member" - }, - IdentityMembershipOrg: { - identity: { - _id: "", - name: "Machine 1", - authMethod: "universal-auth" - }, - organization: "", - role: "member", - status: "accepted" - }, - Organization: { - _id: "", - name: "Acme Corp.", - customerId: "" - }, - Project: { - name: "My Project", - organization: "", - environments: [ - { - name: "development", - slug: "dev" - } - ] - }, - ProjectKey: { - encryptedkey: "", - nonce: "", - sender: { - publicKey: "senders_nacl_public_key" - }, - receiver: "", - workspace: "" - }, - CreateSecret: { - type: "shared", - secretKeyCiphertext: "", - secretKeyIV: "", - secretKeyTag: "", - secretValueCiphertext: "", - secretValueIV: "", - secretValueTag: "", - secretCommentCiphertext: "", - secretCommentIV: "", - secretCommentTag: "" - }, - UpdateSecret: { - id: "", - secretKeyCiphertext: "", - secretKeyIV: "", - secretKeyTag: "", - secretValueCiphertext: "", - secretValueIV: "", - secretValueTag: "", - secretCommentCiphertext: "", - secretCommentIV: "", - secretCommentTag: "" - }, - Secret: { - _id: "", - version: 1, - workspace: "", - type: "shared", - user: null, - secretKeyCiphertext: "", - secretKeyIV: "", - secretKeyTag: "", - secretValueCiphertext: "", - secretValueIV: "", - secretValueTag: "", - secretCommentCiphertext: "", - secretCommentIV: "", - secretCommentTag: "", - updatedAt: "2023-01-13T14:16:12.210Z", - createdAt: "2023-01-13T14:16:12.210Z" - }, - RawSecret: { - _id: "abc123", - version: 1, - workspace: "abc123", - environment: "dev", - secretKey: "STRIPE_KEY", - secretValue: "abc123", - secretComment: "Lorem ipsum" - }, - SecretImport: { - _id: "", - workspace: "abc123", - environment: "dev", - folderId: "root", - imports: [], - updatedAt: "2023-01-13T14:16:12.210Z", - createdAt: "2023-01-13T14:16:12.210Z" - }, - Log: { - _id: "", - user: { - _id: "", - email: "johndoe@gmail.com", - firstName: "John", - lastName: "Doe" - }, - workspace: "", - actionNames: ["addSecrets"], - actions: [ - { - name: "addSecrets", - user: "", - workspace: "", - payload: [ - { - oldSecretVersion: "", - newSecretVersion: "" - } - ] - } - ], - channel: "cli", - ipAddress: "192.168.0.1", - updatedAt: "2023-01-13T14:16:12.210Z", - createdAt: "2023-01-13T14:16:12.210Z" - }, - SecretSnapshot: { - workspace: "", - version: 1, - secretVersions: [ - { - _id: "" - } - ] - }, - SecretVersion: { - _id: "", - secret: "", - version: 1, - workspace: "", - type: "shared", - user: "", - environment: "dev", - isDeleted: "", - secretKeyCiphertext: "", - secretKeyIV: "", - secretKeyTag: "", - secretValueCiphertext: "", - secretValueIV: "", - secretValueTag: "" - }, - ServiceTokenData: { - _id: "", - name: "", - workspace: "", - environment: "", - user: { - _id: "", - firstName: "", - lastName: "" - }, - expiresAt: "2023-01-13T14:16:12.210Z", - encryptedKey: "", - iv: "", - tag: "", - updatedAt: "2023-01-13T14:16:12.210Z", - createdAt: "2023-01-13T14:16:12.210Z" - }, - AuditLog: { - actor: { - type: "", - metadata: {} - }, - organization: "", - workspace: "", - ipAddress: "", - event: { - type: "", - metadata: {} - }, - userAgent: "", - userAgentType: "", - expiresAt: "" - } - } - }; - - const outputJSONFile = "../spec.json"; - const outputYAMLFile = "../docs/spec.yaml"; - const endpointsFiles = ["../src/index.ts"]; - - const spec = await swaggerAutogen(outputJSONFile, endpointsFiles, doc); - - await fs.writeFile(outputYAMLFile, yaml.dump(spec.data)); -}; - -generateOpenAPISpec(); diff --git a/backend-mongo/test-resources/docker-compose.test.yml b/backend-mongo/test-resources/docker-compose.test.yml deleted file mode 100644 index e9a8c519a..000000000 --- a/backend-mongo/test-resources/docker-compose.test.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: '3' - -services: - mongo-test: - image: mongo - container_name: infisical-test-mongo - restart: always - ports: - - 27018:27017 - environment: - - MONGO_INITDB_ROOT_USERNAME=test - - MONGO_INITDB_ROOT_PASSWORD=test1234 diff --git a/backend-mongo/test-resources/env-vars.js b/backend-mongo/test-resources/env-vars.js deleted file mode 100644 index 3149a27c9..000000000 --- a/backend-mongo/test-resources/env-vars.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-disable no-undef */ -process.env.MONGO_URL = - 'mongodb://test:test1234@localhost:27018/?authSource=admin'; -process.env.MONGO_USERNAME = 'test'; -process.env.MONGO_PASSWORD = 'test1234'; -process.env.NODE_ENV = 'test'; -process.env.JWT_SIGNUP_SECRET= "38ea90fb7998b92176080f457d890392" -process.env.JWT_REFRESH_SECRET= "7764c7bbf3928ad501591a3e005eb364" -process.env.JWT_AUTH_SECRET= "5239fea3a4720c0e524f814a540e14a2" -process.env.JWT_SERVICE_SECRET= "8509fb8b90c9b53e9e61d1e35826dcb5" -process.env.ENCRYPTION_KEY="e05f54dffd58b5ab9b09e4c6fca7aff7" -process.env.ROOT_ENCRYPTION_KEY="MJA3DWJXjHiL6xjkUI2QCQuy/D+/SAbRNU1+rEo9gvQ=" diff --git a/backend-mongo/tests/data/batch-create-secrets-with-some-missing-params.json b/backend-mongo/tests/data/batch-create-secrets-with-some-missing-params.json deleted file mode 100644 index 40d07827c..000000000 --- a/backend-mongo/tests/data/batch-create-secrets-with-some-missing-params.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "method": "POST", - "secret": { - "workspace": "63cefb15c8d3175601cfa989", - "type": "shared", - "tags": [], - "environment": "dev", - "secretKeyCiphertext": "eaX9a2g=", - "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", - "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", - "secretValueCiphertext": "cw==", - "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", - "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", - "secretCommentCiphertext": "", - "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", - "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" - } - }, - { - "method": "POST", - "secret": { - "workspace": "63cefb15c8d3175601cfa989", - "type": "shared", - "tags": [], - "environment": "dev", - "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", - "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", - "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", - "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", - "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", - "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" - } - }, - { - "method": "POST", - "secret": { - "workspace": "63cefb15c8d3175601cfa989", - "type": "shared", - "tags": [], - "environment": "dev", - "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", - "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", - "secretValueCiphertext": "cw==", - "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", - "secretCommentCiphertext": "", - "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", - "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" - } - } -] \ No newline at end of file diff --git a/backend-mongo/tests/data/batch-secrets-no-override.json b/backend-mongo/tests/data/batch-secrets-no-override.json deleted file mode 100644 index 7236c907a..000000000 --- a/backend-mongo/tests/data/batch-secrets-no-override.json +++ /dev/null @@ -1,56 +0,0 @@ -[ - { - "method": "POST", - "secret": { - "workspace": "63cefb15c8d3175601cfa989", - "type": "shared", - "tags": [], - "environment": "dev", - "secretKeyCiphertext": "eaX9a2g=", - "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", - "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", - "secretValueCiphertext": "cw==", - "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", - "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", - "secretCommentCiphertext": "", - "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", - "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" - } - }, - { - "method": "POST", - "secret": { - "workspace": "63cefb15c8d3175601cfa989", - "type": "shared", - "tags": [], - "environment": "dev", - "secretKeyCiphertext": "eaX9a2g=", - "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", - "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", - "secretValueCiphertext": "cw==", - "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", - "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", - "secretCommentCiphertext": "", - "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", - "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" - } - }, - { - "method": "POST", - "secret": { - "workspace": "63cefb15c8d3175601cfa989", - "type": "shared", - "tags": [], - "environment": "dev", - "secretKeyCiphertext": "eaX9a2g=", - "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", - "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", - "secretValueCiphertext": "cw==", - "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", - "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", - "secretCommentCiphertext": "", - "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", - "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" - } - } -] \ No newline at end of file diff --git a/backend-mongo/tests/data/batch-secrets-with-overrides.json b/backend-mongo/tests/data/batch-secrets-with-overrides.json deleted file mode 100644 index 6173289aa..000000000 --- a/backend-mongo/tests/data/batch-secrets-with-overrides.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "method": "POST", - "secret": { - "workspace": "63cefb15c8d3175601cfa989", - "type": "shared", - "environment": "dev", - "secretKeyCiphertext": "IVMtGWE=", - "secretKeyIV": "BDsG7/ylk7mT8MrIMn0e7w==", - "secretKeyTag": "1ujy08fctmZ1xTXMYr23UQ==", - "secretValueCiphertext": "I9psUg==", - "secretValueIV": "W+DJETpCerHkFv8AR9Fv4w==", - "secretValueTag": "yODOeN3HBr/usly4VSMt9w==", - "secretCommentCiphertext": "", - "secretCommentIV": "QET7oX2ZiuLDSzwrkeL2Ig==", - "secretCommentTag": "6P3xeA9eO+3Wp66ROHXgfg==" - } - }, - { - "method": "POST", - "secret": { - "workspace": "63cefb15c8d3175601cfa989", - "type": "personal", - "user": "63cefa6ec8d3175601cfa980", - "tags": [], - "environment": "dev", - "secretKeyCiphertext": "Q7lyRO8=", - "secretKeyIV": "yz8koc3d63ywJMiGXpCNSw==", - "secretKeyTag": "j2bMQ2d4sDZKA0OaKM5SXA==", - "secretValueCiphertext": "X4kaiShmtGZt", - "secretValueIV": "p/GdbksLVveNLsV3vz5GLA==", - "secretValueTag": "//dhRL+pagecavHJCtMPWg==", - "secretCommentCiphertext": "", - "secretCommentIV": "7eYJzuilvjQPutqrqbd2MQ==", - "secretCommentTag": "LpPv9K0Hhd5noE39Zu9U+w==" - } - } -] \ No newline at end of file diff --git a/backend-mongo/tests/helper/helper.ts b/backend-mongo/tests/helper/helper.ts deleted file mode 100644 index 510f5f353..000000000 --- a/backend-mongo/tests/helper/helper.ts +++ /dev/null @@ -1,98 +0,0 @@ -// Helper functions for integration tests - -import axiosInstance from "../../src/config/request"; -import { Secret } from "../../src/models"; -import { testUserEmail, testUserPassword } from "../../src/utils/addDevelopmentUser"; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const crypto = require("crypto") -// eslint-disable-next-line @typescript-eslint/no-var-requires -const jsrp = require("jsrp"); -// eslint-disable-next-line @typescript-eslint/no-var-requires -const axios = require("axios"); -import { plainTextWorkspaceKey, testWorkspaceId } from "../../src/utils/addDevelopmentUser"; -import { - encryptSymmetric128BitHexKeyUTF8, -} from "../../src/utils/crypto"; - -interface TokenData { - token: string; - publicKey: string; - encryptedPrivateKey: string; - iv: string; - tag: string; -} - -export const getJWTFromTestUser = (): Promise => { - return new Promise((resolve, reject) => { - const client = new jsrp.client(); - const EMAIL = testUserEmail - const PASSWORD = testUserPassword - - client.init({ - username: EMAIL, - password: PASSWORD, - }, async () => { - const clientPublicKey = client.getPublicKey(); - - // POST: /login1 - const reqBody = { - email: EMAIL, - clientPublicKey, - } - - - const loginOneRes = await axiosInstance.post("http://localhost:4000/api/v1/auth/login1", reqBody); - const serverPublicKey = loginOneRes.data.serverPublicKey; - const salt = loginOneRes.data.salt; - - client.setSalt(salt); - client.setServerPublicKey(serverPublicKey); - const clientSharedKey = client.getSharedKey(); // shared Key - const clientProof = client.getProof(); // called M1 - - // POST: /login2 - const reqBody2 = { - email: EMAIL, - clientProof, - } - - const response2 = await axiosInstance.post("http://localhost:4000/api/v1/auth/login2", reqBody2); - - resolve(response2.data) - }) - }); -} - -export const getServiceTokenFromTestUser = async () => { - const loggedInUserDetails = await getJWTFromTestUser() - const randomBytes = crypto.randomBytes(16).toString("hex"); - const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ - plaintext: plainTextWorkspaceKey, - key: randomBytes, - }); - - const newServiceToken = await axiosInstance.post("http://localhost:4000/api/v2/service-token/", { - "name": "test service token", - "workspaceId": testWorkspaceId, - "environment": "dev", - "encryptedKey": ciphertext, - "iv": iv, - "tag": tag, - "expiresIn": Date.now() + 90000, - "permissions": ["read"], - }, { - headers: { - "Authorization": `Bearer ${loggedInUserDetails.token}`, - }, - }); - - return `${newServiceToken.data.serviceToken}.${randomBytes}` -} - -export const deleteAllSecrets = async () => { - await Secret.deleteMany() -} - -export const getAllSecrets = async () => { - return await Secret.find() -} \ No newline at end of file diff --git a/backend-mongo/tests/integration-tests/routes/v2/secrets.test.ts b/backend-mongo/tests/integration-tests/routes/v2/secrets.test.ts deleted file mode 100644 index 700a6e8a2..000000000 --- a/backend-mongo/tests/integration-tests/routes/v2/secrets.test.ts +++ /dev/null @@ -1,408 +0,0 @@ -// import request from 'supertest' -// import main from '../../../../src/index' -// import { testWorkspaceId } from '../../../../src/utils/addDevelopmentUser'; -// import { deleteAllSecrets, getAllSecrets, getJWTFromTestUser, getServiceTokenFromTestUser } from '../../../helper/helper'; -// // eslint-disable-next-line @typescript-eslint/no-var-requires -// const batchSecretRequestWithNoOverride = require('../../../data/batch-secrets-no-override.json'); -// // eslint-disable-next-line @typescript-eslint/no-var-requires -// const batchSecretRequestWithOverrides = require('../../../data/batch-secrets-with-overrides.json'); - -// // eslint-disable-next-line @typescript-eslint/no-var-requires -// const batchSecretRequestWithBadRequest = require('../../../data/batch-create-secrets-with-some-missing-params.json'); - -// let server: any; -// beforeAll(async () => { -// server = await main; -// }); - -// afterAll(async () => { -// server.close(); -// }); - -// describe("GET /api/v2/secrets", () => { -// describe("Get secrets via JTW", () => { -// test("should create secrets and read secrets via jwt", async () => { -// try { -// // get login details -// const loginResponse = await getJWTFromTestUser() - -// // create creates -// const createSecretsResponse = await request(server) -// .post("/api/v2/secrets/batch") -// .set('Authorization', `Bearer ${loginResponse.token}`) -// .send({ -// workspaceId: testWorkspaceId, -// environment: "dev", -// requests: batchSecretRequestWithNoOverride -// }) - -// expect(createSecretsResponse.statusCode).toBe(200) - - -// const getSecrets = await request(server) -// .get("/api/v2/secrets") -// .set('Authorization', `Bearer ${loginResponse.token}`) -// .query({ -// workspaceId: testWorkspaceId, -// environment: "dev" -// }) - -// expect(getSecrets.statusCode).toBe(200) -// expect(getSecrets.body).toHaveProperty("secrets") -// expect(getSecrets.body.secrets).toHaveLength(3) -// expect(getSecrets.body.secrets).toBeInstanceOf(Array); - -// getSecrets.body.secrets.forEach((secret: any) => { -// expect(secret).toHaveProperty('_id'); -// expect(secret._id).toBeTruthy(); - -// expect(secret).toHaveProperty('version'); -// expect(secret.version).toBeTruthy(); - -// expect(secret).toHaveProperty('workspace'); -// expect(secret.workspace).toBeTruthy(); - -// expect(secret).toHaveProperty('type'); -// expect(secret.type).toBeTruthy(); - -// expect(secret).toHaveProperty('tags'); -// expect(secret.tags).toHaveLength(0); - -// expect(secret).toHaveProperty('environment'); -// expect(secret.environment).toEqual("dev"); - -// expect(secret).toHaveProperty('secretKeyCiphertext'); -// expect(secret.secretKeyCiphertext).toBeTruthy(); - -// expect(secret).toHaveProperty('secretKeyIV'); -// expect(secret.secretKeyIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretKeyTag'); -// expect(secret.secretKeyTag).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueCiphertext'); -// expect(secret.secretValueCiphertext).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueIV'); -// expect(secret.secretValueIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueTag'); -// expect(secret.secretValueTag).toBeTruthy(); - -// expect(secret).toHaveProperty('secretCommentCiphertext'); -// expect(secret.secretCommentCiphertext).toBeFalsy(); - -// expect(secret).toHaveProperty('secretCommentIV'); -// expect(secret.secretCommentIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretCommentTag'); -// expect(secret.secretCommentTag).toBeTruthy(); - -// expect(secret).toHaveProperty('createdAt'); -// expect(secret.createdAt).toBeTruthy(); - -// expect(secret).toHaveProperty('updatedAt'); -// expect(secret.updatedAt).toBeTruthy(); -// }); -// } finally { -// // clean up -// await deleteAllSecrets() -// } -// }) - -// test("Get secrets via jwt when personal overrides exist", async () => { -// try { -// // get login details -// const loginResponse = await getJWTFromTestUser() - -// // create creates -// const createSecretsResponse = await request(server) -// .post("/api/v2/secrets/batch") -// .set('Authorization', `Bearer ${loginResponse.token}`) -// .send({ -// workspaceId: testWorkspaceId, -// environment: "dev", -// requests: batchSecretRequestWithOverrides -// }) - -// expect(createSecretsResponse.statusCode).toBe(200) - -// const getSecrets = await request(server) -// .get("/api/v2/secrets") -// .set('Authorization', `Bearer ${loginResponse.token}`) -// .query({ -// workspaceId: testWorkspaceId, -// environment: "dev" -// }) - -// expect(getSecrets.statusCode).toBe(200) -// expect(getSecrets.body).toHaveProperty("secrets") -// expect(getSecrets.body.secrets).toHaveLength(2) -// expect(getSecrets.body.secrets).toBeInstanceOf(Array); - -// getSecrets.body.secrets.forEach((secret: any) => { -// expect(secret).toHaveProperty('_id'); -// expect(secret._id).toBeTruthy(); - -// expect(secret).toHaveProperty('version'); -// expect(secret.version).toBeTruthy(); - -// expect(secret).toHaveProperty('workspace'); -// expect(secret.workspace).toBeTruthy(); - -// expect(secret).toHaveProperty('type'); -// expect(secret.type).toBeTruthy(); - -// expect(secret).toHaveProperty('tags'); -// expect(secret.tags).toHaveLength(0); - -// expect(secret).toHaveProperty('environment'); -// expect(secret.environment).toEqual("dev"); - -// expect(secret).toHaveProperty('secretKeyCiphertext'); -// expect(secret.secretKeyCiphertext).toBeTruthy(); - -// expect(secret).toHaveProperty('secretKeyIV'); -// expect(secret.secretKeyIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretKeyTag'); -// expect(secret.secretKeyTag).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueCiphertext'); -// expect(secret.secretValueCiphertext).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueIV'); -// expect(secret.secretValueIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueTag'); -// expect(secret.secretValueTag).toBeTruthy(); - -// expect(secret).toHaveProperty('secretCommentCiphertext'); -// expect(secret.secretCommentCiphertext).toBeFalsy(); - -// expect(secret).toHaveProperty('secretCommentIV'); -// expect(secret.secretCommentIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretCommentTag'); -// expect(secret.secretCommentTag).toBeTruthy(); - -// expect(secret).toHaveProperty('createdAt'); -// expect(secret.createdAt).toBeTruthy(); - -// expect(secret).toHaveProperty('updatedAt'); -// expect(secret.updatedAt).toBeTruthy(); -// }); -// } finally { -// // clean up -// await deleteAllSecrets() -// } -// }) -// }) - -// describe("fetch secrets via service token", () => { -// test("Get secrets via jwt when personal overrides exist", async () => { -// try { -// // get login details -// const loginResponse = await getJWTFromTestUser() - -// // create creates -// const createSecretsResponse = await request(server) -// .post("/api/v2/secrets/batch") -// .set('Authorization', `Bearer ${loginResponse.token}`) -// .send({ -// workspaceId: testWorkspaceId, -// environment: "dev", -// requests: batchSecretRequestWithOverrides -// }) - -// expect(createSecretsResponse.statusCode).toBe(200) - -// // now use the service token to fetch secrets -// const serviceToken = await getServiceTokenFromTestUser() - -// const getSecrets = await request(server) -// .get("/api/v2/secrets") -// .set('Authorization', `Bearer ${serviceToken}`) -// .query({ -// workspaceId: testWorkspaceId, -// environment: "dev" -// }) - -// expect(getSecrets.statusCode).toBe(200) -// expect(getSecrets.body).toHaveProperty("secrets") -// expect(getSecrets.body.secrets).toHaveLength(2) -// expect(getSecrets.body.secrets).toBeInstanceOf(Array); - -// getSecrets.body.secrets.forEach((secret: any) => { -// expect(secret).toHaveProperty('_id'); -// expect(secret._id).toBeTruthy(); - -// expect(secret).toHaveProperty('version'); -// expect(secret.version).toBeTruthy(); - -// expect(secret).toHaveProperty('workspace'); -// expect(secret.workspace).toBeTruthy(); - -// expect(secret).toHaveProperty('type'); -// expect(secret.type).toBeTruthy(); - -// expect(secret).toHaveProperty('tags'); -// expect(secret.tags).toHaveLength(0); - -// expect(secret).toHaveProperty('environment'); -// expect(secret.environment).toEqual("dev"); - -// expect(secret).toHaveProperty('secretKeyCiphertext'); -// expect(secret.secretKeyCiphertext).toBeTruthy(); - -// expect(secret).toHaveProperty('secretKeyIV'); -// expect(secret.secretKeyIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretKeyTag'); -// expect(secret.secretKeyTag).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueCiphertext'); -// expect(secret.secretValueCiphertext).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueIV'); -// expect(secret.secretValueIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueTag'); -// expect(secret.secretValueTag).toBeTruthy(); - -// expect(secret).toHaveProperty('secretCommentCiphertext'); -// expect(secret.secretCommentCiphertext).toBeFalsy(); - -// expect(secret).toHaveProperty('secretCommentIV'); -// expect(secret.secretCommentIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretCommentTag'); -// expect(secret.secretCommentTag).toBeTruthy(); - -// expect(secret).toHaveProperty('createdAt'); -// expect(secret.createdAt).toBeTruthy(); - -// expect(secret).toHaveProperty('updatedAt'); -// expect(secret.updatedAt).toBeTruthy(); -// }); -// } finally { -// // clean up -// await deleteAllSecrets() -// } -// }) - -// test("should create secrets and read secrets via service token when no overrides", async () => { -// try { -// // get login details -// const loginResponse = await getJWTFromTestUser() - -// // create secrets -// const createSecretsResponse = await request(server) -// .post("/api/v2/secrets/batch") -// .set('Authorization', `Bearer ${loginResponse.token}`) -// .send({ -// workspaceId: testWorkspaceId, -// environment: "dev", -// requests: batchSecretRequestWithNoOverride -// }) - -// expect(createSecretsResponse.statusCode).toBe(200) - - -// // now use the service token to fetch secrets -// const serviceToken = await getServiceTokenFromTestUser() - -// const getSecrets = await request(server) -// .get("/api/v2/secrets") -// .set('Authorization', `Bearer ${serviceToken}`) -// .query({ -// workspaceId: testWorkspaceId, -// environment: "dev" -// }) - -// expect(getSecrets.statusCode).toBe(200) -// expect(getSecrets.body).toHaveProperty("secrets") -// expect(getSecrets.body.secrets).toHaveLength(3) -// expect(getSecrets.body.secrets).toBeInstanceOf(Array); - -// getSecrets.body.secrets.forEach((secret: any) => { -// expect(secret).toHaveProperty('_id'); -// expect(secret._id).toBeTruthy(); - -// expect(secret).toHaveProperty('version'); -// expect(secret.version).toBeTruthy(); - -// expect(secret).toHaveProperty('workspace'); -// expect(secret.workspace).toBeTruthy(); - -// expect(secret).toHaveProperty('type'); -// expect(secret.type).toBeTruthy(); - -// expect(secret).toHaveProperty('tags'); -// expect(secret.tags).toHaveLength(0); - -// expect(secret).toHaveProperty('environment'); -// expect(secret.environment).toEqual("dev"); - -// expect(secret).toHaveProperty('secretKeyCiphertext'); -// expect(secret.secretKeyCiphertext).toBeTruthy(); - -// expect(secret).toHaveProperty('secretKeyIV'); -// expect(secret.secretKeyIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretKeyTag'); -// expect(secret.secretKeyTag).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueCiphertext'); -// expect(secret.secretValueCiphertext).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueIV'); -// expect(secret.secretValueIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretValueTag'); -// expect(secret.secretValueTag).toBeTruthy(); - -// expect(secret).toHaveProperty('secretCommentCiphertext'); -// expect(secret.secretCommentCiphertext).toBeFalsy(); - -// expect(secret).toHaveProperty('secretCommentIV'); -// expect(secret.secretCommentIV).toBeTruthy(); - -// expect(secret).toHaveProperty('secretCommentTag'); -// expect(secret.secretCommentTag).toBeTruthy(); - -// expect(secret).toHaveProperty('createdAt'); -// expect(secret.createdAt).toBeTruthy(); - -// expect(secret).toHaveProperty('updatedAt'); -// expect(secret.updatedAt).toBeTruthy(); -// }); -// } finally { -// // clean up -// await deleteAllSecrets() -// } -// }) -// }) - -// describe("create secrets via JWT", () => { -// test("Create secrets via jwt when some requests have missing required parameters", async () => { -// // get login details -// const loginResponse = await getJWTFromTestUser() - -// // create creates -// const createSecretsResponse = await request(server) -// .post("/api/v2/secrets/batch") -// .set('Authorization', `Bearer ${loginResponse.token}`) -// .send({ -// workspaceId: testWorkspaceId, -// environment: "dev", -// requests: batchSecretRequestWithBadRequest -// }) - -// const allSecretsInDB = await getAllSecrets() - -// expect(createSecretsResponse.statusCode).toBe(500) // TODO should be set to 400 -// expect(allSecretsInDB).toHaveLength(0) -// }) -// }) -// }) \ No newline at end of file diff --git a/backend-mongo/tests/integration-tests/routes/v2/service-tokens.ts b/backend-mongo/tests/integration-tests/routes/v2/service-tokens.ts deleted file mode 100644 index 15d776bdd..000000000 --- a/backend-mongo/tests/integration-tests/routes/v2/service-tokens.ts +++ /dev/null @@ -1,58 +0,0 @@ -import request from "supertest" -import main from "../../../../src/index" -import { getServiceTokenFromTestUser } from "../../../helper/helper"; -let server: any; - -beforeAll(async () => { - server = await main; -}); - -afterAll(async () => { - server.close(); -}); - -describe("GET /api/v2/service-token", () => { - describe("Get service token details", () => { - test("should respond create and get the details of a service token", async () => { - // generate a service token - const serviceToken = await getServiceTokenFromTestUser() - - // get the service token details - const serviceTokenDetails = await request(server) - .get("/api/v2/service-token") - .set("Authorization", `Bearer ${serviceToken}`) - - expect(serviceTokenDetails.body).toMatchObject({ - _id: expect.any(String), - name: "test service token", - workspace: "63cefb15c8d3175601cfa989", - environment: "dev", - user: { - _id: "63cefa6ec8d3175601cfa980", - email: "test@localhost.local", - firstName: "Jake", - lastName: "Moni", - isMfaEnabled: false, - mfaMethods: expect.any(Array), - devices: [ - { - ip: expect.any(String), - userAgent: expect.any(String), - _id: expect.any(String), - }, - ], - createdAt: expect.any(String), - updatedAt: expect.any(String), - }, - lastUsed: expect.any(String), - expiresAt: expect.any(String), - encryptedKey: expect.any(String), - iv: expect.any(String), - tag: expect.any(String), - permissions: ["read"], - createdAt: expect.any(String), - updatedAt: expect.any(String), - }); - }) - }) -}) \ No newline at end of file diff --git a/backend-mongo/tests/setupTests.ts b/backend-mongo/tests/setupTests.ts deleted file mode 100644 index 8d259252e..000000000 --- a/backend-mongo/tests/setupTests.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Server } from "http"; -import main from "../src"; -import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; -import request from "supertest"; -import { githubPushEventSecretScan } from "../src/queues/secret-scanning/githubScanPushEvent"; -import { syncSecretsToThirdPartyServices } from "../src/queues/integrations/syncSecretsToThirdPartyServices"; - -let server: Server; - -beforeAll(async () => { - server = await main; -}); - -afterAll(async () => { - server.close(); - githubPushEventSecretScan.close() - syncSecretsToThirdPartyServices.close() -}); - -describe("Healthcheck endpoint", () => { - it("GET /healthcheck should return OK", async () => { - const res = await request(server).get("/healthcheck"); - expect(res.status).toEqual(200); - }); -}); diff --git a/backend-mongo/tests/unit-tests/utils/crypto.test.ts b/backend-mongo/tests/unit-tests/utils/crypto.test.ts deleted file mode 100644 index f9f2aba01..000000000 --- a/backend-mongo/tests/unit-tests/utils/crypto.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { describe, expect, test } from "@jest/globals"; -import { - decryptAsymmetric, - encryptAsymmetric, -} from "../../../src/utils/crypto"; - -describe("Crypto", () => { - describe("encryptAsymmetric", () => { - describe("given all valid publicKey, privateKey and plaintext", () => { - const publicKey = "6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw="; - const privateKey = "Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0="; - const plaintext = "secret-message"; - - test("should encrypt plain text", () => { - const result = encryptAsymmetric({ plaintext, publicKey, privateKey }); - expect(result.ciphertext).toBeDefined(); - expect(result.nonce).toBeDefined(); - }); - }); - - describe("given empty/undefined publicKey", () => { - let publicKey: string; - const privateKey = "Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0="; - const plaintext = "secret-message"; - - test("should throw error if publicKey is undefined", () => { - expect(() => { - encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError("invalid encoding"); - }); - - test("should throw error if publicKey is empty string", () => { - publicKey = ""; - expect(() => { - encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError("bad public key size"); - }); - }); - - describe("given empty/undefined privateKey", () => { - const publicKey = "6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw="; - let privateKey: string; - const plaintext = "secret-message"; - - test("should throw error if privateKey is undefined", () => { - expect(() => { - encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError("invalid encoding"); - }); - - test("should throw error if privateKey is empty string", () => { - privateKey = ""; - expect(() => { - encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError("bad secret key size"); - }); - }); - - describe("given undefined/invalid plaint text", () => { - const publicKey = "6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw="; - const privateKey = "Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0="; - let plaintext: string; - - test("should throw error if plaintext is undefined", () => { - expect(() => { - encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError("expected string"); - }); - - test("should encrypt plaintext containing special characters", () => { - plaintext = "131@#$%235!@#&*(&123sadfkjadjf"; - const result = encryptAsymmetric({ - plaintext, - publicKey, - privateKey, - }); - expect(result.ciphertext).toBeDefined(); - expect(result.nonce).toBeDefined(); - }); - }); - }); - - describe("decryptAsymmetric", () => { - describe("given all valid publicKey, privateKey and plaintext", () => { - const publicKey = "6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw="; - const privateKey = "Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0="; - const plaintext = "secret-message"; - - test("should decrypt the encrypted plaintext", () => { - const encryptedResult = encryptAsymmetric({ - plaintext, - publicKey, - privateKey, - }); - const ciphertext = encryptedResult.ciphertext; - const nonce = encryptedResult.nonce; - - const decryptedResult = decryptAsymmetric({ - ciphertext, - nonce, - publicKey, - privateKey, - }); - - expect(decryptedResult).toBeDefined(); - expect(decryptedResult).toEqual(plaintext); - }); - }); - - describe("given ciphertext or nonce is modified before decrypt", () => { - const publicKey = "6U5m6S5jlyazJ+R4z7Yf/Ah4th4JwKxDN8Wn7+upvzw="; - const privateKey = "Z8W53YV+2ddjJCrFwzptjK96y2QsQI9oXuvfcx+qxz0="; - const plaintext = "secret-message"; - - test("should throw error if ciphertext is modified", () => { - const encryptedResult = encryptAsymmetric({ - plaintext, - publicKey, - privateKey, - }); - const ciphertext = "=12adfJ@#52af1231=123"; // modified - const nonce = encryptedResult.nonce; - - expect(() => { - decryptAsymmetric({ - ciphertext, - nonce, - publicKey, - privateKey, - }); - }).toThrowError("invalid encoding"); - }); - - test("should throw error if nonce is modified", () => { - const encryptedResult = encryptAsymmetric({ - plaintext, - publicKey, - privateKey, - }); - const ciphertext = encryptedResult.ciphertext; - const nonce = "=12adfJ@#52af1231=123"; // modified - - expect(() => { - decryptAsymmetric({ - ciphertext, - nonce, - publicKey, - privateKey, - }); - }).toThrowError("invalid encoding"); - }); - }); - }); -}); diff --git a/backend-mongo/tests/unit-tests/utils/posthog.test.ts b/backend-mongo/tests/unit-tests/utils/posthog.test.ts deleted file mode 100644 index f449f39f2..000000000 --- a/backend-mongo/tests/unit-tests/utils/posthog.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { describe, expect, test } from "@jest/globals"; -import { getUserAgentType } from "../../../src/utils/posthog"; - -describe("posthog getChannelFromUserAgent", () => { - test("should return 'web' when userAgent includes 'mozilla'", () => { - const userAgent = - "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.115 Mobile Safari/537.36"; - const channel = getUserAgentType(userAgent); - expect(channel).toBe("web"); - }); - - test("should return 'cli'", () => { - const userAgent = "cli"; - const channel = getUserAgentType(userAgent); - expect(channel).toBe("cli"); - }); - - test("should return 'k8-operator'", () => { - const userAgent = "k8-operator"; - const channel = getUserAgentType(userAgent); - expect(channel).toBe("k8-operator"); - }); - - test("should return undefined if no userAgent", () => { - const userAgent = undefined; - const channel = getUserAgentType(userAgent); - expect(channel).toBe("other"); - }); -}); diff --git a/backend-mongo/tsconfig.json b/backend-mongo/tsconfig.json deleted file mode 100644 index a908b72e9..000000000 --- a/backend-mongo/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "target": "es2016", - "lib": ["es6", "es2021"], - "module": "commonjs", - "rootDir": "src", - "resolveJsonModule": true, - "allowJs": true, - "outDir": "build", - "esModuleInterop": true, - "moduleResolution": "node", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitAny": true, - "skipLibCheck": true, - "typeRoots": ["./src/types", "./node_modules/@types"] - }, - "ts-node": { - "swc": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules"] -}