mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 16:27:40 +00:00
Merge pull request #152 from Zamion101/feat/error-handling
Refactoring backend codebase to use central error handling and logging
This commit is contained in:
Vendored
+2
@@ -14,6 +14,8 @@ declare global {
|
|||||||
JWT_SIGNUP_SECRET: string;
|
JWT_SIGNUP_SECRET: string;
|
||||||
MONGO_URL: string;
|
MONGO_URL: string;
|
||||||
NODE_ENV: 'development' | 'staging' | 'testing' | 'production';
|
NODE_ENV: 'development' | 'staging' | 'testing' | 'production';
|
||||||
|
VERBOSE_ERROR_OUTPUT: string;
|
||||||
|
LOKI_HOST: string;
|
||||||
CLIENT_ID_HEROKU: string;
|
CLIENT_ID_HEROKU: string;
|
||||||
CLIENT_ID_VERCEL: string;
|
CLIENT_ID_VERCEL: string;
|
||||||
CLIENT_ID_NETLIFY: string;
|
CLIENT_ID_NETLIFY: string;
|
||||||
|
|||||||
Generated
+408
-33
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "infisical-api",
|
"name": "infisical-api",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
@@ -12957,6 +12957,11 @@
|
|||||||
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
|
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@colors/colors": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="
|
||||||
|
},
|
||||||
"@cspotcode/source-map-support": {
|
"@cspotcode/source-map-support": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||||
@@ -12966,6 +12971,16 @@
|
|||||||
"@jridgewell/trace-mapping": "0.3.9"
|
"@jridgewell/trace-mapping": "0.3.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@dabh/diagnostics": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
|
||||||
|
"requires": {
|
||||||
|
"colorspace": "1.1.x",
|
||||||
|
"enabled": "2.0.x",
|
||||||
|
"kuler": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@eslint/eslintrc": {
|
"@eslint/eslintrc": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
|
||||||
@@ -13413,6 +13428,84 @@
|
|||||||
"maxmind": "^4.2.0"
|
"maxmind": "^4.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@napi-rs/snappy-android-arm-eabi": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm-eabi/-/snappy-android-arm-eabi-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-NKd/ztuVEgQaAaNVQ5zZaCB9VV+7+uBXBHqhaE5iSapQhLc41szTlT0s68FCee75OoT3vhqdA6Jp5TrzZ2WOaw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-android-arm64": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm64/-/snappy-android-arm64-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-DktruMAO0K0toTnxNHg2GWNIAPJqdvIchCsdsRaKyuEnG101qBg0mYiRCAhxHgbT6RJlOGbUPKkbA9KKRhEJUg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-darwin-arm64": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-arm64/-/snappy-darwin-arm64-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-3LZyoAw3Qa5F7sCCTkSkhmGlydwUKU6L3Jl46eKHO2Ctm8Gcjxww6T7MfwlwGZ6JqAM6d1d++WLzUZPCGXVmag==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-darwin-x64": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-x64/-/snappy-darwin-x64-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-X1D2F67bQkPwr5iSR29/RnOrLwAkB55YO6t41toABzla3mflLDpzZcakz6FokIukykf7ey31/t73v/4pbgaBkg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-freebsd-x64": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-freebsd-x64/-/snappy-freebsd-x64-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-vSeuf+An8jFVHPAn5IbWE9hTGU9PFAaZLj/X7rKTQQtZstnDsHgWe6u4g7FHLuOdwQ8TvhcxAEpNlYIXIk4AJg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-linux-arm-gnueabihf": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm-gnueabihf/-/snappy-linux-arm-gnueabihf-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-/yyN6QsnOs3D1+jI3SfRX+gtnD86rbixdfmgxv9g40+FrDaDTLAu/3VuZIqH02qqq/xiWbDnkO+42RGxXDzTCw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-linux-arm64-gnu": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-gnu/-/snappy-linux-arm64-gnu-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-StEeUCSwUoajgrBtiCQPTkHu+0Q4QlYndghGZNdbN1zJ1ny70YzPpevaFBUyjI/eJ+FN9uICKtwTPtQNSILS5g==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-linux-arm64-musl": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-musl/-/snappy-linux-arm64-musl-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-jWEBRzj+lswZVYf0b5eY0fjMlBL9L9yqjmTuv2UIMjJNHPuR282LK/s3Fm9sYIXQtKkiCo5JyhmIcoghZ3v0Eg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-linux-x64-gnu": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-gnu/-/snappy-linux-x64-gnu-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-41DPoAUFAU9VNrj/96qKfStH2Xq88ZYIsSz8BlITDm2ScoeDGOGbmaWguCXU7I+bC2uKWTmUVMXKqk6tVY6LEg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-linux-x64-musl": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-musl/-/snappy-linux-x64-musl-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-xR4hzFQqVq6J8Zf6XyUVtFJBaRgDyAQYUoBsCr92tZ7gI/0RlWCV6Q6JMO/wP5CSsvyFJIAtSUXXqlzIpw0GPA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-win32-arm64-msvc": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-arm64-msvc/-/snappy-win32-arm64-msvc-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-2mHPadctsaYtrfSV5Na8ooTdI5rflPxP1pceY4us6vbjeWrfgB+KQCuEFOHsGXqFNfsi6L9nWH8nB9swnxnSyw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-win32-ia32-msvc": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-ia32-msvc/-/snappy-win32-ia32-msvc-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-FOMgs9W71hdgjyl3T9F7b/WEIuoryfgBqsyhtHjAaa/98R0BUHl0bOoHg8ka0b5GgnhLBHkX2Yd6VD+Si9Q2ww==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@napi-rs/snappy-win32-x64-msvc": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-x64-msvc/-/snappy-win32-x64-msvc-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-Mu3yELySvzhBcNTVCq+hYxVh+lH3/KjoQ5HIEb3DDPoX0AGRTm3XZa+usq8pFWjl91Cgp9nWK+9lVSkCCIRaKA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -13560,6 +13653,60 @@
|
|||||||
"@maxmind/geoip2-node": "^3.4.0"
|
"@maxmind/geoip2-node": "^3.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@protobufjs/aspromise": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
|
||||||
|
},
|
||||||
|
"@protobufjs/base64": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
|
||||||
|
},
|
||||||
|
"@protobufjs/codegen": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
|
||||||
|
},
|
||||||
|
"@protobufjs/eventemitter": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
|
||||||
|
},
|
||||||
|
"@protobufjs/fetch": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
|
||||||
|
"requires": {
|
||||||
|
"@protobufjs/aspromise": "^1.1.1",
|
||||||
|
"@protobufjs/inquire": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@protobufjs/float": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
|
||||||
|
},
|
||||||
|
"@protobufjs/inquire": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
|
||||||
|
},
|
||||||
|
"@protobufjs/path": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
|
||||||
|
},
|
||||||
|
"@protobufjs/pool": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
|
||||||
|
},
|
||||||
|
"@protobufjs/utf8": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
||||||
|
},
|
||||||
"@sentry/node": {
|
"@sentry/node": {
|
||||||
"version": "7.19.0",
|
"version": "7.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.19.0.tgz",
|
||||||
@@ -13852,6 +13999,10 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/long": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA=="
|
||||||
"@types/libsodium-wrappers": {
|
"@types/libsodium-wrappers": {
|
||||||
"version": "0.7.10",
|
"version": "0.7.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
|
"resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
|
||||||
@@ -13877,6 +14028,12 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/prettier": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/qs": {
|
"@types/qs": {
|
||||||
"version": "6.9.7",
|
"version": "6.9.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||||
@@ -14098,8 +14255,7 @@
|
|||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||||
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
|
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"acorn-walk": {
|
"acorn-walk": {
|
||||||
"version": "8.2.0",
|
"version": "8.2.0",
|
||||||
@@ -14204,6 +14360,16 @@
|
|||||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"async": {
|
||||||
|
"version": "3.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||||
|
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
||||||
|
},
|
||||||
|
"async-exit-hook": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw=="
|
||||||
|
},
|
||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
@@ -14414,6 +14580,11 @@
|
|||||||
"buffer": "^5.6.0"
|
"buffer": "^5.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"btoa": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g=="
|
||||||
|
},
|
||||||
"buffer": {
|
"buffer": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
@@ -14565,6 +14736,30 @@
|
|||||||
"integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
|
"integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"color": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^1.9.3",
|
||||||
|
"color-string": "^1.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"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=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"color-convert": {
|
"color-convert": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
@@ -14577,8 +14772,25 @@
|
|||||||
"color-name": {
|
"color-name": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
"dev": true
|
},
|
||||||
|
"color-string": {
|
||||||
|
"version": "1.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||||
|
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||||
|
"requires": {
|
||||||
|
"color-name": "^1.0.0",
|
||||||
|
"simple-swizzle": "^0.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"colorspace": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
|
||||||
|
"requires": {
|
||||||
|
"color": "^3.1.3",
|
||||||
|
"text-hex": "1.0.x"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"combined-stream": {
|
"combined-stream": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
@@ -14846,6 +15058,11 @@
|
|||||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
|
||||||
|
},
|
||||||
"encodeurl": {
|
"encodeurl": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
@@ -15140,8 +15357,7 @@
|
|||||||
"express-rate-limit": {
|
"express-rate-limit": {
|
||||||
"version": "6.7.0",
|
"version": "6.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
|
||||||
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
|
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA=="
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"express-validator": {
|
"express-validator": {
|
||||||
"version": "6.14.2",
|
"version": "6.14.2",
|
||||||
@@ -15233,6 +15449,11 @@
|
|||||||
"bser": "2.1.1"
|
"bser": "2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fecha": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
|
||||||
|
},
|
||||||
"file-entry-cache": {
|
"file-entry-cache": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||||
@@ -15311,6 +15532,11 @@
|
|||||||
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
|
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"fn.name": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
|
||||||
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.15.2",
|
"version": "1.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
@@ -15711,8 +15937,7 @@
|
|||||||
"is-stream": {
|
"is-stream": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"isexe": {
|
"isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@@ -16018,8 +16243,7 @@
|
|||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
|
||||||
"integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
|
"integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"jest-regex-util": {
|
"jest-regex-util": {
|
||||||
"version": "29.2.0",
|
"version": "29.2.0",
|
||||||
@@ -16129,6 +16353,7 @@
|
|||||||
"@jest/transform": "^29.3.1",
|
"@jest/transform": "^29.3.1",
|
||||||
"@jest/types": "^29.3.1",
|
"@jest/types": "^29.3.1",
|
||||||
"@types/babel__traverse": "^7.0.6",
|
"@types/babel__traverse": "^7.0.6",
|
||||||
|
"@types/prettier": "^2.1.5",
|
||||||
"babel-preset-current-node-syntax": "^1.0.0",
|
"babel-preset-current-node-syntax": "^1.0.0",
|
||||||
"chalk": "^4.0.0",
|
"chalk": "^4.0.0",
|
||||||
"expect": "^29.3.1",
|
"expect": "^29.3.1",
|
||||||
@@ -16336,6 +16561,11 @@
|
|||||||
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"kuler": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
|
||||||
|
},
|
||||||
"leven": {
|
"leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||||
@@ -16397,10 +16627,27 @@
|
|||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lru_map": {
|
"lodash.once": {
|
||||||
"version": "0.3.3",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||||
"integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="
|
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
|
||||||
|
},
|
||||||
|
"logform": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/logform/-/logform-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==",
|
||||||
|
"requires": {
|
||||||
|
"@colors/colors": "1.5.0",
|
||||||
|
"fecha": "^4.2.0",
|
||||||
|
"ms": "^2.1.1",
|
||||||
|
"safe-stable-stringify": "^2.3.1",
|
||||||
|
"triple-beam": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"long": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||||
},
|
},
|
||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
@@ -16410,6 +16657,11 @@
|
|||||||
"yallist": "^4.0.0"
|
"yallist": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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=="
|
||||||
|
},
|
||||||
"make-dir": {
|
"make-dir": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||||
@@ -18393,14 +18645,6 @@
|
|||||||
"minipass": "^3.1.1"
|
"minipass": "^3.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"string_decoder": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"bundled": true,
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "~5.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
@@ -18411,6 +18655,14 @@
|
|||||||
"strip-ansi": "^6.0.1"
|
"strip-ansi": "^6.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"bundled": true,
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
@@ -18578,6 +18830,14 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"one-time": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
|
||||||
|
"requires": {
|
||||||
|
"fn.name": "1.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"onetime": {
|
"onetime": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||||
@@ -18805,6 +19065,26 @@
|
|||||||
"sisteransi": "^1.0.5"
|
"sisteransi": "^1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"protobufjs": {
|
||||||
|
"version": "6.11.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz",
|
||||||
|
"integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==",
|
||||||
|
"requires": {
|
||||||
|
"@protobufjs/aspromise": "^1.1.2",
|
||||||
|
"@protobufjs/base64": "^1.1.2",
|
||||||
|
"@protobufjs/codegen": "^2.0.4",
|
||||||
|
"@protobufjs/eventemitter": "^1.1.0",
|
||||||
|
"@protobufjs/fetch": "^1.1.0",
|
||||||
|
"@protobufjs/float": "^1.0.2",
|
||||||
|
"@protobufjs/inquire": "^1.1.0",
|
||||||
|
"@protobufjs/path": "^1.1.2",
|
||||||
|
"@protobufjs/pool": "^1.1.0",
|
||||||
|
"@protobufjs/utf8": "^1.1.0",
|
||||||
|
"@types/long": "^4.0.1",
|
||||||
|
"@types/node": ">=13.7.0",
|
||||||
|
"long": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"proxy-addr": {
|
"proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
@@ -18999,6 +19279,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||||
},
|
},
|
||||||
|
"safe-stable-stringify": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-dVHE6bMtS/bnL2mwualjc6IxEv1F+OCUpA46pKUj6F8uDbUM0jCCulPqRNPSnWwGNKx5etqMjZYdXtrm5KJZGA=="
|
||||||
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
@@ -19124,6 +19409,21 @@
|
|||||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"simple-swizzle": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
||||||
|
"requires": {
|
||||||
|
"is-arrayish": "^0.3.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"is-arrayish": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"simple-update-notifier": {
|
"simple-update-notifier": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz",
|
||||||
@@ -19158,6 +19458,27 @@
|
|||||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||||
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="
|
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="
|
||||||
},
|
},
|
||||||
|
"snappy": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/snappy/-/snappy-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-mL7GGPJ+WdsaFT5aR/uEqCq8cPg2VbhyifDEP7AeqIVDsAC8LBGYbZP1Qzoa2Ym84OW7JEQXqIpwqFp1EQw5BA==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"@napi-rs/snappy-android-arm-eabi": "7.1.1",
|
||||||
|
"@napi-rs/snappy-android-arm64": "7.1.1",
|
||||||
|
"@napi-rs/snappy-darwin-arm64": "7.1.1",
|
||||||
|
"@napi-rs/snappy-darwin-x64": "7.1.1",
|
||||||
|
"@napi-rs/snappy-freebsd-x64": "7.1.1",
|
||||||
|
"@napi-rs/snappy-linux-arm-gnueabihf": "7.1.1",
|
||||||
|
"@napi-rs/snappy-linux-arm64-gnu": "7.1.1",
|
||||||
|
"@napi-rs/snappy-linux-arm64-musl": "7.1.1",
|
||||||
|
"@napi-rs/snappy-linux-x64-gnu": "7.1.1",
|
||||||
|
"@napi-rs/snappy-linux-x64-musl": "7.1.1",
|
||||||
|
"@napi-rs/snappy-win32-arm64-msvc": "7.1.1",
|
||||||
|
"@napi-rs/snappy-win32-ia32-msvc": "7.1.1",
|
||||||
|
"@napi-rs/snappy-win32-x64-msvc": "7.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"socks": {
|
"socks": {
|
||||||
"version": "2.7.1",
|
"version": "2.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
|
||||||
@@ -19202,6 +19523,11 @@
|
|||||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"stack-trace": {
|
||||||
|
"version": "0.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||||
|
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="
|
||||||
|
},
|
||||||
"stack-utils": {
|
"stack-utils": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
||||||
@@ -19234,14 +19560,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
|
||||||
"integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="
|
"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": {
|
"string-length": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
|
||||||
@@ -19263,6 +19581,14 @@
|
|||||||
"strip-ansi": "^6.0.1"
|
"strip-ansi": "^6.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
@@ -19367,6 +19693,11 @@
|
|||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"text-hex": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
|
||||||
|
},
|
||||||
"text-table": {
|
"text-table": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||||
@@ -19422,6 +19753,11 @@
|
|||||||
"punycode": "^2.1.1"
|
"punycode": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"triple-beam": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
|
||||||
|
},
|
||||||
"ts-jest": {
|
"ts-jest": {
|
||||||
"version": "29.0.3",
|
"version": "29.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz",
|
||||||
@@ -19572,8 +19908,7 @@
|
|||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "8.3.2",
|
"version": "8.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
"devOptional": true
|
|
||||||
},
|
},
|
||||||
"v8-compile-cache-lib": {
|
"v8-compile-cache-lib": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@@ -19663,6 +19998,46 @@
|
|||||||
"isexe": "^2.0.0"
|
"isexe": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"winston": {
|
||||||
|
"version": "3.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz",
|
||||||
|
"integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==",
|
||||||
|
"requires": {
|
||||||
|
"@colors/colors": "1.5.0",
|
||||||
|
"@dabh/diagnostics": "^2.0.2",
|
||||||
|
"async": "^3.2.3",
|
||||||
|
"is-stream": "^2.0.0",
|
||||||
|
"logform": "^2.4.0",
|
||||||
|
"one-time": "^1.0.0",
|
||||||
|
"readable-stream": "^3.4.0",
|
||||||
|
"safe-stable-stringify": "^2.3.1",
|
||||||
|
"stack-trace": "0.0.x",
|
||||||
|
"triple-beam": "^1.3.0",
|
||||||
|
"winston-transport": "^4.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"winston-loki": {
|
||||||
|
"version": "6.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/winston-loki/-/winston-loki-6.0.6.tgz",
|
||||||
|
"integrity": "sha512-cll+nv5T/b9uJXqca0N2WKL1JJNuJND9E6WOOAuSGkZ44L9VQ/QK9F+/5VKbv6LIP9p0nvPSOYxtACCDb/9iWw==",
|
||||||
|
"requires": {
|
||||||
|
"async-exit-hook": "2.0.1",
|
||||||
|
"btoa": "^1.2.1",
|
||||||
|
"protobufjs": "^6.8.8",
|
||||||
|
"snappy": "7.1.1",
|
||||||
|
"winston-transport": "^4.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"winston-transport": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==",
|
||||||
|
"requires": {
|
||||||
|
"logform": "^2.3.2",
|
||||||
|
"readable-stream": "^3.6.0",
|
||||||
|
"triple-beam": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"word-wrap": {
|
"word-wrap": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||||
|
|||||||
@@ -28,7 +28,9 @@
|
|||||||
"stripe": "^10.7.0",
|
"stripe": "^10.7.0",
|
||||||
"tweetnacl": "^1.0.3",
|
"tweetnacl": "^1.0.3",
|
||||||
"tweetnacl-util": "^0.15.1",
|
"tweetnacl-util": "^0.15.1",
|
||||||
"typescript": "^4.9.3"
|
"typescript": "^4.9.3",
|
||||||
|
"winston": "^3.8.2",
|
||||||
|
"winston-loki": "^6.0.6"
|
||||||
},
|
},
|
||||||
"name": "infisical-api",
|
"name": "infisical-api",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|||||||
+19
-2
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable no-console */
|
|
||||||
|
|
||||||
|
import { patchRouterParam } from './utils/patchAsyncRoutes';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import helmet from 'helmet';
|
import helmet from 'helmet';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
@@ -29,6 +29,12 @@ import {
|
|||||||
integration as integrationRouter,
|
integration as integrationRouter,
|
||||||
integrationAuth as integrationAuthRouter
|
integrationAuth as integrationAuthRouter
|
||||||
} from './routes';
|
} from './routes';
|
||||||
|
import { getLogger } from './utils/logger';
|
||||||
|
import { RouteNotFoundError } from './utils/errors';
|
||||||
|
import { requestErrorHandler } from './middleware/requestErrorHandler';
|
||||||
|
|
||||||
|
//* Patch Async route params to handle Promise Rejections
|
||||||
|
patchRouterParam()
|
||||||
|
|
||||||
export const app = express();
|
export const app = express();
|
||||||
|
|
||||||
@@ -69,6 +75,17 @@ app.use('/api/v1/stripe', stripeRouter);
|
|||||||
app.use('/api/v1/integration', integrationRouter);
|
app.use('/api/v1/integration', integrationRouter);
|
||||||
app.use('/api/v1/integration-auth', integrationAuthRouter);
|
app.use('/api/v1/integration-auth', integrationAuthRouter);
|
||||||
|
|
||||||
|
|
||||||
|
//* 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`}))
|
||||||
|
})
|
||||||
|
|
||||||
|
//* Error Handling Middleware (must be after all routing logic)
|
||||||
|
app.use(requestErrorHandler)
|
||||||
|
|
||||||
|
|
||||||
export const server = app.listen(PORT, () => {
|
export const server = app.listen(PORT, () => {
|
||||||
console.log(`Listening on PORT ${[PORT]}`);
|
getLogger("backend-main").info(`Server started listening at port ${PORT}`)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ const JWT_SIGNUP_LIFETIME = process.env.JWT_SIGNUP_LIFETIME! || '15m';
|
|||||||
const JWT_SIGNUP_SECRET = process.env.JWT_SIGNUP_SECRET!;
|
const JWT_SIGNUP_SECRET = process.env.JWT_SIGNUP_SECRET!;
|
||||||
const MONGO_URL = process.env.MONGO_URL!;
|
const MONGO_URL = process.env.MONGO_URL!;
|
||||||
const NODE_ENV = process.env.NODE_ENV! || 'production';
|
const NODE_ENV = process.env.NODE_ENV! || 'production';
|
||||||
|
const VERBOSE_ERROR_OUTPUT = process.env.VERBOSE_ERROR_OUTPUT! === 'true' && true;
|
||||||
|
const LOKI_HOST = process.env.LOKI_HOST || undefined;
|
||||||
const CLIENT_SECRET_HEROKU = process.env.CLIENT_SECRET_HEROKU!;
|
const CLIENT_SECRET_HEROKU = process.env.CLIENT_SECRET_HEROKU!;
|
||||||
const CLIENT_ID_HEROKU = process.env.CLIENT_ID_HEROKU!;
|
const CLIENT_ID_HEROKU = process.env.CLIENT_ID_HEROKU!;
|
||||||
const CLIENT_ID_VERCEL = process.env.CLIENT_ID_VERCEL!;
|
const CLIENT_ID_VERCEL = process.env.CLIENT_ID_VERCEL!;
|
||||||
@@ -53,6 +55,8 @@ export {
|
|||||||
JWT_SIGNUP_SECRET,
|
JWT_SIGNUP_SECRET,
|
||||||
MONGO_URL,
|
MONGO_URL,
|
||||||
NODE_ENV,
|
NODE_ENV,
|
||||||
|
VERBOSE_ERROR_OUTPUT,
|
||||||
|
LOKI_HOST,
|
||||||
CLIENT_ID_HEROKU,
|
CLIENT_ID_HEROKU,
|
||||||
CLIENT_ID_VERCEL,
|
CLIENT_ID_VERCEL,
|
||||||
CLIENT_ID_NETLIFY,
|
CLIENT_ID_NETLIFY,
|
||||||
|
|||||||
@@ -2,18 +2,18 @@ import * as Sentry from '@sentry/node';
|
|||||||
import {
|
import {
|
||||||
Bot,
|
Bot,
|
||||||
Integration,
|
Integration,
|
||||||
IIntegration,
|
|
||||||
IntegrationAuth,
|
IntegrationAuth,
|
||||||
IIntegrationAuth
|
|
||||||
} from '../models';
|
} from '../models';
|
||||||
import { exchangeCode, exchangeRefresh, syncSecrets } from '../integrations';
|
import { exchangeCode, exchangeRefresh, syncSecrets } from '../integrations';
|
||||||
import { BotService, IntegrationService } from '../services';
|
import { BotService } from '../services';
|
||||||
import {
|
import {
|
||||||
ENV_DEV,
|
ENV_DEV,
|
||||||
EVENT_PUSH_SECRETS,
|
EVENT_PUSH_SECRETS,
|
||||||
INTEGRATION_VERCEL,
|
INTEGRATION_VERCEL,
|
||||||
INTEGRATION_NETLIFY
|
INTEGRATION_NETLIFY
|
||||||
} from '../variables';
|
} from '../variables';
|
||||||
|
import { UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
import RequestError from '../utils/requestError';
|
||||||
|
|
||||||
interface Update {
|
interface Update {
|
||||||
workspace: string;
|
workspace: string;
|
||||||
@@ -176,12 +176,13 @@ const syncIntegrationsHelper = async ({
|
|||||||
*/
|
*/
|
||||||
const getIntegrationAuthRefreshHelper = async ({ integrationAuthId }: { integrationAuthId: string }) => {
|
const getIntegrationAuthRefreshHelper = async ({ integrationAuthId }: { integrationAuthId: string }) => {
|
||||||
let refreshToken;
|
let refreshToken;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const integrationAuth = await IntegrationAuth
|
const integrationAuth = await IntegrationAuth
|
||||||
.findById(integrationAuthId)
|
.findById(integrationAuthId)
|
||||||
.select('+refreshCiphertext +refreshIV +refreshTag');
|
.select('+refreshCiphertext +refreshIV +refreshTag');
|
||||||
|
|
||||||
if (!integrationAuth) throw new Error('Failed to find integration auth');
|
if (!integrationAuth) throw UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'});
|
||||||
|
|
||||||
refreshToken = await BotService.decryptSymmetric({
|
refreshToken = await BotService.decryptSymmetric({
|
||||||
workspaceId: integrationAuth.workspace.toString(),
|
workspaceId: integrationAuth.workspace.toString(),
|
||||||
@@ -193,7 +194,10 @@ const syncIntegrationsHelper = async ({
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser(null);
|
Sentry.setUser(null);
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
throw new Error('Failed to get integration refresh token');
|
if(err instanceof RequestError)
|
||||||
|
throw err
|
||||||
|
else
|
||||||
|
throw new Error('Failed to get integration refresh token');
|
||||||
}
|
}
|
||||||
|
|
||||||
return refreshToken;
|
return refreshToken;
|
||||||
@@ -209,12 +213,13 @@ const syncIntegrationsHelper = async ({
|
|||||||
*/
|
*/
|
||||||
const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { integrationAuthId: string }) => {
|
const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { integrationAuthId: string }) => {
|
||||||
let accessToken;
|
let accessToken;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const integrationAuth = await IntegrationAuth
|
const integrationAuth = await IntegrationAuth
|
||||||
.findById(integrationAuthId)
|
.findById(integrationAuthId)
|
||||||
.select('workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt + refreshCiphertext');
|
.select('workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt + refreshCiphertext');
|
||||||
|
|
||||||
if (!integrationAuth) throw new Error('Failed to find integration auth');
|
if (!integrationAuth) throw UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'});
|
||||||
|
|
||||||
accessToken = await BotService.decryptSymmetric({
|
accessToken = await BotService.decryptSymmetric({
|
||||||
workspaceId: integrationAuth.workspace.toString(),
|
workspaceId: integrationAuth.workspace.toString(),
|
||||||
@@ -240,7 +245,10 @@ const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { integrati
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser(null);
|
Sentry.setUser(null);
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
throw new Error('Failed to get integration access token');
|
if(err instanceof RequestError)
|
||||||
|
throw err
|
||||||
|
else
|
||||||
|
throw new Error('Failed to get integration access token');
|
||||||
}
|
}
|
||||||
|
|
||||||
return accessToken;
|
return accessToken;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const validateMembership = async ({
|
|||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
let membership;
|
let membership;
|
||||||
|
//TODO: Refactor code to take advantage of using RequestError. It's possible to create new types of errors for more detailed errors
|
||||||
try {
|
try {
|
||||||
membership = await Membership.findOne({
|
membership = await Membership.findOne({
|
||||||
user: userId,
|
user: userId,
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ const exchangeRefreshHeroku = async ({
|
|||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
let accessToken;
|
let accessToken;
|
||||||
|
//TODO: Refactor code to take advantage of using RequestError. It's possible to create new types of errors for more detailed errors
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(
|
const res = await axios.post(
|
||||||
INTEGRATION_HEROKU_TOKEN_URL,
|
INTEGRATION_HEROKU_TOKEN_URL,
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { ErrorRequestHandler } from "express";
|
||||||
|
|
||||||
|
import * as Sentry from '@sentry/node';
|
||||||
|
import { InternalServerError } from "../utils/errors";
|
||||||
|
import { getLogger } from "../utils/logger";
|
||||||
|
import RequestError, { LogLevel } from "../utils/requestError";
|
||||||
|
|
||||||
|
|
||||||
|
export const requestErrorHandler: ErrorRequestHandler = (error: RequestError|Error, req, res, next) => {
|
||||||
|
if(res.headersSent) return next();
|
||||||
|
//TODO: Find better way to type check for error. In current setting you need to cast type to get the functions and variables from RequestError
|
||||||
|
if(!(error instanceof RequestError)){
|
||||||
|
error = InternalServerError({context: {exception: error.message}, stack: error.stack})
|
||||||
|
getLogger('backend-main').log((<RequestError>error).levelName.toLowerCase(), (<RequestError>error).message)
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Set Sentry user identification if req.user is populated
|
||||||
|
if(req.user !== undefined && req.user !== null){
|
||||||
|
Sentry.setUser({ email: req.user.email })
|
||||||
|
}
|
||||||
|
//* Only sent error to Sentry if LogLevel is one of the following level 'ERROR', 'EMERGENCY' or 'CRITICAL'
|
||||||
|
//* with this we will eliminate false-positive errors like 'BadRequestError', 'UnauthorizedRequestError' and so on
|
||||||
|
if([LogLevel.ERROR, LogLevel.EMERGENCY, LogLevel.CRITICAL].includes((<RequestError>error).level)){
|
||||||
|
Sentry.captureException(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status((<RequestError>error).statusCode).json((<RequestError>error).format(req))
|
||||||
|
next()
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { User } from '../models';
|
import { User } from '../models';
|
||||||
import { JWT_AUTH_SECRET } from '../config';
|
import { JWT_AUTH_SECRET } from '../config';
|
||||||
|
import { AccountNotFoundError, BadRequestError, UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
|
||||||
declare module 'jsonwebtoken' {
|
declare module 'jsonwebtoken' {
|
||||||
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
||||||
@@ -20,32 +20,25 @@ declare module 'jsonwebtoken' {
|
|||||||
*/
|
*/
|
||||||
const requireAuth = async (req: Request, res: Response, next: NextFunction) => {
|
const requireAuth = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
// JWT authentication middleware
|
// JWT authentication middleware
|
||||||
try {
|
const [ AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE ] = <[string, string]>req.headers['authorization']?.split(' ', 2) ?? [null, null]
|
||||||
if (!req.headers?.authorization)
|
if(AUTH_TOKEN_TYPE === null) return next(BadRequestError({message: `Missing Authorization Header in the request header.`}))
|
||||||
throw new Error('Failed to locate authorization 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 token = req.headers.authorization.split(' ')[1];
|
const decodedToken = <jwt.UserIDJwtPayload>(
|
||||||
const decodedToken = <jwt.UserIDJwtPayload>(
|
jwt.verify(AUTH_TOKEN_VALUE, JWT_AUTH_SECRET)
|
||||||
jwt.verify(token, JWT_AUTH_SECRET)
|
);
|
||||||
);
|
|
||||||
|
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
_id: decodedToken.userId
|
_id: decodedToken.userId
|
||||||
}).select('+publicKey');
|
}).select('+publicKey');
|
||||||
|
|
||||||
if (!user) throw new Error('Failed to authenticate unfound user');
|
if (!user) return next(AccountNotFoundError({message: 'Failed to locate User account'}))
|
||||||
if (!user?.publicKey)
|
if (!user?.publicKey)
|
||||||
throw new Error('Failed to authenticate not fully set up account');
|
return next(UnauthorizedRequestError({message: 'Unable to authenticate due to partially set up account'}))
|
||||||
|
|
||||||
req.user = user;
|
req.user = user;
|
||||||
return next();
|
return next();
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error: 'Failed to authenticate user. Try logging in'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default requireAuth;
|
export default requireAuth;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { Bot } from '../models';
|
import { Bot } from '../models';
|
||||||
import { validateMembership } from '../helpers/membership';
|
import { validateMembership } from '../helpers/membership';
|
||||||
|
import { AccountNotFoundError } from '../utils/errors';
|
||||||
|
|
||||||
type req = 'params' | 'body' | 'query';
|
type req = 'params' | 'body' | 'query';
|
||||||
|
|
||||||
@@ -15,30 +15,22 @@ const requireBotAuth = ({
|
|||||||
location?: req;
|
location?: req;
|
||||||
}) => {
|
}) => {
|
||||||
return async (req: Request, res: Response, next: NextFunction) => {
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
const bot = await Bot.findOne({ _id: req[location].botId });
|
||||||
const bot = await Bot.findOne({ _id: req[location].botId });
|
|
||||||
|
if (!bot) {
|
||||||
if (!bot) {
|
return next(AccountNotFoundError({message: 'Failed to locate Bot account'}))
|
||||||
throw new Error('Failed to find bot');
|
|
||||||
}
|
|
||||||
|
|
||||||
await validateMembership({
|
|
||||||
userId: req.user._id.toString(),
|
|
||||||
workspaceId: bot.workspace.toString(),
|
|
||||||
acceptedRoles,
|
|
||||||
acceptedStatuses
|
|
||||||
});
|
|
||||||
|
|
||||||
req.bot = bot;
|
|
||||||
|
|
||||||
next();
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error: 'Failed bot authorization'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await validateMembership({
|
||||||
|
userId: req.user._id.toString(),
|
||||||
|
workspaceId: bot.workspace.toString(),
|
||||||
|
acceptedRoles,
|
||||||
|
acceptedStatuses
|
||||||
|
});
|
||||||
|
|
||||||
|
req.bot = bot;
|
||||||
|
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { Bot, Integration, IntegrationAuth, Membership } from '../models';
|
import { Integration, IntegrationAuth } from '../models';
|
||||||
import { IntegrationService } from '../services';
|
import { IntegrationService } from '../services';
|
||||||
import { validateMembership } from '../helpers/membership';
|
import { validateMembership } from '../helpers/membership';
|
||||||
|
import { IntegrationNotFoundError, UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate if user on request is a member of workspace with proper roles associated
|
* Validate if user on request is a member of workspace with proper roles associated
|
||||||
@@ -21,48 +21,40 @@ const requireIntegrationAuth = ({
|
|||||||
return async (req: Request, res: Response, next: NextFunction) => {
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
// integration authorization middleware
|
// integration authorization middleware
|
||||||
|
|
||||||
try {
|
const { integrationId } = req.params;
|
||||||
const { integrationId } = req.params;
|
|
||||||
|
|
||||||
// validate integration accessibility
|
// validate integration accessibility
|
||||||
const integration = await Integration.findOne({
|
const integration = await Integration.findOne({
|
||||||
_id: integrationId
|
_id: integrationId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!integration) {
|
if (!integration) {
|
||||||
throw new Error('Failed to find integration');
|
return next(IntegrationNotFoundError({message: 'Failed to locate Integration'}))
|
||||||
}
|
|
||||||
|
|
||||||
await validateMembership({
|
|
||||||
userId: req.user._id.toString(),
|
|
||||||
workspaceId: integration.workspace.toString(),
|
|
||||||
acceptedRoles,
|
|
||||||
acceptedStatuses
|
|
||||||
});
|
|
||||||
|
|
||||||
const integrationAuth = await IntegrationAuth.findOne({
|
|
||||||
_id: integration.integrationAuth
|
|
||||||
}).select(
|
|
||||||
'+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!integrationAuth) {
|
|
||||||
throw new Error('Failed to find integration authorization');
|
|
||||||
}
|
|
||||||
|
|
||||||
req.integration = integration;
|
|
||||||
req.accessToken = await IntegrationService.getIntegrationAuthAccess({
|
|
||||||
integrationAuthId: integrationAuth._id.toString()
|
|
||||||
});
|
|
||||||
|
|
||||||
return next();
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error: 'Failed integration authorization'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await validateMembership({
|
||||||
|
userId: req.user._id.toString(),
|
||||||
|
workspaceId: integration.workspace.toString(),
|
||||||
|
acceptedRoles,
|
||||||
|
acceptedStatuses
|
||||||
|
});
|
||||||
|
|
||||||
|
const integrationAuth = await IntegrationAuth.findOne({
|
||||||
|
_id: integration.integrationAuth
|
||||||
|
}).select(
|
||||||
|
'+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!integrationAuth) {
|
||||||
|
return next(UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'}))
|
||||||
|
}
|
||||||
|
|
||||||
|
req.integration = integration;
|
||||||
|
req.accessToken = await IntegrationService.getIntegrationAuthAccess({
|
||||||
|
integrationAuthId: integrationAuth._id.toString()
|
||||||
|
});
|
||||||
|
|
||||||
|
return next();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Request, Response, NextFunction } from 'express';
|
|||||||
import { IntegrationAuth } from '../models';
|
import { IntegrationAuth } from '../models';
|
||||||
import { IntegrationService } from '../services';
|
import { IntegrationService } from '../services';
|
||||||
import { validateMembership } from '../helpers/membership';
|
import { validateMembership } from '../helpers/membership';
|
||||||
|
import { UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate if user on request is a member of workspace with proper roles associated
|
* Validate if user on request is a member of workspace with proper roles associated
|
||||||
@@ -22,41 +23,33 @@ const requireIntegrationAuthorizationAuth = ({
|
|||||||
attachAccessToken?: boolean;
|
attachAccessToken?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
return async (req: Request, res: Response, next: NextFunction) => {
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
const { integrationAuthId } = req.params;
|
||||||
const { integrationAuthId } = req.params;
|
|
||||||
|
|
||||||
const integrationAuth = await IntegrationAuth.findOne({
|
const integrationAuth = await IntegrationAuth.findOne({
|
||||||
_id: integrationAuthId
|
_id: integrationAuthId
|
||||||
}).select(
|
}).select(
|
||||||
'+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt'
|
'+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!integrationAuth) {
|
if (!integrationAuth) {
|
||||||
throw new Error('Failed to find integration authorization');
|
return next(UnauthorizedRequestError({message: 'Failed to locate Integration Authorization credentials'}))
|
||||||
}
|
}
|
||||||
|
|
||||||
await validateMembership({
|
await validateMembership({
|
||||||
userId: req.user._id.toString(),
|
userId: req.user._id.toString(),
|
||||||
workspaceId: integrationAuth.workspace.toString(),
|
workspaceId: integrationAuth.workspace.toString(),
|
||||||
acceptedRoles,
|
acceptedRoles,
|
||||||
acceptedStatuses
|
acceptedStatuses
|
||||||
});
|
});
|
||||||
|
|
||||||
req.integrationAuth = integrationAuth;
|
req.integrationAuth = integrationAuth;
|
||||||
if (attachAccessToken) {
|
if (attachAccessToken) {
|
||||||
req.accessToken = await IntegrationService.getIntegrationAuthAccess({
|
req.accessToken = await IntegrationService.getIntegrationAuthAccess({
|
||||||
integrationAuthId: integrationAuth._id.toString()
|
integrationAuthId: integrationAuth._id.toString()
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error: 'Failed (authorization) integration authorizationt'
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { IOrganization, MembershipOrg } from '../models';
|
import { IOrganization, MembershipOrg } from '../models';
|
||||||
|
import { UnauthorizedRequestError, ValidationError } from '../utils/errors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate if user on request is a member with proper roles for organization
|
* Validate if user on request is a member with proper roles for organization
|
||||||
@@ -19,35 +19,28 @@ const requireOrganizationAuth = ({
|
|||||||
return async (req: Request, res: Response, next: NextFunction) => {
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
// organization authorization middleware
|
// organization authorization middleware
|
||||||
|
|
||||||
try {
|
// validate organization membership
|
||||||
// validate organization membership
|
const membershipOrg = await MembershipOrg.findOne({
|
||||||
const membershipOrg = await MembershipOrg.findOne({
|
user: req.user._id,
|
||||||
user: req.user._id,
|
organization: req.params.organizationId
|
||||||
organization: req.params.organizationId
|
}).populate<{ organization: IOrganization }>('organization');
|
||||||
}).populate<{ organization: IOrganization }>('organization');
|
|
||||||
|
|
||||||
if (!membershipOrg) {
|
|
||||||
throw new Error('Failed to find organization membership');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!acceptedRoles.includes(membershipOrg.role)) {
|
if (!membershipOrg) {
|
||||||
throw new Error('Failed to validate organization membership role');
|
return next(UnauthorizedRequestError({message: "You're not a member of this Organization."}))
|
||||||
}
|
|
||||||
|
|
||||||
if (!acceptedStatuses.includes(membershipOrg.status)) {
|
|
||||||
throw new Error('Failed to validate organization membership status');
|
|
||||||
}
|
|
||||||
|
|
||||||
req.membershipOrg = membershipOrg;
|
|
||||||
|
|
||||||
return next();
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error: 'Failed organization authorization'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
//TODO is this important to validate? I mean is it possible to save wrong role to database or get wrong role from databse? - Zamion101
|
||||||
|
if (!acceptedRoles.includes(membershipOrg.role)) {
|
||||||
|
return next(ValidationError({message: 'Failed to validate Organization Membership Role'}))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!acceptedStatuses.includes(membershipOrg.status)) {
|
||||||
|
return next(ValidationError({message: 'Failed to validate Organization Membership Status'}))
|
||||||
|
}
|
||||||
|
|
||||||
|
req.membershipOrg = membershipOrg;
|
||||||
|
|
||||||
|
return next();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { ServiceToken } from '../models';
|
import { ServiceToken } from '../models';
|
||||||
import { JWT_SERVICE_SECRET } from '../config';
|
import { JWT_SERVICE_SECRET } from '../config';
|
||||||
|
import { BadRequestError, UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
|
||||||
declare module 'jsonwebtoken' {
|
declare module 'jsonwebtoken' {
|
||||||
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
||||||
@@ -24,33 +24,27 @@ const requireServiceTokenAuth = async (
|
|||||||
next: NextFunction
|
next: NextFunction
|
||||||
) => {
|
) => {
|
||||||
// JWT service token middleware
|
// JWT service token middleware
|
||||||
try {
|
|
||||||
if (!req.headers?.authorization)
|
const [ AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE ] = <[string, string]>req.headers['authorization']?.split(' ', 2) ?? [null, null]
|
||||||
throw new Error('Failed to locate authorization header');
|
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 token = req.headers.authorization.split(' ')[1];
|
const decodedToken = <jwt.UserIDJwtPayload>(
|
||||||
|
jwt.verify(AUTH_TOKEN_VALUE, JWT_SERVICE_SECRET)
|
||||||
|
);
|
||||||
|
|
||||||
const decodedToken = <jwt.UserIDJwtPayload>(
|
const serviceToken = await ServiceToken.findOne({
|
||||||
jwt.verify(token, JWT_SERVICE_SECRET)
|
_id: decodedToken.serviceTokenId
|
||||||
);
|
})
|
||||||
|
.populate('user', '+publicKey')
|
||||||
|
.select('+encryptedKey +publicKey +nonce');
|
||||||
|
|
||||||
const serviceToken = await ServiceToken.findOne({
|
if (!serviceToken) return next(UnauthorizedRequestError({message: 'The service token does not match the record in the database'}))
|
||||||
_id: decodedToken.serviceTokenId
|
|
||||||
})
|
|
||||||
.populate('user', '+publicKey')
|
|
||||||
.select('+encryptedKey +publicKey +nonce');
|
|
||||||
|
|
||||||
if (!serviceToken) throw new Error('Failed to find service token');
|
req.serviceToken = serviceToken;
|
||||||
|
return next();
|
||||||
req.serviceToken = serviceToken;
|
|
||||||
return next();
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error: 'Failed to authenticate service token'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default requireServiceTokenAuth;
|
export default requireServiceTokenAuth;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { User } from '../models';
|
import { User } from '../models';
|
||||||
import { JWT_SIGNUP_SECRET } from '../config';
|
import { JWT_SIGNUP_SECRET } from '../config';
|
||||||
|
import { BadRequestError, UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
|
||||||
declare module 'jsonwebtoken' {
|
declare module 'jsonwebtoken' {
|
||||||
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
||||||
@@ -21,32 +21,24 @@ const requireSignupAuth = async (
|
|||||||
) => {
|
) => {
|
||||||
// JWT (temporary) authentication middleware for complete signup
|
// JWT (temporary) authentication middleware for complete signup
|
||||||
|
|
||||||
try {
|
const [ AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE ] = <[string, string]>req.headers['authorization']?.split(' ', 2) ?? [null, null]
|
||||||
if (!req.headers?.authorization)
|
if(AUTH_TOKEN_TYPE === null) return next(BadRequestError({message: `Missing Authorization Header in the request header.`}))
|
||||||
throw new Error('Failed to locate authorization 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.UserIDJwtPayload>(
|
||||||
|
jwt.verify(AUTH_TOKEN_VALUE, JWT_SIGNUP_SECRET)
|
||||||
|
);
|
||||||
|
|
||||||
const token = req.headers.authorization.split(' ')[1];
|
const user = await User.findOne({
|
||||||
const decodedToken = <jwt.UserIDJwtPayload>(
|
_id: decodedToken.userId
|
||||||
jwt.verify(token, JWT_SIGNUP_SECRET)
|
}).select('+publicKey');
|
||||||
);
|
|
||||||
|
|
||||||
const user = await User.findOne({
|
if (!user)
|
||||||
_id: decodedToken.userId
|
return next(UnauthorizedRequestError({message: 'Unable to authenticate for User account completion. Try logging in again'}))
|
||||||
}).select('+publicKey');
|
|
||||||
|
|
||||||
if (!user)
|
req.user = user;
|
||||||
throw new Error('Failed to temporarily authenticate unfound user');
|
return next();
|
||||||
|
|
||||||
req.user = user;
|
|
||||||
return next();
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error:
|
|
||||||
'Failed to temporarily authenticate user for complete account. Try logging in'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default requireSignupAuth;
|
export default requireSignupAuth;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { validateMembership } from '../helpers/membership';
|
import { validateMembership } from '../helpers/membership';
|
||||||
|
import { UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
|
||||||
type req = 'params' | 'body' | 'query';
|
type req = 'params' | 'body' | 'query';
|
||||||
|
|
||||||
@@ -36,11 +36,7 @@ const requireWorkspaceAuth = ({
|
|||||||
|
|
||||||
return next();
|
return next();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser(null);
|
return next(UnauthorizedRequestError({message: 'Unable to authenticate workspace'}))
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error: 'Failed workspace authorization'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { validationResult } from 'express-validator';
|
import { validationResult } from 'express-validator';
|
||||||
|
import { BadRequestError, UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate intended inputs on [req] via express-validator
|
* Validate intended inputs on [req] via express-validator
|
||||||
@@ -15,16 +15,12 @@ const validate = (req: Request, res: Response, next: NextFunction) => {
|
|||||||
try {
|
try {
|
||||||
const errors = validationResult(req);
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return res.status(400).json({ errors: errors.array() });
|
return next(BadRequestError({context: {errors: errors.array}}))
|
||||||
}
|
}
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser(null);
|
return next(UnauthorizedRequestError({message: 'Unauthenticated requests are not allowed. Try logging in'}))
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(401).send({
|
|
||||||
error: "Looks like you're unauthenticated . Try logging in"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,16 @@ import {
|
|||||||
POSTHOG_PROJECT_API_KEY,
|
POSTHOG_PROJECT_API_KEY,
|
||||||
TELEMETRY_ENABLED
|
TELEMETRY_ENABLED
|
||||||
} from '../config';
|
} from '../config';
|
||||||
|
import { getLogger } from '../utils/logger';
|
||||||
|
|
||||||
console.log('TELEMETRY_ENABLED: ', TELEMETRY_ENABLED);
|
if(TELEMETRY_ENABLED){
|
||||||
|
getLogger("backend-main").info([
|
||||||
|
"",
|
||||||
|
"Infisical collects telemetry data about general usage.",
|
||||||
|
"The data 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 for investors as we support Infisical as open-source software.",
|
||||||
|
"To opt out of telemetry, you can set `TELEMETRY_ENABLED=false` within the environment variables",
|
||||||
|
].join('\n'))
|
||||||
|
}
|
||||||
|
|
||||||
let postHogClient: any;
|
let postHogClient: any;
|
||||||
if (NODE_ENV === 'production' && TELEMETRY_ENABLED) {
|
if (NODE_ENV === 'production' && TELEMETRY_ENABLED) {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable no-console */
|
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import { getLogger } from '../utils/logger';
|
||||||
|
|
||||||
export const initDatabase = (MONGO_URL: string) => {
|
export const initDatabase = (MONGO_URL: string) => {
|
||||||
mongoose
|
mongoose
|
||||||
.connect(MONGO_URL)
|
.connect(MONGO_URL)
|
||||||
.then(() => console.log('Successfully connected to DB'))
|
.then(() => getLogger("database").info("Database connection established"))
|
||||||
.catch((e) => console.log('Failed to connect to DB ', e));
|
.catch((e) => getLogger("database").error(`Unable to establish Database connection due to the error.\n${e}`));
|
||||||
return mongoose.connection;
|
return mongoose.connection;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable no-console */
|
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { createTerminus } from '@godaddy/terminus';
|
import { createTerminus } from '@godaddy/terminus';
|
||||||
|
import { getLogger } from '../utils/logger';
|
||||||
|
|
||||||
export const setUpHealthEndpoint = <T>(server: T) => {
|
export const setUpHealthEndpoint = <T>(server: T) => {
|
||||||
const onSignal = () => {
|
const onSignal = () => {
|
||||||
console.log('Server is starting clean-up');
|
getLogger('backend-main').info('Server is starting clean-up');
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
if (mongoose.connection && mongoose.connection.readyState == 1) {
|
if (mongoose.connection && mongoose.connection.readyState == 1) {
|
||||||
|
|||||||
Vendored
+1
@@ -1,5 +1,6 @@
|
|||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
|
|
||||||
|
|
||||||
// TODO: fix (any) types
|
// TODO: fix (any) types
|
||||||
declare global {
|
declare global {
|
||||||
namespace Express {
|
namespace Express {
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
import RequestError, { LogLevel, RequestErrorContext } from "./requestError"
|
||||||
|
|
||||||
|
//* ----->[GENERAL HTTP ERRORS]<-----
|
||||||
|
export const RouteNotFoundError = (error?: Partial<RequestErrorContext>) => 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<RequestErrorContext>) => 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<RequestErrorContext>) => 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<RequestErrorContext>) => new RequestError({
|
||||||
|
logLevel: error?.logLevel ?? LogLevel.INFO,
|
||||||
|
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<RequestErrorContext>) => 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 InternalServerError = (error?: Partial<RequestErrorContext>) => 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<RequestErrorContext>) => 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<RequestErrorContext>) => 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 ERRORS]<-----
|
||||||
|
export const IntegrationNotFoundError = (error?: Partial<RequestErrorContext>) => 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<RequestErrorContext>) => 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
|
||||||
|
})
|
||||||
|
|
||||||
|
//* ----->[ORGANIZATION ERRORS]<-----
|
||||||
|
export const OrganizationNotFoundError = (error?: Partial<RequestErrorContext>) => 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
|
||||||
|
})
|
||||||
|
|
||||||
|
//* ----->[ACCOUNT ERRORS]<-----
|
||||||
|
export const AccountNotFoundError = (error?: Partial<RequestErrorContext>) => 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
|
||||||
|
})
|
||||||
|
|
||||||
|
//* ----->[MISC ERRORS]<-----
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import { createLogger, format, transports } from 'winston';
|
||||||
|
import LokiTransport from 'winston-loki';
|
||||||
|
import { LOKI_HOST, NODE_ENV } from '../config';
|
||||||
|
|
||||||
|
const { combine, colorize, label, printf, splat, timestamp } = format;
|
||||||
|
|
||||||
|
const logFormat = (prefix: string) => combine(
|
||||||
|
timestamp(),
|
||||||
|
splat(),
|
||||||
|
label({ label: prefix }),
|
||||||
|
printf((info) => `${info.timestamp} ${info.label} ${info.level}: ${info.message}`)
|
||||||
|
);
|
||||||
|
|
||||||
|
const createLoggerWithLabel = (level: string, label: string) => {
|
||||||
|
const _level = level.toLowerCase() || 'info'
|
||||||
|
//* Always add Console output to transports
|
||||||
|
const _transports: any[] = [
|
||||||
|
new transports.Console({
|
||||||
|
format: combine(
|
||||||
|
colorize(),
|
||||||
|
logFormat(label),
|
||||||
|
// format.json()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
]
|
||||||
|
//* Add LokiTransport if it's enabled
|
||||||
|
if(LOKI_HOST !== undefined){
|
||||||
|
_transports.push(
|
||||||
|
new LokiTransport({
|
||||||
|
host: LOKI_HOST,
|
||||||
|
handleExceptions: true,
|
||||||
|
handleRejections: true,
|
||||||
|
batching: true,
|
||||||
|
level: _level,
|
||||||
|
timeout: 30000,
|
||||||
|
format: format.combine(
|
||||||
|
format.json()
|
||||||
|
),
|
||||||
|
labels: {app: process.env.npm_package_name, version: process.env.npm_package_version, environment: NODE_ENV},
|
||||||
|
onConnectionError: (err: Error)=> console.error('Connection error while connecting to Loki Server.\n', err)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return createLogger({
|
||||||
|
level: _level,
|
||||||
|
transports: _transports,
|
||||||
|
format: format.combine(
|
||||||
|
logFormat(label),
|
||||||
|
format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] })
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_LOGGERS = {
|
||||||
|
"backend-main": createLoggerWithLabel('info', '[IFSC:backend-main]'),
|
||||||
|
"database": createLoggerWithLabel('info', '[IFSC:database]'),
|
||||||
|
}
|
||||||
|
type LoggerNames = keyof typeof DEFAULT_LOGGERS
|
||||||
|
|
||||||
|
export const getLogger = (loggerName: LoggerNames) => {
|
||||||
|
return DEFAULT_LOGGERS[loggerName]
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
Original work Copyright (c) 2016, Nikolay Nemshilov <[email protected]>
|
||||||
|
Modified work Copyright (c) 2016, David Banham <[email protected]>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||||
|
with or without fee is hereby granted, provided that the above copyright notice
|
||||||
|
and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||||
|
THIS SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
/* eslint-env node */
|
||||||
|
const Layer = require('express/lib/router/layer');
|
||||||
|
const Router = require('express/lib/router');
|
||||||
|
|
||||||
|
const last = (arr = []) => arr[arr.length - 1];
|
||||||
|
const noop = Function.prototype;
|
||||||
|
|
||||||
|
function copyFnProps(oldFn, newFn) {
|
||||||
|
Object.keys(oldFn).forEach((key) => {
|
||||||
|
newFn[key] = oldFn[key];
|
||||||
|
});
|
||||||
|
return newFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrap(fn) {
|
||||||
|
const newFn = function newFn(...args) {
|
||||||
|
const ret = fn.apply(this, args);
|
||||||
|
const next = (args.length === 5 ? args[2] : last(args)) || noop;
|
||||||
|
if (ret && ret.catch) ret.catch(err => next(err));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
Object.defineProperty(newFn, 'length', {
|
||||||
|
value: fn.length,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
return copyFnProps(fn, newFn);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function patchRouterParam() {
|
||||||
|
const originalParam = Router.prototype.constructor.param;
|
||||||
|
Router.prototype.constructor.param = function param(name, fn) {
|
||||||
|
fn = wrap(fn);
|
||||||
|
return originalParam.call(this, name, fn);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(Layer.prototype, 'handle', {
|
||||||
|
enumerable: true,
|
||||||
|
get() {
|
||||||
|
return this.__handle;
|
||||||
|
},
|
||||||
|
set(fn) {
|
||||||
|
fn = wrap(fn);
|
||||||
|
this.__handle = fn;
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
import { Request } from 'express'
|
||||||
|
import { VERBOSE_ERROR_OUTPUT } from '../config'
|
||||||
|
|
||||||
|
export enum LogLevel {
|
||||||
|
DEBUG = 100,
|
||||||
|
INFO = 200,
|
||||||
|
NOTICE = 250,
|
||||||
|
WARNING = 300,
|
||||||
|
ERROR = 400,
|
||||||
|
CRITICAL = 500,
|
||||||
|
ALERT = 550,
|
||||||
|
EMERGENCY = 600,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RequestErrorContext = {
|
||||||
|
logLevel?: LogLevel,
|
||||||
|
statusCode: number,
|
||||||
|
type: string,
|
||||||
|
message: string,
|
||||||
|
context?: Record<string, unknown>,
|
||||||
|
stack?: string|undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class RequestError extends Error{
|
||||||
|
|
||||||
|
private _logLevel: LogLevel
|
||||||
|
private _logName: string
|
||||||
|
statusCode: number
|
||||||
|
type: string
|
||||||
|
context: Record<string, unknown>
|
||||||
|
extra: Record<string, string|number|symbol>[]
|
||||||
|
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.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<string, string|boolean|number>[]){
|
||||||
|
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 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
|
||||||
|
if(!VERBOSE_ERROR_OUTPUT){
|
||||||
|
_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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user