Merge remote-tracking branch 'origin' into pg-ssl

This commit is contained in:
Tuan Dang
2024-02-03 15:16:47 -08:00
232 changed files with 2524 additions and 4438 deletions
+4 -2
View File
@@ -1,6 +1,6 @@
# Description 📣 # Description 📣
<!-- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. --> <!-- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. Here's how we expect a pull request to be : https://infisical.com/docs/contributing/getting-started/pull-requests -->
## Type ✨ ## Type ✨
@@ -19,4 +19,6 @@
--- ---
- [ ] I have read the [contributing guide](https://infisical.com/docs/contributing/overview), agreed and acknowledged the [code of conduct](https://infisical.com/docs/contributing/code-of-conduct). 📝 - [ ] I have read the [contributing guide](https://infisical.com/docs/contributing/getting-started/overview), agreed and acknowledged the [code of conduct](https://infisical.com/docs/contributing/getting-started/code-of-conduct). 📝
<!-- If you have any questions regarding contribution, here's the FAQ : https://infisical.com/docs/contributing/getting-started/faq -->
+4 -4
View File
@@ -19,14 +19,14 @@ infisical:
## @param backend.name Backend name ## @param backend.name Backend name
## ##
name: infisical name: infisical
replicaCount: 2 replicaCount: 3
image: image:
repository: infisical/infisical repository: infisical/staging_infisical
tag: "latest-postgres" tag: "latest"
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
deploymentAnnotations: deploymentAnnotations:
secrets.infisical.com/auto-reload: "true" secrets.infisical.com/auto-reload: "false"
kubeSecretRef: "infisical-gamma-secrets" kubeSecretRef: "infisical-gamma-secrets"
+20 -15
View File
@@ -1,27 +1,39 @@
/* eslint-env node */
module.exports = { module.exports = {
root: true,
env: { env: {
browser: true, es6: true,
es2021: true node: true
}, },
extends: ["airbnb-base", "airbnb-typescript/base", "prettier"], extends: [
plugins: ["prettier", "simple-import-sort", "import"], "eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-type-checked",
"airbnb-base",
"airbnb-typescript/base",
"plugin:prettier/recommended",
"prettier"
],
plugins: ["@typescript-eslint", "simple-import-sort", "import"],
parser: "@typescript-eslint/parser",
parserOptions: { parserOptions: {
ecmaVersion: "latest", project: true,
sourceType: "module", sourceType: "module",
project: "./tsconfig.json",
tsconfigRootDir: __dirname tsconfigRootDir: __dirname
}, },
root: true,
rules: { rules: {
"@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off",
"no-void": "off",
"consistent-return": "off", // my style "consistent-return": "off", // my style
"import/order": "off", // for simple-import-order "import/order": "off", // for simple-import-order
"import/prefer-default-export": "off", // why "import/prefer-default-export": "off", // why
"no-restricted-syntax": "off", "no-restricted-syntax": "off",
// importing rules
"simple-import-sort/exports": "error",
"import/first": "error", "import/first": "error",
"import/newline-after-import": "error", "import/newline-after-import": "error",
"import/no-duplicates": "error", "import/no-duplicates": "error",
"simple-import-sort/exports": "error",
"simple-import-sort/imports": [ "simple-import-sort/imports": [
"warn", "warn",
{ {
@@ -45,12 +57,5 @@ module.exports = {
] ]
} }
] ]
},
settings: {
"import/resolver": {
typescript: {
project: ["./tsconfig.json"]
}
}
} }
}; };
+2 -2
View File
@@ -1,7 +1,7 @@
{ {
"singleQuote": false, "singleQuote": false,
"printWidth": 100, "printWidth": 120,
"trailingComma": "none", "trailingComma": "none",
"tabWidth": 2, "tabWidth": 2,
"semi": true "semi": true
} }
+3 -1
View File
@@ -16,9 +16,11 @@ export const mockQueue = (): TQueueServiceFactory => {
queues[name] = jobFn; queues[name] = jobFn;
workers[name] = jobFn; workers[name] = jobFn;
}, },
listen: async (name, event) => { listen: (name, event) => {
events[name] = event; events[name] = event;
}, },
clearQueue: async () => {},
stopJobById: async () => {},
stopRepeatableJobByJobId: async () => true stopRepeatableJobByJobId: async () => true
}; };
}; };
+78 -46
View File
@@ -13,6 +13,7 @@
"@casl/ability": "^6.5.0", "@casl/ability": "^6.5.0",
"@fastify/cookie": "^9.2.0", "@fastify/cookie": "^9.2.0",
"@fastify/cors": "^8.4.1", "@fastify/cors": "^8.4.1",
"@fastify/etag": "^5.1.0",
"@fastify/formbody": "^7.4.0", "@fastify/formbody": "^7.4.0",
"@fastify/helmet": "^11.1.1", "@fastify/helmet": "^11.1.1",
"@fastify/passport": "^2.4.0", "@fastify/passport": "^2.4.0",
@@ -25,6 +26,8 @@
"@octokit/webhooks-types": "^7.3.1", "@octokit/webhooks-types": "^7.3.1",
"@serdnam/pino-cloudwatch-transport": "^1.0.4", "@serdnam/pino-cloudwatch-transport": "^1.0.4",
"@sindresorhus/slugify": "^2.2.1", "@sindresorhus/slugify": "^2.2.1",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"@ucast/mongo2js": "^1.3.4", "@ucast/mongo2js": "^1.3.4",
"ajv": "^8.12.0", "ajv": "^8.12.0",
"argon2": "^0.31.2", "argon2": "^0.31.2",
@@ -34,6 +37,8 @@
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"bullmq": "^5.1.1", "bullmq": "^5.1.1",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-airbnb-typescript": "^17.1.0",
"fastify": "^4.24.3", "fastify": "^4.24.3",
"fastify-plugin": "^4.5.1", "fastify-plugin": "^4.5.1",
@@ -80,10 +85,6 @@
"@types/picomatch": "^2.3.3", "@types/picomatch": "^2.3.3",
"@types/prompt-sync": "^4.2.3", "@types/prompt-sync": "^4.2.3",
"@types/uuid": "^9.0.7", "@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^6.13.2",
"@typescript-eslint/parser": "^6.13.2",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1", "eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1", "eslint-plugin-import": "^2.29.1",
@@ -1671,6 +1672,14 @@
"resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz",
"integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==" "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ=="
}, },
"node_modules/@fastify/etag": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@fastify/etag/-/etag-5.1.0.tgz",
"integrity": "sha512-j/huE8baxgF22idzY35a579b6uP+9ykE9Jt02xY4ZApELNr2KGZmQOKTQsZS94TfKMLfPHwkoM8FfZRq8OZDXg==",
"dependencies": {
"fastify-plugin": "^4.0.0"
}
},
"node_modules/@fastify/fast-json-stringify-compiler": { "node_modules/@fastify/fast-json-stringify-compiler": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz", "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz",
@@ -4530,15 +4539,15 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "6.13.2", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz",
"integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "integrity": "sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.5.1", "@eslint-community/regexpp": "^4.5.1",
"@typescript-eslint/scope-manager": "6.13.2", "@typescript-eslint/scope-manager": "6.20.0",
"@typescript-eslint/type-utils": "6.13.2", "@typescript-eslint/type-utils": "6.20.0",
"@typescript-eslint/utils": "6.13.2", "@typescript-eslint/utils": "6.20.0",
"@typescript-eslint/visitor-keys": "6.13.2", "@typescript-eslint/visitor-keys": "6.20.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.2.4", "ignore": "^5.2.4",
@@ -4585,14 +4594,14 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "6.13.2", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz",
"integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "6.13.2", "@typescript-eslint/scope-manager": "6.20.0",
"@typescript-eslint/types": "6.13.2", "@typescript-eslint/types": "6.20.0",
"@typescript-eslint/typescript-estree": "6.13.2", "@typescript-eslint/typescript-estree": "6.20.0",
"@typescript-eslint/visitor-keys": "6.13.2", "@typescript-eslint/visitor-keys": "6.20.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -4633,12 +4642,12 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "6.13.2", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz",
"integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.13.2", "@typescript-eslint/types": "6.20.0",
"@typescript-eslint/visitor-keys": "6.13.2" "@typescript-eslint/visitor-keys": "6.20.0"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^16.0.0 || >=18.0.0"
@@ -4649,12 +4658,12 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "6.13.2", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz",
"integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "integrity": "sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "6.13.2", "@typescript-eslint/typescript-estree": "6.20.0",
"@typescript-eslint/utils": "6.13.2", "@typescript-eslint/utils": "6.20.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^1.0.1" "ts-api-utils": "^1.0.1"
}, },
@@ -4696,9 +4705,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "6.13.2", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz",
"integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==",
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^16.0.0 || >=18.0.0"
}, },
@@ -4708,15 +4717,16 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "6.13.2", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz",
"integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.13.2", "@typescript-eslint/types": "6.20.0",
"@typescript-eslint/visitor-keys": "6.13.2", "@typescript-eslint/visitor-keys": "6.20.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
"minimatch": "9.0.3",
"semver": "^7.5.4", "semver": "^7.5.4",
"ts-api-utils": "^1.0.1" "ts-api-utils": "^1.0.1"
}, },
@@ -4733,6 +4743,14 @@
} }
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -4749,22 +4767,36 @@
} }
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "6.13.2", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz",
"integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12", "@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0", "@types/semver": "^7.5.0",
"@typescript-eslint/scope-manager": "6.13.2", "@typescript-eslint/scope-manager": "6.20.0",
"@typescript-eslint/types": "6.13.2", "@typescript-eslint/types": "6.20.0",
"@typescript-eslint/typescript-estree": "6.13.2", "@typescript-eslint/typescript-estree": "6.20.0",
"semver": "^7.5.4" "semver": "^7.5.4"
}, },
"engines": { "engines": {
@@ -4779,11 +4811,11 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "6.13.2", "version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz",
"integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.13.2", "@typescript-eslint/types": "6.20.0",
"eslint-visitor-keys": "^3.4.1" "eslint-visitor-keys": "^3.4.1"
}, },
"engines": { "engines": {
+5 -4
View File
@@ -45,10 +45,6 @@
"@types/picomatch": "^2.3.3", "@types/picomatch": "^2.3.3",
"@types/prompt-sync": "^4.2.3", "@types/prompt-sync": "^4.2.3",
"@types/uuid": "^9.0.7", "@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^6.13.2",
"@typescript-eslint/parser": "^6.13.2",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1", "eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1", "eslint-plugin-import": "^2.29.1",
@@ -71,6 +67,7 @@
"@casl/ability": "^6.5.0", "@casl/ability": "^6.5.0",
"@fastify/cookie": "^9.2.0", "@fastify/cookie": "^9.2.0",
"@fastify/cors": "^8.4.1", "@fastify/cors": "^8.4.1",
"@fastify/etag": "^5.1.0",
"@fastify/formbody": "^7.4.0", "@fastify/formbody": "^7.4.0",
"@fastify/helmet": "^11.1.1", "@fastify/helmet": "^11.1.1",
"@fastify/passport": "^2.4.0", "@fastify/passport": "^2.4.0",
@@ -83,6 +80,8 @@
"@octokit/webhooks-types": "^7.3.1", "@octokit/webhooks-types": "^7.3.1",
"@serdnam/pino-cloudwatch-transport": "^1.0.4", "@serdnam/pino-cloudwatch-transport": "^1.0.4",
"@sindresorhus/slugify": "^2.2.1", "@sindresorhus/slugify": "^2.2.1",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"@ucast/mongo2js": "^1.3.4", "@ucast/mongo2js": "^1.3.4",
"ajv": "^8.12.0", "ajv": "^8.12.0",
"argon2": "^0.31.2", "argon2": "^0.31.2",
@@ -92,6 +91,8 @@
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"bullmq": "^5.1.1", "bullmq": "^5.1.1",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-airbnb-typescript": "^17.1.0",
"fastify": "^4.24.3", "fastify": "^4.24.3",
"fastify-plugin": "^4.5.1", "fastify-plugin": "^4.5.1",
+1 -6
View File
@@ -1,9 +1,4 @@
import { import { FastifyInstance, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from "fastify";
FastifyInstance,
RawReplyDefaultExpression,
RawRequestDefaultExpression,
RawServerDefault
} from "fastify";
import { Logger } from "pino"; import { Logger } from "pino";
import { ZodTypeProvider } from "@app/server/plugins/fastify-zod"; import { ZodTypeProvider } from "@app/server/plugins/fastify-zod";
+18 -90
View File
@@ -177,11 +177,7 @@ declare module "knex/types/tables" {
TUserEncryptionKeysInsert, TUserEncryptionKeysInsert,
TUserEncryptionKeysUpdate TUserEncryptionKeysUpdate
>; >;
[TableName.AuthTokens]: Knex.CompositeTableType< [TableName.AuthTokens]: Knex.CompositeTableType<TAuthTokens, TAuthTokensInsert, TAuthTokensUpdate>;
TAuthTokens,
TAuthTokensInsert,
TAuthTokensUpdate
>;
[TableName.AuthTokenSession]: Knex.CompositeTableType< [TableName.AuthTokenSession]: Knex.CompositeTableType<
TAuthTokenSessions, TAuthTokenSessions,
TAuthTokenSessionsInsert, TAuthTokenSessionsInsert,
@@ -192,32 +188,16 @@ declare module "knex/types/tables" {
TBackupPrivateKeyInsert, TBackupPrivateKeyInsert,
TBackupPrivateKeyUpdate TBackupPrivateKeyUpdate
>; >;
[TableName.Organization]: Knex.CompositeTableType< [TableName.Organization]: Knex.CompositeTableType<TOrganizations, TOrganizationsInsert, TOrganizationsUpdate>;
TOrganizations, [TableName.OrgMembership]: Knex.CompositeTableType<TOrgMemberships, TOrgMembershipsInsert, TOrgMembershipsUpdate>;
TOrganizationsInsert,
TOrganizationsUpdate
>;
[TableName.OrgMembership]: Knex.CompositeTableType<
TOrgMemberships,
TOrgMembershipsInsert,
TOrgMembershipsUpdate
>;
[TableName.OrgRoles]: Knex.CompositeTableType<TOrgRoles, TOrgRolesInsert, TOrgRolesUpdate>; [TableName.OrgRoles]: Knex.CompositeTableType<TOrgRoles, TOrgRolesInsert, TOrgRolesUpdate>;
[TableName.IncidentContact]: Knex.CompositeTableType< [TableName.IncidentContact]: Knex.CompositeTableType<
TIncidentContacts, TIncidentContacts,
TIncidentContactsInsert, TIncidentContactsInsert,
TIncidentContactsUpdate TIncidentContactsUpdate
>; >;
[TableName.UserAction]: Knex.CompositeTableType< [TableName.UserAction]: Knex.CompositeTableType<TUserActions, TUserActionsInsert, TUserActionsUpdate>;
TUserActions, [TableName.SuperAdmin]: Knex.CompositeTableType<TSuperAdmin, TSuperAdminInsert, TSuperAdminUpdate>;
TUserActionsInsert,
TUserActionsUpdate
>;
[TableName.SuperAdmin]: Knex.CompositeTableType<
TSuperAdmin,
TSuperAdminInsert,
TSuperAdminUpdate
>;
[TableName.ApiKey]: Knex.CompositeTableType<TApiKeys, TApiKeysInsert, TApiKeysUpdate>; [TableName.ApiKey]: Knex.CompositeTableType<TApiKeys, TApiKeysInsert, TApiKeysUpdate>;
[TableName.Project]: Knex.CompositeTableType<TProjects, TProjectsInsert, TProjectsUpdate>; [TableName.Project]: Knex.CompositeTableType<TProjects, TProjectsInsert, TProjectsUpdate>;
[TableName.ProjectMembership]: Knex.CompositeTableType< [TableName.ProjectMembership]: Knex.CompositeTableType<
@@ -230,73 +210,33 @@ declare module "knex/types/tables" {
TProjectEnvironmentsInsert, TProjectEnvironmentsInsert,
TProjectEnvironmentsUpdate TProjectEnvironmentsUpdate
>; >;
[TableName.ProjectBot]: Knex.CompositeTableType< [TableName.ProjectBot]: Knex.CompositeTableType<TProjectBots, TProjectBotsInsert, TProjectBotsUpdate>;
TProjectBots, [TableName.ProjectRoles]: Knex.CompositeTableType<TProjectRoles, TProjectRolesInsert, TProjectRolesUpdate>;
TProjectBotsInsert, [TableName.ProjectKeys]: Knex.CompositeTableType<TProjectKeys, TProjectKeysInsert, TProjectKeysUpdate>;
TProjectBotsUpdate
>;
[TableName.ProjectRoles]: Knex.CompositeTableType<
TProjectRoles,
TProjectRolesInsert,
TProjectRolesUpdate
>;
[TableName.ProjectKeys]: Knex.CompositeTableType<
TProjectKeys,
TProjectKeysInsert,
TProjectKeysUpdate
>;
[TableName.Secret]: Knex.CompositeTableType<TSecrets, TSecretsInsert, TSecretsUpdate>; [TableName.Secret]: Knex.CompositeTableType<TSecrets, TSecretsInsert, TSecretsUpdate>;
[TableName.SecretBlindIndex]: Knex.CompositeTableType< [TableName.SecretBlindIndex]: Knex.CompositeTableType<
TSecretBlindIndexes, TSecretBlindIndexes,
TSecretBlindIndexesInsert, TSecretBlindIndexesInsert,
TSecretBlindIndexesUpdate TSecretBlindIndexesUpdate
>; >;
[TableName.SecretVersion]: Knex.CompositeTableType< [TableName.SecretVersion]: Knex.CompositeTableType<TSecretVersions, TSecretVersionsInsert, TSecretVersionsUpdate>;
TSecretVersions, [TableName.SecretFolder]: Knex.CompositeTableType<TSecretFolders, TSecretFoldersInsert, TSecretFoldersUpdate>;
TSecretVersionsInsert,
TSecretVersionsUpdate
>;
[TableName.SecretFolder]: Knex.CompositeTableType<
TSecretFolders,
TSecretFoldersInsert,
TSecretFoldersUpdate
>;
[TableName.SecretFolderVersion]: Knex.CompositeTableType< [TableName.SecretFolderVersion]: Knex.CompositeTableType<
TSecretFolderVersions, TSecretFolderVersions,
TSecretFolderVersionsInsert, TSecretFolderVersionsInsert,
TSecretFolderVersionsUpdate TSecretFolderVersionsUpdate
>; >;
[TableName.SecretTag]: Knex.CompositeTableType< [TableName.SecretTag]: Knex.CompositeTableType<TSecretTags, TSecretTagsInsert, TSecretTagsUpdate>;
TSecretTags, [TableName.SecretImport]: Knex.CompositeTableType<TSecretImports, TSecretImportsInsert, TSecretImportsUpdate>;
TSecretTagsInsert, [TableName.Integration]: Knex.CompositeTableType<TIntegrations, TIntegrationsInsert, TIntegrationsUpdate>;
TSecretTagsUpdate
>;
[TableName.SecretImport]: Knex.CompositeTableType<
TSecretImports,
TSecretImportsInsert,
TSecretImportsUpdate
>;
[TableName.Integration]: Knex.CompositeTableType<
TIntegrations,
TIntegrationsInsert,
TIntegrationsUpdate
>;
[TableName.Webhook]: Knex.CompositeTableType<TWebhooks, TWebhooksInsert, TWebhooksUpdate>; [TableName.Webhook]: Knex.CompositeTableType<TWebhooks, TWebhooksInsert, TWebhooksUpdate>;
[TableName.ServiceToken]: Knex.CompositeTableType< [TableName.ServiceToken]: Knex.CompositeTableType<TServiceTokens, TServiceTokensInsert, TServiceTokensUpdate>;
TServiceTokens,
TServiceTokensInsert,
TServiceTokensUpdate
>;
[TableName.IntegrationAuth]: Knex.CompositeTableType< [TableName.IntegrationAuth]: Knex.CompositeTableType<
TIntegrationAuths, TIntegrationAuths,
TIntegrationAuthsInsert, TIntegrationAuthsInsert,
TIntegrationAuthsUpdate TIntegrationAuthsUpdate
>; >;
[TableName.Identity]: Knex.CompositeTableType< [TableName.Identity]: Knex.CompositeTableType<TIdentities, TIdentitiesInsert, TIdentitiesUpdate>;
TIdentities,
TIdentitiesInsert,
TIdentitiesUpdate
>;
[TableName.IdentityUniversalAuth]: Knex.CompositeTableType< [TableName.IdentityUniversalAuth]: Knex.CompositeTableType<
TIdentityUniversalAuths, TIdentityUniversalAuths,
TIdentityUniversalAuthsInsert, TIdentityUniversalAuthsInsert,
@@ -362,11 +302,7 @@ declare module "knex/types/tables" {
TSecretRotationOutputsInsert, TSecretRotationOutputsInsert,
TSecretRotationOutputsUpdate TSecretRotationOutputsUpdate
>; >;
[TableName.Snapshot]: Knex.CompositeTableType< [TableName.Snapshot]: Knex.CompositeTableType<TSecretSnapshots, TSecretSnapshotsInsert, TSecretSnapshotsUpdate>;
TSecretSnapshots,
TSecretSnapshotsInsert,
TSecretSnapshotsUpdate
>;
[TableName.SnapshotSecret]: Knex.CompositeTableType< [TableName.SnapshotSecret]: Knex.CompositeTableType<
TSecretSnapshotSecrets, TSecretSnapshotSecrets,
TSecretSnapshotSecretsInsert, TSecretSnapshotSecretsInsert,
@@ -377,11 +313,7 @@ declare module "knex/types/tables" {
TSecretSnapshotFoldersInsert, TSecretSnapshotFoldersInsert,
TSecretSnapshotFoldersUpdate TSecretSnapshotFoldersUpdate
>; >;
[TableName.SamlConfig]: Knex.CompositeTableType< [TableName.SamlConfig]: Knex.CompositeTableType<TSamlConfigs, TSamlConfigsInsert, TSamlConfigsUpdate>;
TSamlConfigs,
TSamlConfigsInsert,
TSamlConfigsUpdate
>;
[TableName.OrgBot]: Knex.CompositeTableType<TOrgBots, TOrgBotsInsert, TOrgBotsUpdate>; [TableName.OrgBot]: Knex.CompositeTableType<TOrgBots, TOrgBotsInsert, TOrgBotsUpdate>;
[TableName.AuditLog]: Knex.CompositeTableType<TAuditLogs, TAuditLogsInsert, TAuditLogsUpdate>; [TableName.AuditLog]: Knex.CompositeTableType<TAuditLogs, TAuditLogsInsert, TAuditLogsUpdate>;
[TableName.GitAppInstallSession]: Knex.CompositeTableType< [TableName.GitAppInstallSession]: Knex.CompositeTableType<
@@ -395,11 +327,7 @@ declare module "knex/types/tables" {
TSecretScanningGitRisksInsert, TSecretScanningGitRisksInsert,
TSecretScanningGitRisksUpdate TSecretScanningGitRisksUpdate
>; >;
[TableName.TrustedIps]: Knex.CompositeTableType< [TableName.TrustedIps]: Knex.CompositeTableType<TTrustedIps, TTrustedIpsInsert, TTrustedIpsUpdate>;
TTrustedIps,
TTrustedIpsInsert,
TTrustedIpsUpdate
>;
// Junction tables // Junction tables
[TableName.JnSecretTag]: Knex.CompositeTableType< [TableName.JnSecretTag]: Knex.CompositeTableType<
TSecretTagJunction, TSecretTagJunction,
@@ -38,12 +38,7 @@ export async function up(knex: Knex): Promise<void> {
} }
await createOnUpdateTrigger(knex, TableName.SecretVersion); await createOnUpdateTrigger(knex, TableName.SecretVersion);
// many to many relation between tags // many to many relation between tags
await createJunctionTable( await createJunctionTable(knex, TableName.SecretVersionTag, TableName.SecretVersion, TableName.SecretTag);
knex,
TableName.SecretVersionTag,
TableName.SecretVersion,
TableName.SecretTag
);
} }
export async function down(knex: Knex): Promise<void> { export async function down(knex: Knex): Promise<void> {
@@ -50,10 +50,7 @@ export async function up(knex: Knex): Promise<void> {
t.string("integration").notNullable(); t.string("integration").notNullable();
t.jsonb("metadata"); t.jsonb("metadata");
t.uuid("integrationAuthId").notNullable(); t.uuid("integrationAuthId").notNullable();
t.foreign("integrationAuthId") t.foreign("integrationAuthId").references("id").inTable(TableName.IntegrationAuth).onDelete("CASCADE");
.references("id")
.inTable(TableName.IntegrationAuth)
.onDelete("CASCADE");
t.uuid("envId").notNullable(); t.uuid("envId").notNullable();
t.string("secretPath").defaultTo("/").notNullable(); t.string("secretPath").defaultTo("/").notNullable();
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE"); t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
@@ -31,10 +31,7 @@ export async function up(knex: Knex): Promise<void> {
t.boolean("isClientSecretRevoked").defaultTo(false).notNullable(); t.boolean("isClientSecretRevoked").defaultTo(false).notNullable();
t.timestamps(true, true, true); t.timestamps(true, true, true);
t.uuid("identityUAId").notNullable(); t.uuid("identityUAId").notNullable();
t.foreign("identityUAId") t.foreign("identityUAId").references("id").inTable(TableName.IdentityUniversalAuth).onDelete("CASCADE");
.references("id")
.inTable(TableName.IdentityUniversalAuth)
.onDelete("CASCADE");
}); });
} }
await createOnUpdateTrigger(knex, TableName.IdentityUniversalAuth); await createOnUpdateTrigger(knex, TableName.IdentityUniversalAuth);
@@ -19,7 +19,7 @@ export async function up(knex: Knex): Promise<void> {
.references("id") .references("id")
.inTable(TableName.IdentityUaClientSecret) .inTable(TableName.IdentityUaClientSecret)
.onDelete("CASCADE"); .onDelete("CASCADE");
t.uuid("identityId").notNullable(); t.uuid("identityId").notNullable();
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE"); t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
t.timestamps(true, true, true); t.timestamps(true, true, true);
}); });
@@ -21,15 +21,9 @@ export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable(TableName.SecretApprovalPolicyApprover, (t) => { await knex.schema.createTable(TableName.SecretApprovalPolicyApprover, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.uuid("approverId").notNullable(); t.uuid("approverId").notNullable();
t.foreign("approverId") t.foreign("approverId").references("id").inTable(TableName.ProjectMembership).onDelete("CASCADE");
.references("id")
.inTable(TableName.ProjectMembership)
.onDelete("CASCADE");
t.uuid("policyId").notNullable(); t.uuid("policyId").notNullable();
t.foreign("policyId") t.foreign("policyId").references("id").inTable(TableName.SecretApprovalPolicy).onDelete("CASCADE");
.references("id")
.inTable(TableName.SecretApprovalPolicy)
.onDelete("CASCADE");
t.timestamps(true, true, true); t.timestamps(true, true, true);
}); });
} }
@@ -11,23 +11,14 @@ export async function up(knex: Knex): Promise<void> {
t.boolean("hasMerged").defaultTo(false).notNullable(); t.boolean("hasMerged").defaultTo(false).notNullable();
t.string("status").defaultTo("open").notNullable(); t.string("status").defaultTo("open").notNullable();
t.jsonb("conflicts"); t.jsonb("conflicts");
t.foreign("policyId") t.foreign("policyId").references("id").inTable(TableName.SecretApprovalPolicy).onDelete("CASCADE");
.references("id")
.inTable(TableName.SecretApprovalPolicy)
.onDelete("CASCADE");
t.string("slug").notNullable(); t.string("slug").notNullable();
t.uuid("folderId").notNullable(); t.uuid("folderId").notNullable();
t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE"); t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE");
t.uuid("statusChangeBy"); t.uuid("statusChangeBy");
t.foreign("statusChangeBy") t.foreign("statusChangeBy").references("id").inTable(TableName.ProjectMembership).onDelete("SET NULL");
.references("id")
.inTable(TableName.ProjectMembership)
.onDelete("SET NULL");
t.uuid("committerId").notNullable(); t.uuid("committerId").notNullable();
t.foreign("committerId") t.foreign("committerId").references("id").inTable(TableName.ProjectMembership).onDelete("CASCADE");
.references("id")
.inTable(TableName.ProjectMembership)
.onDelete("CASCADE");
t.timestamps(true, true, true); t.timestamps(true, true, true);
}); });
} }
@@ -40,10 +31,7 @@ export async function up(knex: Knex): Promise<void> {
t.foreign("member").references("id").inTable(TableName.ProjectMembership).onDelete("CASCADE"); t.foreign("member").references("id").inTable(TableName.ProjectMembership).onDelete("CASCADE");
t.string("status").notNullable(); t.string("status").notNullable();
t.uuid("requestId").notNullable(); t.uuid("requestId").notNullable();
t.foreign("requestId") t.foreign("requestId").references("id").inTable(TableName.SecretApprovalRequest).onDelete("CASCADE");
.references("id")
.inTable(TableName.SecretApprovalRequest)
.onDelete("CASCADE");
t.timestamps(true, true, true); t.timestamps(true, true, true);
}); });
} }
@@ -73,18 +61,12 @@ export async function up(knex: Knex): Promise<void> {
t.timestamps(true, true, true); t.timestamps(true, true, true);
// commit details // commit details
t.uuid("requestId").notNullable(); t.uuid("requestId").notNullable();
t.foreign("requestId") t.foreign("requestId").references("id").inTable(TableName.SecretApprovalRequest).onDelete("CASCADE");
.references("id")
.inTable(TableName.SecretApprovalRequest)
.onDelete("CASCADE");
t.string("op").notNullable(); t.string("op").notNullable();
t.uuid("secretId"); t.uuid("secretId");
t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("SET NULL"); t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("SET NULL");
t.uuid("secretVersion"); t.uuid("secretVersion");
t.foreign("secretVersion") t.foreign("secretVersion").references("id").inTable(TableName.SecretVersion).onDelete("SET NULL");
.references("id")
.inTable(TableName.SecretVersion)
.onDelete("SET NULL");
}); });
} }
await createOnUpdateTrigger(knex, TableName.SecretApprovalRequestSecret); await createOnUpdateTrigger(knex, TableName.SecretApprovalRequestSecret);
@@ -93,10 +75,7 @@ export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable(TableName.SecretApprovalRequestSecretTag, (t) => { await knex.schema.createTable(TableName.SecretApprovalRequestSecretTag, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.uuid("secretId").notNullable(); t.uuid("secretId").notNullable();
t.foreign("secretId") t.foreign("secretId").references("id").inTable(TableName.SecretApprovalRequestSecret).onDelete("CASCADE");
.references("id")
.inTable(TableName.SecretApprovalRequestSecret)
.onDelete("CASCADE");
t.uuid("tagId").notNullable(); t.uuid("tagId").notNullable();
t.foreign("tagId").references("id").inTable(TableName.SecretTag).onDelete("CASCADE"); t.foreign("tagId").references("id").inTable(TableName.SecretTag).onDelete("CASCADE");
t.timestamps(true, true, true); t.timestamps(true, true, true);
@@ -32,10 +32,7 @@ export async function up(knex: Knex): Promise<void> {
t.uuid("secretId").notNullable(); t.uuid("secretId").notNullable();
t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("CASCADE"); t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("CASCADE");
t.uuid("rotationId").notNullable(); t.uuid("rotationId").notNullable();
t.foreign("rotationId") t.foreign("rotationId").references("id").inTable(TableName.SecretRotation).onDelete("CASCADE");
.references("id")
.inTable(TableName.SecretRotation)
.onDelete("CASCADE");
}); });
} }
} }
@@ -25,10 +25,7 @@ export async function up(knex: Knex): Promise<void> {
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE"); t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
// not a relation kept like that to keep it when rolled back // not a relation kept like that to keep it when rolled back
t.uuid("secretVersionId").notNullable(); t.uuid("secretVersionId").notNullable();
t.foreign("secretVersionId") t.foreign("secretVersionId").references("id").inTable(TableName.SecretVersion).onDelete("CASCADE");
.references("id")
.inTable(TableName.SecretVersion)
.onDelete("CASCADE");
t.uuid("snapshotId").notNullable(); t.uuid("snapshotId").notNullable();
t.foreign("snapshotId").references("id").inTable(TableName.Snapshot).onDelete("CASCADE"); t.foreign("snapshotId").references("id").inTable(TableName.Snapshot).onDelete("CASCADE");
t.timestamps(true, true, true); t.timestamps(true, true, true);
@@ -42,10 +39,7 @@ export async function up(knex: Knex): Promise<void> {
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE"); t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
// not a relation kept like that to keep it when rolled back // not a relation kept like that to keep it when rolled back
t.uuid("folderVersionId").notNullable(); t.uuid("folderVersionId").notNullable();
t.foreign("folderVersionId") t.foreign("folderVersionId").references("id").inTable(TableName.SecretFolderVersion).onDelete("CASCADE");
.references("id")
.inTable(TableName.SecretFolderVersion)
.onDelete("CASCADE");
t.uuid("snapshotId").notNullable(); t.uuid("snapshotId").notNullable();
t.foreign("snapshotId").references("id").inTable(TableName.Snapshot).onDelete("CASCADE"); t.foreign("snapshotId").references("id").inTable(TableName.Snapshot).onDelete("CASCADE");
t.timestamps(true, true, true); t.timestamps(true, true, true);
@@ -15,7 +15,7 @@ export async function up(knex: Knex): Promise<void> {
t.timestamps(true, true, true); t.timestamps(true, true, true);
}); });
} }
createOnUpdateTrigger(knex, TableName.GitAppInstallSession); await createOnUpdateTrigger(knex, TableName.GitAppInstallSession);
if (!(await knex.schema.hasTable(TableName.GitAppOrg))) { if (!(await knex.schema.hasTable(TableName.GitAppOrg))) {
await knex.schema.createTable(TableName.GitAppOrg, (t) => { await knex.schema.createTable(TableName.GitAppOrg, (t) => {
@@ -28,7 +28,7 @@ export async function up(knex: Knex): Promise<void> {
t.timestamps(true, true, true); t.timestamps(true, true, true);
}); });
} }
createOnUpdateTrigger(knex, TableName.GitAppOrg); await createOnUpdateTrigger(knex, TableName.GitAppOrg);
if (!(await knex.schema.hasTable(TableName.SecretScanningGitRisk))) { if (!(await knex.schema.hasTable(TableName.SecretScanningGitRisk))) {
await knex.schema.createTable(TableName.SecretScanningGitRisk, (t) => { await knex.schema.createTable(TableName.SecretScanningGitRisk, (t) => {
@@ -66,7 +66,7 @@ export async function up(knex: Knex): Promise<void> {
t.timestamps(true, true, true); t.timestamps(true, true, true);
}); });
} }
createOnUpdateTrigger(knex, TableName.SecretScanningGitRisk); await createOnUpdateTrigger(knex, TableName.SecretScanningGitRisk);
} }
export async function down(knex: Knex): Promise<void> { export async function down(knex: Knex): Promise<void> {
+1 -1
View File
@@ -15,7 +15,7 @@ export const ApiKeysSchema = z.object({
secretHash: z.string(), secretHash: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
userId: z.string().uuid(), userId: z.string().uuid()
}); });
export type TApiKeys = z.infer<typeof ApiKeysSchema>; export type TApiKeys = z.infer<typeof ApiKeysSchema>;
+1 -1
View File
@@ -20,7 +20,7 @@ export const AuditLogsSchema = z.object({
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
orgId: z.string().uuid().nullable().optional(), orgId: z.string().uuid().nullable().optional(),
projectId: z.string().nullable().optional(), projectId: z.string().nullable().optional()
}); });
export type TAuditLogs = z.infer<typeof AuditLogsSchema>; export type TAuditLogs = z.infer<typeof AuditLogsSchema>;
@@ -16,7 +16,7 @@ export const AuthTokenSessionsSchema = z.object({
lastUsed: z.date(), lastUsed: z.date(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
userId: z.string().uuid(), userId: z.string().uuid()
}); });
export type TAuthTokenSessions = z.infer<typeof AuthTokenSessionsSchema>; export type TAuthTokenSessions = z.infer<typeof AuthTokenSessionsSchema>;
+1 -1
View File
@@ -17,7 +17,7 @@ export const AuthTokensSchema = z.object({
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
userId: z.string().uuid().nullable().optional(), userId: z.string().uuid().nullable().optional(),
orgId: z.string().uuid().nullable().optional(), orgId: z.string().uuid().nullable().optional()
}); });
export type TAuthTokens = z.infer<typeof AuthTokensSchema>; export type TAuthTokens = z.infer<typeof AuthTokensSchema>;
+1 -1
View File
@@ -18,7 +18,7 @@ export const BackupPrivateKeySchema = z.object({
verifier: z.string(), verifier: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
userId: z.string().uuid(), userId: z.string().uuid()
}); });
export type TBackupPrivateKey = z.infer<typeof BackupPrivateKeySchema>; export type TBackupPrivateKey = z.infer<typeof BackupPrivateKeySchema>;
@@ -13,7 +13,7 @@ export const GitAppInstallSessionsSchema = z.object({
userId: z.string().uuid().nullable().optional(), userId: z.string().uuid().nullable().optional(),
orgId: z.string().uuid(), orgId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TGitAppInstallSessions = z.infer<typeof GitAppInstallSessionsSchema>; export type TGitAppInstallSessions = z.infer<typeof GitAppInstallSessionsSchema>;
+1 -1
View File
@@ -13,7 +13,7 @@ export const GitAppOrgSchema = z.object({
userId: z.string().uuid(), userId: z.string().uuid(),
orgId: z.string().uuid(), orgId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TGitAppOrg = z.infer<typeof GitAppOrgSchema>; export type TGitAppOrg = z.infer<typeof GitAppOrgSchema>;
+1 -1
View File
@@ -12,7 +12,7 @@ export const IdentitiesSchema = z.object({
name: z.string(), name: z.string(),
authMethod: z.string().nullable().optional(), authMethod: z.string().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TIdentities = z.infer<typeof IdentitiesSchema>; export type TIdentities = z.infer<typeof IdentitiesSchema>;
@@ -19,7 +19,7 @@ export const IdentityAccessTokensSchema = z.object({
identityUAClientSecretId: z.string().nullable().optional(), identityUAClientSecretId: z.string().nullable().optional(),
identityId: z.string().uuid(), identityId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>; export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
@@ -14,7 +14,7 @@ export const IdentityOrgMembershipsSchema = z.object({
orgId: z.string().uuid(), orgId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
identityId: z.string().uuid(), identityId: z.string().uuid()
}); });
export type TIdentityOrgMemberships = z.infer<typeof IdentityOrgMembershipsSchema>; export type TIdentityOrgMemberships = z.infer<typeof IdentityOrgMembershipsSchema>;
@@ -14,7 +14,7 @@ export const IdentityProjectMembershipsSchema = z.object({
projectId: z.string(), projectId: z.string(),
identityId: z.string().uuid(), identityId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TIdentityProjectMemberships = z.infer<typeof IdentityProjectMembershipsSchema>; export type TIdentityProjectMemberships = z.infer<typeof IdentityProjectMembershipsSchema>;
@@ -19,7 +19,7 @@ export const IdentityUaClientSecretsSchema = z.object({
isClientSecretRevoked: z.boolean().default(false), isClientSecretRevoked: z.boolean().default(false),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
identityUAId: z.string().uuid(), identityUAId: z.string().uuid()
}); });
export type TIdentityUaClientSecrets = z.infer<typeof IdentityUaClientSecretsSchema>; export type TIdentityUaClientSecrets = z.infer<typeof IdentityUaClientSecretsSchema>;
@@ -17,7 +17,7 @@ export const IdentityUniversalAuthsSchema = z.object({
accessTokenTrustedIps: z.unknown(), accessTokenTrustedIps: z.unknown(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
identityId: z.string().uuid(), identityId: z.string().uuid()
}); });
export type TIdentityUniversalAuths = z.infer<typeof IdentityUniversalAuthsSchema>; export type TIdentityUniversalAuths = z.infer<typeof IdentityUniversalAuthsSchema>;
+1 -1
View File
@@ -12,7 +12,7 @@ export const IncidentContactsSchema = z.object({
email: z.string(), email: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
orgId: z.string().uuid(), orgId: z.string().uuid()
}); });
export type TIncidentContacts = z.infer<typeof IncidentContactsSchema>; export type TIncidentContacts = z.infer<typeof IncidentContactsSchema>;
+1 -1
View File
@@ -29,7 +29,7 @@ export const IntegrationAuthsSchema = z.object({
keyEncoding: z.string(), keyEncoding: z.string(),
projectId: z.string(), projectId: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TIntegrationAuths = z.infer<typeof IntegrationAuthsSchema>; export type TIntegrationAuths = z.infer<typeof IntegrationAuthsSchema>;
+2 -2
View File
@@ -25,9 +25,9 @@ export const IntegrationsSchema = z.object({
metadata: z.unknown().nullable().optional(), metadata: z.unknown().nullable().optional(),
integrationAuthId: z.string().uuid(), integrationAuthId: z.string().uuid(),
envId: z.string().uuid(), envId: z.string().uuid(),
secretPath: z.string().default('/'), secretPath: z.string().default("/"),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TIntegrations = z.infer<typeof IntegrationsSchema>; export type TIntegrations = z.infer<typeof IntegrationsSchema>;
+1 -1
View File
@@ -23,7 +23,7 @@ export const OrgBotsSchema = z.object({
privateKeyKeyEncoding: z.string(), privateKeyKeyEncoding: z.string(),
orgId: z.string().uuid(), orgId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TOrgBots = z.infer<typeof OrgBotsSchema>; export type TOrgBots = z.infer<typeof OrgBotsSchema>;
+2 -2
View File
@@ -10,13 +10,13 @@ import { TImmutableDBKeys } from "./models";
export const OrgMembershipsSchema = z.object({ export const OrgMembershipsSchema = z.object({
id: z.string().uuid(), id: z.string().uuid(),
role: z.string(), role: z.string(),
status: z.string().default('invited'), status: z.string().default("invited"),
inviteEmail: z.string().nullable().optional(), inviteEmail: z.string().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
userId: z.string().uuid().nullable().optional(), userId: z.string().uuid().nullable().optional(),
orgId: z.string().uuid(), orgId: z.string().uuid(),
roleId: z.string().uuid().nullable().optional(), roleId: z.string().uuid().nullable().optional()
}); });
export type TOrgMemberships = z.infer<typeof OrgMembershipsSchema>; export type TOrgMemberships = z.infer<typeof OrgMembershipsSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const OrgRolesSchema = z.object({
permissions: z.unknown(), permissions: z.unknown(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
orgId: z.string().uuid(), orgId: z.string().uuid()
}); });
export type TOrgRoles = z.infer<typeof OrgRolesSchema>; export type TOrgRoles = z.infer<typeof OrgRolesSchema>;
+1 -1
View File
@@ -13,7 +13,7 @@ export const OrganizationsSchema = z.object({
customerId: z.string().nullable().optional(), customerId: z.string().nullable().optional(),
slug: z.string(), slug: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TOrganizations = z.infer<typeof OrganizationsSchema>; export type TOrganizations = z.infer<typeof OrganizationsSchema>;
+1 -1
View File
@@ -22,7 +22,7 @@ export const ProjectBotsSchema = z.object({
projectId: z.string(), projectId: z.string(),
senderId: z.string().uuid().nullable().optional(), senderId: z.string().uuid().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TProjectBots = z.infer<typeof ProjectBotsSchema>; export type TProjectBots = z.infer<typeof ProjectBotsSchema>;
@@ -14,7 +14,7 @@ export const ProjectEnvironmentsSchema = z.object({
position: z.number(), position: z.number(),
projectId: z.string(), projectId: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TProjectEnvironments = z.infer<typeof ProjectEnvironmentsSchema>; export type TProjectEnvironments = z.infer<typeof ProjectEnvironmentsSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const ProjectKeysSchema = z.object({
senderId: z.string().uuid().nullable().optional(), senderId: z.string().uuid().nullable().optional(),
projectId: z.string(), projectId: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TProjectKeys = z.infer<typeof ProjectKeysSchema>; export type TProjectKeys = z.infer<typeof ProjectKeysSchema>;
@@ -14,7 +14,7 @@ export const ProjectMembershipsSchema = z.object({
updatedAt: z.date(), updatedAt: z.date(),
userId: z.string().uuid(), userId: z.string().uuid(),
projectId: z.string(), projectId: z.string(),
roleId: z.string().uuid().nullable().optional(), roleId: z.string().uuid().nullable().optional()
}); });
export type TProjectMemberships = z.infer<typeof ProjectMembershipsSchema>; export type TProjectMemberships = z.infer<typeof ProjectMembershipsSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const ProjectRolesSchema = z.object({
permissions: z.unknown(), permissions: z.unknown(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
projectId: z.string(), projectId: z.string()
}); });
export type TProjectRoles = z.infer<typeof ProjectRolesSchema>; export type TProjectRoles = z.infer<typeof ProjectRolesSchema>;
+1 -1
View File
@@ -14,7 +14,7 @@ export const ProjectsSchema = z.object({
autoCapitalization: z.boolean().default(true).nullable().optional(), autoCapitalization: z.boolean().default(true).nullable().optional(),
orgId: z.string().uuid(), orgId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TProjects = z.infer<typeof ProjectsSchema>; export type TProjects = z.infer<typeof ProjectsSchema>;
+1 -1
View File
@@ -22,7 +22,7 @@ export const SamlConfigsSchema = z.object({
certTag: z.string().nullable().optional(), certTag: z.string().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
orgId: z.string().uuid(), orgId: z.string().uuid()
}); });
export type TSamlConfigs = z.infer<typeof SamlConfigsSchema>; export type TSamlConfigs = z.infer<typeof SamlConfigsSchema>;
@@ -12,7 +12,7 @@ export const SecretApprovalPoliciesApproversSchema = z.object({
approverId: z.string().uuid(), approverId: z.string().uuid(),
policyId: z.string().uuid(), policyId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretApprovalPoliciesApprovers = z.infer<typeof SecretApprovalPoliciesApproversSchema>; export type TSecretApprovalPoliciesApprovers = z.infer<typeof SecretApprovalPoliciesApproversSchema>;
@@ -14,7 +14,7 @@ export const SecretApprovalPoliciesSchema = z.object({
approvals: z.number().default(1), approvals: z.number().default(1),
envId: z.string().uuid(), envId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>; export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>;
@@ -12,7 +12,7 @@ export const SecretApprovalRequestSecretTagsSchema = z.object({
secretId: z.string().uuid(), secretId: z.string().uuid(),
tagId: z.string().uuid(), tagId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretApprovalRequestSecretTags = z.infer<typeof SecretApprovalRequestSecretTagsSchema>; export type TSecretApprovalRequestSecretTags = z.infer<typeof SecretApprovalRequestSecretTagsSchema>;
@@ -13,7 +13,7 @@ export const SecretApprovalRequestsReviewersSchema = z.object({
status: z.string(), status: z.string(),
requestId: z.string().uuid(), requestId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretApprovalRequestsReviewers = z.infer<typeof SecretApprovalRequestsReviewersSchema>; export type TSecretApprovalRequestsReviewers = z.infer<typeof SecretApprovalRequestsReviewersSchema>;
@@ -23,15 +23,15 @@ export const SecretApprovalRequestsSecretsSchema = z.object({
secretReminderNote: z.string().nullable().optional(), secretReminderNote: z.string().nullable().optional(),
secretReminderRepeatDays: z.number().nullable().optional(), secretReminderRepeatDays: z.number().nullable().optional(),
skipMultilineEncoding: z.boolean().default(false).nullable().optional(), skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
algorithm: z.string().default('aes-256-gcm'), algorithm: z.string().default("aes-256-gcm"),
keyEncoding: z.string().default('utf8'), keyEncoding: z.string().default("utf8"),
metadata: z.unknown().nullable().optional(), metadata: z.unknown().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
requestId: z.string().uuid(), requestId: z.string().uuid(),
op: z.string(), op: z.string(),
secretId: z.string().uuid().nullable().optional(), secretId: z.string().uuid().nullable().optional(),
secretVersion: z.string().uuid().nullable().optional(), secretVersion: z.string().uuid().nullable().optional()
}); });
export type TSecretApprovalRequestsSecrets = z.infer<typeof SecretApprovalRequestsSecretsSchema>; export type TSecretApprovalRequestsSecrets = z.infer<typeof SecretApprovalRequestsSecretsSchema>;
@@ -11,14 +11,14 @@ export const SecretApprovalRequestsSchema = z.object({
id: z.string().uuid(), id: z.string().uuid(),
policyId: z.string().uuid(), policyId: z.string().uuid(),
hasMerged: z.boolean().default(false), hasMerged: z.boolean().default(false),
status: z.string().default('open'), status: z.string().default("open"),
conflicts: z.unknown().nullable().optional(), conflicts: z.unknown().nullable().optional(),
slug: z.string(), slug: z.string(),
folderId: z.string().uuid(), folderId: z.string().uuid(),
statusChangeBy: z.string().uuid().nullable().optional(), statusChangeBy: z.string().uuid().nullable().optional(),
committerId: z.string().uuid(), committerId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretApprovalRequests = z.infer<typeof SecretApprovalRequestsSchema>; export type TSecretApprovalRequests = z.infer<typeof SecretApprovalRequestsSchema>;
@@ -12,11 +12,11 @@ export const SecretBlindIndexesSchema = z.object({
encryptedSaltCipherText: z.string(), encryptedSaltCipherText: z.string(),
saltIV: z.string(), saltIV: z.string(),
saltTag: z.string(), saltTag: z.string(),
algorithm: z.string().default('aes-256-gcm'), algorithm: z.string().default("aes-256-gcm"),
keyEncoding: z.string().default('utf8'), keyEncoding: z.string().default("utf8"),
projectId: z.string(), projectId: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretBlindIndexes = z.infer<typeof SecretBlindIndexesSchema>; export type TSecretBlindIndexes = z.infer<typeof SecretBlindIndexesSchema>;
@@ -14,7 +14,7 @@ export const SecretFolderVersionsSchema = z.object({
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
envId: z.string().uuid(), envId: z.string().uuid(),
folderId: z.string().uuid(), folderId: z.string().uuid()
}); });
export type TSecretFolderVersions = z.infer<typeof SecretFolderVersionsSchema>; export type TSecretFolderVersions = z.infer<typeof SecretFolderVersionsSchema>;
+1 -1
View File
@@ -14,7 +14,7 @@ export const SecretFoldersSchema = z.object({
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
envId: z.string().uuid(), envId: z.string().uuid(),
parentId: z.string().uuid().nullable().optional(), parentId: z.string().uuid().nullable().optional()
}); });
export type TSecretFolders = z.infer<typeof SecretFoldersSchema>; export type TSecretFolders = z.infer<typeof SecretFoldersSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const SecretImportsSchema = z.object({
position: z.number(), position: z.number(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
folderId: z.string().uuid(), folderId: z.string().uuid()
}); });
export type TSecretImports = z.infer<typeof SecretImportsSchema>; export type TSecretImports = z.infer<typeof SecretImportsSchema>;
@@ -11,7 +11,7 @@ export const SecretRotationOutputsSchema = z.object({
id: z.string().uuid(), id: z.string().uuid(),
key: z.string(), key: z.string(),
secretId: z.string().uuid(), secretId: z.string().uuid(),
rotationId: z.string().uuid(), rotationId: z.string().uuid()
}); });
export type TSecretRotationOutputs = z.infer<typeof SecretRotationOutputsSchema>; export type TSecretRotationOutputs = z.infer<typeof SecretRotationOutputsSchema>;
+1 -1
View File
@@ -22,7 +22,7 @@ export const SecretRotationsSchema = z.object({
keyEncoding: z.string().nullable().optional(), keyEncoding: z.string().nullable().optional(),
envId: z.string().uuid(), envId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretRotations = z.infer<typeof SecretRotationsSchema>; export type TSecretRotations = z.infer<typeof SecretRotationsSchema>;
@@ -38,7 +38,7 @@ export const SecretScanningGitRisksSchema = z.object({
status: z.string().nullable().optional(), status: z.string().nullable().optional(),
orgId: z.string().uuid(), orgId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretScanningGitRisks = z.infer<typeof SecretScanningGitRisksSchema>; export type TSecretScanningGitRisks = z.infer<typeof SecretScanningGitRisksSchema>;
@@ -13,7 +13,7 @@ export const SecretSnapshotFoldersSchema = z.object({
folderVersionId: z.string().uuid(), folderVersionId: z.string().uuid(),
snapshotId: z.string().uuid(), snapshotId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretSnapshotFolders = z.infer<typeof SecretSnapshotFoldersSchema>; export type TSecretSnapshotFolders = z.infer<typeof SecretSnapshotFoldersSchema>;
@@ -13,7 +13,7 @@ export const SecretSnapshotSecretsSchema = z.object({
secretVersionId: z.string().uuid(), secretVersionId: z.string().uuid(),
snapshotId: z.string().uuid(), snapshotId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretSnapshotSecrets = z.infer<typeof SecretSnapshotSecretsSchema>; export type TSecretSnapshotSecrets = z.infer<typeof SecretSnapshotSecretsSchema>;
+1 -1
View File
@@ -13,7 +13,7 @@ export const SecretSnapshotsSchema = z.object({
folderId: z.string().uuid(), folderId: z.string().uuid(),
parentFolderId: z.string().uuid().nullable().optional(), parentFolderId: z.string().uuid().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSecretSnapshots = z.infer<typeof SecretSnapshotsSchema>; export type TSecretSnapshots = z.infer<typeof SecretSnapshotsSchema>;
@@ -10,7 +10,7 @@ import { TImmutableDBKeys } from "./models";
export const SecretTagJunctionSchema = z.object({ export const SecretTagJunctionSchema = z.object({
id: z.string().uuid(), id: z.string().uuid(),
secretsId: z.string().uuid(), secretsId: z.string().uuid(),
secret_tagsId: z.string().uuid(), secret_tagsId: z.string().uuid()
}); });
export type TSecretTagJunction = z.infer<typeof SecretTagJunctionSchema>; export type TSecretTagJunction = z.infer<typeof SecretTagJunctionSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const SecretTagsSchema = z.object({
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
createdBy: z.string().uuid().nullable().optional(), createdBy: z.string().uuid().nullable().optional(),
projectId: z.string(), projectId: z.string()
}); });
export type TSecretTags = z.infer<typeof SecretTagsSchema>; export type TSecretTags = z.infer<typeof SecretTagsSchema>;
@@ -10,7 +10,7 @@ import { TImmutableDBKeys } from "./models";
export const SecretVersionTagJunctionSchema = z.object({ export const SecretVersionTagJunctionSchema = z.object({
id: z.string().uuid(), id: z.string().uuid(),
secret_versionsId: z.string().uuid(), secret_versionsId: z.string().uuid(),
secret_tagsId: z.string().uuid(), secret_tagsId: z.string().uuid()
}); });
export type TSecretVersionTagJunction = z.infer<typeof SecretVersionTagJunctionSchema>; export type TSecretVersionTagJunction = z.infer<typeof SecretVersionTagJunctionSchema>;
+1 -1
View File
@@ -21,7 +21,7 @@ export const ServiceTokensSchema = z.object({
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
createdBy: z.string(), createdBy: z.string(),
projectId: z.string(), projectId: z.string()
}); });
export type TServiceTokens = z.infer<typeof ServiceTokensSchema>; export type TServiceTokens = z.infer<typeof ServiceTokensSchema>;
+1 -1
View File
@@ -12,7 +12,7 @@ export const SuperAdminSchema = z.object({
initialized: z.boolean().default(false).nullable().optional(), initialized: z.boolean().default(false).nullable().optional(),
allowSignUp: z.boolean().default(true).nullable().optional(), allowSignUp: z.boolean().default(true).nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TSuperAdmin = z.infer<typeof SuperAdminSchema>; export type TSuperAdmin = z.infer<typeof SuperAdminSchema>;
+1 -1
View File
@@ -16,7 +16,7 @@ export const TrustedIpsSchema = z.object({
comment: z.string().nullable().optional(), comment: z.string().nullable().optional(),
projectId: z.string(), projectId: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TTrustedIps = z.infer<typeof TrustedIpsSchema>; export type TTrustedIps = z.infer<typeof TrustedIpsSchema>;
+1 -1
View File
@@ -12,7 +12,7 @@ export const UserActionsSchema = z.object({
action: z.string(), action: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
userId: z.string().uuid(), userId: z.string().uuid()
}); });
export type TUserActions = z.infer<typeof UserActionsSchema>; export type TUserActions = z.infer<typeof UserActionsSchema>;
@@ -21,7 +21,7 @@ export const UserEncryptionKeysSchema = z.object({
tag: z.string(), tag: z.string(),
salt: z.string(), salt: z.string(),
verifier: z.string(), verifier: z.string(),
userId: z.string().uuid(), userId: z.string().uuid()
}); });
export type TUserEncryptionKeys = z.infer<typeof UserEncryptionKeysSchema>; export type TUserEncryptionKeys = z.infer<typeof UserEncryptionKeysSchema>;
+1 -1
View File
@@ -19,7 +19,7 @@ export const UsersSchema = z.object({
mfaMethods: z.string().array().nullable().optional(), mfaMethods: z.string().array().nullable().optional(),
devices: z.unknown().nullable().optional(), devices: z.unknown().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date()
}); });
export type TUsers = z.infer<typeof UsersSchema>; export type TUsers = z.infer<typeof UsersSchema>;
+2 -2
View File
@@ -9,7 +9,7 @@ import { TImmutableDBKeys } from "./models";
export const WebhooksSchema = z.object({ export const WebhooksSchema = z.object({
id: z.string().uuid(), id: z.string().uuid(),
secretPath: z.string().default('/'), secretPath: z.string().default("/"),
url: z.string(), url: z.string(),
lastStatus: z.string().nullable().optional(), lastStatus: z.string().nullable().optional(),
lastRunErrorMessage: z.string().nullable().optional(), lastRunErrorMessage: z.string().nullable().optional(),
@@ -21,7 +21,7 @@ export const WebhooksSchema = z.object({
keyEncoding: z.string().nullable().optional(), keyEncoding: z.string().nullable().optional(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
envId: z.string().uuid(), envId: z.string().uuid()
}); });
export type TWebhooks = z.infer<typeof WebhooksSchema>; export type TWebhooks = z.infer<typeof WebhooksSchema>;
+6 -8
View File
@@ -48,14 +48,12 @@ export const generateUserSrpKeys = async (password: string) => {
await new Promise((resolve) => { await new Promise((resolve) => {
client.init({ username: seedData1.email, password: seedData1.password }, () => resolve(null)); client.init({ username: seedData1.email, password: seedData1.password }, () => resolve(null));
}); });
const { salt, verifier } = await new Promise<{ salt: string; verifier: string }>( const { salt, verifier } = await new Promise<{ salt: string; verifier: string }>((resolve, reject) => {
(resolve, reject) => { client.createVerifier((err, res) => {
client.createVerifier((err, res) => { if (err) return reject(err);
if (err) return reject(err); return resolve(res);
return resolve(res); });
}); });
}
);
const derivedKey = await argon2.hash(password, { const derivedKey = await argon2.hash(password, {
salt: Buffer.from(salt), salt: Buffer.from(salt),
memoryCost: 65536, memoryCost: 65536,
+2 -2
View File
@@ -14,7 +14,7 @@ export async function seed(knex: Knex): Promise<void> {
const [user] = await knex(TableName.Users) const [user] = await knex(TableName.Users)
.insert([ .insert([
{ {
// @ts-ignore to calculate predefined // @ts-expect-error exluded type id needs to be inserted here to keep it testable
id: seedData1.id, id: seedData1.id,
email: seedData1.email, email: seedData1.email,
superAdmin: true, superAdmin: true,
@@ -48,7 +48,7 @@ export async function seed(knex: Knex): Promise<void> {
]); ]);
await knex(TableName.AuthTokenSession).insert({ await knex(TableName.AuthTokenSession).insert({
// @ts-ignore // @ts-expect-error exluded type id needs to be inserted here to keep it testable
id: seedData1.token.id, id: seedData1.token.id,
userId: seedData1.id, userId: seedData1.id,
ip: "151.196.220.213", ip: "151.196.220.213",
+1 -1
View File
@@ -14,7 +14,7 @@ export async function seed(knex: Knex): Promise<void> {
const [org] = await knex(TableName.Organization) const [org] = await knex(TableName.Organization)
.insert([ .insert([
{ {
// @ts-ignore because we need that id for api calls // @ts-expect-error exluded type id needs to be inserted here to keep it testable
id: seedData1.organization.id, id: seedData1.organization.id,
name: "infisical", name: "infisical",
slug: "infisical", slug: "infisical",
+2 -4
View File
@@ -20,7 +20,7 @@ export async function seed(knex: Knex): Promise<void> {
name: seedData1.project.name, name: seedData1.project.name,
orgId: seedData1.organization.id, orgId: seedData1.organization.id,
slug: "first-project", slug: "first-project",
// @ts-ignore pre calc id // @ts-expect-error exluded type id needs to be inserted here to keep it testable
id: seedData1.project.id id: seedData1.project.id
}) })
.returning("*"); .returning("*");
@@ -45,7 +45,5 @@ export async function seed(knex: Knex): Promise<void> {
})) }))
) )
.returning("*"); .returning("*");
await knex(TableName.SecretFolder).insert( await knex(TableName.SecretFolder).insert(envs.map(({ id }) => ({ name: "root", envId: id, parentId: null })));
envs.map(({ id }) => ({ name: "root", envId: id, parentId: null }))
);
} }
+1 -6
View File
@@ -2,12 +2,7 @@ import { Knex } from "knex";
import { TableName } from "./schemas"; import { TableName } from "./schemas";
export const createJunctionTable = ( export const createJunctionTable = (knex: Knex, tableName: TableName, table1Name: TableName, table2Name: TableName) =>
knex: Knex,
tableName: TableName,
table1Name: TableName,
table2Name: TableName
) =>
knex.schema.createTable(tableName, (table) => { knex.schema.createTable(tableName, (table) => {
table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
table.uuid(`${table1Name}Id`).unsigned().notNullable(); // Foreign key for table1 table.uuid(`${table1Name}Id`).unsigned().notNullable(); // Foreign key for table1
+24 -1
View File
@@ -1,3 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
// TODO(akhilmhdh): Fix this when licence service gets it type
import { z } from "zod"; import { z } from "zod";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -79,7 +82,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const data = await server.services.license.startOrgTrail({ const data = await server.services.license.startOrgTrial({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
orgId: req.params.organizationId, orgId: req.params.organizationId,
@@ -89,6 +92,26 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
} }
}); });
server.route({
url: "/:organizationId/customer-portal-session",
method: "POST",
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
200: z.any()
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const data = await server.services.license.createOrganizationPortalSession({
actorId: req.permission.id,
actor: req.permission.type,
orgId: req.params.organizationId
});
return data;
}
});
server.route({ server.route({
url: "/:organizationId/plan/billing", url: "/:organizationId/plan/billing",
method: "GET", method: "GET",
+2 -14
View File
@@ -26,12 +26,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const role = await server.services.orgRole.createRole(req.permission.id, req.params.organizationId, req.body);
const role = await server.services.orgRole.createRole(
req.permission.id,
req.params.organizationId,
req.body
);
return { role }; return { role };
} }
}); });
@@ -58,7 +53,6 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const role = await server.services.orgRole.updateRole( const role = await server.services.orgRole.updateRole(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
@@ -85,7 +79,6 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const role = await server.services.orgRole.deleteRole( const role = await server.services.orgRole.deleteRole(
req.permission.id, req.permission.id,
req.params.organizationId, req.params.organizationId,
@@ -114,11 +107,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const roles = await server.services.orgRole.listRoles(req.permission.id, req.params.organizationId);
const roles = await server.services.orgRole.listRoles(
req.permission.id,
req.params.organizationId
);
return { data: { roles } }; return { data: { roles } };
} }
}); });
@@ -139,7 +128,6 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const { permissions, membership } = await server.services.orgRole.getUserPermission( const { permissions, membership } = await server.services.orgRole.getUserPermission(
req.permission.id, req.permission.id,
req.params.organizationId req.params.organizationId
@@ -141,7 +141,6 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const { permissions, membership } = await server.services.projectRole.getUserPermission( const { permissions, membership } = await server.services.projectRole.getUserPermission(
req.permission.id, req.permission.id,
req.params.projectId req.params.projectId
+17 -8
View File
@@ -1,3 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
// All the any rules are disabled because passport typesense with fastify is really poor
import { Authenticator } from "@fastify/passport"; import { Authenticator } from "@fastify/passport";
import fastifySession from "@fastify/session"; import fastifySession from "@fastify/session";
import { MultiSamlStrategy } from "@node-saml/passport-saml"; import { MultiSamlStrategy } from "@node-saml/passport-saml";
@@ -33,6 +41,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
new MultiSamlStrategy( new MultiSamlStrategy(
{ {
passReqToCallback: true, passReqToCallback: true,
// eslint-disable-next-line
getSamlOptions: async (req, done) => { getSamlOptions: async (req, done) => {
try { try {
const { ssoIdentifier } = req.params; const { ssoIdentifier } = req.params;
@@ -67,13 +76,17 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
} }
} }
}, },
// eslint-disable-next-line
async (req, profile, cb) => { async (req, profile, cb) => {
try { try {
const serverCfg = getServerCfg(); const serverCfg = getServerCfg();
if (!profile) throw new BadRequestError({ message: "Missing profile" }); if (!profile) throw new BadRequestError({ message: "Missing profile" });
const { email, firstName } = profile; const { firstName } = profile;
if (!email || !firstName) const email = profile?.email ?? (profile?.emailAddress as string); // emailRippling is added because in Rippling the field `email` reserved
if (!email || !firstName) {
throw new BadRequestError({ message: "Invalid request. Missing email or first name" }); throw new BadRequestError({ message: "Invalid request. Missing email or first name" });
}
const { isUserCompleted, providerAuthToken } = await server.services.saml.samlLogin({ const { isUserCompleted, providerAuthToken } = await server.services.saml.samlLogin({
email, email,
@@ -137,15 +150,11 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
handler: (req, res) => { handler: (req, res) => {
if (req.passportUser.isUserCompleted) { if (req.passportUser.isUserCompleted) {
return res.redirect( return res.redirect(
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent( `${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
req.passportUser.providerAuthToken
)}`
); );
} }
return res.redirect( return res.redirect(
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent( `${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
req.passportUser.providerAuthToken
)}`
); );
} }
}); });
@@ -111,7 +111,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
}), }),
response: { response: {
200: z.object({ 200: z.object({
approvals: sapPubSchema.merge(z.object({approvers:z.string().array()})).array() approvals: sapPubSchema.merge(z.object({ approvers: z.string().array() })).array()
}) })
} }
}, },
@@ -137,7 +137,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
}), }),
response: { response: {
200: z.object({ 200: z.object({
policy: sapPubSchema.merge(z.object({approvers:z.string().array()})).optional() policy: sapPubSchema.merge(z.object({ approvers: z.string().array() })).optional()
}) })
} }
}, },
@@ -9,10 +9,7 @@ import {
SecretVersionsSchema SecretVersionsSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { import { ApprovalStatus, RequestState } from "@app/ee/services/secret-approval-request/secret-approval-request-types";
ApprovalStatus,
RequestState
} from "@app/ee/services/secret-approval-request/secret-approval-request-types";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
@@ -41,9 +38,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
approvers: z.string().array(), approvers: z.string().array(),
secretPath: z.string().optional().nullable() secretPath: z.string().optional().nullable()
}), }),
commits: z commits: z.object({ op: z.string(), secretId: z.string().nullable().optional() }).array(),
.object({ op: z.string(), secretId: z.string().nullable().optional() })
.array(),
environment: z.string(), environment: z.string(),
reviewers: z.object({ member: z.string(), status: z.string() }).array(), reviewers: z.object({ member: z.string(), status: z.string() }).array(),
approvers: z.string().array() approvers: z.string().array()
@@ -174,11 +169,12 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
...req.auditLogInfo, ...req.auditLogInfo,
event: { event: {
type: isClosing ? EventType.SECRET_APPROVAL_CLOSED : EventType.SECRET_APPROVAL_REOPENED, type: isClosing ? EventType.SECRET_APPROVAL_CLOSED : EventType.SECRET_APPROVAL_REOPENED,
// eslint-disable-next-line
metadata: { metadata: {
[isClosing ? ("closedBy" as const) : ("reopenedBy" as const)]: [isClosing ? ("closedBy" as const) : ("reopenedBy" as const)]: approval.statusChangeBy as string,
approval.statusChangeBy as string,
secretApprovalRequestId: approval.id, secretApprovalRequestId: approval.id,
secretApprovalRequestSlug: approval.slug secretApprovalRequestSlug: approval.slug
// eslint-disable-next-line
} as any } as any
// akhilmhdh: had to apply any to avoid ts issue with this // akhilmhdh: had to apply any to avoid ts issue with this
} }
@@ -62,12 +62,11 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
}, },
onRequest: verifyAuth([AuthMode.JWT]), onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => { handler: async (req) => {
const appInstallationCompleted = const appInstallationCompleted = await server.services.secretScanning.getOrgInstallationStatus({
await server.services.secretScanning.getOrgInstallationStatus({ actor: req.permission.type,
actor: req.permission.type, actorId: req.permission.id,
actorId: req.permission.id, orgId: req.params.organizationId
orgId: req.params.organizationId });
});
return { appInstallationCompleted }; return { appInstallationCompleted };
} }
}); });
@@ -2,6 +2,7 @@ import { Knex } from "knex";
import { TDbClient } from "@app/db"; import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas"; import { TableName } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { ormify, stripUndefinedInWhere } from "@app/lib/knex"; import { ormify, stripUndefinedInWhere } from "@app/lib/knex";
export type TAuditLogDALFactory = ReturnType<typeof auditLogDALFactory>; export type TAuditLogDALFactory = ReturnType<typeof auditLogDALFactory>;
@@ -22,40 +23,46 @@ export const auditLogDALFactory = (db: TDbClient) => {
const auditLogOrm = ormify(db, TableName.AuditLog); const auditLogOrm = ormify(db, TableName.AuditLog);
const find = async ( const find = async (
{ { orgId, projectId, userAgentType, startDate, endDate, limit = 20, offset = 0, actor, eventType }: TFindQuery,
orgId,
projectId,
userAgentType,
startDate,
endDate,
limit = 20,
offset = 0,
actor,
eventType
}: TFindQuery,
tx?: Knex tx?: Knex
) => { ) => {
const sqlQuery = (tx || db)(TableName.AuditLog) try {
.where( const sqlQuery = (tx || db)(TableName.AuditLog)
stripUndefinedInWhere({ .where(
projectId, stripUndefinedInWhere({
orgId, projectId,
eventType, orgId,
actor, eventType,
userAgentType actor,
}) userAgentType
) })
.limit(limit) )
.offset(offset); .limit(limit)
if (startDate) { .offset(offset)
sqlQuery.where("createdAt", ">=", startDate); .orderBy("createdAt", "desc");
if (startDate) {
void sqlQuery.where("createdAt", ">=", startDate);
}
if (endDate) {
void sqlQuery.where("createdAt", "<=", endDate);
}
const docs = await sqlQuery;
return docs;
} catch (error) {
throw new DatabaseError({ error });
} }
if (endDate) {
sqlQuery.where("createdAt", "<=", endDate);
}
const docs = await sqlQuery;
return docs;
}; };
return { ...auditLogOrm, find }; // delete all audit log that have expired
const pruneAuditLog = async (tx?: Knex) => {
try {
const today = new Date();
const docs = await (tx || db)(TableName.AuditLog).where("expiresAt", "<", today).del();
return docs;
} catch (error) {
throw new DatabaseError({ error, name: "PruneAuditLog" });
}
};
return { ...auditLogOrm, pruneAuditLog, find };
}; };
@@ -1,3 +1,4 @@
import { logger } from "@app/lib/logger";
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue"; import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
import { TProjectDALFactory } from "@app/services/project/project-dal"; import { TProjectDALFactory } from "@app/services/project/project-dal";
@@ -43,6 +44,8 @@ export const auditLogQueueServiceFactory = ({
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
const ttl = plan.auditLogsRetentionDays * MS_IN_DAY; const ttl = plan.auditLogsRetentionDays * MS_IN_DAY;
// skip inserting if audit log retention is 0 meaning its not supported
if (ttl === 0) return;
await auditLogDAL.create({ await auditLogDAL.create({
actor: actor.type, actor: actor.type,
actorMetadata: actor.metadata, actorMetadata: actor.metadata,
@@ -57,7 +60,35 @@ export const auditLogQueueServiceFactory = ({
}); });
}); });
queueService.start(QueueName.AuditLogPrune, async () => {
logger.info(`${QueueName.AuditLogPrune}: queue task started`);
await auditLogDAL.pruneAuditLog();
logger.info(`${QueueName.AuditLogPrune}: queue task completed`);
});
// we do a repeat cron job in utc timezone at 12 Midnight each day
const startAuditLogPruneJob = async () => {
// clear previous job
await queueService.stopRepeatableJob(
QueueName.AuditLogPrune,
QueueJobs.AuditLogPrune,
{ pattern: "0 0 * * *", utc: true },
QueueName.AuditLogPrune // just a job id
);
await queueService.queue(QueueName.AuditLogPrune, QueueJobs.AuditLogPrune, undefined, {
delay: 5000,
jobId: QueueName.AuditLogPrune,
repeat: { pattern: "0 0 * * *", utc: true }
});
};
queueService.listen(QueueName.AuditLogPrune, "failed", (err) => {
logger.error(err?.failedReason, `${QueueName.AuditLogPrune}: log pruning failed`);
});
return { return {
pushToLog pushToLog,
startAuditLogPruneJob
}; };
}; };
@@ -34,10 +34,7 @@ export const auditLogServiceFactory = ({
auditLogActor auditLogActor
}: TListProjectAuditLogDTO) => { }: TListProjectAuditLogDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs);
ProjectPermissionActions.Read,
ProjectPermissionSub.AuditLogs
);
const auditLogs = await auditLogDAL.find({ const auditLogs = await auditLogDAL.find({
startDate, startDate,
endDate, endDate,
@@ -48,20 +45,17 @@ export const auditLogServiceFactory = ({
actor: auditLogActor, actor: auditLogActor,
projectId projectId
}); });
return auditLogs.map( return auditLogs.map(({ eventType: logEventType, actor: eActor, actorMetadata, eventMetadata, ...el }) => ({
({ eventType: logEventType, actor: eActor, actorMetadata, eventMetadata, ...el }) => ({ ...el,
...el, event: { type: logEventType, metadata: eventMetadata },
event: { type: logEventType, metadata: eventMetadata }, actor: { type: eActor, metadata: actorMetadata }
actor: { type: eActor, metadata: actorMetadata } }));
})
);
}; };
const createAuditLog = async (data: TCreateAuditLogDTO) => { const createAuditLog = async (data: TCreateAuditLogDTO) => {
// add all cases in which project id or org id cannot be added // add all cases in which project id or org id cannot be added
if (data.event.type !== EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH) { if (data.event.type !== EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH) {
if (!data.projectId && !data.orgId) if (!data.projectId && !data.orgId) throw new BadRequestError({ message: "Must either project id or org id" });
throw new BadRequestError({ message: "Must either project id or org id" });
} }
return auditLogQueue.pushToLog(data); return auditLogQueue.pushToLog(data);
}; };
+7 -11
View File
@@ -31,15 +31,11 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
secretRotation: true secretRotation: true
}); });
export const setupLicenceRequestWithStore = ( export const setupLicenceRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
baseURL: string,
refreshUrl: string,
licenseKey: string
) => {
let token: string; let token: string;
const licenceReq = axios.create({ const licenceReq = axios.create({
baseURL, baseURL,
timeout: 35 * 1000, timeout: 35 * 1000
// signal: AbortSignal.timeout(60 * 1000) // signal: AbortSignal.timeout(60 * 1000)
}); });
@@ -47,7 +43,7 @@ export const setupLicenceRequestWithStore = (
const appCfg = getConfig(); const appCfg = getConfig();
const { const {
data: { token: authToken } data: { token: authToken }
} = await request.post( } = await request.post<{ token: string }>(
refreshUrl, refreshUrl,
{}, {},
{ {
@@ -75,18 +71,18 @@ export const setupLicenceRequestWithStore = (
licenceReq.interceptors.response.use( licenceReq.interceptors.response.use(
(response) => response, (response) => response,
async (err) => { async (err) => {
const originalRequest = err.config; const originalRequest = (err as AxiosError).config;
// eslint-disable-next-line // eslint-disable-next-line
if ((err as AxiosError)?.response?.status === 401 && !originalRequest._retry) { if ((err as AxiosError)?.response?.status === 401 && !(originalRequest as any)._retry) {
// eslint-disable-next-line // eslint-disable-next-line
originalRequest._retry = true; (originalRequest as any)._retry = true; // injected
// refresh // refresh
await refreshLicence(); await refreshLicence();
licenceReq.defaults.headers.common.Authorization = `Bearer ${token}`; licenceReq.defaults.headers.common.Authorization = `Bearer ${token}`;
return licenceReq(originalRequest); return licenceReq(originalRequest!);
} }
return Promise.reject(err); return Promise.reject(err);
@@ -13,7 +13,7 @@ export const licenseDALFactory = (db: TDbClient) => {
.where({ status: OrgMembershipStatus.Accepted }) .where({ status: OrgMembershipStatus.Accepted })
.andWhere((bd) => { .andWhere((bd) => {
if (orgId) { if (orgId) {
bd.where({ orgId }); void bd.where({ orgId });
} }
}) })
.count(); .count();
@@ -1,3 +1,9 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
// eslint-disable @typescript-eslint/no-unsafe-assignment
// TODO(akhilmhdh): With tony find out the api structure and fill it here
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import NodeCache from "node-cache"; import NodeCache from "node-cache";
@@ -14,6 +20,7 @@ import {
InstanceType, InstanceType,
TAddOrgPmtMethodDTO, TAddOrgPmtMethodDTO,
TAddOrgTaxIdDTO, TAddOrgTaxIdDTO,
TCreateOrgPortalSession,
TDelOrgPmtMethodDTO, TDelOrgPmtMethodDTO,
TDelOrgTaxIdDTO, TDelOrgTaxIdDTO,
TFeatureSet, TFeatureSet,
@@ -24,7 +31,7 @@ import {
TOrgPlanDTO, TOrgPlanDTO,
TOrgPlansTableDTO, TOrgPlansTableDTO,
TOrgPmtMethodsDTO, TOrgPmtMethodsDTO,
TStartOrgTrailDTO, TStartOrgTrialDTO,
TUpdateOrgBillingDetailsDTO TUpdateOrgBillingDetailsDTO
} from "./license-types"; } from "./license-types";
@@ -40,11 +47,7 @@ const LICENSE_SERVER_CLOUD_LOGIN = "/api/auth/v1/license-server-login";
const LICENSE_SERVER_ON_PREM_LOGIN = "/api/auth/v1/licence-login"; const LICENSE_SERVER_ON_PREM_LOGIN = "/api/auth/v1/licence-login";
const FEATURE_CACHE_KEY = (orgId: string, projectId?: string) => `${orgId}-${projectId || ""}`; const FEATURE_CACHE_KEY = (orgId: string, projectId?: string) => `${orgId}-${projectId || ""}`;
export const licenseServiceFactory = ({ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }: TLicenseServiceFactoryDep) => {
orgDAL,
permissionService,
licenseDAL
}: TLicenseServiceFactoryDep) => {
let isValidLicense = false; let isValidLicense = false;
let instanceType = InstanceType.OnPrem; let instanceType = InstanceType.OnPrem;
let onPremFeatures: TFeatureSet = getDefaultOnPremFeatures(); let onPremFeatures: TFeatureSet = getDefaultOnPremFeatures();
@@ -77,9 +80,7 @@ export const licenseServiceFactory = ({
if (token) { if (token) {
const { const {
data: { currentPlan } data: { currentPlan }
} = await licenseServerOnPremApi.request.get<{ currentPlan: TFeatureSet }>( } = await licenseServerOnPremApi.request.get<{ currentPlan: TFeatureSet }>("/api/license/v1/plan");
"/api/license/v1/plan"
);
onPremFeatures = currentPlan; onPremFeatures = currentPlan;
instanceType = InstanceType.EnterpriseOnPrem; instanceType = InstanceType.EnterpriseOnPrem;
logger.info(`Instance type: ${InstanceType.EnterpriseOnPrem}`); logger.info(`Instance type: ${InstanceType.EnterpriseOnPrem}`);
@@ -91,7 +92,7 @@ export const licenseServiceFactory = ({
// else it would reach catch statement // else it would reach catch statement
isValidLicense = true; isValidLicense = true;
} catch (error) { } catch (error) {
logger.error(`init-license: encountered an error when init license [error=${error}]`); logger.error(`init-license: encountered an error when init license [error]`, error);
} }
}; };
@@ -118,7 +119,10 @@ export const licenseServiceFactory = ({
return currentPlan; return currentPlan;
} }
} catch (error) { } catch (error) {
logger.error(`getPlan: encountered an error when fetching pan [orgId=${orgId}] [projectId=${projectId}] [error=${error}]`); logger.error(
`getPlan: encountered an error when fetching pan [orgId=${orgId}] [projectId=${projectId}] [error]`,
error
);
return onPremFeatures; return onPremFeatures;
} }
return onPremFeatures; return onPremFeatures;
@@ -135,7 +139,7 @@ export const licenseServiceFactory = ({
if (instanceType === InstanceType.Cloud) { if (instanceType === InstanceType.Cloud) {
const { const {
data: { customerId } data: { customerId }
} = await licenseServerCloudApi.request.post( } = await licenseServerCloudApi.request.post<{ customerId: string }>(
"/api/license-server/v1/customers", "/api/license-server/v1/customers",
{ {
email, email,
@@ -158,12 +162,9 @@ export const licenseServiceFactory = ({
const count = await licenseDAL.countOfOrgMembers(orgId); const count = await licenseDAL.countOfOrgMembers(orgId);
if (org?.customerId) { if (org?.customerId) {
await licenseServerCloudApi.request.patch( await licenseServerCloudApi.request.patch(`/api/license-server/v1/customers/${org.customerId}/cloud-plan`, {
`/api/license-server/v1/customers/${org.customerId}/cloud-plan`, quantity: count
{ });
quantity: count
}
);
} }
featureStore.del(orgId); featureStore.del(orgId);
} else if (instanceType === InstanceType.EnterpriseOnPrem) { } else if (instanceType === InstanceType.EnterpriseOnPrem) {
@@ -174,17 +175,9 @@ export const licenseServiceFactory = ({
}; };
// below all are api calls // below all are api calls
const getOrgPlansTableByBillCycle = async ({ const getOrgPlansTableByBillCycle = async ({ orgId, actor, actorId, billingCycle }: TOrgPlansTableDTO) => {
orgId,
actor,
actorId,
billingCycle
}: TOrgPlansTableDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const { data } = await licenseServerCloudApi.request.get( const { data } = await licenseServerCloudApi.request.get(
`/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}` `/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}`
); );
@@ -193,24 +186,15 @@ export const licenseServiceFactory = ({
const getOrgPlan = async ({ orgId, actor, actorId, projectId }: TOrgPlanDTO) => { const getOrgPlan = async ({ orgId, actor, actorId, projectId }: TOrgPlanDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const plan = await getPlan(orgId, projectId); const plan = await getPlan(orgId, projectId);
return plan; return plan;
}; };
const startOrgTrail = async ({ orgId, actorId, actor, success_url }: TStartOrgTrailDTO) => { const startOrgTrial = async ({ orgId, actorId, actor, success_url }: TStartOrgTrialDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Billing);
OrgPermissionActions.Create, ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing);
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -222,19 +206,63 @@ export const licenseServiceFactory = ({
const { const {
data: { url } data: { url }
} = await licenseServerCloudApi.request.post( } = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/session/trail`, `/api/license-server/v1/customers/${organization.customerId}/session/trial`,
{ success_url } { success_url }
); );
featureStore.del(FEATURE_CACHE_KEY(orgId)); featureStore.del(FEATURE_CACHE_KEY(orgId));
return { url }; return { url };
}; };
const createOrganizationPortalSession = async ({ orgId, actorId, actor }: TCreateOrgPortalSession) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Billing);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
throw new BadRequestError({
message: "Failed to find organization"
});
}
const {
data: { pmtMethods }
} = await licenseServerCloudApi.request.get<{ pmtMethods: string[] }>(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/payment-methods`
);
if (pmtMethods.length < 1) {
// case: organization has no payment method on file
// -> redirect to add payment method portal
const {
data: { url }
} = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/payment-methods`,
{
success_url: `${appCfg.SITE_URL}/dashboard`,
cancel_url: `${appCfg.SITE_URL}/dashboard`
}
);
return { url };
}
// case: organization has payment method on file
// -> redirect to billing portal
const {
data: { url }
} = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/billing-portal`,
{
return_url: `${appCfg.SITE_URL}/dashboard`
}
);
return { url };
};
const getOrgBillingInfo = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => { const getOrgBillingInfo = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -251,10 +279,7 @@ export const licenseServiceFactory = ({
// returns org current plan feature table // returns org current plan feature table
const getOrgPlanTable = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => { const getOrgPlanTable = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -270,10 +295,7 @@ export const licenseServiceFactory = ({
const getOrgBillingDetails = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => { const getOrgBillingDetails = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -288,18 +310,9 @@ export const licenseServiceFactory = ({
return data; return data;
}; };
const updateOrgBillingDetails = async ({ const updateOrgBillingDetails = async ({ actorId, actor, orgId, name, email }: TUpdateOrgBillingDetailsDTO) => {
actorId,
actor,
orgId,
name,
email
}: TUpdateOrgBillingDetailsDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -319,10 +332,7 @@ export const licenseServiceFactory = ({
const getOrgPmtMethods = async ({ orgId, actor, actorId }: TOrgPmtMethodsDTO) => { const getOrgPmtMethods = async ({ orgId, actor, actorId }: TOrgPmtMethodsDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -339,18 +349,9 @@ export const licenseServiceFactory = ({
return pmtMethods; return pmtMethods;
}; };
const addOrgPmtMethods = async ({ const addOrgPmtMethods = async ({ orgId, actor, actorId, success_url, cancel_url }: TAddOrgPmtMethodDTO) => {
orgId,
actor,
actorId,
success_url,
cancel_url
}: TAddOrgPmtMethodDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -372,10 +373,7 @@ export const licenseServiceFactory = ({
const delOrgPmtMethods = async ({ actorId, actor, orgId, pmtMethodId }: TDelOrgPmtMethodDTO) => { const delOrgPmtMethods = async ({ actorId, actor, orgId, pmtMethodId }: TDelOrgPmtMethodDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -392,10 +390,7 @@ export const licenseServiceFactory = ({
const getOrgTaxIds = async ({ orgId, actor, actorId }: TGetOrgTaxIdDTO) => { const getOrgTaxIds = async ({ orgId, actor, actorId }: TGetOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -413,10 +408,7 @@ export const licenseServiceFactory = ({
const addOrgTaxId = async ({ actorId, actor, orgId, type, value }: TAddOrgTaxIdDTO) => { const addOrgTaxId = async ({ actorId, actor, orgId, type, value }: TAddOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -437,10 +429,7 @@ export const licenseServiceFactory = ({
const delOrgTaxId = async ({ orgId, actor, actorId, taxId }: TDelOrgTaxIdDTO) => { const delOrgTaxId = async ({ orgId, actor, actorId, taxId }: TDelOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -457,10 +446,7 @@ export const licenseServiceFactory = ({
const getOrgTaxInvoices = async ({ actorId, actor, orgId }: TOrgInvoiceDTO) => { const getOrgTaxInvoices = async ({ actorId, actor, orgId }: TOrgInvoiceDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -471,18 +457,13 @@ export const licenseServiceFactory = ({
const { const {
data: { invoices } data: { invoices }
} = await licenseServerCloudApi.request.get( } = await licenseServerCloudApi.request.get(`/api/license-server/v1/customers/${organization.customerId}/invoices`);
`/api/license-server/v1/customers/${organization.customerId}/invoices`
);
return invoices; return invoices;
}; };
const getOrgLicenses = async ({ orgId, actor, actorId }: TOrgLicensesDTO) => { const getOrgLicenses = async ({ orgId, actor, actorId }: TOrgLicensesDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) { if (!organization) {
@@ -493,9 +474,7 @@ export const licenseServiceFactory = ({
const { const {
data: { licenses } data: { licenses }
} = await licenseServerCloudApi.request.get( } = await licenseServerCloudApi.request.get(`/api/license-server/v1/customers/${organization.customerId}/licenses`);
`/api/license-server/v1/customers/${organization.customerId}/licenses`
);
return licenses; return licenses;
}; };
@@ -511,7 +490,8 @@ export const licenseServiceFactory = ({
refreshPlan, refreshPlan,
getOrgPlan, getOrgPlan,
getOrgPlansTableByBillCycle, getOrgPlansTableByBillCycle,
startOrgTrail, startOrgTrial,
createOrganizationPortalSession,
getOrgBillingInfo, getOrgBillingInfo,
getOrgPlanTable, getOrgPlanTable,
getOrgBillingDetails, getOrgBillingDetails,
@@ -40,10 +40,12 @@ export type TOrgPlanDTO = {
projectId?: string; projectId?: string;
} & TOrgPermission; } & TOrgPermission;
export type TStartOrgTrailDTO = { export type TStartOrgTrialDTO = {
success_url: string; success_url: string;
} & TOrgPermission; } & TOrgPermission;
export type TCreateOrgPortalSession = TOrgPermission;
export type TGetOrgBillInfoDTO = TOrgPermission; export type TGetOrgBillInfoDTO = TOrgPermission;
export type TOrgPlanTableDTO = TOrgPermission; export type TOrgPlanTableDTO = TOrgPermission;
@@ -9,11 +9,7 @@ export const permissionDALFactory = (db: TDbClient) => {
const getOrgPermission = async (userId: string, orgId: string) => { const getOrgPermission = async (userId: string, orgId: string) => {
try { try {
const membership = await db(TableName.OrgMembership) const membership = await db(TableName.OrgMembership)
.leftJoin( .leftJoin(TableName.OrgRoles, `${TableName.OrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
TableName.OrgRoles,
`${TableName.OrgMembership}.roleId`,
`${TableName.OrgRoles}.id`
)
.where("userId", userId) .where("userId", userId)
.where(`${TableName.OrgMembership}.orgId`, orgId) .where(`${TableName.OrgMembership}.orgId`, orgId)
.select("permissions") .select("permissions")
@@ -29,11 +25,7 @@ export const permissionDALFactory = (db: TDbClient) => {
const getOrgIdentityPermission = async (identityId: string, orgId: string) => { const getOrgIdentityPermission = async (identityId: string, orgId: string) => {
try { try {
const membership = await db(TableName.IdentityOrgMembership) const membership = await db(TableName.IdentityOrgMembership)
.leftJoin( .leftJoin(TableName.OrgRoles, `${TableName.IdentityOrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
TableName.OrgRoles,
`${TableName.IdentityOrgMembership}.roleId`,
`${TableName.OrgRoles}.id`
)
.where("identityId", identityId) .where("identityId", identityId)
.where(`${TableName.IdentityOrgMembership}.orgId`, orgId) .where(`${TableName.IdentityOrgMembership}.orgId`, orgId)
.select(selectAllTableCols(TableName.IdentityOrgMembership)) .select(selectAllTableCols(TableName.IdentityOrgMembership))
@@ -48,11 +40,7 @@ export const permissionDALFactory = (db: TDbClient) => {
const getProjectPermission = async (userId: string, projectId: string) => { const getProjectPermission = async (userId: string, projectId: string) => {
try { try {
const membership = await db(TableName.ProjectMembership) const membership = await db(TableName.ProjectMembership)
.leftJoin( .leftJoin(TableName.ProjectRoles, `${TableName.ProjectMembership}.roleId`, `${TableName.ProjectRoles}.id`)
TableName.ProjectRoles,
`${TableName.ProjectMembership}.roleId`,
`${TableName.ProjectRoles}.id`
)
.where("userId", userId) .where("userId", userId)
.where(`${TableName.ProjectMembership}.projectId`, projectId) .where(`${TableName.ProjectMembership}.projectId`, projectId)
.select(selectAllTableCols(TableName.ProjectMembership)) .select(selectAllTableCols(TableName.ProjectMembership))
@@ -16,12 +16,7 @@ import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal";
import { TProjectRoleDALFactory } from "@app/services/project-role/project-role-dal"; import { TProjectRoleDALFactory } from "@app/services/project-role/project-role-dal";
import { TServiceTokenDALFactory } from "@app/services/service-token/service-token-dal"; import { TServiceTokenDALFactory } from "@app/services/service-token/service-token-dal";
import { import { orgAdminPermissions, orgMemberPermissions, orgNoAccessPermissions, OrgPermissionSet } from "./org-permission";
orgAdminPermissions,
orgMemberPermissions,
orgNoAccessPermissions,
OrgPermissionSet
} from "./org-permission";
import { TPermissionDALFactory } from "./permission-dal"; import { TPermissionDALFactory } from "./permission-dal";
import { import {
buildServiceTokenProjectPermission, buildServiceTokenProjectPermission,
@@ -188,9 +183,9 @@ export const permissionServiceFactory = ({
? { permission: MongoAbility<ProjectPermissionSet, MongoQuery>; membership: undefined } ? { permission: MongoAbility<ProjectPermissionSet, MongoQuery>; membership: undefined }
: { : {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>; permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
membership: (T extends ActorType.USER membership: (T extends ActorType.USER ? TProjectMemberships : TIdentityProjectMemberships) & {
? TProjectMemberships permissions?: unknown;
: TIdentityProjectMemberships) & { permissions?: unknown }; };
}; };
const getProjectPermission = async <T extends ActorType>( const getProjectPermission = async <T extends ActorType>(
@@ -214,9 +209,7 @@ export const permissionServiceFactory = ({
}; };
const getProjectPermissionByRole = async (role: string, projectId: string) => { const getProjectPermissionByRole = async (role: string, projectId: string) => {
const isCustomRole = !Object.values(ProjectMembershipRole).includes( const isCustomRole = !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole);
role as ProjectMembershipRole
);
if (isCustomRole) { if (isCustomRole) {
const projectRole = await projectRoleDAL.findOne({ slug: role, projectId }); const projectRole = await projectRoleDAL.findOne({ slug: role, projectId });
if (!projectRole) throw new BadRequestError({ message: "Role not found" }); if (!projectRole) throw new BadRequestError({ message: "Role not found" });
@@ -239,17 +239,29 @@ export const buildServiceTokenProjectPermission = (
const { can, build } = new AbilityBuilder<MongoAbility<ProjectPermissionSet>>(createMongoAbility); const { can, build } = new AbilityBuilder<MongoAbility<ProjectPermissionSet>>(createMongoAbility);
scopes.forEach(({ secretPath, environment }) => { scopes.forEach(({ secretPath, environment }) => {
if (canWrite) { if (canWrite) {
// TODO: @Akhi // TODO: @Akhi
// @ts-expect-error type // @ts-expect-error type
can(ProjectPermissionActions.Edit, ProjectPermissionSub.Secrets, { secretPath: { $glob: secretPath }, environment }); can(ProjectPermissionActions.Edit, ProjectPermissionSub.Secrets, {
// @ts-expect-error type secretPath: { $glob: secretPath },
can(ProjectPermissionActions.Create, ProjectPermissionSub.Secrets, { secretPath: { $glob: secretPath }, environment }); environment
// @ts-expect-error type });
can(ProjectPermissionActions.Delete, ProjectPermissionSub.Secrets, {secretPath: { $glob: secretPath }, environment }); // @ts-expect-error type
can(ProjectPermissionActions.Create, ProjectPermissionSub.Secrets, {
secretPath: { $glob: secretPath },
environment
});
// @ts-expect-error type
can(ProjectPermissionActions.Delete, ProjectPermissionSub.Secrets, {
secretPath: { $glob: secretPath },
environment
});
} }
if (canRead) { if (canRead) {
// @ts-expect-error type // @ts-expect-error type
can(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets, { secretPath: { $glob: secretPath }, environment }); can(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets, {
secretPath: { $glob: secretPath },
environment
});
} }
}); });
@@ -258,6 +270,8 @@ export const buildServiceTokenProjectPermission = (
export const projectNoAccessPermissions = buildNoAccessProjectPermission(); export const projectNoAccessPermissions = buildNoAccessProjectPermission();
/* eslint-disable */
/** /**
* Extracts and formats permissions from a CASL Ability object or a raw permission set. * Extracts and formats permissions from a CASL Ability object or a raw permission set.
* @param ability * @param ability
@@ -287,3 +301,5 @@ export const isAtLeastAsPrivilegedWorkspace = (
return set1.size >= set2.size; return set1.size >= set2.size;
}; };
/* eslint-enable */
@@ -38,10 +38,7 @@ import {
type TSamlConfigServiceFactoryDep = { type TSamlConfigServiceFactoryDep = {
samlConfigDAL: TSamlConfigDALFactory; samlConfigDAL: TSamlConfigDALFactory;
userDAL: Pick<TUserDALFactory, "create" | "findUserByEmail" | "transaction" | "updateById">; userDAL: Pick<TUserDALFactory, "create" | "findUserByEmail" | "transaction" | "updateById">;
orgDAL: Pick< orgDAL: Pick<TOrgDALFactory, "createMembership" | "updateMembershipById" | "findMembership" | "findOrgById">;
TOrgDALFactory,
"createMembership" | "updateMembershipById" | "findMembership" | "findOrgById"
>;
orgBotDAL: Pick<TOrgBotDALFactory, "findOne" | "create" | "transaction">; orgBotDAL: Pick<TOrgBotDALFactory, "findOne" | "create" | "transaction">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">; licenseService: Pick<TLicenseServiceFactory, "getPlan">;
@@ -68,10 +65,7 @@ export const samlConfigServiceFactory = ({
authProvider authProvider
}: TCreateSamlCfgDTO) => { }: TCreateSamlCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Sso);
OrgPermissionActions.Create,
OrgPermissionSubjects.Sso
);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
if (!plan.samlSSO) if (!plan.samlSSO)
@@ -128,16 +122,8 @@ export const samlConfigServiceFactory = ({
keyEncoding: orgBot.symmetricKeyKeyEncoding as SecretKeyEncoding keyEncoding: orgBot.symmetricKeyKeyEncoding as SecretKeyEncoding
}); });
const { const { ciphertext: encryptedEntryPoint, iv: entryPointIV, tag: entryPointTag } = encryptSymmetric(entryPoint, key);
ciphertext: encryptedEntryPoint, const { ciphertext: encryptedIssuer, iv: issuerIV, tag: issuerTag } = encryptSymmetric(issuer, key);
iv: entryPointIV,
tag: entryPointTag
} = encryptSymmetric(entryPoint, key);
const {
ciphertext: encryptedIssuer,
iv: issuerIV,
tag: issuerTag
} = encryptSymmetric(issuer, key);
const { ciphertext: encryptedCert, iv: certIV, tag: certTag } = encryptSymmetric(cert, key); const { ciphertext: encryptedCert, iv: certIV, tag: certTag } = encryptSymmetric(cert, key);
const samlConfig = await samlConfigDAL.create({ const samlConfig = await samlConfigDAL.create({
@@ -168,10 +154,7 @@ export const samlConfigServiceFactory = ({
authProvider authProvider
}: TUpdateSamlCfgDTO) => { }: TUpdateSamlCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso);
OrgPermissionActions.Edit,
OrgPermissionSubjects.Sso
);
const plan = await licenseService.getPlan(orgId); const plan = await licenseService.getPlan(orgId);
if (!plan.samlSSO) if (!plan.samlSSO)
throw new BadRequestError({ throw new BadRequestError({
@@ -181,8 +164,7 @@ export const samlConfigServiceFactory = ({
const updateQuery: TSamlConfigsUpdate = { authProvider, isActive }; const updateQuery: TSamlConfigsUpdate = { authProvider, isActive };
const orgBot = await orgBotDAL.findOne({ orgId }); const orgBot = await orgBotDAL.findOne({ orgId });
if (!orgBot) if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
const key = infisicalSymmetricDecrypt({ const key = infisicalSymmetricDecrypt({
ciphertext: orgBot.encryptedSymmetricKey, ciphertext: orgBot.encryptedSymmetricKey,
iv: orgBot.symmetricKeyIV, iv: orgBot.symmetricKeyIV,
@@ -201,11 +183,7 @@ export const samlConfigServiceFactory = ({
updateQuery.entryPointTag = entryPointTag; updateQuery.entryPointTag = entryPointTag;
} }
if (issuer) { if (issuer) {
const { const { ciphertext: encryptedIssuer, iv: issuerIV, tag: issuerTag } = encryptSymmetric(issuer, key);
ciphertext: encryptedIssuer,
iv: issuerIV,
tag: issuerTag
} = encryptSymmetric(issuer, key);
updateQuery.encryptedIssuer = encryptedIssuer; updateQuery.encryptedIssuer = encryptedIssuer;
updateQuery.issuerIV = issuerIV; updateQuery.issuerIV = issuerIV;
updateQuery.issuerTag = issuerTag; updateQuery.issuerTag = issuerTag;
@@ -239,9 +217,9 @@ export const samlConfigServiceFactory = ({
"64f23239a5d4ed17f1e544c4": "9256337f-e3da-43d7-8266-39c9276e8426", "64f23239a5d4ed17f1e544c4": "9256337f-e3da-43d7-8266-39c9276e8426",
"65348e49db355e6e4782571f": "b8a227c7-843e-410e-8982-b4976a599b69", "65348e49db355e6e4782571f": "b8a227c7-843e-410e-8982-b4976a599b69",
"657a219fc8a80c2eff97eb38": "fcab1573-ae7f-4fcf-9645-646207acf035" "657a219fc8a80c2eff97eb38": "fcab1573-ae7f-4fcf-9645-646207acf035"
}; };
const id = UUIDToMongoId[dto.id] ?? dto.id const id = UUIDToMongoId[dto.id] ?? dto.id;
ssoConfig = await samlConfigDAL.findById(id); ssoConfig = await samlConfigDAL.findById(id);
} }
@@ -249,15 +227,8 @@ export const samlConfigServiceFactory = ({
// when dto is type id means it's internally used // when dto is type id means it's internally used
if (dto.type === "org") { if (dto.type === "org") {
const { permission } = await permissionService.getOrgPermission( const { permission } = await permissionService.getOrgPermission(dto.actor, dto.actorId, ssoConfig.orgId);
dto.actor, ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso);
dto.actorId,
ssoConfig!.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Sso
);
} }
const { const {
entryPointTag, entryPointTag,
@@ -272,8 +243,7 @@ export const samlConfigServiceFactory = ({
} = ssoConfig; } = ssoConfig;
const orgBot = await orgBotDAL.findOne({ orgId: ssoConfig.orgId }); const orgBot = await orgBotDAL.findOne({ orgId: ssoConfig.orgId });
if (!orgBot) if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
const key = infisicalSymmetricDecrypt({ const key = infisicalSymmetricDecrypt({
ciphertext: orgBot.encryptedSymmetricKey, ciphertext: orgBot.encryptedSymmetricKey,
iv: orgBot.symmetricKeyIV, iv: orgBot.symmetricKeyIV,
@@ -330,8 +300,7 @@ export const samlConfigServiceFactory = ({
const appCfg = getConfig(); const appCfg = getConfig();
let user = await userDAL.findUserByEmail(email); let user = await userDAL.findUserByEmail(email);
const isSamlSignUpDisabled = !isSignupAllowed && !user; const isSamlSignUpDisabled = !isSignupAllowed && !user;
if (isSamlSignUpDisabled) if (isSamlSignUpDisabled) throw new BadRequestError({ message: "User signup disabled", name: "Saml SSO login" });
throw new BadRequestError({ message: "User signup disabled", name: "Saml SSO login" });
const organization = await orgDAL.findOrgById(orgId); const organization = await orgDAL.findOrgById(orgId);
if (!organization) throw new BadRequestError({ message: "Org not found" }); if (!organization) throw new BadRequestError({ message: "Org not found" });
@@ -400,7 +369,7 @@ export const samlConfigServiceFactory = ({
isUserCompleted, isUserCompleted,
...(relayState ...(relayState
? { ? {
callbackPort: JSON.parse(relayState).callbackPort as string callbackPort: (JSON.parse(relayState) as { callbackPort: string }).callbackPort
} }
: {}) : {})
}, },
@@ -2,9 +2,7 @@ import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas"; import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex"; import { ormify } from "@app/lib/knex";
export type TSecretApprovalPolicyApproverDALFactory = ReturnType< export type TSecretApprovalPolicyApproverDALFactory = ReturnType<typeof secretApprovalPolicyApproverDALFactory>;
typeof secretApprovalPolicyApproverDALFactory
>;
export const secretApprovalPolicyApproverDALFactory = (db: TDbClient) => { export const secretApprovalPolicyApproverDALFactory = (db: TDbClient) => {
const sapApproverOrm = ormify(db, TableName.SecretApprovalPolicyApprover); const sapApproverOrm = ormify(db, TableName.SecretApprovalPolicyApprover);
@@ -3,13 +3,7 @@ import { Knex } from "knex";
import { TDbClient } from "@app/db"; import { TDbClient } from "@app/db";
import { TableName, TSecretApprovalPolicies } from "@app/db/schemas"; import { TableName, TSecretApprovalPolicies } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors"; import { DatabaseError } from "@app/lib/errors";
import { import { buildFindFilter, mergeOneToManyRelation, ormify, selectAllTableCols, TFindFilter } from "@app/lib/knex";
buildFindFilter,
mergeOneToManyRelation,
ormify,
selectAllTableCols,
TFindFilter
} from "@app/lib/knex";
export type TSecretApprovalPolicyDALFactory = ReturnType<typeof secretApprovalPolicyDALFactory>; export type TSecretApprovalPolicyDALFactory = ReturnType<typeof secretApprovalPolicyDALFactory>;
@@ -18,12 +12,9 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
const sapFindQuery = (tx: Knex, filter: TFindFilter<TSecretApprovalPolicies>) => const sapFindQuery = (tx: Knex, filter: TFindFilter<TSecretApprovalPolicies>) =>
tx(TableName.SecretApprovalPolicy) tx(TableName.SecretApprovalPolicy)
// eslint-disable-next-line
.where(buildFindFilter(filter)) .where(buildFindFilter(filter))
.join( .join(TableName.Environment, `${TableName.SecretApprovalPolicy}.envId`, `${TableName.Environment}.id`)
TableName.Environment,
`${TableName.SecretApprovalPolicy}.envId`,
`${TableName.Environment}.id`
)
.join( .join(
TableName.SecretApprovalPolicyApprover, TableName.SecretApprovalPolicyApprover,
`${TableName.SecretApprovalPolicy}.id`, `${TableName.SecretApprovalPolicy}.id`,
@@ -59,10 +50,7 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
} }
}; };
const find = async ( const find = async (filter: TFindFilter<TSecretApprovalPolicies & { projectId: string }>, tx?: Knex) => {
filter: TFindFilter<TSecretApprovalPolicies & { projectId: string }>,
tx?: Knex
) => {
try { try {
const docs = await sapFindQuery(tx || db, filter); const docs = await sapFindQuery(tx || db, filter);
const formatedDoc = mergeOneToManyRelation( const formatedDoc = mergeOneToManyRelation(
@@ -2,10 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability";
import picomatch from "picomatch"; import picomatch from "picomatch";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
ProjectPermissionActions,
ProjectPermissionSub
} from "@app/ee/services/permission/project-permission";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { containsGlobPatterns } from "@app/lib/picomatch"; import { containsGlobPatterns } from "@app/lib/picomatch";
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal"; import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
@@ -34,9 +31,7 @@ type TSecretApprovalPolicyServiceFactoryDep = {
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find">; projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find">;
}; };
export type TSecretApprovalPolicyServiceFactory = ReturnType< export type TSecretApprovalPolicyServiceFactory = ReturnType<typeof secretApprovalPolicyServiceFactory>;
typeof secretApprovalPolicyServiceFactory
>;
export const secretApprovalPolicyServiceFactory = ({ export const secretApprovalPolicyServiceFactory = ({
secretApprovalPolicyDAL, secretApprovalPolicyDAL,
@@ -105,18 +100,10 @@ export const secretApprovalPolicyServiceFactory = ({
secretPolicyId secretPolicyId
}: TUpdateSapDTO) => { }: TUpdateSapDTO) => {
const secretApprovalPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId); const secretApprovalPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId);
if (!secretApprovalPolicy) if (!secretApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
throw new BadRequestError({ message: "Secret approval policy not found" });
const { permission } = await permissionService.getProjectPermission( const { permission } = await permissionService.getProjectPermission(actor, actorId, secretApprovalPolicy.projectId);
actor, ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval);
actorId,
secretApprovalPolicy.projectId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.SecretApproval
);
const updatedSap = await secretApprovalPolicyDAL.transaction(async (tx) => { const updatedSap = await secretApprovalPolicyDAL.transaction(async (tx) => {
const doc = await secretApprovalPolicyDAL.updateById( const doc = await secretApprovalPolicyDAL.updateById(
@@ -162,11 +149,7 @@ export const secretApprovalPolicyServiceFactory = ({
const sapPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId); const sapPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId);
if (!sapPolicy) throw new BadRequestError({ message: "Secret approval policy not found" }); if (!sapPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
const { permission } = await permissionService.getProjectPermission( const { permission } = await permissionService.getProjectPermission(actor, actorId, sapPolicy.projectId);
actor,
actorId,
sapPolicy.projectId
);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
ProjectPermissionSub.SecretApproval ProjectPermissionSub.SecretApproval
@@ -178,20 +161,13 @@ export const secretApprovalPolicyServiceFactory = ({
const getSecretApprovalPolicyByProjectId = async ({ actorId, actor, projectId }: TListSapDTO) => { const getSecretApprovalPolicyByProjectId = async ({ actorId, actor, projectId }: TListSapDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretApproval
);
const sapPolicies = await secretApprovalPolicyDAL.find({ projectId }); const sapPolicies = await secretApprovalPolicyDAL.find({ projectId });
return sapPolicies; return sapPolicies;
}; };
const getSecretApprovalPolicy = async ( const getSecretApprovalPolicy = async (projectId: string, environment: string, secretPath: string) => {
projectId: string,
environment: string,
secretPath: string
) => {
const env = await projectEnvDAL.findOne({ slug: environment, projectId }); const env = await projectEnvDAL.findOne({ slug: environment, projectId });
if (!env) throw new BadRequestError({ message: "Environment not found" }); if (!env) throw new BadRequestError({ message: "Environment not found" });
@@ -199,14 +175,11 @@ export const secretApprovalPolicyServiceFactory = ({
if (!policies.length) return; if (!policies.length) return;
// this will filter policies either without scoped to secret path or the one that matches with secret path // this will filter policies either without scoped to secret path or the one that matches with secret path
const policiesFilteredByPath = policies.filter( const policiesFilteredByPath = policies.filter(
({ secretPath: policyPath }) => ({ secretPath: policyPath }) => !policyPath || picomatch.isMatch(secretPath, policyPath, { strictSlashes: false })
!policyPath || picomatch.isMatch(secretPath, policyPath, { strictSlashes: false })
); );
// now sort by priority. exact secret path gets first match followed by glob followed by just env scoped // now sort by priority. exact secret path gets first match followed by glob followed by just env scoped
// if that is tie get by first createdAt // if that is tie get by first createdAt
const policiesByPriority = policiesFilteredByPath.sort( const policiesByPriority = policiesFilteredByPath.sort((a, b) => getPolicyScore(b) - getPolicyScore(a));
(a, b) => getPolicyScore(b) - getPolicyScore(a)
);
const finalPolicy = policiesByPriority.shift(); const finalPolicy = policiesByPriority.shift();
return finalPolicy; return finalPolicy;
}; };
@@ -1,15 +1,14 @@
import { Knex } from "knex"; import { Knex } from "knex";
import { TDbClient } from "@app/db"; import { TDbClient } from "@app/db";
import { SecretApprovalRequestsSchema, TableName, TSecretApprovalRequests } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { import {
ormify, SecretApprovalRequestsSchema,
selectAllTableCols, TableName,
sqlNestRelationships, TSecretApprovalRequests,
stripUndefinedInWhere, TSecretApprovalRequestsSecrets
TFindFilter } from "@app/db/schemas";
} from "@app/lib/knex"; import { DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols, sqlNestRelationships, stripUndefinedInWhere, TFindFilter } from "@app/lib/knex";
import { RequestState } from "./secret-approval-request-types"; import { RequestState } from "./secret-approval-request-types";
@@ -31,11 +30,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
const findQuery = (filter: TFindFilter<TSecretApprovalRequests>, tx: Knex) => const findQuery = (filter: TFindFilter<TSecretApprovalRequests>, tx: Knex) =>
tx(TableName.SecretApprovalRequest) tx(TableName.SecretApprovalRequest)
.where(filter) .where(filter)
.join( .join(TableName.SecretFolder, `${TableName.SecretApprovalRequest}.folderId`, `${TableName.SecretFolder}.id`)
TableName.SecretFolder,
`${TableName.SecretApprovalRequest}.folderId`,
`${TableName.SecretFolder}.id`
)
.join(TableName.Environment, `${TableName.SecretFolder}.envId`, `${TableName.Environment}.id`) .join(TableName.Environment, `${TableName.SecretFolder}.envId`, `${TableName.Environment}.id`)
.join( .join(
TableName.SecretApprovalPolicy, TableName.SecretApprovalPolicy,
@@ -87,8 +82,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
{ {
key: "reviewerMemberId", key: "reviewerMemberId",
label: "reviewers" as const, label: "reviewers" as const,
mapper: ({ reviewerMemberId: member, reviewerStatus: status }) => mapper: ({ reviewerMemberId: member, reviewerStatus: status }) => (member ? { member, status } : undefined)
member ? { member, status } : undefined
}, },
{ key: "approverId", label: "approvers" as const, mapper: ({ approverId }) => approverId } { key: "approverId", label: "approvers" as const, mapper: ({ approverId }) => approverId }
] ]
@@ -109,26 +103,19 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
.with( .with(
"temp", "temp",
(tx || db)(TableName.SecretApprovalRequest) (tx || db)(TableName.SecretApprovalRequest)
.join( .join(TableName.SecretFolder, `${TableName.SecretApprovalRequest}.folderId`, `${TableName.SecretFolder}.id`)
TableName.SecretFolder, .join(TableName.Environment, `${TableName.SecretFolder}.envId`, `${TableName.Environment}.id`)
`${TableName.SecretApprovalRequest}.folderId`,
`${TableName.SecretFolder}.id`
)
.join(
TableName.Environment,
`${TableName.SecretFolder}.envId`,
`${TableName.Environment}.id`
)
.join( .join(
TableName.SecretApprovalPolicyApprover, TableName.SecretApprovalPolicyApprover,
`${TableName.SecretApprovalRequest}.policyId`, `${TableName.SecretApprovalRequest}.policyId`,
`${TableName.SecretApprovalPolicyApprover}.policyId` `${TableName.SecretApprovalPolicyApprover}.policyId`
) )
.where({ projectId }) .where({ projectId })
.andWhere((bd) => .andWhere(
bd (bd) =>
.where(`${TableName.SecretApprovalPolicyApprover}.approverId`, membershipId) void bd
.orWhere(`${TableName.SecretApprovalRequest}.committerId`, membershipId) .where(`${TableName.SecretApprovalPolicyApprover}.approverId`, membershipId)
.orWhere(`${TableName.SecretApprovalRequest}.committerId`, membershipId)
) )
.select("status", `${TableName.SecretApprovalRequest}.id`) .select("status", `${TableName.SecretApprovalRequest}.id`)
.groupBy(`${TableName.SecretApprovalRequest}.id`, "status") .groupBy(`${TableName.SecretApprovalRequest}.id`, "status")
@@ -141,11 +128,11 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
return { return {
open: parseInt( open: parseInt(
(docs.find(({ status }) => status === RequestState.Open)?.count as string) || "0", (docs.find(({ status }) => status === RequestState.Open) as { count: string })?.count || "0",
10 10
), ),
closed: parseInt( closed: parseInt(
(docs.find(({ status }) => status === RequestState.Closed)?.count as string) || "0", (docs.find(({ status }) => status === RequestState.Closed) as { count: string })?.count || "0",
10 10
) )
}; };
@@ -155,31 +142,15 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
}; };
const findByProjectId = async ( const findByProjectId = async (
{ { status, limit = 20, offset = 0, projectId, committer, environment, membershipId }: TFindQueryFilter,
status,
limit = 20,
offset = 0,
projectId,
committer,
environment,
membershipId
}: TFindQueryFilter,
tx?: Knex tx?: Knex
) => { ) => {
try { try {
// akhilmhdh: If ever u wanted a 1 to so many relationship connected with pagination // akhilmhdh: If ever u wanted a 1 to so many relationship connected with pagination
// this is the place u wanna look at. // this is the place u wanna look at.
const query = (tx || db)(TableName.SecretApprovalRequest) const query = (tx || db)(TableName.SecretApprovalRequest)
.join( .join(TableName.SecretFolder, `${TableName.SecretApprovalRequest}.folderId`, `${TableName.SecretFolder}.id`)
TableName.SecretFolder, .join(TableName.Environment, `${TableName.SecretFolder}.envId`, `${TableName.Environment}.id`)
`${TableName.SecretApprovalRequest}.folderId`,
`${TableName.SecretFolder}.id`
)
.join(
TableName.Environment,
`${TableName.SecretFolder}.envId`,
`${TableName.Environment}.id`
)
.join( .join(
TableName.SecretApprovalPolicy, TableName.SecretApprovalPolicy,
`${TableName.SecretApprovalRequest}.policyId`, `${TableName.SecretApprovalRequest}.policyId`,
@@ -195,7 +166,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
`${TableName.SecretApprovalRequest}.id`, `${TableName.SecretApprovalRequest}.id`,
`${TableName.SecretApprovalRequestReviewer}.requestId` `${TableName.SecretApprovalRequestReviewer}.requestId`
) )
.leftJoin( .leftJoin<TSecretApprovalRequestsSecrets>(
TableName.SecretApprovalRequestSecret, TableName.SecretApprovalRequestSecret,
`${TableName.SecretApprovalRequestSecret}.requestId`, `${TableName.SecretApprovalRequestSecret}.requestId`,
`${TableName.SecretApprovalRequest}.id` `${TableName.SecretApprovalRequest}.id`
@@ -208,10 +179,11 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
committerId: committer committerId: committer
}) })
) )
.andWhere((bd) => .andWhere(
bd (bd) =>
.where(`${TableName.SecretApprovalPolicyApprover}.approverId`, membershipId) void bd
.orWhere(`${TableName.SecretApprovalRequest}.committerId`, membershipId) .where(`${TableName.SecretApprovalPolicyApprover}.approverId`, membershipId)
.orWhere(`${TableName.SecretApprovalRequest}.committerId`, membershipId)
) )
.select(selectAllTableCols(TableName.SecretApprovalRequest)) .select(selectAllTableCols(TableName.SecretApprovalRequest))
.select( .select(
@@ -257,8 +229,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
{ {
key: "reviewerMemberId", key: "reviewerMemberId",
label: "reviewers" as const, label: "reviewers" as const,
mapper: ({ reviewerMemberId: member, reviewerStatus: s }) => mapper: ({ reviewerMemberId: member, reviewerStatus: s }) => (member ? { member, status: s } : undefined)
member ? { member, status: s } : undefined
}, },
{ {
key: "approverId", key: "approverId",
@@ -2,9 +2,7 @@ import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas"; import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex"; import { ormify } from "@app/lib/knex";
export type TSecretApprovalRequestReviewerDALFactory = ReturnType< export type TSecretApprovalRequestReviewerDALFactory = ReturnType<typeof secretApprovalRequestReviewerDALFactory>;
typeof secretApprovalRequestReviewerDALFactory
>;
export const secretApprovalRequestReviewerDALFactory = (db: TDbClient) => { export const secretApprovalRequestReviewerDALFactory = (db: TDbClient) => {
const secretApprovalRequestReviewerOrm = ormify(db, TableName.SecretApprovalRequestReviewer); const secretApprovalRequestReviewerOrm = ormify(db, TableName.SecretApprovalRequestReviewer);
@@ -1,13 +1,11 @@
import { Knex } from "knex"; import { Knex } from "knex";
import { TDbClient } from "@app/db"; import { TDbClient } from "@app/db";
import { SecretApprovalRequestsSecretsSchema, TableName } from "@app/db/schemas"; import { SecretApprovalRequestsSecretsSchema, TableName, TSecretTags } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors"; import { DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex"; import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
export type TSecretApprovalRequestSecretDALFactory = ReturnType< export type TSecretApprovalRequestSecretDALFactory = ReturnType<typeof secretApprovalRequestSecretDALFactory>;
typeof secretApprovalRequestSecretDALFactory
>;
export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => { export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
const secretApprovalRequestSecretOrm = ormify(db, TableName.SecretApprovalRequestSecret); const secretApprovalRequestSecretOrm = ormify(db, TableName.SecretApprovalRequestSecret);
@@ -25,16 +23,8 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
`${TableName.SecretApprovalRequestSecret}.id`, `${TableName.SecretApprovalRequestSecret}.id`,
`${TableName.SecretApprovalRequestSecretTag}.secretId` `${TableName.SecretApprovalRequestSecretTag}.secretId`
) )
.leftJoin( .leftJoin(TableName.SecretTag, `${TableName.SecretApprovalRequestSecretTag}.tagId`, `${TableName.SecretTag}.id`)
TableName.SecretTag, .leftJoin(TableName.Secret, `${TableName.SecretApprovalRequestSecret}.secretId`, `${TableName.Secret}.id`)
`${TableName.SecretApprovalRequestSecretTag}.tagId`,
`${TableName.SecretTag}.id`
)
.leftJoin(
TableName.Secret,
`${TableName.SecretApprovalRequestSecret}.secretId`,
`${TableName.Secret}.id`
)
.leftJoin( .leftJoin(
TableName.SecretVersion, TableName.SecretVersion,
`${TableName.SecretVersion}.id`, `${TableName.SecretVersion}.id`,
@@ -45,7 +35,7 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
`${TableName.SecretVersionTag}.${TableName.SecretVersion}Id`, `${TableName.SecretVersionTag}.${TableName.SecretVersion}Id`,
`${TableName.SecretVersion}.id` `${TableName.SecretVersion}.id`
) )
.leftJoin( .leftJoin<TSecretTags>(
db.ref(TableName.SecretTag).as("secVerTag"), db.ref(TableName.SecretTag).as("secVerTag"),
`${TableName.SecretVersionTag}.${TableName.SecretTag}Id`, `${TableName.SecretVersionTag}.${TableName.SecretTag}Id`,
db.ref("id").withSchema("secVerTag") db.ref("id").withSchema("secVerTag")
@@ -75,37 +65,24 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
db.ref("secretValueCiphertext").withSchema(TableName.Secret).as("orgSecValueCiphertext"), db.ref("secretValueCiphertext").withSchema(TableName.Secret).as("orgSecValueCiphertext"),
db.ref("secretCommentIV").withSchema(TableName.Secret).as("orgSecCommentIV"), db.ref("secretCommentIV").withSchema(TableName.Secret).as("orgSecCommentIV"),
db.ref("secretCommentTag").withSchema(TableName.Secret).as("orgSecCommentTag"), db.ref("secretCommentTag").withSchema(TableName.Secret).as("orgSecCommentTag"),
db db.ref("secretCommentCiphertext").withSchema(TableName.Secret).as("orgSecCommentCiphertext")
.ref("secretCommentCiphertext")
.withSchema(TableName.Secret)
.as("orgSecCommentCiphertext")
) )
.select( .select(
db.ref("version").withSchema(TableName.SecretVersion).as("secVerVersion"), db.ref("version").withSchema(TableName.SecretVersion).as("secVerVersion"),
db.ref("secretKeyIV").withSchema(TableName.SecretVersion).as("secVerKeyIV"), db.ref("secretKeyIV").withSchema(TableName.SecretVersion).as("secVerKeyIV"),
db.ref("secretKeyTag").withSchema(TableName.SecretVersion).as("secVerKeyTag"), db.ref("secretKeyTag").withSchema(TableName.SecretVersion).as("secVerKeyTag"),
db db.ref("secretKeyCiphertext").withSchema(TableName.SecretVersion).as("secVerKeyCiphertext"),
.ref("secretKeyCiphertext")
.withSchema(TableName.SecretVersion)
.as("secVerKeyCiphertext"),
db.ref("secretValueIV").withSchema(TableName.SecretVersion).as("secVerValueIV"), db.ref("secretValueIV").withSchema(TableName.SecretVersion).as("secVerValueIV"),
db.ref("secretValueTag").withSchema(TableName.SecretVersion).as("secVerValueTag"), db.ref("secretValueTag").withSchema(TableName.SecretVersion).as("secVerValueTag"),
db db.ref("secretValueCiphertext").withSchema(TableName.SecretVersion).as("secVerValueCiphertext"),
.ref("secretValueCiphertext")
.withSchema(TableName.SecretVersion)
.as("secVerValueCiphertext"),
db.ref("secretCommentIV").withSchema(TableName.SecretVersion).as("secVerCommentIV"), db.ref("secretCommentIV").withSchema(TableName.SecretVersion).as("secVerCommentIV"),
db.ref("secretCommentTag").withSchema(TableName.SecretVersion).as("secVerCommentTag"), db.ref("secretCommentTag").withSchema(TableName.SecretVersion).as("secVerCommentTag"),
db db.ref("secretCommentCiphertext").withSchema(TableName.SecretVersion).as("secVerCommentCiphertext")
.ref("secretCommentCiphertext")
.withSchema(TableName.SecretVersion)
.as("secVerCommentCiphertext")
); );
const formatedDoc = sqlNestRelationships({ const formatedDoc = sqlNestRelationships({
data: doc, data: doc,
key: "id", key: "id",
parentMapper: (data) => parentMapper: (data) => SecretApprovalRequestsSecretsSchema.omit({ secretVersion: true }).parse(data),
SecretApprovalRequestsSecretsSchema.omit({ secretVersion: true }).parse(data),
childrenMapper: [ childrenMapper: [
{ {
key: "tagJnId", key: "tagJnId",
@@ -186,15 +163,14 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
{ {
key: "secVerTagId", key: "secVerTagId",
label: "tags" as const, label: "tags" as const,
mapper: ({ mapper: ({ secVerTagId: id, secVerTagName: name, secVerTagSlug: slug, secVerTagColor: color }) => ({
secVerTagId: id, // eslint-disable-next-line
secVerTagName: name,
secVerTagSlug: slug,
secVerTagColor: color
}) => ({
id, id,
// eslint-disable-next-line
name, name,
// eslint-disable-next-line
slug, slug,
// eslint-disable-next-line
color color
}) })
} }

Some files were not shown because too many files have changed in this diff Show More