mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-22 15:06:12 +00:00
Compare commits
59 Commits
daniel/eve
...
infisical/
Author | SHA1 | Date | |
---|---|---|---|
9476594978 | |||
02be9ebd5e | |||
eb29d1dc28 | |||
114a4b1412 | |||
cde8cef8b0 | |||
7207997cea | |||
aaabfb7870 | |||
40cb5c4394 | |||
60b73879df | |||
4339ef4737 | |||
d98669700d | |||
162f339149 | |||
d3eb0c4cc9 | |||
4b4295f53d | |||
6c4d193b12 | |||
d08d412f54 | |||
bb4810470f | |||
24e9c0a39f | |||
3161d0ee67 | |||
8a7e18dc7c | |||
0497c3b49e | |||
e6a89fb9d0 | |||
d9828db2ec | |||
f11efc9e3f | |||
32bad10c0e | |||
41064920f7 | |||
8d8e23add2 | |||
a2a959cc32 | |||
d6cde48181 | |||
23966c12e2 | |||
2a233ea43c | |||
fe497d87c0 | |||
0c3060e1c6 | |||
5d64398e58 | |||
2f6f713c98 | |||
4f47d43801 | |||
6cf9a83c16 | |||
c3adc8b188 | |||
a723c456aa | |||
c455ef7ced | |||
f9d0680dc3 | |||
7a4e8b8c32 | |||
8e83b0f2dd | |||
59c6837071 | |||
d4d23e06a8 | |||
9d202e8501 | |||
1f9f15136e | |||
5d71b02f8d | |||
9d2a0f1d54 | |||
0f4da61aaa | |||
26abb7d89f | |||
892a25edfe | |||
3b9ceff21c | |||
d64d935d7d | |||
8aaed739d5 | |||
7d8b399102 | |||
1594165768 | |||
29d91d83ab | |||
4057e2c6ab |
.env.example
.github
backend
e2e-test
package-lock.jsonpackage.jsonscripts
src
@types
cache
db
migrations
schemas
api-keys.tsaudit-logs.tsauth-token-sessions.tsauth-tokens.tsbackup-private-key.tsgit-app-install-sessions.tsgit-app-org.tsidentities.tsidentity-access-tokens.tsidentity-org-memberships.tsidentity-project-memberships.tsidentity-ua-client-secrets.tsidentity-universal-auths.tsincident-contacts.tsintegration-auths.tsintegrations.tsorg-bots.tsorg-memberships.tsorg-roles.tsorganizations.tsproject-bots.tsproject-environments.tsproject-keys.tsproject-memberships.tsproject-roles.tsprojects.tssaml-configs.tsscim-tokens.tssecret-approval-policies-approvers.tssecret-approval-policies.tssecret-approval-request-secret-tags.tssecret-approval-requests-reviewers.tssecret-approval-requests-secrets.tssecret-approval-requests.tssecret-blind-indexes.tssecret-folder-versions.tssecret-folders.tssecret-imports.tssecret-rotation-outputs.tssecret-rotations.tssecret-scanning-git-risks.tssecret-snapshot-folders.tssecret-snapshot-secrets.tssecret-snapshots.tssecret-tag-junction.tssecret-tags.tssecret-version-tag-junction.tssecret-versions.tssecrets.tsservice-tokens.tssuper-admin.tstrusted-ips.tsuser-actions.tsuser-encryption-keys.tsusers.tswebhooks.ts
ee/services
license
secret-rotation/secret-rotation-queue
secret-scanning/secret-scanning-queue
event
keystore
lib/config
main.tsqueue
server
services
event
project-membership
secret-tag
super-admin
telemetry
cli/packages
docker-compose.dev.ymldocker-compose.prod.ymldocs
contributing/platform
documentation
getting-started
platform
images
platform/ldap/jumpcloud
self-hosting
integrations/platforms
mint.jsonself-hosting
frontend
package-lock.jsonpackage.json
src
components/v2/UpgradeProjectAlert
i18n.tsviews
SecretMainPage
Settings/PersonalSettingsPage/PersonalGeneralTab
helm-charts/infisical-standalone-postgres
nginx
pg-migrator/src
@ -19,10 +19,6 @@ POSTGRES_DB=infisical
|
||||
# Redis
|
||||
REDIS_URL=redis://redis:6379
|
||||
|
||||
# Optional credentials for MongoDB container instance and Mongo-Express
|
||||
MONGO_USERNAME=root
|
||||
MONGO_PASSWORD=example
|
||||
|
||||
# Website URL
|
||||
# Required
|
||||
SITE_URL=http://localhost:8080
|
||||
|
13
.github/values.yaml
vendored
13
.github/values.yaml
vendored
@ -13,11 +13,10 @@ fullnameOverride: ""
|
||||
##
|
||||
|
||||
infisical:
|
||||
## @param backend.enabled Enable backend
|
||||
##
|
||||
autoDatabaseSchemaMigration: false
|
||||
|
||||
enabled: false
|
||||
## @param backend.name Backend name
|
||||
##
|
||||
|
||||
name: infisical
|
||||
replicaCount: 3
|
||||
image:
|
||||
@ -50,3 +49,9 @@ ingress:
|
||||
- secretName: letsencrypt-prod
|
||||
hosts:
|
||||
- gamma.infisical.com
|
||||
|
||||
postgresql:
|
||||
enabled: false
|
||||
|
||||
redis:
|
||||
enabled: false
|
||||
|
30
backend/e2e-test/mocks/keystore.ts
Normal file
30
backend/e2e-test/mocks/keystore.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
|
||||
export const mockKeyStore = (): TKeyStoreFactory => {
|
||||
const store: Record<string, string | number | Buffer> = {};
|
||||
|
||||
return {
|
||||
setItem: async (key, value) => {
|
||||
store[key] = value;
|
||||
return "OK";
|
||||
},
|
||||
setItemWithExpiry: async (key, value) => {
|
||||
store[key] = value;
|
||||
return "OK";
|
||||
},
|
||||
deleteItem: async (key) => {
|
||||
delete store[key];
|
||||
return 1;
|
||||
},
|
||||
getItem: async (key) => {
|
||||
const value = store[key];
|
||||
if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
incrementBy: async () => {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
};
|
@ -14,6 +14,7 @@ import { AuthTokenType } from "@app/services/auth/auth-type";
|
||||
|
||||
import { mockQueue } from "./mocks/queue";
|
||||
import { mockSmtpServer } from "./mocks/smtp";
|
||||
import { mockKeyStore } from "./mocks/keystore";
|
||||
|
||||
dotenv.config({ path: path.join(__dirname, "../../.env.test"), debug: true });
|
||||
export default {
|
||||
@ -41,7 +42,8 @@ export default {
|
||||
await db.seed.run();
|
||||
const smtp = mockSmtpServer();
|
||||
const queue = mockQueue();
|
||||
const server = await main({ db, smtp, logger, queue });
|
||||
const keyStore = mockKeyStore();
|
||||
const server = await main({ db, smtp, logger, queue, keyStore });
|
||||
// @ts-expect-error type
|
||||
globalThis.testServer = server;
|
||||
// @ts-expect-error type
|
||||
|
96
backend/package-lock.json
generated
96
backend/package-lock.json
generated
@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-secrets-manager": "^3.504.0",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@fastify/cookie": "^9.2.0",
|
||||
"@fastify/cookie": "^9.3.1",
|
||||
"@fastify/cors": "^8.5.0",
|
||||
"@fastify/etag": "^5.1.0",
|
||||
"@fastify/formbody": "^7.4.0",
|
||||
@ -29,11 +29,11 @@
|
||||
"@ucast/mongo2js": "^1.3.4",
|
||||
"ajv": "^8.12.0",
|
||||
"argon2": "^0.31.2",
|
||||
"aws-sdk": "^2.1549.0",
|
||||
"aws-sdk": "^2.1553.0",
|
||||
"axios": "^1.6.7",
|
||||
"axios-retry": "^4.0.0",
|
||||
"bcrypt": "^5.1.1",
|
||||
"bullmq": "^5.1.6",
|
||||
"bullmq": "^5.3.3",
|
||||
"dotenv": "^16.4.1",
|
||||
"fastify": "^4.26.0",
|
||||
"fastify-plugin": "^4.5.1",
|
||||
@ -62,7 +62,6 @@
|
||||
"tweetnacl": "^1.0.3",
|
||||
"tweetnacl-util": "^0.15.1",
|
||||
"uuid": "^9.0.1",
|
||||
"ws": "^8.16.0",
|
||||
"zod": "^3.22.4",
|
||||
"zod-to-json-schema": "^3.22.4"
|
||||
},
|
||||
@ -82,7 +81,6 @@
|
||||
"@types/prompt-sync": "^4.2.3",
|
||||
"@types/resolve": "^1.20.6",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
||||
"@typescript-eslint/parser": "^6.20.0",
|
||||
"eslint": "^8.56.0",
|
||||
@ -1689,9 +1687,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/cookie": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-9.2.0.tgz",
|
||||
"integrity": "sha512-fkg1yjjQRHPFAxSHeLC8CqYuNzvR6Lwlj/KjrzQcGjNBK+K82nW+UfCjfN71g1GkoVoc1GTOgIWkFJpcMfMkHQ==",
|
||||
"version": "9.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-9.3.1.tgz",
|
||||
"integrity": "sha512-h1NAEhB266+ZbZ0e9qUE6NnNR07i7DnNXWG9VbbZ8uC6O/hxHpl+Zoe5sw1yfdZ2U6XhToUGDnzQtWJdCaPwfg==",
|
||||
"dependencies": {
|
||||
"cookie-signature": "^1.1.0",
|
||||
"fastify-plugin": "^4.0.0"
|
||||
@ -2195,7 +2193,6 @@
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "2.0.5",
|
||||
"run-parallel": "^1.1.9"
|
||||
@ -2208,7 +2205,6 @@
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
@ -2217,7 +2213,6 @@
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
||||
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.scandir": "2.1.5",
|
||||
"fastq": "^1.6.0"
|
||||
@ -4213,15 +4208,6 @@
|
||||
"integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
|
||||
"integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/xml-crypto": {
|
||||
"version": "1.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/xml-crypto/-/xml-crypto-1.4.6.tgz",
|
||||
@ -5200,9 +5186,9 @@
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/aws-sdk": {
|
||||
"version": "2.1549.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1549.0.tgz",
|
||||
"integrity": "sha512-SoVfrrV3A2mxH+NV2tA0eMtG301glhewvhL3Ob4107qLWjvwjy/CoWLclMLmfXniTGxbI8tsgN0r5mLZUKey3Q==",
|
||||
"version": "2.1553.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1553.0.tgz",
|
||||
"integrity": "sha512-CfZaw8dR9e642aBOeFhkFL7KoQApeLR15uH2IQqfL/12snWYayAAesYh0tEaU+XbhrH0CUsf2Zro5IraEXEZMg==",
|
||||
"dependencies": {
|
||||
"buffer": "4.9.2",
|
||||
"events": "1.1.1",
|
||||
@ -5453,7 +5439,6 @@
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
@ -5503,14 +5488,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/bullmq": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.1.6.tgz",
|
||||
"integrity": "sha512-VkLfig+xm4U3hc4QChzuuAy0NGQ9dfPB8o54hmcZHCX9ofp0Zn6bEY+W3Ytkk76eYwPAgXfywDBlAb2Unjl1Rg==",
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.3.3.tgz",
|
||||
"integrity": "sha512-Gc/68HxiCHLMPBiGIqtINxcf8HER/5wvBYMY/6x3tFejlvldUBFaAErMTLDv4TnPsTyzNPrfBKmFCEM58uVnJg==",
|
||||
"dependencies": {
|
||||
"cron-parser": "^4.6.0",
|
||||
"glob": "^8.0.3",
|
||||
"fast-glob": "^3.3.2",
|
||||
"ioredis": "^5.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
"minimatch": "^9.0.3",
|
||||
"msgpackr": "^1.10.1",
|
||||
"node-abort-controller": "^3.1.1",
|
||||
"semver": "^7.5.4",
|
||||
@ -5518,6 +5504,28 @@
|
||||
"uuid": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bullmq/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/bullmq/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/bundle-require": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.2.tgz",
|
||||
@ -6917,7 +6925,6 @@
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
@ -7069,7 +7076,6 @@
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
@ -7521,7 +7527,6 @@
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
@ -8122,7 +8127,6 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -8153,7 +8157,6 @@
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
@ -8188,7 +8191,6 @@
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
@ -8945,7 +8947,6 @@
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
@ -8962,7 +8963,6 @@
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"braces": "^3.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
@ -8975,7 +8975,6 @@
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
@ -10568,7 +10567,6 @@
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@ -10915,7 +10913,6 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@ -11716,7 +11713,6 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
@ -13731,26 +13727,6 @@
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.16.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
|
||||
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml-crypto": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-3.2.0.tgz",
|
||||
|
@ -46,7 +46,6 @@
|
||||
"@types/prompt-sync": "^4.2.3",
|
||||
"@types/resolve": "^1.20.6",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
||||
"@typescript-eslint/parser": "^6.20.0",
|
||||
"eslint": "^8.56.0",
|
||||
@ -73,7 +72,7 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-secrets-manager": "^3.504.0",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@fastify/cookie": "^9.2.0",
|
||||
"@fastify/cookie": "^9.3.1",
|
||||
"@fastify/cors": "^8.5.0",
|
||||
"@fastify/etag": "^5.1.0",
|
||||
"@fastify/formbody": "^7.4.0",
|
||||
@ -91,11 +90,11 @@
|
||||
"@ucast/mongo2js": "^1.3.4",
|
||||
"ajv": "^8.12.0",
|
||||
"argon2": "^0.31.2",
|
||||
"aws-sdk": "^2.1549.0",
|
||||
"aws-sdk": "^2.1553.0",
|
||||
"axios": "^1.6.7",
|
||||
"axios-retry": "^4.0.0",
|
||||
"bcrypt": "^5.1.1",
|
||||
"bullmq": "^5.1.6",
|
||||
"bullmq": "^5.3.3",
|
||||
"dotenv": "^16.4.1",
|
||||
"fastify": "^4.26.0",
|
||||
"fastify-plugin": "^4.5.1",
|
||||
@ -124,7 +123,6 @@
|
||||
"tweetnacl": "^1.0.3",
|
||||
"tweetnacl-util": "^0.15.1",
|
||||
"uuid": "^9.0.1",
|
||||
"ws": "^8.16.0",
|
||||
"zod": "^3.22.4",
|
||||
"zod-to-json-schema": "^3.22.4"
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ const getZodDefaultValue = (type: unknown, value: string | number | boolean | Ob
|
||||
if (!value || value === "null") return;
|
||||
switch (type) {
|
||||
case "uuid":
|
||||
return;
|
||||
return `.default("00000000-0000-0000-0000-000000000000")`;
|
||||
case "character varying": {
|
||||
if (value === "gen_random_uuid()") return;
|
||||
if (typeof value === "string" && value.includes("::")) {
|
||||
@ -100,7 +100,8 @@ const main = async () => {
|
||||
const columnName = columnNames[colNum];
|
||||
const colInfo = columns[columnName];
|
||||
let ztype = getZodPrimitiveType(colInfo.type);
|
||||
if (colInfo.defaultValue) {
|
||||
// don't put optional on id
|
||||
if (colInfo.defaultValue && columnName !== "id") {
|
||||
const { defaultValue } = colInfo;
|
||||
const zSchema = getZodDefaultValue(colInfo.type, defaultValue);
|
||||
if (zSchema) {
|
||||
@ -120,6 +121,7 @@ const main = async () => {
|
||||
.split("_")
|
||||
.reduce((prev, curr) => prev + `${curr.at(0)?.toUpperCase()}${curr.slice(1).toLowerCase()}`, "");
|
||||
|
||||
// the insert and update are changed to zod input type to use default cases
|
||||
writeFileSync(
|
||||
path.join(__dirname, "../src/db/schemas", `${dashcase}.ts`),
|
||||
`// Code generated by automation script, DO NOT EDIT.
|
||||
@ -134,8 +136,8 @@ import { TImmutableDBKeys } from "./models";
|
||||
export const ${pascalCase}Schema = z.object({${schema}});
|
||||
|
||||
export type T${pascalCase} = z.infer<typeof ${pascalCase}Schema>;
|
||||
export type T${pascalCase}Insert = Omit<T${pascalCase}, TImmutableDBKeys>;
|
||||
export type T${pascalCase}Update = Partial<Omit<T${pascalCase}, TImmutableDBKeys>>;
|
||||
export type T${pascalCase}Insert = Omit<z.input<typeof ${pascalCase}Schema>, TImmutableDBKeys>;
|
||||
export type T${pascalCase}Update = Partial<Omit<z.input<typeof ${pascalCase}Schema>, TImmutableDBKeys>>;
|
||||
`
|
||||
);
|
||||
}
|
||||
|
17
backend/src/@types/fastify.d.ts
vendored
17
backend/src/@types/fastify.d.ts
vendored
@ -20,7 +20,6 @@ import { TAuthPasswordFactory } from "@app/services/auth/auth-password-service";
|
||||
import { TAuthSignupFactory } from "@app/services/auth/auth-signup-service";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
||||
import { TEventServiceFactory } from "@app/services/event/event-service";
|
||||
import { TIdentityServiceFactory } from "@app/services/identity/identity-service";
|
||||
import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
|
||||
import { TIdentityProjectServiceFactory } from "@app/services/identity-project/identity-project-service";
|
||||
@ -72,21 +71,6 @@ declare module "fastify" {
|
||||
ssoConfig: Awaited<ReturnType<TSamlConfigServiceFactory["getSaml"]>>;
|
||||
}
|
||||
|
||||
interface FastifyReply {
|
||||
sse: ({
|
||||
data,
|
||||
error
|
||||
}:
|
||||
| {
|
||||
data: string;
|
||||
error?: false;
|
||||
}
|
||||
| {
|
||||
error: true;
|
||||
errorMessage: string;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
interface FastifyInstance {
|
||||
services: {
|
||||
login: TAuthLoginFactory;
|
||||
@ -129,7 +113,6 @@ declare module "fastify" {
|
||||
trustedIp: TTrustedIpServiceFactory;
|
||||
secretBlindIndex: TSecretBlindIndexServiceFactory;
|
||||
telemetry: TTelemetryServiceFactory;
|
||||
event: TEventServiceFactory;
|
||||
};
|
||||
// this is exclusive use for middlewares in which we need to inject data
|
||||
// everywhere else access using service layer
|
||||
|
6
backend/src/cache/redis.ts
vendored
6
backend/src/cache/redis.ts
vendored
@ -1,6 +0,0 @@
|
||||
import Redis from "ioredis";
|
||||
|
||||
export const initRedisConnection = (redisUrl: string) => {
|
||||
const redis = new Redis(redisUrl);
|
||||
return redis;
|
||||
};
|
21
backend/src/db/migrations/20240226094411_instance-id.ts
Normal file
21
backend/src/db/migrations/20240226094411_instance-id.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
const ADMIN_CONFIG_UUID = "00000000-0000-0000-0000-000000000000";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
|
||||
t.uuid("instanceId").notNullable().defaultTo(knex.fn.uuid());
|
||||
});
|
||||
// this is updated to avoid race condition on replication
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
await knex(TableName.SuperAdmin).update({ id: ADMIN_CONFIG_UUID }).whereNotNull("id").limit(1);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
|
||||
t.dropColumn("instanceId");
|
||||
});
|
||||
}
|
@ -19,5 +19,5 @@ export const ApiKeysSchema = z.object({
|
||||
});
|
||||
|
||||
export type TApiKeys = z.infer<typeof ApiKeysSchema>;
|
||||
export type TApiKeysInsert = Omit<TApiKeys, TImmutableDBKeys>;
|
||||
export type TApiKeysUpdate = Partial<Omit<TApiKeys, TImmutableDBKeys>>;
|
||||
export type TApiKeysInsert = Omit<z.input<typeof ApiKeysSchema>, TImmutableDBKeys>;
|
||||
export type TApiKeysUpdate = Partial<Omit<z.input<typeof ApiKeysSchema>, TImmutableDBKeys>>;
|
||||
|
@ -24,5 +24,5 @@ export const AuditLogsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TAuditLogs = z.infer<typeof AuditLogsSchema>;
|
||||
export type TAuditLogsInsert = Omit<TAuditLogs, TImmutableDBKeys>;
|
||||
export type TAuditLogsUpdate = Partial<Omit<TAuditLogs, TImmutableDBKeys>>;
|
||||
export type TAuditLogsInsert = Omit<z.input<typeof AuditLogsSchema>, TImmutableDBKeys>;
|
||||
export type TAuditLogsUpdate = Partial<Omit<z.input<typeof AuditLogsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -20,5 +20,5 @@ export const AuthTokenSessionsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TAuthTokenSessions = z.infer<typeof AuthTokenSessionsSchema>;
|
||||
export type TAuthTokenSessionsInsert = Omit<TAuthTokenSessions, TImmutableDBKeys>;
|
||||
export type TAuthTokenSessionsUpdate = Partial<Omit<TAuthTokenSessions, TImmutableDBKeys>>;
|
||||
export type TAuthTokenSessionsInsert = Omit<z.input<typeof AuthTokenSessionsSchema>, TImmutableDBKeys>;
|
||||
export type TAuthTokenSessionsUpdate = Partial<Omit<z.input<typeof AuthTokenSessionsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -21,5 +21,5 @@ export const AuthTokensSchema = z.object({
|
||||
});
|
||||
|
||||
export type TAuthTokens = z.infer<typeof AuthTokensSchema>;
|
||||
export type TAuthTokensInsert = Omit<TAuthTokens, TImmutableDBKeys>;
|
||||
export type TAuthTokensUpdate = Partial<Omit<TAuthTokens, TImmutableDBKeys>>;
|
||||
export type TAuthTokensInsert = Omit<z.input<typeof AuthTokensSchema>, TImmutableDBKeys>;
|
||||
export type TAuthTokensUpdate = Partial<Omit<z.input<typeof AuthTokensSchema>, TImmutableDBKeys>>;
|
||||
|
@ -22,5 +22,5 @@ export const BackupPrivateKeySchema = z.object({
|
||||
});
|
||||
|
||||
export type TBackupPrivateKey = z.infer<typeof BackupPrivateKeySchema>;
|
||||
export type TBackupPrivateKeyInsert = Omit<TBackupPrivateKey, TImmutableDBKeys>;
|
||||
export type TBackupPrivateKeyUpdate = Partial<Omit<TBackupPrivateKey, TImmutableDBKeys>>;
|
||||
export type TBackupPrivateKeyInsert = Omit<z.input<typeof BackupPrivateKeySchema>, TImmutableDBKeys>;
|
||||
export type TBackupPrivateKeyUpdate = Partial<Omit<z.input<typeof BackupPrivateKeySchema>, TImmutableDBKeys>>;
|
||||
|
@ -17,5 +17,5 @@ export const GitAppInstallSessionsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TGitAppInstallSessions = z.infer<typeof GitAppInstallSessionsSchema>;
|
||||
export type TGitAppInstallSessionsInsert = Omit<TGitAppInstallSessions, TImmutableDBKeys>;
|
||||
export type TGitAppInstallSessionsUpdate = Partial<Omit<TGitAppInstallSessions, TImmutableDBKeys>>;
|
||||
export type TGitAppInstallSessionsInsert = Omit<z.input<typeof GitAppInstallSessionsSchema>, TImmutableDBKeys>;
|
||||
export type TGitAppInstallSessionsUpdate = Partial<Omit<z.input<typeof GitAppInstallSessionsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -17,5 +17,5 @@ export const GitAppOrgSchema = z.object({
|
||||
});
|
||||
|
||||
export type TGitAppOrg = z.infer<typeof GitAppOrgSchema>;
|
||||
export type TGitAppOrgInsert = Omit<TGitAppOrg, TImmutableDBKeys>;
|
||||
export type TGitAppOrgUpdate = Partial<Omit<TGitAppOrg, TImmutableDBKeys>>;
|
||||
export type TGitAppOrgInsert = Omit<z.input<typeof GitAppOrgSchema>, TImmutableDBKeys>;
|
||||
export type TGitAppOrgUpdate = Partial<Omit<z.input<typeof GitAppOrgSchema>, TImmutableDBKeys>>;
|
||||
|
@ -16,5 +16,5 @@ export const IdentitiesSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIdentities = z.infer<typeof IdentitiesSchema>;
|
||||
export type TIdentitiesInsert = Omit<TIdentities, TImmutableDBKeys>;
|
||||
export type TIdentitiesUpdate = Partial<Omit<TIdentities, TImmutableDBKeys>>;
|
||||
export type TIdentitiesInsert = Omit<z.input<typeof IdentitiesSchema>, TImmutableDBKeys>;
|
||||
export type TIdentitiesUpdate = Partial<Omit<z.input<typeof IdentitiesSchema>, TImmutableDBKeys>>;
|
||||
|
@ -23,5 +23,5 @@ export const IdentityAccessTokensSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
||||
export type TIdentityAccessTokensInsert = Omit<TIdentityAccessTokens, TImmutableDBKeys>;
|
||||
export type TIdentityAccessTokensUpdate = Partial<Omit<TIdentityAccessTokens, TImmutableDBKeys>>;
|
||||
export type TIdentityAccessTokensInsert = Omit<z.input<typeof IdentityAccessTokensSchema>, TImmutableDBKeys>;
|
||||
export type TIdentityAccessTokensUpdate = Partial<Omit<z.input<typeof IdentityAccessTokensSchema>, TImmutableDBKeys>>;
|
||||
|
@ -18,5 +18,7 @@ export const IdentityOrgMembershipsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIdentityOrgMemberships = z.infer<typeof IdentityOrgMembershipsSchema>;
|
||||
export type TIdentityOrgMembershipsInsert = Omit<TIdentityOrgMemberships, TImmutableDBKeys>;
|
||||
export type TIdentityOrgMembershipsUpdate = Partial<Omit<TIdentityOrgMemberships, TImmutableDBKeys>>;
|
||||
export type TIdentityOrgMembershipsInsert = Omit<z.input<typeof IdentityOrgMembershipsSchema>, TImmutableDBKeys>;
|
||||
export type TIdentityOrgMembershipsUpdate = Partial<
|
||||
Omit<z.input<typeof IdentityOrgMembershipsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -18,5 +18,10 @@ export const IdentityProjectMembershipsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIdentityProjectMemberships = z.infer<typeof IdentityProjectMembershipsSchema>;
|
||||
export type TIdentityProjectMembershipsInsert = Omit<TIdentityProjectMemberships, TImmutableDBKeys>;
|
||||
export type TIdentityProjectMembershipsUpdate = Partial<Omit<TIdentityProjectMemberships, TImmutableDBKeys>>;
|
||||
export type TIdentityProjectMembershipsInsert = Omit<
|
||||
z.input<typeof IdentityProjectMembershipsSchema>,
|
||||
TImmutableDBKeys
|
||||
>;
|
||||
export type TIdentityProjectMembershipsUpdate = Partial<
|
||||
Omit<z.input<typeof IdentityProjectMembershipsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -23,5 +23,7 @@ export const IdentityUaClientSecretsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIdentityUaClientSecrets = z.infer<typeof IdentityUaClientSecretsSchema>;
|
||||
export type TIdentityUaClientSecretsInsert = Omit<TIdentityUaClientSecrets, TImmutableDBKeys>;
|
||||
export type TIdentityUaClientSecretsUpdate = Partial<Omit<TIdentityUaClientSecrets, TImmutableDBKeys>>;
|
||||
export type TIdentityUaClientSecretsInsert = Omit<z.input<typeof IdentityUaClientSecretsSchema>, TImmutableDBKeys>;
|
||||
export type TIdentityUaClientSecretsUpdate = Partial<
|
||||
Omit<z.input<typeof IdentityUaClientSecretsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -21,5 +21,7 @@ export const IdentityUniversalAuthsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIdentityUniversalAuths = z.infer<typeof IdentityUniversalAuthsSchema>;
|
||||
export type TIdentityUniversalAuthsInsert = Omit<TIdentityUniversalAuths, TImmutableDBKeys>;
|
||||
export type TIdentityUniversalAuthsUpdate = Partial<Omit<TIdentityUniversalAuths, TImmutableDBKeys>>;
|
||||
export type TIdentityUniversalAuthsInsert = Omit<z.input<typeof IdentityUniversalAuthsSchema>, TImmutableDBKeys>;
|
||||
export type TIdentityUniversalAuthsUpdate = Partial<
|
||||
Omit<z.input<typeof IdentityUniversalAuthsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -16,5 +16,5 @@ export const IncidentContactsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIncidentContacts = z.infer<typeof IncidentContactsSchema>;
|
||||
export type TIncidentContactsInsert = Omit<TIncidentContacts, TImmutableDBKeys>;
|
||||
export type TIncidentContactsUpdate = Partial<Omit<TIncidentContacts, TImmutableDBKeys>>;
|
||||
export type TIncidentContactsInsert = Omit<z.input<typeof IncidentContactsSchema>, TImmutableDBKeys>;
|
||||
export type TIncidentContactsUpdate = Partial<Omit<z.input<typeof IncidentContactsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -33,5 +33,5 @@ export const IntegrationAuthsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIntegrationAuths = z.infer<typeof IntegrationAuthsSchema>;
|
||||
export type TIntegrationAuthsInsert = Omit<TIntegrationAuths, TImmutableDBKeys>;
|
||||
export type TIntegrationAuthsUpdate = Partial<Omit<TIntegrationAuths, TImmutableDBKeys>>;
|
||||
export type TIntegrationAuthsInsert = Omit<z.input<typeof IntegrationAuthsSchema>, TImmutableDBKeys>;
|
||||
export type TIntegrationAuthsUpdate = Partial<Omit<z.input<typeof IntegrationAuthsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -31,5 +31,5 @@ export const IntegrationsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIntegrations = z.infer<typeof IntegrationsSchema>;
|
||||
export type TIntegrationsInsert = Omit<TIntegrations, TImmutableDBKeys>;
|
||||
export type TIntegrationsUpdate = Partial<Omit<TIntegrations, TImmutableDBKeys>>;
|
||||
export type TIntegrationsInsert = Omit<z.input<typeof IntegrationsSchema>, TImmutableDBKeys>;
|
||||
export type TIntegrationsUpdate = Partial<Omit<z.input<typeof IntegrationsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -27,5 +27,5 @@ export const OrgBotsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TOrgBots = z.infer<typeof OrgBotsSchema>;
|
||||
export type TOrgBotsInsert = Omit<TOrgBots, TImmutableDBKeys>;
|
||||
export type TOrgBotsUpdate = Partial<Omit<TOrgBots, TImmutableDBKeys>>;
|
||||
export type TOrgBotsInsert = Omit<z.input<typeof OrgBotsSchema>, TImmutableDBKeys>;
|
||||
export type TOrgBotsUpdate = Partial<Omit<z.input<typeof OrgBotsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -20,5 +20,5 @@ export const OrgMembershipsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TOrgMemberships = z.infer<typeof OrgMembershipsSchema>;
|
||||
export type TOrgMembershipsInsert = Omit<TOrgMemberships, TImmutableDBKeys>;
|
||||
export type TOrgMembershipsUpdate = Partial<Omit<TOrgMemberships, TImmutableDBKeys>>;
|
||||
export type TOrgMembershipsInsert = Omit<z.input<typeof OrgMembershipsSchema>, TImmutableDBKeys>;
|
||||
export type TOrgMembershipsUpdate = Partial<Omit<z.input<typeof OrgMembershipsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -19,5 +19,5 @@ export const OrgRolesSchema = z.object({
|
||||
});
|
||||
|
||||
export type TOrgRoles = z.infer<typeof OrgRolesSchema>;
|
||||
export type TOrgRolesInsert = Omit<TOrgRoles, TImmutableDBKeys>;
|
||||
export type TOrgRolesUpdate = Partial<Omit<TOrgRoles, TImmutableDBKeys>>;
|
||||
export type TOrgRolesInsert = Omit<z.input<typeof OrgRolesSchema>, TImmutableDBKeys>;
|
||||
export type TOrgRolesUpdate = Partial<Omit<z.input<typeof OrgRolesSchema>, TImmutableDBKeys>>;
|
||||
|
@ -19,5 +19,5 @@ export const OrganizationsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TOrganizations = z.infer<typeof OrganizationsSchema>;
|
||||
export type TOrganizationsInsert = Omit<TOrganizations, TImmutableDBKeys>;
|
||||
export type TOrganizationsUpdate = Partial<Omit<TOrganizations, TImmutableDBKeys>>;
|
||||
export type TOrganizationsInsert = Omit<z.input<typeof OrganizationsSchema>, TImmutableDBKeys>;
|
||||
export type TOrganizationsUpdate = Partial<Omit<z.input<typeof OrganizationsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -26,5 +26,5 @@ export const ProjectBotsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TProjectBots = z.infer<typeof ProjectBotsSchema>;
|
||||
export type TProjectBotsInsert = Omit<TProjectBots, TImmutableDBKeys>;
|
||||
export type TProjectBotsUpdate = Partial<Omit<TProjectBots, TImmutableDBKeys>>;
|
||||
export type TProjectBotsInsert = Omit<z.input<typeof ProjectBotsSchema>, TImmutableDBKeys>;
|
||||
export type TProjectBotsUpdate = Partial<Omit<z.input<typeof ProjectBotsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -18,5 +18,5 @@ export const ProjectEnvironmentsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TProjectEnvironments = z.infer<typeof ProjectEnvironmentsSchema>;
|
||||
export type TProjectEnvironmentsInsert = Omit<TProjectEnvironments, TImmutableDBKeys>;
|
||||
export type TProjectEnvironmentsUpdate = Partial<Omit<TProjectEnvironments, TImmutableDBKeys>>;
|
||||
export type TProjectEnvironmentsInsert = Omit<z.input<typeof ProjectEnvironmentsSchema>, TImmutableDBKeys>;
|
||||
export type TProjectEnvironmentsUpdate = Partial<Omit<z.input<typeof ProjectEnvironmentsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -19,5 +19,5 @@ export const ProjectKeysSchema = z.object({
|
||||
});
|
||||
|
||||
export type TProjectKeys = z.infer<typeof ProjectKeysSchema>;
|
||||
export type TProjectKeysInsert = Omit<TProjectKeys, TImmutableDBKeys>;
|
||||
export type TProjectKeysUpdate = Partial<Omit<TProjectKeys, TImmutableDBKeys>>;
|
||||
export type TProjectKeysInsert = Omit<z.input<typeof ProjectKeysSchema>, TImmutableDBKeys>;
|
||||
export type TProjectKeysUpdate = Partial<Omit<z.input<typeof ProjectKeysSchema>, TImmutableDBKeys>>;
|
||||
|
@ -18,5 +18,5 @@ export const ProjectMembershipsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TProjectMemberships = z.infer<typeof ProjectMembershipsSchema>;
|
||||
export type TProjectMembershipsInsert = Omit<TProjectMemberships, TImmutableDBKeys>;
|
||||
export type TProjectMembershipsUpdate = Partial<Omit<TProjectMemberships, TImmutableDBKeys>>;
|
||||
export type TProjectMembershipsInsert = Omit<z.input<typeof ProjectMembershipsSchema>, TImmutableDBKeys>;
|
||||
export type TProjectMembershipsUpdate = Partial<Omit<z.input<typeof ProjectMembershipsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -19,5 +19,5 @@ export const ProjectRolesSchema = z.object({
|
||||
});
|
||||
|
||||
export type TProjectRoles = z.infer<typeof ProjectRolesSchema>;
|
||||
export type TProjectRolesInsert = Omit<TProjectRoles, TImmutableDBKeys>;
|
||||
export type TProjectRolesUpdate = Partial<Omit<TProjectRoles, TImmutableDBKeys>>;
|
||||
export type TProjectRolesInsert = Omit<z.input<typeof ProjectRolesSchema>, TImmutableDBKeys>;
|
||||
export type TProjectRolesUpdate = Partial<Omit<z.input<typeof ProjectRolesSchema>, TImmutableDBKeys>>;
|
||||
|
@ -20,5 +20,5 @@ export const ProjectsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TProjects = z.infer<typeof ProjectsSchema>;
|
||||
export type TProjectsInsert = Omit<TProjects, TImmutableDBKeys>;
|
||||
export type TProjectsUpdate = Partial<Omit<TProjects, TImmutableDBKeys>>;
|
||||
export type TProjectsInsert = Omit<z.input<typeof ProjectsSchema>, TImmutableDBKeys>;
|
||||
export type TProjectsUpdate = Partial<Omit<z.input<typeof ProjectsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -27,5 +27,5 @@ export const SamlConfigsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSamlConfigs = z.infer<typeof SamlConfigsSchema>;
|
||||
export type TSamlConfigsInsert = Omit<TSamlConfigs, TImmutableDBKeys>;
|
||||
export type TSamlConfigsUpdate = Partial<Omit<TSamlConfigs, TImmutableDBKeys>>;
|
||||
export type TSamlConfigsInsert = Omit<z.input<typeof SamlConfigsSchema>, TImmutableDBKeys>;
|
||||
export type TSamlConfigsUpdate = Partial<Omit<z.input<typeof SamlConfigsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -17,5 +17,5 @@ export const ScimTokensSchema = z.object({
|
||||
});
|
||||
|
||||
export type TScimTokens = z.infer<typeof ScimTokensSchema>;
|
||||
export type TScimTokensInsert = Omit<TScimTokens, TImmutableDBKeys>;
|
||||
export type TScimTokensUpdate = Partial<Omit<TScimTokens, TImmutableDBKeys>>;
|
||||
export type TScimTokensInsert = Omit<z.input<typeof ScimTokensSchema>, TImmutableDBKeys>;
|
||||
export type TScimTokensUpdate = Partial<Omit<z.input<typeof ScimTokensSchema>, TImmutableDBKeys>>;
|
||||
|
@ -16,5 +16,10 @@ export const SecretApprovalPoliciesApproversSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretApprovalPoliciesApprovers = z.infer<typeof SecretApprovalPoliciesApproversSchema>;
|
||||
export type TSecretApprovalPoliciesApproversInsert = Omit<TSecretApprovalPoliciesApprovers, TImmutableDBKeys>;
|
||||
export type TSecretApprovalPoliciesApproversUpdate = Partial<Omit<TSecretApprovalPoliciesApprovers, TImmutableDBKeys>>;
|
||||
export type TSecretApprovalPoliciesApproversInsert = Omit<
|
||||
z.input<typeof SecretApprovalPoliciesApproversSchema>,
|
||||
TImmutableDBKeys
|
||||
>;
|
||||
export type TSecretApprovalPoliciesApproversUpdate = Partial<
|
||||
Omit<z.input<typeof SecretApprovalPoliciesApproversSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -18,5 +18,7 @@ export const SecretApprovalPoliciesSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>;
|
||||
export type TSecretApprovalPoliciesInsert = Omit<TSecretApprovalPolicies, TImmutableDBKeys>;
|
||||
export type TSecretApprovalPoliciesUpdate = Partial<Omit<TSecretApprovalPolicies, TImmutableDBKeys>>;
|
||||
export type TSecretApprovalPoliciesInsert = Omit<z.input<typeof SecretApprovalPoliciesSchema>, TImmutableDBKeys>;
|
||||
export type TSecretApprovalPoliciesUpdate = Partial<
|
||||
Omit<z.input<typeof SecretApprovalPoliciesSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -16,5 +16,10 @@ export const SecretApprovalRequestSecretTagsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretApprovalRequestSecretTags = z.infer<typeof SecretApprovalRequestSecretTagsSchema>;
|
||||
export type TSecretApprovalRequestSecretTagsInsert = Omit<TSecretApprovalRequestSecretTags, TImmutableDBKeys>;
|
||||
export type TSecretApprovalRequestSecretTagsUpdate = Partial<Omit<TSecretApprovalRequestSecretTags, TImmutableDBKeys>>;
|
||||
export type TSecretApprovalRequestSecretTagsInsert = Omit<
|
||||
z.input<typeof SecretApprovalRequestSecretTagsSchema>,
|
||||
TImmutableDBKeys
|
||||
>;
|
||||
export type TSecretApprovalRequestSecretTagsUpdate = Partial<
|
||||
Omit<z.input<typeof SecretApprovalRequestSecretTagsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -17,5 +17,10 @@ export const SecretApprovalRequestsReviewersSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretApprovalRequestsReviewers = z.infer<typeof SecretApprovalRequestsReviewersSchema>;
|
||||
export type TSecretApprovalRequestsReviewersInsert = Omit<TSecretApprovalRequestsReviewers, TImmutableDBKeys>;
|
||||
export type TSecretApprovalRequestsReviewersUpdate = Partial<Omit<TSecretApprovalRequestsReviewers, TImmutableDBKeys>>;
|
||||
export type TSecretApprovalRequestsReviewersInsert = Omit<
|
||||
z.input<typeof SecretApprovalRequestsReviewersSchema>,
|
||||
TImmutableDBKeys
|
||||
>;
|
||||
export type TSecretApprovalRequestsReviewersUpdate = Partial<
|
||||
Omit<z.input<typeof SecretApprovalRequestsReviewersSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -35,5 +35,10 @@ export const SecretApprovalRequestsSecretsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretApprovalRequestsSecrets = z.infer<typeof SecretApprovalRequestsSecretsSchema>;
|
||||
export type TSecretApprovalRequestsSecretsInsert = Omit<TSecretApprovalRequestsSecrets, TImmutableDBKeys>;
|
||||
export type TSecretApprovalRequestsSecretsUpdate = Partial<Omit<TSecretApprovalRequestsSecrets, TImmutableDBKeys>>;
|
||||
export type TSecretApprovalRequestsSecretsInsert = Omit<
|
||||
z.input<typeof SecretApprovalRequestsSecretsSchema>,
|
||||
TImmutableDBKeys
|
||||
>;
|
||||
export type TSecretApprovalRequestsSecretsUpdate = Partial<
|
||||
Omit<z.input<typeof SecretApprovalRequestsSecretsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -22,5 +22,7 @@ export const SecretApprovalRequestsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretApprovalRequests = z.infer<typeof SecretApprovalRequestsSchema>;
|
||||
export type TSecretApprovalRequestsInsert = Omit<TSecretApprovalRequests, TImmutableDBKeys>;
|
||||
export type TSecretApprovalRequestsUpdate = Partial<Omit<TSecretApprovalRequests, TImmutableDBKeys>>;
|
||||
export type TSecretApprovalRequestsInsert = Omit<z.input<typeof SecretApprovalRequestsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretApprovalRequestsUpdate = Partial<
|
||||
Omit<z.input<typeof SecretApprovalRequestsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -20,5 +20,5 @@ export const SecretBlindIndexesSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretBlindIndexes = z.infer<typeof SecretBlindIndexesSchema>;
|
||||
export type TSecretBlindIndexesInsert = Omit<TSecretBlindIndexes, TImmutableDBKeys>;
|
||||
export type TSecretBlindIndexesUpdate = Partial<Omit<TSecretBlindIndexes, TImmutableDBKeys>>;
|
||||
export type TSecretBlindIndexesInsert = Omit<z.input<typeof SecretBlindIndexesSchema>, TImmutableDBKeys>;
|
||||
export type TSecretBlindIndexesUpdate = Partial<Omit<z.input<typeof SecretBlindIndexesSchema>, TImmutableDBKeys>>;
|
||||
|
@ -18,5 +18,5 @@ export const SecretFolderVersionsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretFolderVersions = z.infer<typeof SecretFolderVersionsSchema>;
|
||||
export type TSecretFolderVersionsInsert = Omit<TSecretFolderVersions, TImmutableDBKeys>;
|
||||
export type TSecretFolderVersionsUpdate = Partial<Omit<TSecretFolderVersions, TImmutableDBKeys>>;
|
||||
export type TSecretFolderVersionsInsert = Omit<z.input<typeof SecretFolderVersionsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretFolderVersionsUpdate = Partial<Omit<z.input<typeof SecretFolderVersionsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -18,5 +18,5 @@ export const SecretFoldersSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretFolders = z.infer<typeof SecretFoldersSchema>;
|
||||
export type TSecretFoldersInsert = Omit<TSecretFolders, TImmutableDBKeys>;
|
||||
export type TSecretFoldersUpdate = Partial<Omit<TSecretFolders, TImmutableDBKeys>>;
|
||||
export type TSecretFoldersInsert = Omit<z.input<typeof SecretFoldersSchema>, TImmutableDBKeys>;
|
||||
export type TSecretFoldersUpdate = Partial<Omit<z.input<typeof SecretFoldersSchema>, TImmutableDBKeys>>;
|
||||
|
@ -19,5 +19,5 @@ export const SecretImportsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretImports = z.infer<typeof SecretImportsSchema>;
|
||||
export type TSecretImportsInsert = Omit<TSecretImports, TImmutableDBKeys>;
|
||||
export type TSecretImportsUpdate = Partial<Omit<TSecretImports, TImmutableDBKeys>>;
|
||||
export type TSecretImportsInsert = Omit<z.input<typeof SecretImportsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretImportsUpdate = Partial<Omit<z.input<typeof SecretImportsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -15,5 +15,5 @@ export const SecretRotationOutputsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretRotationOutputs = z.infer<typeof SecretRotationOutputsSchema>;
|
||||
export type TSecretRotationOutputsInsert = Omit<TSecretRotationOutputs, TImmutableDBKeys>;
|
||||
export type TSecretRotationOutputsUpdate = Partial<Omit<TSecretRotationOutputs, TImmutableDBKeys>>;
|
||||
export type TSecretRotationOutputsInsert = Omit<z.input<typeof SecretRotationOutputsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretRotationOutputsUpdate = Partial<Omit<z.input<typeof SecretRotationOutputsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -26,5 +26,5 @@ export const SecretRotationsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretRotations = z.infer<typeof SecretRotationsSchema>;
|
||||
export type TSecretRotationsInsert = Omit<TSecretRotations, TImmutableDBKeys>;
|
||||
export type TSecretRotationsUpdate = Partial<Omit<TSecretRotations, TImmutableDBKeys>>;
|
||||
export type TSecretRotationsInsert = Omit<z.input<typeof SecretRotationsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretRotationsUpdate = Partial<Omit<z.input<typeof SecretRotationsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -42,5 +42,7 @@ export const SecretScanningGitRisksSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretScanningGitRisks = z.infer<typeof SecretScanningGitRisksSchema>;
|
||||
export type TSecretScanningGitRisksInsert = Omit<TSecretScanningGitRisks, TImmutableDBKeys>;
|
||||
export type TSecretScanningGitRisksUpdate = Partial<Omit<TSecretScanningGitRisks, TImmutableDBKeys>>;
|
||||
export type TSecretScanningGitRisksInsert = Omit<z.input<typeof SecretScanningGitRisksSchema>, TImmutableDBKeys>;
|
||||
export type TSecretScanningGitRisksUpdate = Partial<
|
||||
Omit<z.input<typeof SecretScanningGitRisksSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -17,5 +17,5 @@ export const SecretSnapshotFoldersSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretSnapshotFolders = z.infer<typeof SecretSnapshotFoldersSchema>;
|
||||
export type TSecretSnapshotFoldersInsert = Omit<TSecretSnapshotFolders, TImmutableDBKeys>;
|
||||
export type TSecretSnapshotFoldersUpdate = Partial<Omit<TSecretSnapshotFolders, TImmutableDBKeys>>;
|
||||
export type TSecretSnapshotFoldersInsert = Omit<z.input<typeof SecretSnapshotFoldersSchema>, TImmutableDBKeys>;
|
||||
export type TSecretSnapshotFoldersUpdate = Partial<Omit<z.input<typeof SecretSnapshotFoldersSchema>, TImmutableDBKeys>>;
|
||||
|
@ -17,5 +17,5 @@ export const SecretSnapshotSecretsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretSnapshotSecrets = z.infer<typeof SecretSnapshotSecretsSchema>;
|
||||
export type TSecretSnapshotSecretsInsert = Omit<TSecretSnapshotSecrets, TImmutableDBKeys>;
|
||||
export type TSecretSnapshotSecretsUpdate = Partial<Omit<TSecretSnapshotSecrets, TImmutableDBKeys>>;
|
||||
export type TSecretSnapshotSecretsInsert = Omit<z.input<typeof SecretSnapshotSecretsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretSnapshotSecretsUpdate = Partial<Omit<z.input<typeof SecretSnapshotSecretsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -17,5 +17,5 @@ export const SecretSnapshotsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretSnapshots = z.infer<typeof SecretSnapshotsSchema>;
|
||||
export type TSecretSnapshotsInsert = Omit<TSecretSnapshots, TImmutableDBKeys>;
|
||||
export type TSecretSnapshotsUpdate = Partial<Omit<TSecretSnapshots, TImmutableDBKeys>>;
|
||||
export type TSecretSnapshotsInsert = Omit<z.input<typeof SecretSnapshotsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretSnapshotsUpdate = Partial<Omit<z.input<typeof SecretSnapshotsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -14,5 +14,5 @@ export const SecretTagJunctionSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretTagJunction = z.infer<typeof SecretTagJunctionSchema>;
|
||||
export type TSecretTagJunctionInsert = Omit<TSecretTagJunction, TImmutableDBKeys>;
|
||||
export type TSecretTagJunctionUpdate = Partial<Omit<TSecretTagJunction, TImmutableDBKeys>>;
|
||||
export type TSecretTagJunctionInsert = Omit<z.input<typeof SecretTagJunctionSchema>, TImmutableDBKeys>;
|
||||
export type TSecretTagJunctionUpdate = Partial<Omit<z.input<typeof SecretTagJunctionSchema>, TImmutableDBKeys>>;
|
||||
|
@ -19,5 +19,5 @@ export const SecretTagsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretTags = z.infer<typeof SecretTagsSchema>;
|
||||
export type TSecretTagsInsert = Omit<TSecretTags, TImmutableDBKeys>;
|
||||
export type TSecretTagsUpdate = Partial<Omit<TSecretTags, TImmutableDBKeys>>;
|
||||
export type TSecretTagsInsert = Omit<z.input<typeof SecretTagsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretTagsUpdate = Partial<Omit<z.input<typeof SecretTagsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -14,5 +14,7 @@ export const SecretVersionTagJunctionSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretVersionTagJunction = z.infer<typeof SecretVersionTagJunctionSchema>;
|
||||
export type TSecretVersionTagJunctionInsert = Omit<TSecretVersionTagJunction, TImmutableDBKeys>;
|
||||
export type TSecretVersionTagJunctionUpdate = Partial<Omit<TSecretVersionTagJunction, TImmutableDBKeys>>;
|
||||
export type TSecretVersionTagJunctionInsert = Omit<z.input<typeof SecretVersionTagJunctionSchema>, TImmutableDBKeys>;
|
||||
export type TSecretVersionTagJunctionUpdate = Partial<
|
||||
Omit<z.input<typeof SecretVersionTagJunctionSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
|
@ -36,5 +36,5 @@ export const SecretVersionsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecretVersions = z.infer<typeof SecretVersionsSchema>;
|
||||
export type TSecretVersionsInsert = Omit<TSecretVersions, TImmutableDBKeys>;
|
||||
export type TSecretVersionsUpdate = Partial<Omit<TSecretVersions, TImmutableDBKeys>>;
|
||||
export type TSecretVersionsInsert = Omit<z.input<typeof SecretVersionsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretVersionsUpdate = Partial<Omit<z.input<typeof SecretVersionsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -34,5 +34,5 @@ export const SecretsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TSecrets = z.infer<typeof SecretsSchema>;
|
||||
export type TSecretsInsert = Omit<TSecrets, TImmutableDBKeys>;
|
||||
export type TSecretsUpdate = Partial<Omit<TSecrets, TImmutableDBKeys>>;
|
||||
export type TSecretsInsert = Omit<z.input<typeof SecretsSchema>, TImmutableDBKeys>;
|
||||
export type TSecretsUpdate = Partial<Omit<z.input<typeof SecretsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -25,5 +25,5 @@ export const ServiceTokensSchema = z.object({
|
||||
});
|
||||
|
||||
export type TServiceTokens = z.infer<typeof ServiceTokensSchema>;
|
||||
export type TServiceTokensInsert = Omit<TServiceTokens, TImmutableDBKeys>;
|
||||
export type TServiceTokensUpdate = Partial<Omit<TServiceTokens, TImmutableDBKeys>>;
|
||||
export type TServiceTokensInsert = Omit<z.input<typeof ServiceTokensSchema>, TImmutableDBKeys>;
|
||||
export type TServiceTokensUpdate = Partial<Omit<z.input<typeof ServiceTokensSchema>, TImmutableDBKeys>>;
|
||||
|
@ -13,9 +13,10 @@ export const SuperAdminSchema = z.object({
|
||||
allowSignUp: z.boolean().default(true).nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
allowedSignUpDomain: z.string().nullable().optional()
|
||||
allowedSignUpDomain: z.string().nullable().optional(),
|
||||
instanceId: z.string().uuid().default("00000000-0000-0000-0000-000000000000")
|
||||
});
|
||||
|
||||
export type TSuperAdmin = z.infer<typeof SuperAdminSchema>;
|
||||
export type TSuperAdminInsert = Omit<TSuperAdmin, TImmutableDBKeys>;
|
||||
export type TSuperAdminUpdate = Partial<Omit<TSuperAdmin, TImmutableDBKeys>>;
|
||||
export type TSuperAdminInsert = Omit<z.input<typeof SuperAdminSchema>, TImmutableDBKeys>;
|
||||
export type TSuperAdminUpdate = Partial<Omit<z.input<typeof SuperAdminSchema>, TImmutableDBKeys>>;
|
||||
|
@ -20,5 +20,5 @@ export const TrustedIpsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TTrustedIps = z.infer<typeof TrustedIpsSchema>;
|
||||
export type TTrustedIpsInsert = Omit<TTrustedIps, TImmutableDBKeys>;
|
||||
export type TTrustedIpsUpdate = Partial<Omit<TTrustedIps, TImmutableDBKeys>>;
|
||||
export type TTrustedIpsInsert = Omit<z.input<typeof TrustedIpsSchema>, TImmutableDBKeys>;
|
||||
export type TTrustedIpsUpdate = Partial<Omit<z.input<typeof TrustedIpsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -16,5 +16,5 @@ export const UserActionsSchema = z.object({
|
||||
});
|
||||
|
||||
export type TUserActions = z.infer<typeof UserActionsSchema>;
|
||||
export type TUserActionsInsert = Omit<TUserActions, TImmutableDBKeys>;
|
||||
export type TUserActionsUpdate = Partial<Omit<TUserActions, TImmutableDBKeys>>;
|
||||
export type TUserActionsInsert = Omit<z.input<typeof UserActionsSchema>, TImmutableDBKeys>;
|
||||
export type TUserActionsUpdate = Partial<Omit<z.input<typeof UserActionsSchema>, TImmutableDBKeys>>;
|
||||
|
@ -25,5 +25,5 @@ export const UserEncryptionKeysSchema = z.object({
|
||||
});
|
||||
|
||||
export type TUserEncryptionKeys = z.infer<typeof UserEncryptionKeysSchema>;
|
||||
export type TUserEncryptionKeysInsert = Omit<TUserEncryptionKeys, TImmutableDBKeys>;
|
||||
export type TUserEncryptionKeysUpdate = Partial<Omit<TUserEncryptionKeys, TImmutableDBKeys>>;
|
||||
export type TUserEncryptionKeysInsert = Omit<z.input<typeof UserEncryptionKeysSchema>, TImmutableDBKeys>;
|
||||
export type TUserEncryptionKeysUpdate = Partial<Omit<z.input<typeof UserEncryptionKeysSchema>, TImmutableDBKeys>>;
|
||||
|
@ -24,5 +24,5 @@ export const UsersSchema = z.object({
|
||||
});
|
||||
|
||||
export type TUsers = z.infer<typeof UsersSchema>;
|
||||
export type TUsersInsert = Omit<TUsers, TImmutableDBKeys>;
|
||||
export type TUsersUpdate = Partial<Omit<TUsers, TImmutableDBKeys>>;
|
||||
export type TUsersInsert = Omit<z.input<typeof UsersSchema>, TImmutableDBKeys>;
|
||||
export type TUsersUpdate = Partial<Omit<z.input<typeof UsersSchema>, TImmutableDBKeys>>;
|
||||
|
@ -25,5 +25,5 @@ export const WebhooksSchema = z.object({
|
||||
});
|
||||
|
||||
export type TWebhooks = z.infer<typeof WebhooksSchema>;
|
||||
export type TWebhooksInsert = Omit<TWebhooks, TImmutableDBKeys>;
|
||||
export type TWebhooksUpdate = Partial<Omit<TWebhooks, TImmutableDBKeys>>;
|
||||
export type TWebhooksInsert = Omit<z.input<typeof WebhooksSchema>, TImmutableDBKeys>;
|
||||
export type TWebhooksUpdate = Partial<Omit<z.input<typeof WebhooksSchema>, TImmutableDBKeys>>;
|
||||
|
@ -505,6 +505,9 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }:
|
||||
get isValidLicense() {
|
||||
return isValidLicense;
|
||||
},
|
||||
getInstanceType() {
|
||||
return instanceType;
|
||||
},
|
||||
getPlan,
|
||||
updateSubscriptionOrgMemberCount,
|
||||
refreshPlan,
|
||||
|
@ -240,7 +240,7 @@ export const secretRotationQueueFactory = ({
|
||||
);
|
||||
});
|
||||
|
||||
telemetryService.sendPostHogEvents({
|
||||
await telemetryService.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretRotated,
|
||||
distinctId: "",
|
||||
properties: {
|
||||
|
@ -158,7 +158,7 @@ export const secretScanningQueueFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
telemetryService.sendPostHogEvents({
|
||||
await telemetryService.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretScannerPush,
|
||||
distinctId: repository.fullName,
|
||||
properties: {
|
||||
@ -228,7 +228,7 @@ export const secretScanningQueueFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
telemetryService.sendPostHogEvents({
|
||||
await telemetryService.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretScannerFull,
|
||||
distinctId: repository.fullName,
|
||||
properties: {
|
||||
|
@ -1,188 +0,0 @@
|
||||
import { URL } from "node:url";
|
||||
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { Server as WebSocketServer, ServerOptions, WebSocket } from "ws";
|
||||
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip";
|
||||
import { ActorType, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
import { TIdentityAccessTokenDALFactory } from "@app/services/identity-access-token/identity-access-token-dal";
|
||||
import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
|
||||
import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-token/identity-access-token-types";
|
||||
|
||||
type TEventSubscriptionFactoryDep = {
|
||||
identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
|
||||
identityAccessTokenServiceFactory: TIdentityAccessTokenServiceFactory;
|
||||
permissionService: TPermissionServiceFactory;
|
||||
};
|
||||
|
||||
enum AuthenticationErrors {
|
||||
NO_PROJECT_ID = "Unauthorized. Project ID is missing",
|
||||
NO_MACHINE = "Unauthorized. Machine Identity Access Token is missing",
|
||||
INVALID_TOKEN_TYPE = "Unauthorized. Invalid token type",
|
||||
INVALID_TOKEN = "Unauthorized. Invalid token",
|
||||
NO_PERMISSION = "Unauthorized. No permission to access project"
|
||||
}
|
||||
|
||||
export type TEventSubscriptionFactory = ReturnType<typeof eventSubscriptionFactory>;
|
||||
|
||||
export const eventSubscriptionFactory = ({
|
||||
identityAccessTokenDAL,
|
||||
permissionService,
|
||||
identityAccessTokenServiceFactory
|
||||
}: TEventSubscriptionFactoryDep) => {
|
||||
const config = getConfig();
|
||||
let connection: WebSocketServer | null = null;
|
||||
const clients = new Map<string, WebSocket[]>();
|
||||
|
||||
const verifyConnection: ServerOptions["verifyClient"] = (info, cb) => {
|
||||
void (async () => {
|
||||
const machineIdentityAccessToken = info.req.headers["machine-identity-access-token"];
|
||||
const projectId = info.req.headers["project-id"];
|
||||
|
||||
if (!projectId || typeof projectId !== "string") {
|
||||
cb(false, 401, AuthenticationErrors.NO_PROJECT_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!machineIdentityAccessToken || typeof machineIdentityAccessToken !== "string") {
|
||||
cb(false, 401, AuthenticationErrors.NO_MACHINE);
|
||||
return;
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(machineIdentityAccessToken, config.AUTH_SECRET) as TIdentityAccessTokenJwtPayload;
|
||||
|
||||
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) {
|
||||
cb(false, 401, AuthenticationErrors.INVALID_TOKEN_TYPE);
|
||||
return;
|
||||
}
|
||||
|
||||
await identityAccessTokenServiceFactory.fnValidateIdentityAccessToken(
|
||||
decodedToken,
|
||||
info.req.socket.remoteAddress
|
||||
);
|
||||
|
||||
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
||||
[`${TableName.IdentityAccessToken}.id` as "id"]: decodedToken.identityAccessTokenId,
|
||||
isAccessTokenRevoked: false
|
||||
});
|
||||
|
||||
if (!identityAccessToken) {
|
||||
cb(false, 401, AuthenticationErrors.INVALID_TOKEN);
|
||||
return;
|
||||
}
|
||||
|
||||
const ipAddress = info.req.socket.remoteAddress;
|
||||
|
||||
if (ipAddress) {
|
||||
// This throws, and im not sure if it really should. TODO
|
||||
checkIPAgainstBlocklist({
|
||||
ipAddress,
|
||||
trustedIps: identityAccessToken?.accessTokenTrustedIps as TIp[]
|
||||
});
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
ActorType.IDENTITY,
|
||||
identityAccessToken.identityId,
|
||||
projectId
|
||||
);
|
||||
try {
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets);
|
||||
} catch (err) {
|
||||
cb(false, 401, AuthenticationErrors.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
|
||||
cb(true);
|
||||
})();
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
if (connection) return;
|
||||
|
||||
connection = new WebSocketServer({
|
||||
port: 8091,
|
||||
verifyClient: verifyConnection
|
||||
});
|
||||
|
||||
// Purely for testing purposes.
|
||||
connection.on("connection", (ws) => {
|
||||
const projectId = new URL(ws.url).searchParams.get("projectId");
|
||||
|
||||
if (!projectId) {
|
||||
ws.send("Unauthorized. Project ID is missing");
|
||||
ws.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clients.has(projectId)) {
|
||||
clients.set(projectId, []);
|
||||
}
|
||||
clients.get(projectId)?.push(ws);
|
||||
|
||||
ws.on("message", (message) => {
|
||||
console.log("received: %s", message);
|
||||
});
|
||||
|
||||
ws.on("close", () => {
|
||||
const projectClients = clients.get(projectId);
|
||||
|
||||
if (!projectClients) return;
|
||||
|
||||
const index = projectClients.indexOf(ws);
|
||||
|
||||
if (index !== -1) {
|
||||
projectClients.splice(index, 1);
|
||||
}
|
||||
|
||||
if (projectClients.length === 0) {
|
||||
clients.delete(projectId);
|
||||
} else {
|
||||
clients.set(projectId, projectClients);
|
||||
}
|
||||
});
|
||||
|
||||
ws.send("Connected.");
|
||||
});
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const sendNotification = (projectId: string) => {
|
||||
const MESSAGE = "NEW_CHANGE";
|
||||
|
||||
if (!connection) {
|
||||
throw new Error("Connection not initialized");
|
||||
}
|
||||
|
||||
for (const client of connection.clients) {
|
||||
client.send(MESSAGE);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
init
|
||||
};
|
||||
};
|
||||
|
||||
// var WebSocketServer = require("ws").Server;
|
||||
// var ws = new WebSocketServer({
|
||||
// verifyClient: function (info, cb) {
|
||||
// var token = info.req.headers.token;
|
||||
// if (!token) cb(false, 401, "Unauthorized");
|
||||
// else {
|
||||
// jwt.verify(token, "secret-key", function (err, decoded) {
|
||||
// if (err) {
|
||||
// cb(false, 401, "Unauthorized");
|
||||
// } else {
|
||||
// info.req.user = decoded; //[1]
|
||||
// cb(true);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// });
|
20
backend/src/keystore/keystore.ts
Normal file
20
backend/src/keystore/keystore.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { Redis } from "ioredis";
|
||||
|
||||
export type TKeyStoreFactory = ReturnType<typeof keyStoreFactory>;
|
||||
|
||||
export const keyStoreFactory = (redisUrl: string) => {
|
||||
const redis = new Redis(redisUrl);
|
||||
|
||||
const setItem = async (key: string, value: string | number | Buffer) => redis.set(key, value);
|
||||
|
||||
const getItem = async (key: string) => redis.get(key);
|
||||
|
||||
const setItemWithExpiry = async (key: string, exp: number | string, value: string | number | Buffer) =>
|
||||
redis.setex(key, exp, value);
|
||||
|
||||
const deleteItem = async (key: string) => redis.del(key);
|
||||
|
||||
const incrementBy = async (key: string, value: number) => redis.incrby(key, value);
|
||||
|
||||
return { setItem, getItem, setItemWithExpiry, deleteItem, incrementBy };
|
||||
};
|
@ -94,14 +94,17 @@ const envSchema = z
|
||||
SECRET_SCANNING_WEBHOOK_SECRET: zpStr(z.string().optional()),
|
||||
SECRET_SCANNING_GIT_APP_ID: zpStr(z.string().optional()),
|
||||
SECRET_SCANNING_PRIVATE_KEY: zpStr(z.string().optional()),
|
||||
// LICENCE
|
||||
// LICENSE
|
||||
LICENSE_SERVER_URL: zpStr(z.string().optional().default("https://portal.infisical.com")),
|
||||
LICENSE_SERVER_KEY: zpStr(z.string().optional()),
|
||||
LICENSE_KEY: zpStr(z.string().optional()),
|
||||
|
||||
// GENERIC
|
||||
STANDALONE_MODE: z
|
||||
.enum(["true", "false"])
|
||||
.transform((val) => val === "true")
|
||||
.optional()
|
||||
.optional(),
|
||||
INFISICAL_CLOUD: zodStrBool.default("false")
|
||||
})
|
||||
.transform((data) => ({
|
||||
...data,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import dotenv from "dotenv";
|
||||
|
||||
import { initDbConnection } from "./db";
|
||||
import { keyStoreFactory } from "./keystore/keystore";
|
||||
import { formatSmtpConfig, initEnvConfig } from "./lib/config/env";
|
||||
import { initLogger } from "./lib/logger";
|
||||
import { queueServiceFactory } from "./queue";
|
||||
@ -19,8 +20,9 @@ const run = async () => {
|
||||
|
||||
const smtp = smtpServiceFactory(formatSmtpConfig());
|
||||
const queue = queueServiceFactory(appCfg.REDIS_URL);
|
||||
const keyStore = keyStoreFactory(appCfg.REDIS_URL);
|
||||
|
||||
const server = await main({ db, smtp, logger, queue });
|
||||
const server = await main({ db, smtp, logger, queue, keyStore });
|
||||
const bootstrap = await bootstrapCheck({ db });
|
||||
// eslint-disable-next-line
|
||||
process.on("SIGINT", async () => {
|
||||
|
@ -13,6 +13,7 @@ export enum QueueName {
|
||||
SecretReminder = "secret-reminder",
|
||||
AuditLog = "audit-log",
|
||||
AuditLogPrune = "audit-log-prune",
|
||||
TelemetryInstanceStats = "telemtry-self-hosted-stats",
|
||||
IntegrationSync = "sync-integrations",
|
||||
SecretWebhook = "secret-webhook",
|
||||
SecretFullRepoScan = "secret-full-repo-scan",
|
||||
@ -26,6 +27,7 @@ export enum QueueJobs {
|
||||
AuditLog = "audit-log-job",
|
||||
AuditLogPrune = "audit-log-prune-job",
|
||||
SecWebhook = "secret-webhook-trigger",
|
||||
TelemetryInstanceStats = "telemetry-self-hosted-stats",
|
||||
IntegrationSync = "secret-integration-pull",
|
||||
SecretScan = "secret-scan",
|
||||
UpgradeProjectToGhost = "upgrade-project-to-ghost-job"
|
||||
@ -67,7 +69,6 @@ export type TQueueJobTypes = {
|
||||
payload: TScanFullRepoEventPayload;
|
||||
};
|
||||
[QueueName.SecretPushEventScan]: { name: QueueJobs.SecretScan; payload: TScanPushEventPayload };
|
||||
|
||||
[QueueName.UpgradeProjectToGhost]: {
|
||||
name: QueueJobs.UpgradeProjectToGhost;
|
||||
payload: {
|
||||
@ -81,6 +82,10 @@ export type TQueueJobTypes = {
|
||||
};
|
||||
};
|
||||
};
|
||||
[QueueName.TelemetryInstanceStats]: {
|
||||
name: QueueJobs.TelemetryInstanceStats;
|
||||
payload: undefined;
|
||||
};
|
||||
};
|
||||
|
||||
export type TQueueServiceFactory = ReturnType<typeof queueServiceFactory>;
|
||||
|
@ -14,6 +14,7 @@ import fasitfy from "fastify";
|
||||
import { Knex } from "knex";
|
||||
import { Logger } from "pino";
|
||||
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { TQueueServiceFactory } from "@app/queue";
|
||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||
@ -31,10 +32,11 @@ type TMain = {
|
||||
smtp: TSmtpService;
|
||||
logger?: Logger;
|
||||
queue: TQueueServiceFactory;
|
||||
keyStore: TKeyStoreFactory;
|
||||
};
|
||||
|
||||
// Run the server!
|
||||
export const main = async ({ db, smtp, logger, queue }: TMain) => {
|
||||
export const main = async ({ db, smtp, logger, queue, keyStore }: TMain) => {
|
||||
const appCfg = getConfig();
|
||||
const server = fasitfy({
|
||||
logger: appCfg.NODE_ENV === "test" ? false : logger,
|
||||
@ -70,7 +72,7 @@ export const main = async ({ db, smtp, logger, queue }: TMain) => {
|
||||
}
|
||||
await server.register(helmet, { contentSecurityPolicy: false });
|
||||
|
||||
await server.register(registerRoutes, { smtp, queue, db });
|
||||
await server.register(registerRoutes, { smtp, queue, db, keyStore });
|
||||
|
||||
if (appCfg.isProductionMode) {
|
||||
await server.register(registerExternalNextjs, {
|
||||
|
@ -1,47 +0,0 @@
|
||||
import { FastifyPluginAsync, FastifyReply } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
export const serversideEvents: FastifyPluginAsync = fp(async function serversideEventsPlgin(instance): Promise<void> {
|
||||
instance.decorateReply("sse", function handler(this: FastifyReply, input): void {
|
||||
// if this already set, it's not first event
|
||||
if (!this.raw.headersSent) {
|
||||
console.log("Setting headers");
|
||||
Object.entries(this.getHeaders()).forEach(([key, value]) => {
|
||||
this.raw.setHeader(key, value ?? "");
|
||||
});
|
||||
this.raw.setHeader("Cache-Control", "no-cache");
|
||||
this.raw.setHeader("Content-Type", "text/event-stream");
|
||||
this.raw.setHeader("Access-Control-Allow-Origin", "*");
|
||||
this.raw.setHeader("Connection", "keep-alive");
|
||||
this.raw.flushHeaders(); // flush the headers to establish SSE with client
|
||||
|
||||
// Ngnix will close idle connections even if the connection is keep-alive. So we send a ping every 15 seconds to keep the connection truly alive.
|
||||
const interval = setInterval(() => {
|
||||
console.log("Sending ping");
|
||||
if (!this.raw.writableEnded) {
|
||||
this.raw.write("event: ping\n");
|
||||
this.raw.write("data: Heartbeat\n\n");
|
||||
}
|
||||
}, 15_000);
|
||||
|
||||
this.raw.on("close", () => {
|
||||
console.log("Connection closed");
|
||||
clearInterval(interval);
|
||||
this.raw.end();
|
||||
});
|
||||
}
|
||||
|
||||
if (input.error) {
|
||||
this.raw.write("event: error\n");
|
||||
this.raw.write(
|
||||
`data: ${JSON.stringify({
|
||||
error: input.errorMessage
|
||||
})}\n\n`
|
||||
);
|
||||
this.raw.end();
|
||||
return;
|
||||
}
|
||||
|
||||
this.raw.write(`data: ${input.data}\n\n`); // res.write() instead of res.send()
|
||||
});
|
||||
});
|
@ -34,9 +34,9 @@ import { snapshotFolderDALFactory } from "@app/ee/services/secret-snapshot/snaps
|
||||
import { snapshotSecretDALFactory } from "@app/ee/services/secret-snapshot/snapshot-secret-dal";
|
||||
import { trustedIpDALFactory } from "@app/ee/services/trusted-ip/trusted-ip-dal";
|
||||
import { trustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-service";
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { TQueueServiceFactory } from "@app/queue";
|
||||
import { serversideEvents } from "@app/server/plugins/sse";
|
||||
import { apiKeyDALFactory } from "@app/services/api-key/api-key-dal";
|
||||
import { apiKeyServiceFactory } from "@app/services/api-key/api-key-service";
|
||||
import { authDALFactory } from "@app/services/auth/auth-dal";
|
||||
@ -45,7 +45,6 @@ import { authPaswordServiceFactory } from "@app/services/auth/auth-password-serv
|
||||
import { authSignupServiceFactory } from "@app/services/auth/auth-signup-service";
|
||||
import { tokenDALFactory } from "@app/services/auth-token/auth-token-dal";
|
||||
import { tokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
||||
import { eventServiceFactory } from "@app/services/event/event-service";
|
||||
import { identityDALFactory } from "@app/services/identity/identity-dal";
|
||||
import { identityOrgDALFactory } from "@app/services/identity/identity-org-dal";
|
||||
import { identityServiceFactory } from "@app/services/identity/identity-service";
|
||||
@ -98,6 +97,8 @@ import { serviceTokenServiceFactory } from "@app/services/service-token/service-
|
||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||
import { getServerCfg, superAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
|
||||
import { telemetryDALFactory } from "@app/services/telemetry/telemetry-dal";
|
||||
import { telemetryQueueServiceFactory } from "@app/services/telemetry/telemetry-queue";
|
||||
import { telemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
||||
import { userDALFactory } from "@app/services/user/user-dal";
|
||||
import { userServiceFactory } from "@app/services/user/user-service";
|
||||
@ -114,12 +115,15 @@ import { registerV3Routes } from "./v3";
|
||||
|
||||
export const registerRoutes = async (
|
||||
server: FastifyZodProvider,
|
||||
{ db, smtp: smtpService, queue: queueService }: { db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory }
|
||||
{
|
||||
db,
|
||||
smtp: smtpService,
|
||||
queue: queueService,
|
||||
keyStore
|
||||
}: { db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory; keyStore: TKeyStoreFactory }
|
||||
) => {
|
||||
await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" });
|
||||
|
||||
const cfg = getConfig();
|
||||
|
||||
// db layers
|
||||
const userDAL = userDALFactory(db);
|
||||
const authDAL = authDALFactory(db);
|
||||
@ -163,6 +167,7 @@ export const registerRoutes = async (
|
||||
const auditLogDAL = auditLogDALFactory(db);
|
||||
const trustedIpDAL = trustedIpDALFactory(db);
|
||||
const scimDAL = scimDALFactory(db);
|
||||
const telemetryDAL = telemetryDALFactory(db);
|
||||
|
||||
// ee db layer ops
|
||||
const permissionDAL = permissionDALFactory(db);
|
||||
@ -230,7 +235,16 @@ export const registerRoutes = async (
|
||||
smtpService
|
||||
});
|
||||
|
||||
const telemetryService = telemetryServiceFactory();
|
||||
const telemetryService = telemetryServiceFactory({
|
||||
keyStore,
|
||||
licenseService
|
||||
});
|
||||
const telemetryQueue = telemetryQueueServiceFactory({
|
||||
keyStore,
|
||||
telemetryDAL,
|
||||
queueService
|
||||
});
|
||||
|
||||
const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL });
|
||||
const userService = userServiceFactory({ userDAL });
|
||||
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService });
|
||||
@ -267,7 +281,8 @@ export const registerRoutes = async (
|
||||
userDAL,
|
||||
authService: loginService,
|
||||
serverCfgDAL: superAdminDAL,
|
||||
orgService
|
||||
orgService,
|
||||
keyStore
|
||||
});
|
||||
const apiKeyService = apiKeyServiceFactory({ apiKeyDAL, userDAL });
|
||||
|
||||
@ -494,12 +509,14 @@ export const registerRoutes = async (
|
||||
licenseService
|
||||
});
|
||||
|
||||
const eventService = eventServiceFactory({ redisUrl: cfg.REDIS_URL });
|
||||
|
||||
await superAdminService.initServerCfg();
|
||||
await auditLogQueue.startAuditLogPruneJob();
|
||||
//
|
||||
// setup the communication with license key server
|
||||
await licenseService.init();
|
||||
|
||||
await auditLogQueue.startAuditLogPruneJob();
|
||||
await telemetryQueue.startTelemetryCheck();
|
||||
|
||||
// inject all services
|
||||
server.decorate<FastifyZodProvider["services"]>("services", {
|
||||
login: loginService,
|
||||
@ -541,8 +558,7 @@ export const registerRoutes = async (
|
||||
trustedIp: trustedIpService,
|
||||
scim: scimService,
|
||||
secretBlindIndex: secretBlindIndexService,
|
||||
telemetry: telemetryService,
|
||||
event: eventService
|
||||
telemetry: telemetryService
|
||||
});
|
||||
|
||||
server.decorate<FastifyZodProvider["store"]>("store", {
|
||||
@ -552,7 +568,6 @@ export const registerRoutes = async (
|
||||
await server.register(injectIdentity, { userDAL, serviceTokenDAL });
|
||||
await server.register(injectPermission);
|
||||
await server.register(injectAuditLogInfo);
|
||||
await server.register(serversideEvents, { prefix: "/api/v1/sse" });
|
||||
|
||||
server.route({
|
||||
url: "/api/status",
|
||||
@ -570,6 +585,7 @@ export const registerRoutes = async (
|
||||
}
|
||||
},
|
||||
handler: async () => {
|
||||
const cfg = getConfig();
|
||||
const serverCfg = await getServerCfg();
|
||||
return {
|
||||
date: new Date(),
|
||||
|
@ -16,7 +16,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
config: SuperAdminSchema
|
||||
config: SuperAdminSchema.omit({ createdAt: true, updatedAt: true })
|
||||
})
|
||||
}
|
||||
},
|
||||
@ -90,7 +90,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
||||
userAgent: req.headers["user-agent"] || ""
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.AdminInit,
|
||||
distinctId: user.user.email,
|
||||
properties: {
|
||||
|
@ -51,7 +51,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.MachineIdentityCreated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
|
@ -16,7 +16,6 @@ import { registerProjectRouter } from "./project-router";
|
||||
import { registerSecretFolderRouter } from "./secret-folder-router";
|
||||
import { registerSecretImportRouter } from "./secret-import-router";
|
||||
import { registerSecretTagRouter } from "./secret-tag-router";
|
||||
import { registerServersideEventsRouter } from "./sse-router";
|
||||
import { registerSsoRouter } from "./sso-router";
|
||||
import { registerUserActionRouter } from "./user-action-router";
|
||||
import { registerUserRouter } from "./user-router";
|
||||
@ -58,5 +57,4 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
|
||||
await server.register(registerIntegrationAuthRouter, { prefix: "/integration-auth" });
|
||||
await server.register(registerWebhookRouter, { prefix: "/webhooks" });
|
||||
await server.register(registerIdentityRouter, { prefix: "/identities" });
|
||||
await server.register(registerServersideEventsRouter, { prefix: "/sse" });
|
||||
};
|
||||
|
@ -82,7 +82,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.IntegrationCreated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
|
@ -32,7 +32,7 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.UserOrgInvitation,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
|
@ -1,48 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { logger } from "@app/lib/logger";
|
||||
|
||||
export const registerServersideEventsRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/events/:projectId",
|
||||
schema: {
|
||||
params: z.object({
|
||||
projectId: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.string()
|
||||
}
|
||||
},
|
||||
// onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req, res) => {
|
||||
res.sse({
|
||||
data: JSON.stringify({
|
||||
message: "Connected to event stream"
|
||||
})
|
||||
});
|
||||
|
||||
const subscription = await server.services.event.crateSubscription(req.params.projectId);
|
||||
|
||||
// It's OK to create a event listener here, because it's tied to the local subscription instance. So once the function ends, the listener is removed along with the subscription.
|
||||
// No need to worry about memory leaks!
|
||||
subscription
|
||||
.on("message", (channel, message) => {
|
||||
if (channel === req.params.projectId)
|
||||
res.sse({
|
||||
data: JSON.stringify(message)
|
||||
});
|
||||
})
|
||||
.on("error", (error) => {
|
||||
logger.error(error, "Error in subscription");
|
||||
res.sse({
|
||||
error: true,
|
||||
errorMessage: error.message // ? Should we really return the error message to the client?
|
||||
});
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/return-await, @typescript-eslint/no-misused-promises
|
||||
req.socket.on("close", async () => await subscription.unsubscribe());
|
||||
}
|
||||
});
|
||||
};
|
@ -154,7 +154,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
slug: req.body.slug
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.ProjectCreated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
|
@ -16,7 +16,6 @@ import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { getUserAgentType } from "@app/server/plugins/audit-log";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
import { TEventType } from "@app/services/event/event-types";
|
||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
import { secretRawSchema } from "../sanitizedSchemas";
|
||||
@ -96,7 +95,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretPulled,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -186,7 +185,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretPulled,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -262,7 +261,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretCreated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -337,7 +336,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretUpdated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -407,7 +406,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretDeleted,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -513,7 +512,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
(req.headers["user-agent"] !== "k8-operator" || shouldRecordK8Event);
|
||||
const approximateNumberTotalSecrets = secrets.length * 20;
|
||||
if (shouldCapture) {
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretPulled,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -590,7 +589,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretPulled,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -753,7 +752,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretCreated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -920,15 +919,6 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
newSecretName
|
||||
});
|
||||
|
||||
await server.services.event.publish(req.body.workspaceId, {
|
||||
type: TEventType.SECRET_UPDATE,
|
||||
payload: {
|
||||
secretId: secret.id,
|
||||
secretKey: req.params.secretName,
|
||||
secretPath: "test/path"
|
||||
}
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
projectId: req.body.workspaceId,
|
||||
...req.auditLogInfo,
|
||||
@ -944,7 +934,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretUpdated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -1062,7 +1052,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretDeleted,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -1182,7 +1172,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretCreated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -1302,7 +1292,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretUpdated,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
@ -1410,7 +1400,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.services.telemetry.sendPostHogEvents({
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.SecretDeleted,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
|
@ -1,87 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
import Redis from "ioredis";
|
||||
|
||||
// import { logger } from "@app/lib/logger";
|
||||
import { TEvent, TEventType } from "./event-types";
|
||||
|
||||
type TEventServiceFactoryDep = {
|
||||
redisUrl: string;
|
||||
};
|
||||
|
||||
export type TEventServiceFactory = ReturnType<typeof eventServiceFactory>;
|
||||
|
||||
export const eventServiceFactory = ({ redisUrl }: TEventServiceFactoryDep) => {
|
||||
const publisher = new Redis(redisUrl, { maxRetriesPerRequest: null });
|
||||
|
||||
// Map key: the channel ID.
|
||||
// connections / total number of connections: We keep track of this to know when to unsubscribe and disconnect the client.
|
||||
// client / the subscription: We store this so we can use the same connection/subscription for the same channel. We don't want to create a new connection for each subscription, because that would be a waste of resources and become hard to scale.
|
||||
const redisClients = new Map<
|
||||
string,
|
||||
{
|
||||
client: Redis;
|
||||
connections: number;
|
||||
}
|
||||
>();
|
||||
// Will this work for vertical scaling? The redisClients
|
||||
|
||||
// channel would be the projectId
|
||||
const publish = async (channel: string, event: TEvent[TEventType]) => {
|
||||
await publisher.publish(channel, JSON.stringify(event));
|
||||
};
|
||||
|
||||
const crateSubscription = async (channel: string) => {
|
||||
let subscriber: Redis | null = null;
|
||||
|
||||
const existingSubscriber = redisClients.get(channel);
|
||||
|
||||
if (existingSubscriber) {
|
||||
redisClients.set(channel, {
|
||||
client: existingSubscriber.client,
|
||||
connections: existingSubscriber.connections + 1
|
||||
});
|
||||
|
||||
subscriber = existingSubscriber.client;
|
||||
} else {
|
||||
subscriber = new Redis(redisUrl, { maxRetriesPerRequest: null });
|
||||
|
||||
redisClients.set(channel, {
|
||||
client: subscriber,
|
||||
connections: 1
|
||||
});
|
||||
}
|
||||
|
||||
await subscriber.subscribe(channel, (msg) => {
|
||||
if (msg instanceof Error) {
|
||||
throw msg;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
on: subscriber.on.bind(subscriber),
|
||||
unsubscribe: async () => {
|
||||
const subscriberToRemove = redisClients.get(channel);
|
||||
|
||||
if (subscriberToRemove) {
|
||||
// If there's only 1 connection, we can fully unsubscribe and disconnect the client.
|
||||
if (subscriberToRemove.connections === 1) {
|
||||
await subscriberToRemove.client.unsubscribe(`${channel}`);
|
||||
await subscriberToRemove.client.quit();
|
||||
redisClients.delete(channel);
|
||||
} else {
|
||||
// If there's more than 1 connection, we just decrement the connections count, because there are still other listeners.
|
||||
redisClients.set(channel, {
|
||||
client: subscriberToRemove.client,
|
||||
connections: subscriberToRemove.connections - 1
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
publish,
|
||||
crateSubscription
|
||||
};
|
||||
};
|
@ -1,35 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export enum TEventType {
|
||||
SECRET_UPDATE = "secret_update",
|
||||
SECRET_DELETE = "secret_delete",
|
||||
SECRET_CREATE = "secret_create"
|
||||
}
|
||||
|
||||
export const EventSchema = z.object({
|
||||
secret_create: z.object({
|
||||
payload: z.object({
|
||||
secretId: z.string(),
|
||||
secretKey: z.string(),
|
||||
secretPath: z.string()
|
||||
}),
|
||||
type: z.literal("secret_create")
|
||||
}),
|
||||
secret_update: z.object({
|
||||
payload: z.object({
|
||||
secretId: z.string(),
|
||||
secretKey: z.string(),
|
||||
secretPath: z.string()
|
||||
}),
|
||||
type: z.literal("secret_update")
|
||||
}),
|
||||
secret_delete: z.object({
|
||||
payload: z.object({
|
||||
secretId: z.string(),
|
||||
secretPath: z.string()
|
||||
}),
|
||||
type: z.literal("secret_delete")
|
||||
})
|
||||
});
|
||||
|
||||
export type TEvent = z.infer<typeof EventSchema>;
|
@ -238,6 +238,8 @@ export const projectMembershipServiceFactory = ({
|
||||
|
||||
if (orgMembers.length !== emails.length) throw new BadRequestError({ message: "Some users are not part of org" });
|
||||
|
||||
if (!orgMembers.length) return [];
|
||||
|
||||
const existingMembers = await projectMembershipDAL.find({
|
||||
projectId,
|
||||
$in: { userId: orgMembers.map(({ user }) => user.id).filter(Boolean) }
|
||||
|
@ -19,7 +19,7 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe
|
||||
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags);
|
||||
|
||||
const existingTag = await secretTagDAL.findOne({ slug });
|
||||
const existingTag = await secretTagDAL.findOne({ slug, projectId });
|
||||
if (existingTag) throw new BadRequestError({ message: "Tag already exist" });
|
||||
|
||||
const newTag = await secretTagDAL.create({
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TSuperAdmin, TSuperAdminUpdate } from "@app/db/schemas";
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
|
||||
@ -14,6 +15,7 @@ type TSuperAdminServiceFactoryDep = {
|
||||
userDAL: TUserDALFactory;
|
||||
authService: Pick<TAuthLoginFactory, "generateUserTokens">;
|
||||
orgService: Pick<TOrgServiceFactory, "createOrganization">;
|
||||
keyStore: Pick<TKeyStoreFactory, "getItem" | "setItemWithExpiry" | "deleteItem">;
|
||||
};
|
||||
|
||||
export type TSuperAdminServiceFactory = ReturnType<typeof superAdminServiceFactory>;
|
||||
@ -21,26 +23,53 @@ export type TSuperAdminServiceFactory = ReturnType<typeof superAdminServiceFacto
|
||||
// eslint-disable-next-line
|
||||
export let getServerCfg: () => Promise<TSuperAdmin>;
|
||||
|
||||
const ADMIN_CONFIG_KEY = "infisical-admin-cfg";
|
||||
const ADMIN_CONFIG_KEY_EXP = 60; // 60s
|
||||
const ADMIN_CONFIG_DB_UUID = "00000000-0000-0000-0000-000000000000";
|
||||
|
||||
export const superAdminServiceFactory = ({
|
||||
serverCfgDAL,
|
||||
userDAL,
|
||||
authService,
|
||||
orgService
|
||||
orgService,
|
||||
keyStore
|
||||
}: TSuperAdminServiceFactoryDep) => {
|
||||
const initServerCfg = async () => {
|
||||
// TODO(akhilmhdh): bad pattern time less change this later to me itself
|
||||
getServerCfg = () => serverCfgDAL.findOne({});
|
||||
getServerCfg = async () => {
|
||||
const config = await keyStore.getItem(ADMIN_CONFIG_KEY);
|
||||
// missing in keystore means fetch from db
|
||||
if (!config) {
|
||||
const serverCfg = await serverCfgDAL.findById(ADMIN_CONFIG_DB_UUID);
|
||||
if (serverCfg) {
|
||||
await keyStore.setItemWithExpiry(ADMIN_CONFIG_KEY, ADMIN_CONFIG_KEY_EXP, JSON.stringify(serverCfg)); // insert it back to keystore
|
||||
}
|
||||
return serverCfg;
|
||||
}
|
||||
|
||||
const serverCfg = await serverCfgDAL.findOne({});
|
||||
const keyStoreServerCfg = JSON.parse(config) as TSuperAdmin;
|
||||
return {
|
||||
...keyStoreServerCfg,
|
||||
// this is to allow admin router to work
|
||||
createdAt: new Date(keyStoreServerCfg.createdAt),
|
||||
updatedAt: new Date(keyStoreServerCfg.updatedAt)
|
||||
};
|
||||
};
|
||||
|
||||
// reset on initialized
|
||||
await keyStore.deleteItem(ADMIN_CONFIG_KEY);
|
||||
const serverCfg = await serverCfgDAL.findById(ADMIN_CONFIG_DB_UUID);
|
||||
if (serverCfg) return;
|
||||
const newCfg = await serverCfgDAL.create({ initialized: false, allowSignUp: true });
|
||||
|
||||
// @ts-expect-error id is kept as fixed for idempotence and to avoid race condition
|
||||
const newCfg = await serverCfgDAL.create({ initialized: false, allowSignUp: true, id: ADMIN_CONFIG_DB_UUID });
|
||||
return newCfg;
|
||||
};
|
||||
|
||||
const updateServerCfg = async (data: TSuperAdminUpdate) => {
|
||||
const serverCfg = await getServerCfg();
|
||||
const cfg = await serverCfgDAL.updateById(serverCfg.id, data);
|
||||
return cfg;
|
||||
const updatedServerCfg = await serverCfgDAL.updateById(ADMIN_CONFIG_DB_UUID, data);
|
||||
await keyStore.setItemWithExpiry(ADMIN_CONFIG_KEY, ADMIN_CONFIG_KEY_EXP, JSON.stringify(updatedServerCfg));
|
||||
return updatedServerCfg;
|
||||
};
|
||||
|
||||
const adminSignUp = async ({
|
||||
|
39
backend/src/services/telemetry/telemetry-dal.ts
Normal file
39
backend/src/services/telemetry/telemetry-dal.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
|
||||
export type TTelemetryDALFactory = ReturnType<typeof telemetryDALFactory>;
|
||||
|
||||
export const telemetryDALFactory = (db: TDbClient) => {
|
||||
const getTelemetryInstanceStats = async () => {
|
||||
try {
|
||||
const userCount = (await db(TableName.Users).where({ isGhost: false }).count().first())?.count as string;
|
||||
const users = parseInt(userCount || "0", 10);
|
||||
|
||||
const identityCount = (await db(TableName.Identity).count().first())?.count as string;
|
||||
const identities = parseInt(identityCount || "0", 10);
|
||||
|
||||
const projectCount = (await db(TableName.Project).count().first())?.count as string;
|
||||
const projects = parseInt(projectCount || "0", 10);
|
||||
|
||||
const secretCount = (await db(TableName.Secret).count().first())?.count as string;
|
||||
const secrets = parseInt(secretCount || "0", 10);
|
||||
|
||||
const organizationNames = await db(TableName.Organization).select("name");
|
||||
const organizations = organizationNames.length;
|
||||
|
||||
return {
|
||||
users,
|
||||
identities,
|
||||
projects,
|
||||
secrets,
|
||||
organizations,
|
||||
organizationNames: organizationNames.map(({ name }) => name)
|
||||
};
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "TelemtryInstanceStats" });
|
||||
}
|
||||
};
|
||||
|
||||
return { getTelemetryInstanceStats };
|
||||
};
|
78
backend/src/services/telemetry/telemetry-queue.ts
Normal file
78
backend/src/services/telemetry/telemetry-queue.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import { PostHog } from "posthog-node";
|
||||
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
||||
|
||||
import { getServerCfg } from "../super-admin/super-admin-service";
|
||||
import { TTelemetryDALFactory } from "./telemetry-dal";
|
||||
import { TELEMETRY_SECRET_OPERATIONS_KEY, TELEMETRY_SECRET_PROCESSED_KEY } from "./telemetry-service";
|
||||
import { PostHogEventTypes } from "./telemetry-types";
|
||||
|
||||
type TTelemetryQueueServiceFactoryDep = {
|
||||
queueService: TQueueServiceFactory;
|
||||
keyStore: Pick<TKeyStoreFactory, "getItem" | "deleteItem">;
|
||||
telemetryDAL: TTelemetryDALFactory;
|
||||
};
|
||||
|
||||
export type TTelemetryQueueServiceFactory = ReturnType<typeof telemetryQueueServiceFactory>;
|
||||
|
||||
export const telemetryQueueServiceFactory = ({
|
||||
queueService,
|
||||
keyStore,
|
||||
telemetryDAL
|
||||
}: TTelemetryQueueServiceFactoryDep) => {
|
||||
const appCfg = getConfig();
|
||||
const postHog =
|
||||
appCfg.isProductionMode && appCfg.TELEMETRY_ENABLED
|
||||
? new PostHog(appCfg.POSTHOG_PROJECT_API_KEY, { host: appCfg.POSTHOG_HOST, flushAt: 1, flushInterval: 0 })
|
||||
: undefined;
|
||||
|
||||
queueService.start(QueueName.TelemetryInstanceStats, async () => {
|
||||
const { instanceId } = await getServerCfg();
|
||||
const telemtryStats = await telemetryDAL.getTelemetryInstanceStats();
|
||||
// parse the redis values into integer
|
||||
const numberOfSecretOperationsMade = parseInt((await keyStore.getItem(TELEMETRY_SECRET_OPERATIONS_KEY)) || "0", 10);
|
||||
const numberOfSecretProcessed = parseInt((await keyStore.getItem(TELEMETRY_SECRET_PROCESSED_KEY)) || "0", 10);
|
||||
const stats = { ...telemtryStats, numberOfSecretProcessed, numberOfSecretOperationsMade };
|
||||
|
||||
// send to postHog
|
||||
postHog?.capture({
|
||||
event: PostHogEventTypes.TelemetryInstanceStats,
|
||||
distinctId: instanceId,
|
||||
properties: stats
|
||||
});
|
||||
// reset the stats
|
||||
await keyStore.deleteItem(TELEMETRY_SECRET_PROCESSED_KEY);
|
||||
await keyStore.deleteItem(TELEMETRY_SECRET_OPERATIONS_KEY);
|
||||
});
|
||||
|
||||
// every day at midnight a telemetry job executes on self hosted
|
||||
// this sends some telemetry information like instance id secrets operated etc
|
||||
const startTelemetryCheck = async () => {
|
||||
// this is a fast way to check its cloud or not
|
||||
if (appCfg.INFISICAL_CLOUD) return;
|
||||
// clear previous job
|
||||
await queueService.stopRepeatableJob(
|
||||
QueueName.TelemetryInstanceStats,
|
||||
QueueJobs.TelemetryInstanceStats,
|
||||
{ pattern: "0 0 * * *", utc: true },
|
||||
QueueName.TelemetryInstanceStats // just a job id
|
||||
);
|
||||
if (postHog) {
|
||||
await queueService.queue(QueueName.TelemetryInstanceStats, QueueJobs.TelemetryInstanceStats, undefined, {
|
||||
jobId: QueueName.TelemetryInstanceStats,
|
||||
repeat: { pattern: "0 0 * * *", utc: true }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
queueService.listen(QueueName.TelemetryInstanceStats, "failed", (err) => {
|
||||
logger.error(err?.failedReason, `${QueueName.TelemetryInstanceStats}: failed`);
|
||||
});
|
||||
|
||||
return {
|
||||
startTelemetryCheck
|
||||
};
|
||||
};
|
@ -1,15 +1,24 @@
|
||||
import { PostHog } from "posthog-node";
|
||||
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { InstanceType } from "@app/ee/services/license/license-types";
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
import { logger } from "@app/lib/logger";
|
||||
|
||||
import { TPostHogEvent } from "./telemetry-types";
|
||||
import { PostHogEventTypes, TPostHogEvent, TSecretModifiedEvent } from "./telemetry-types";
|
||||
|
||||
export const TELEMETRY_SECRET_PROCESSED_KEY = "telemetry-secret-processed";
|
||||
export const TELEMETRY_SECRET_OPERATIONS_KEY = "telemetry-secret-operations";
|
||||
|
||||
export type TTelemetryServiceFactory = ReturnType<typeof telemetryServiceFactory>;
|
||||
export type TTelemetryServiceFactoryDep = {
|
||||
keyStore: Pick<TKeyStoreFactory, "getItem" | "incrementBy">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getInstanceType">;
|
||||
};
|
||||
|
||||
// type TTelemetryServiceFactoryDep = {};
|
||||
export const telemetryServiceFactory = () => {
|
||||
export const telemetryServiceFactory = ({ keyStore, licenseService }: TTelemetryServiceFactoryDep) => {
|
||||
const appCfg = getConfig();
|
||||
|
||||
if (appCfg.isProductionMode && !appCfg.TELEMETRY_ENABLED) {
|
||||
@ -21,10 +30,9 @@ To opt into telemetry, you can set "TELEMETRY_ENABLED=true" within the environme
|
||||
`);
|
||||
}
|
||||
|
||||
const postHog =
|
||||
appCfg.isProductionMode && appCfg.TELEMETRY_ENABLED
|
||||
? new PostHog(appCfg.POSTHOG_PROJECT_API_KEY, { host: appCfg.POSTHOG_HOST })
|
||||
: undefined;
|
||||
const postHog = appCfg.TELEMETRY_ENABLED
|
||||
? new PostHog(appCfg.POSTHOG_PROJECT_API_KEY, { host: appCfg.POSTHOG_HOST })
|
||||
: undefined;
|
||||
|
||||
// used for email marketting email sending purpose
|
||||
const sendLoopsEvent = async (email: string, firstName?: string, lastName?: string) => {
|
||||
@ -51,13 +59,33 @@ To opt into telemetry, you can set "TELEMETRY_ENABLED=true" within the environme
|
||||
}
|
||||
};
|
||||
|
||||
const sendPostHogEvents = (event: TPostHogEvent) => {
|
||||
const sendPostHogEvents = async (event: TPostHogEvent) => {
|
||||
if (postHog) {
|
||||
postHog.capture({
|
||||
event: event.event,
|
||||
distinctId: event.distinctId,
|
||||
properties: event.properties
|
||||
});
|
||||
const instanceType = licenseService.getInstanceType();
|
||||
// capture posthog only when its cloud or signup event happens in self hosted
|
||||
if (instanceType === InstanceType.Cloud || event.event === PostHogEventTypes.UserSignedUp) {
|
||||
postHog.capture({
|
||||
event: event.event,
|
||||
distinctId: event.distinctId,
|
||||
properties: event.properties
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
PostHogEventTypes.SecretPulled,
|
||||
PostHogEventTypes.SecretCreated,
|
||||
PostHogEventTypes.SecretDeleted,
|
||||
PostHogEventTypes.SecretUpdated
|
||||
].includes(event.event)
|
||||
) {
|
||||
await keyStore.incrementBy(
|
||||
TELEMETRY_SECRET_PROCESSED_KEY,
|
||||
(event as TSecretModifiedEvent).properties.numberOfSecrets
|
||||
);
|
||||
await keyStore.incrementBy(TELEMETRY_SECRET_OPERATIONS_KEY, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12,7 +12,8 @@ export enum PostHogEventTypes {
|
||||
ProjectCreated = "Project Created",
|
||||
IntegrationCreated = "Integration Created",
|
||||
MachineIdentityCreated = "Machine Identity Created",
|
||||
UserOrgInvitation = "User Org Invitation"
|
||||
UserOrgInvitation = "User Org Invitation",
|
||||
TelemetryInstanceStats = "Self Hosted Instance Stats"
|
||||
}
|
||||
|
||||
export type TSecretModifiedEvent = {
|
||||
@ -101,6 +102,20 @@ export type TUserOrgInvitedEvent = {
|
||||
};
|
||||
};
|
||||
|
||||
export type TTelemetryInstanceStatsEvent = {
|
||||
event: PostHogEventTypes.TelemetryInstanceStats;
|
||||
properties: {
|
||||
users: number;
|
||||
identities: number;
|
||||
projects: number;
|
||||
secrets: number;
|
||||
organizations: number;
|
||||
organizationNames: number;
|
||||
numberOfSecretOperationsMade: number;
|
||||
numberOfSecretProcessed: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type TPostHogEvent = { distinctId: string } & (
|
||||
| TSecretModifiedEvent
|
||||
| TAdminInitEvent
|
||||
@ -110,4 +125,5 @@ export type TPostHogEvent = { distinctId: string } & (
|
||||
| TMachineIdentityCreatedEvent
|
||||
| TIntegrationCreatedEvent
|
||||
| TProjectCreateEvent
|
||||
| TTelemetryInstanceStatsEvent
|
||||
);
|
||||
|
@ -87,16 +87,12 @@ var exportCmd = &cobra.Command{
|
||||
|
||||
var output string
|
||||
if shouldExpandSecrets {
|
||||
substitutions := util.ExpandSecrets(secrets, infisicalToken, "")
|
||||
output, err = formatEnvs(substitutions, format)
|
||||
if err != nil {
|
||||
util.HandleError(err)
|
||||
}
|
||||
} else {
|
||||
output, err = formatEnvs(secrets, format)
|
||||
if err != nil {
|
||||
util.HandleError(err)
|
||||
}
|
||||
secrets = util.ExpandSecrets(secrets, infisicalToken, "")
|
||||
}
|
||||
secrets = util.FilterSecretsByTag(secrets, tagSlugs)
|
||||
output, err = formatEnvs(secrets, format)
|
||||
if err != nil {
|
||||
util.HandleError(err)
|
||||
}
|
||||
|
||||
fmt.Print(output)
|
||||
|
@ -220,6 +220,30 @@ func InjectImportedSecret(plainTextWorkspaceKey []byte, secrets []models.SingleE
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
func FilterSecretsByTag(plainTextSecrets []models.SingleEnvironmentVariable, tagSlugs string) []models.SingleEnvironmentVariable {
|
||||
if tagSlugs == "" {
|
||||
return plainTextSecrets
|
||||
}
|
||||
|
||||
tagSlugsMap := make(map[string]bool)
|
||||
tagSlugsList := strings.Split(tagSlugs, ",")
|
||||
for _, slug := range tagSlugsList {
|
||||
tagSlugsMap[slug] = true
|
||||
}
|
||||
|
||||
filteredSecrets := []models.SingleEnvironmentVariable{}
|
||||
for _, secret := range plainTextSecrets {
|
||||
for _, tag := range secret.Tags {
|
||||
if tagSlugsMap[tag.Slug] {
|
||||
filteredSecrets = append(filteredSecrets, secret)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filteredSecrets
|
||||
}
|
||||
|
||||
func GetAllEnvironmentVariables(params models.GetAllSecretsParameters, projectConfigFilePath string) ([]models.SingleEnvironmentVariable, error) {
|
||||
var infisicalToken string
|
||||
if params.InfisicalToken == "" {
|
||||
|
@ -86,6 +86,7 @@ services:
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- DB_CONNECTION_URI=postgres://infisical:infisical@db/infisical?sslmode=disable
|
||||
- TELEMETRY_ENABLED=false
|
||||
volumes:
|
||||
- ./backend/src:/app/src
|
||||
|
||||
|
@ -52,7 +52,7 @@ services:
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- pg_data:/data/db
|
||||
- pg_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- infisical
|
||||
healthcheck:
|
||||
|
@ -16,49 +16,7 @@ git checkout -b MY_BRANCH_NAME
|
||||
## Set up environment variables
|
||||
|
||||
|
||||
Start by creating a .env file at the root of the Infisical directory then copy the contents of the file below into the .env file.
|
||||
|
||||
<Accordion title=".env file content">
|
||||
```env
|
||||
# Keys
|
||||
# Required key for platform encryption/decryption ops
|
||||
ENCRYPTION_KEY=6c1fe4e407b8911c104518103505b218
|
||||
|
||||
# JWT
|
||||
# Required secrets to sign JWT tokens
|
||||
JWT_SIGNUP_SECRET=3679e04ca949f914c03332aaaeba805a
|
||||
JWT_REFRESH_SECRET=5f2f3c8f0159068dc2bbb3a652a716ff
|
||||
JWT_AUTH_SECRET=4be6ba5602e0fa0ac6ac05c3cd4d247f
|
||||
JWT_SERVICE_SECRET=f32f716d70a42c5703f4656015e76200
|
||||
|
||||
# MongoDB
|
||||
# Backend will connect to the MongoDB instance at connection string MONGO_URL which can either be a ref
|
||||
# to the MongoDB container instance or Mongo Cloud
|
||||
# Required
|
||||
MONGO_URL=mongodb://root:example@mongo:27017/?authSource=admin
|
||||
|
||||
# Optional credentials for MongoDB container instance and Mongo-Express
|
||||
MONGO_USERNAME=root
|
||||
MONGO_PASSWORD=example
|
||||
|
||||
# Website URL
|
||||
# Required
|
||||
SITE_URL=http://localhost:8080
|
||||
|
||||
# Mail/SMTP
|
||||
SMTP_HOST='smtp-server'
|
||||
SMTP_PORT='1025'
|
||||
SMTP_NAME='local'
|
||||
SMTP_USERNAME='team@infisical.com'
|
||||
SMTP_PASSWORD=
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Warning>
|
||||
The pre-populated environment variable values above are meant to be used in development only. They should never be used in production.
|
||||
</Warning>
|
||||
|
||||
View all available [environment variables](https://infisical.com/docs/self-hosting/configuration/envars) and guidance for each.
|
||||
Start by creating a .env file at the root of the Infisical directory then copy the contents of the file linked [here](https://github.com/Infisical/infisical/blob/main/.env.example). View all available [environment variables](https://infisical.com/docs/self-hosting/configuration/envars) and guidance for each.
|
||||
|
||||
## Starting Infisical for development
|
||||
|
||||
@ -72,10 +30,7 @@ docker-compose -f docker-compose.dev.yml up --build --force-recreate
|
||||
```
|
||||
#### Access local server
|
||||
|
||||
Once all the services have spun up, browse to http://localhost:8080. To sign in, you may use the default credentials listed below.
|
||||
|
||||
Email: `test@localhost.local`
|
||||
Password: `testInfisical1`
|
||||
Once all the services have spun up, browse to http://localhost:8080.
|
||||
|
||||
#### Shutdown local server
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "Introduction"
|
||||
---
|
||||
|
||||
Infisical is an [open-source](https://opensource.com/resources/what-open-source), [end-to-end encrypted](https://en.wikipedia.org/wiki/End-to-end_encryption) secret management platform for storing, managing, and syncing
|
||||
Infisical is an [open-source](https://opensource.com/resources/what-open-source), [end-to-end encrypted](https://en.wikipedia.org/wiki/End-to-end_encryption) secrets management platform for storing, managing, and syncing
|
||||
application configuration and secrets like API keys, database credentials, and environment variables across applications and infrastructure.
|
||||
|
||||
Start syncing environment variables with [Infisical Cloud](https://app.infisical.com) or learn how to [host Infisical](/self-hosting/overview) yourself.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user