diff --git a/.env.example b/.env.example index 4029cb141..8a714f77d 100644 --- a/.env.example +++ b/.env.example @@ -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 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e735b10d6..b2a9cabfc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,6 @@ Thanks for taking the time to contribute! πŸ˜ƒ πŸš€ -Please refer to our [Contributing Guide](https://infisical.com/docs/contributing/overview) for instructions on how to contribute. +Please refer to our [Contributing Guide](https://infisical.com/docs/contributing/getting-started/overview) for instructions on how to contribute. We also have some πŸ”₯amazingπŸ”₯ merch for our contributors. Please reach out to tony@infisical.com for more info πŸ‘€ diff --git a/backend/e2e-test/mocks/keystore.ts b/backend/e2e-test/mocks/keystore.ts new file mode 100644 index 000000000..c85244129 --- /dev/null +++ b/backend/e2e-test/mocks/keystore.ts @@ -0,0 +1,30 @@ +import { TKeyStoreFactory } from "@app/keystore/keystore"; + +export const mockKeyStore = (): TKeyStoreFactory => { + const store: Record = {}; + + 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; + } + }; +}; diff --git a/backend/e2e-test/vitest-environment-knex.ts b/backend/e2e-test/vitest-environment-knex.ts index afb1bbabe..c1c750225 100644 --- a/backend/e2e-test/vitest-environment-knex.ts +++ b/backend/e2e-test/vitest-environment-knex.ts @@ -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 diff --git a/backend/package-lock.json b/backend/package-lock.json index 63a62e328..5fd3f392c 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -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", @@ -33,7 +33,7 @@ "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", @@ -1687,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" @@ -2193,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" @@ -2206,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" } @@ -2215,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" @@ -5442,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" }, @@ -5492,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", @@ -5507,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", @@ -6906,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", @@ -7058,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" }, @@ -7510,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" }, @@ -8111,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" } @@ -8142,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" }, @@ -8177,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" } @@ -8934,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" } @@ -8951,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" @@ -8964,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" }, @@ -10557,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", @@ -10904,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", @@ -11705,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" }, diff --git a/backend/package.json b/backend/package.json index bcac08327..2952c5803 100644 --- a/backend/package.json +++ b/backend/package.json @@ -72,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", @@ -94,7 +94,7 @@ "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", diff --git a/backend/scripts/generate-schema-types.ts b/backend/scripts/generate-schema-types.ts index 68330613c..8c913991f 100644 --- a/backend/scripts/generate-schema-types.ts +++ b/backend/scripts/generate-schema-types.ts @@ -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; -export type T${pascalCase}Insert = Omit; -export type T${pascalCase}Update = Partial>; +export type T${pascalCase}Insert = Omit, TImmutableDBKeys>; +export type T${pascalCase}Update = Partial, TImmutableDBKeys>>; ` ); } diff --git a/backend/src/cache/redis.ts b/backend/src/cache/redis.ts deleted file mode 100644 index 4e856fac1..000000000 --- a/backend/src/cache/redis.ts +++ /dev/null @@ -1,6 +0,0 @@ -import Redis from "ioredis"; - -export const initRedisConnection = (redisUrl: string) => { - const redis = new Redis(redisUrl); - return redis; -}; diff --git a/backend/src/db/migrations/20240226094411_instance-id.ts b/backend/src/db/migrations/20240226094411_instance-id.ts new file mode 100644 index 000000000..ae88bb3fd --- /dev/null +++ b/backend/src/db/migrations/20240226094411_instance-id.ts @@ -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 { + 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 { + await knex.schema.alterTable(TableName.SuperAdmin, (t) => { + t.dropColumn("instanceId"); + }); +} diff --git a/backend/src/db/schemas/api-keys.ts b/backend/src/db/schemas/api-keys.ts index ff29a54e1..cf836fd88 100644 --- a/backend/src/db/schemas/api-keys.ts +++ b/backend/src/db/schemas/api-keys.ts @@ -19,5 +19,5 @@ export const ApiKeysSchema = z.object({ }); export type TApiKeys = z.infer; -export type TApiKeysInsert = Omit; -export type TApiKeysUpdate = Partial>; +export type TApiKeysInsert = Omit, TImmutableDBKeys>; +export type TApiKeysUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/audit-logs.ts b/backend/src/db/schemas/audit-logs.ts index f7143bb57..b8906698b 100644 --- a/backend/src/db/schemas/audit-logs.ts +++ b/backend/src/db/schemas/audit-logs.ts @@ -24,5 +24,5 @@ export const AuditLogsSchema = z.object({ }); export type TAuditLogs = z.infer; -export type TAuditLogsInsert = Omit; -export type TAuditLogsUpdate = Partial>; +export type TAuditLogsInsert = Omit, TImmutableDBKeys>; +export type TAuditLogsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/auth-token-sessions.ts b/backend/src/db/schemas/auth-token-sessions.ts index 46ed7c201..3a9376c83 100644 --- a/backend/src/db/schemas/auth-token-sessions.ts +++ b/backend/src/db/schemas/auth-token-sessions.ts @@ -20,5 +20,5 @@ export const AuthTokenSessionsSchema = z.object({ }); export type TAuthTokenSessions = z.infer; -export type TAuthTokenSessionsInsert = Omit; -export type TAuthTokenSessionsUpdate = Partial>; +export type TAuthTokenSessionsInsert = Omit, TImmutableDBKeys>; +export type TAuthTokenSessionsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/auth-tokens.ts b/backend/src/db/schemas/auth-tokens.ts index 9ae8eed44..dd8563b85 100644 --- a/backend/src/db/schemas/auth-tokens.ts +++ b/backend/src/db/schemas/auth-tokens.ts @@ -21,5 +21,5 @@ export const AuthTokensSchema = z.object({ }); export type TAuthTokens = z.infer; -export type TAuthTokensInsert = Omit; -export type TAuthTokensUpdate = Partial>; +export type TAuthTokensInsert = Omit, TImmutableDBKeys>; +export type TAuthTokensUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/backup-private-key.ts b/backend/src/db/schemas/backup-private-key.ts index 5930bbd4a..5a2148aa1 100644 --- a/backend/src/db/schemas/backup-private-key.ts +++ b/backend/src/db/schemas/backup-private-key.ts @@ -22,5 +22,5 @@ export const BackupPrivateKeySchema = z.object({ }); export type TBackupPrivateKey = z.infer; -export type TBackupPrivateKeyInsert = Omit; -export type TBackupPrivateKeyUpdate = Partial>; +export type TBackupPrivateKeyInsert = Omit, TImmutableDBKeys>; +export type TBackupPrivateKeyUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/git-app-install-sessions.ts b/backend/src/db/schemas/git-app-install-sessions.ts index 6c6db40ea..986ae9d8e 100644 --- a/backend/src/db/schemas/git-app-install-sessions.ts +++ b/backend/src/db/schemas/git-app-install-sessions.ts @@ -17,5 +17,5 @@ export const GitAppInstallSessionsSchema = z.object({ }); export type TGitAppInstallSessions = z.infer; -export type TGitAppInstallSessionsInsert = Omit; -export type TGitAppInstallSessionsUpdate = Partial>; +export type TGitAppInstallSessionsInsert = Omit, TImmutableDBKeys>; +export type TGitAppInstallSessionsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/git-app-org.ts b/backend/src/db/schemas/git-app-org.ts index 57e0d474a..627df6b4c 100644 --- a/backend/src/db/schemas/git-app-org.ts +++ b/backend/src/db/schemas/git-app-org.ts @@ -17,5 +17,5 @@ export const GitAppOrgSchema = z.object({ }); export type TGitAppOrg = z.infer; -export type TGitAppOrgInsert = Omit; -export type TGitAppOrgUpdate = Partial>; +export type TGitAppOrgInsert = Omit, TImmutableDBKeys>; +export type TGitAppOrgUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/identities.ts b/backend/src/db/schemas/identities.ts index 005adf025..adf3a6ef2 100644 --- a/backend/src/db/schemas/identities.ts +++ b/backend/src/db/schemas/identities.ts @@ -16,5 +16,5 @@ export const IdentitiesSchema = z.object({ }); export type TIdentities = z.infer; -export type TIdentitiesInsert = Omit; -export type TIdentitiesUpdate = Partial>; +export type TIdentitiesInsert = Omit, TImmutableDBKeys>; +export type TIdentitiesUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/identity-access-tokens.ts b/backend/src/db/schemas/identity-access-tokens.ts index cbd71e5c5..18dbb8193 100644 --- a/backend/src/db/schemas/identity-access-tokens.ts +++ b/backend/src/db/schemas/identity-access-tokens.ts @@ -23,5 +23,5 @@ export const IdentityAccessTokensSchema = z.object({ }); export type TIdentityAccessTokens = z.infer; -export type TIdentityAccessTokensInsert = Omit; -export type TIdentityAccessTokensUpdate = Partial>; +export type TIdentityAccessTokensInsert = Omit, TImmutableDBKeys>; +export type TIdentityAccessTokensUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/identity-org-memberships.ts b/backend/src/db/schemas/identity-org-memberships.ts index 647ec7124..2f29c52e4 100644 --- a/backend/src/db/schemas/identity-org-memberships.ts +++ b/backend/src/db/schemas/identity-org-memberships.ts @@ -18,5 +18,7 @@ export const IdentityOrgMembershipsSchema = z.object({ }); export type TIdentityOrgMemberships = z.infer; -export type TIdentityOrgMembershipsInsert = Omit; -export type TIdentityOrgMembershipsUpdate = Partial>; +export type TIdentityOrgMembershipsInsert = Omit, TImmutableDBKeys>; +export type TIdentityOrgMembershipsUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/identity-project-memberships.ts b/backend/src/db/schemas/identity-project-memberships.ts index 866324c8b..276c9581e 100644 --- a/backend/src/db/schemas/identity-project-memberships.ts +++ b/backend/src/db/schemas/identity-project-memberships.ts @@ -18,5 +18,10 @@ export const IdentityProjectMembershipsSchema = z.object({ }); export type TIdentityProjectMemberships = z.infer; -export type TIdentityProjectMembershipsInsert = Omit; -export type TIdentityProjectMembershipsUpdate = Partial>; +export type TIdentityProjectMembershipsInsert = Omit< + z.input, + TImmutableDBKeys +>; +export type TIdentityProjectMembershipsUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/identity-ua-client-secrets.ts b/backend/src/db/schemas/identity-ua-client-secrets.ts index 60f8d862f..bd549ca5b 100644 --- a/backend/src/db/schemas/identity-ua-client-secrets.ts +++ b/backend/src/db/schemas/identity-ua-client-secrets.ts @@ -23,5 +23,7 @@ export const IdentityUaClientSecretsSchema = z.object({ }); export type TIdentityUaClientSecrets = z.infer; -export type TIdentityUaClientSecretsInsert = Omit; -export type TIdentityUaClientSecretsUpdate = Partial>; +export type TIdentityUaClientSecretsInsert = Omit, TImmutableDBKeys>; +export type TIdentityUaClientSecretsUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/identity-universal-auths.ts b/backend/src/db/schemas/identity-universal-auths.ts index 5a8f0c7ec..eeec2f666 100644 --- a/backend/src/db/schemas/identity-universal-auths.ts +++ b/backend/src/db/schemas/identity-universal-auths.ts @@ -21,5 +21,7 @@ export const IdentityUniversalAuthsSchema = z.object({ }); export type TIdentityUniversalAuths = z.infer; -export type TIdentityUniversalAuthsInsert = Omit; -export type TIdentityUniversalAuthsUpdate = Partial>; +export type TIdentityUniversalAuthsInsert = Omit, TImmutableDBKeys>; +export type TIdentityUniversalAuthsUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/incident-contacts.ts b/backend/src/db/schemas/incident-contacts.ts index 431bf05ab..23c8503b0 100644 --- a/backend/src/db/schemas/incident-contacts.ts +++ b/backend/src/db/schemas/incident-contacts.ts @@ -16,5 +16,5 @@ export const IncidentContactsSchema = z.object({ }); export type TIncidentContacts = z.infer; -export type TIncidentContactsInsert = Omit; -export type TIncidentContactsUpdate = Partial>; +export type TIncidentContactsInsert = Omit, TImmutableDBKeys>; +export type TIncidentContactsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/integration-auths.ts b/backend/src/db/schemas/integration-auths.ts index db602c0af..185beae36 100644 --- a/backend/src/db/schemas/integration-auths.ts +++ b/backend/src/db/schemas/integration-auths.ts @@ -33,5 +33,5 @@ export const IntegrationAuthsSchema = z.object({ }); export type TIntegrationAuths = z.infer; -export type TIntegrationAuthsInsert = Omit; -export type TIntegrationAuthsUpdate = Partial>; +export type TIntegrationAuthsInsert = Omit, TImmutableDBKeys>; +export type TIntegrationAuthsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/integrations.ts b/backend/src/db/schemas/integrations.ts index 62f73d190..cf8c88154 100644 --- a/backend/src/db/schemas/integrations.ts +++ b/backend/src/db/schemas/integrations.ts @@ -31,5 +31,5 @@ export const IntegrationsSchema = z.object({ }); export type TIntegrations = z.infer; -export type TIntegrationsInsert = Omit; -export type TIntegrationsUpdate = Partial>; +export type TIntegrationsInsert = Omit, TImmutableDBKeys>; +export type TIntegrationsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/org-bots.ts b/backend/src/db/schemas/org-bots.ts index b328f1aaf..77be907ec 100644 --- a/backend/src/db/schemas/org-bots.ts +++ b/backend/src/db/schemas/org-bots.ts @@ -27,5 +27,5 @@ export const OrgBotsSchema = z.object({ }); export type TOrgBots = z.infer; -export type TOrgBotsInsert = Omit; -export type TOrgBotsUpdate = Partial>; +export type TOrgBotsInsert = Omit, TImmutableDBKeys>; +export type TOrgBotsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/org-memberships.ts b/backend/src/db/schemas/org-memberships.ts index b2fffa117..585addb7c 100644 --- a/backend/src/db/schemas/org-memberships.ts +++ b/backend/src/db/schemas/org-memberships.ts @@ -20,5 +20,5 @@ export const OrgMembershipsSchema = z.object({ }); export type TOrgMemberships = z.infer; -export type TOrgMembershipsInsert = Omit; -export type TOrgMembershipsUpdate = Partial>; +export type TOrgMembershipsInsert = Omit, TImmutableDBKeys>; +export type TOrgMembershipsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/org-roles.ts b/backend/src/db/schemas/org-roles.ts index 72b582f96..ca01c6574 100644 --- a/backend/src/db/schemas/org-roles.ts +++ b/backend/src/db/schemas/org-roles.ts @@ -19,5 +19,5 @@ export const OrgRolesSchema = z.object({ }); export type TOrgRoles = z.infer; -export type TOrgRolesInsert = Omit; -export type TOrgRolesUpdate = Partial>; +export type TOrgRolesInsert = Omit, TImmutableDBKeys>; +export type TOrgRolesUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/organizations.ts b/backend/src/db/schemas/organizations.ts index a91b93ea5..f2933af86 100644 --- a/backend/src/db/schemas/organizations.ts +++ b/backend/src/db/schemas/organizations.ts @@ -19,5 +19,5 @@ export const OrganizationsSchema = z.object({ }); export type TOrganizations = z.infer; -export type TOrganizationsInsert = Omit; -export type TOrganizationsUpdate = Partial>; +export type TOrganizationsInsert = Omit, TImmutableDBKeys>; +export type TOrganizationsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/project-bots.ts b/backend/src/db/schemas/project-bots.ts index c68576943..1fa59eb78 100644 --- a/backend/src/db/schemas/project-bots.ts +++ b/backend/src/db/schemas/project-bots.ts @@ -26,5 +26,5 @@ export const ProjectBotsSchema = z.object({ }); export type TProjectBots = z.infer; -export type TProjectBotsInsert = Omit; -export type TProjectBotsUpdate = Partial>; +export type TProjectBotsInsert = Omit, TImmutableDBKeys>; +export type TProjectBotsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/project-environments.ts b/backend/src/db/schemas/project-environments.ts index 8b95dbba0..76556b7e9 100644 --- a/backend/src/db/schemas/project-environments.ts +++ b/backend/src/db/schemas/project-environments.ts @@ -18,5 +18,5 @@ export const ProjectEnvironmentsSchema = z.object({ }); export type TProjectEnvironments = z.infer; -export type TProjectEnvironmentsInsert = Omit; -export type TProjectEnvironmentsUpdate = Partial>; +export type TProjectEnvironmentsInsert = Omit, TImmutableDBKeys>; +export type TProjectEnvironmentsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/project-keys.ts b/backend/src/db/schemas/project-keys.ts index 720cd79bf..924918b12 100644 --- a/backend/src/db/schemas/project-keys.ts +++ b/backend/src/db/schemas/project-keys.ts @@ -19,5 +19,5 @@ export const ProjectKeysSchema = z.object({ }); export type TProjectKeys = z.infer; -export type TProjectKeysInsert = Omit; -export type TProjectKeysUpdate = Partial>; +export type TProjectKeysInsert = Omit, TImmutableDBKeys>; +export type TProjectKeysUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/project-memberships.ts b/backend/src/db/schemas/project-memberships.ts index b9f191a84..8576a318e 100644 --- a/backend/src/db/schemas/project-memberships.ts +++ b/backend/src/db/schemas/project-memberships.ts @@ -18,5 +18,5 @@ export const ProjectMembershipsSchema = z.object({ }); export type TProjectMemberships = z.infer; -export type TProjectMembershipsInsert = Omit; -export type TProjectMembershipsUpdate = Partial>; +export type TProjectMembershipsInsert = Omit, TImmutableDBKeys>; +export type TProjectMembershipsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/project-roles.ts b/backend/src/db/schemas/project-roles.ts index 1946ab5e1..e10f6fd4c 100644 --- a/backend/src/db/schemas/project-roles.ts +++ b/backend/src/db/schemas/project-roles.ts @@ -19,5 +19,5 @@ export const ProjectRolesSchema = z.object({ }); export type TProjectRoles = z.infer; -export type TProjectRolesInsert = Omit; -export type TProjectRolesUpdate = Partial>; +export type TProjectRolesInsert = Omit, TImmutableDBKeys>; +export type TProjectRolesUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/projects.ts b/backend/src/db/schemas/projects.ts index 3834d6d58..3965e24c0 100644 --- a/backend/src/db/schemas/projects.ts +++ b/backend/src/db/schemas/projects.ts @@ -20,5 +20,5 @@ export const ProjectsSchema = z.object({ }); export type TProjects = z.infer; -export type TProjectsInsert = Omit; -export type TProjectsUpdate = Partial>; +export type TProjectsInsert = Omit, TImmutableDBKeys>; +export type TProjectsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/saml-configs.ts b/backend/src/db/schemas/saml-configs.ts index 6891d8add..67171469a 100644 --- a/backend/src/db/schemas/saml-configs.ts +++ b/backend/src/db/schemas/saml-configs.ts @@ -27,5 +27,5 @@ export const SamlConfigsSchema = z.object({ }); export type TSamlConfigs = z.infer; -export type TSamlConfigsInsert = Omit; -export type TSamlConfigsUpdate = Partial>; +export type TSamlConfigsInsert = Omit, TImmutableDBKeys>; +export type TSamlConfigsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/scim-tokens.ts b/backend/src/db/schemas/scim-tokens.ts index 593e4f7d9..ab6e10d27 100644 --- a/backend/src/db/schemas/scim-tokens.ts +++ b/backend/src/db/schemas/scim-tokens.ts @@ -17,5 +17,5 @@ export const ScimTokensSchema = z.object({ }); export type TScimTokens = z.infer; -export type TScimTokensInsert = Omit; -export type TScimTokensUpdate = Partial>; +export type TScimTokensInsert = Omit, TImmutableDBKeys>; +export type TScimTokensUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-approval-policies-approvers.ts b/backend/src/db/schemas/secret-approval-policies-approvers.ts index 503299d30..12a3119e6 100644 --- a/backend/src/db/schemas/secret-approval-policies-approvers.ts +++ b/backend/src/db/schemas/secret-approval-policies-approvers.ts @@ -16,5 +16,10 @@ export const SecretApprovalPoliciesApproversSchema = z.object({ }); export type TSecretApprovalPoliciesApprovers = z.infer; -export type TSecretApprovalPoliciesApproversInsert = Omit; -export type TSecretApprovalPoliciesApproversUpdate = Partial>; +export type TSecretApprovalPoliciesApproversInsert = Omit< + z.input, + TImmutableDBKeys +>; +export type TSecretApprovalPoliciesApproversUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-approval-policies.ts b/backend/src/db/schemas/secret-approval-policies.ts index 6c331f1b1..d907ef1e0 100644 --- a/backend/src/db/schemas/secret-approval-policies.ts +++ b/backend/src/db/schemas/secret-approval-policies.ts @@ -18,5 +18,7 @@ export const SecretApprovalPoliciesSchema = z.object({ }); export type TSecretApprovalPolicies = z.infer; -export type TSecretApprovalPoliciesInsert = Omit; -export type TSecretApprovalPoliciesUpdate = Partial>; +export type TSecretApprovalPoliciesInsert = Omit, TImmutableDBKeys>; +export type TSecretApprovalPoliciesUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-approval-request-secret-tags.ts b/backend/src/db/schemas/secret-approval-request-secret-tags.ts index f5e7ba632..2851321e2 100644 --- a/backend/src/db/schemas/secret-approval-request-secret-tags.ts +++ b/backend/src/db/schemas/secret-approval-request-secret-tags.ts @@ -16,5 +16,10 @@ export const SecretApprovalRequestSecretTagsSchema = z.object({ }); export type TSecretApprovalRequestSecretTags = z.infer; -export type TSecretApprovalRequestSecretTagsInsert = Omit; -export type TSecretApprovalRequestSecretTagsUpdate = Partial>; +export type TSecretApprovalRequestSecretTagsInsert = Omit< + z.input, + TImmutableDBKeys +>; +export type TSecretApprovalRequestSecretTagsUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-approval-requests-reviewers.ts b/backend/src/db/schemas/secret-approval-requests-reviewers.ts index a3657f1f9..f3ff88047 100644 --- a/backend/src/db/schemas/secret-approval-requests-reviewers.ts +++ b/backend/src/db/schemas/secret-approval-requests-reviewers.ts @@ -17,5 +17,10 @@ export const SecretApprovalRequestsReviewersSchema = z.object({ }); export type TSecretApprovalRequestsReviewers = z.infer; -export type TSecretApprovalRequestsReviewersInsert = Omit; -export type TSecretApprovalRequestsReviewersUpdate = Partial>; +export type TSecretApprovalRequestsReviewersInsert = Omit< + z.input, + TImmutableDBKeys +>; +export type TSecretApprovalRequestsReviewersUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-approval-requests-secrets.ts b/backend/src/db/schemas/secret-approval-requests-secrets.ts index 810a4f2cf..b795b47b4 100644 --- a/backend/src/db/schemas/secret-approval-requests-secrets.ts +++ b/backend/src/db/schemas/secret-approval-requests-secrets.ts @@ -35,5 +35,10 @@ export const SecretApprovalRequestsSecretsSchema = z.object({ }); export type TSecretApprovalRequestsSecrets = z.infer; -export type TSecretApprovalRequestsSecretsInsert = Omit; -export type TSecretApprovalRequestsSecretsUpdate = Partial>; +export type TSecretApprovalRequestsSecretsInsert = Omit< + z.input, + TImmutableDBKeys +>; +export type TSecretApprovalRequestsSecretsUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-approval-requests.ts b/backend/src/db/schemas/secret-approval-requests.ts index 590c283f5..6ee97fbb6 100644 --- a/backend/src/db/schemas/secret-approval-requests.ts +++ b/backend/src/db/schemas/secret-approval-requests.ts @@ -22,5 +22,7 @@ export const SecretApprovalRequestsSchema = z.object({ }); export type TSecretApprovalRequests = z.infer; -export type TSecretApprovalRequestsInsert = Omit; -export type TSecretApprovalRequestsUpdate = Partial>; +export type TSecretApprovalRequestsInsert = Omit, TImmutableDBKeys>; +export type TSecretApprovalRequestsUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-blind-indexes.ts b/backend/src/db/schemas/secret-blind-indexes.ts index fa919babd..474e0aa54 100644 --- a/backend/src/db/schemas/secret-blind-indexes.ts +++ b/backend/src/db/schemas/secret-blind-indexes.ts @@ -20,5 +20,5 @@ export const SecretBlindIndexesSchema = z.object({ }); export type TSecretBlindIndexes = z.infer; -export type TSecretBlindIndexesInsert = Omit; -export type TSecretBlindIndexesUpdate = Partial>; +export type TSecretBlindIndexesInsert = Omit, TImmutableDBKeys>; +export type TSecretBlindIndexesUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-folder-versions.ts b/backend/src/db/schemas/secret-folder-versions.ts index 8c550d065..8bef6e83f 100644 --- a/backend/src/db/schemas/secret-folder-versions.ts +++ b/backend/src/db/schemas/secret-folder-versions.ts @@ -18,5 +18,5 @@ export const SecretFolderVersionsSchema = z.object({ }); export type TSecretFolderVersions = z.infer; -export type TSecretFolderVersionsInsert = Omit; -export type TSecretFolderVersionsUpdate = Partial>; +export type TSecretFolderVersionsInsert = Omit, TImmutableDBKeys>; +export type TSecretFolderVersionsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-folders.ts b/backend/src/db/schemas/secret-folders.ts index 648238b0a..0f9684d0e 100644 --- a/backend/src/db/schemas/secret-folders.ts +++ b/backend/src/db/schemas/secret-folders.ts @@ -18,5 +18,5 @@ export const SecretFoldersSchema = z.object({ }); export type TSecretFolders = z.infer; -export type TSecretFoldersInsert = Omit; -export type TSecretFoldersUpdate = Partial>; +export type TSecretFoldersInsert = Omit, TImmutableDBKeys>; +export type TSecretFoldersUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-imports.ts b/backend/src/db/schemas/secret-imports.ts index 9c1ee905f..9d42d8da5 100644 --- a/backend/src/db/schemas/secret-imports.ts +++ b/backend/src/db/schemas/secret-imports.ts @@ -19,5 +19,5 @@ export const SecretImportsSchema = z.object({ }); export type TSecretImports = z.infer; -export type TSecretImportsInsert = Omit; -export type TSecretImportsUpdate = Partial>; +export type TSecretImportsInsert = Omit, TImmutableDBKeys>; +export type TSecretImportsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-rotation-outputs.ts b/backend/src/db/schemas/secret-rotation-outputs.ts index 3b594365a..3ac5c2c9e 100644 --- a/backend/src/db/schemas/secret-rotation-outputs.ts +++ b/backend/src/db/schemas/secret-rotation-outputs.ts @@ -15,5 +15,5 @@ export const SecretRotationOutputsSchema = z.object({ }); export type TSecretRotationOutputs = z.infer; -export type TSecretRotationOutputsInsert = Omit; -export type TSecretRotationOutputsUpdate = Partial>; +export type TSecretRotationOutputsInsert = Omit, TImmutableDBKeys>; +export type TSecretRotationOutputsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-rotations.ts b/backend/src/db/schemas/secret-rotations.ts index 4c65712fa..b491edc46 100644 --- a/backend/src/db/schemas/secret-rotations.ts +++ b/backend/src/db/schemas/secret-rotations.ts @@ -26,5 +26,5 @@ export const SecretRotationsSchema = z.object({ }); export type TSecretRotations = z.infer; -export type TSecretRotationsInsert = Omit; -export type TSecretRotationsUpdate = Partial>; +export type TSecretRotationsInsert = Omit, TImmutableDBKeys>; +export type TSecretRotationsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-scanning-git-risks.ts b/backend/src/db/schemas/secret-scanning-git-risks.ts index 85cfcd376..08ba690e4 100644 --- a/backend/src/db/schemas/secret-scanning-git-risks.ts +++ b/backend/src/db/schemas/secret-scanning-git-risks.ts @@ -42,5 +42,7 @@ export const SecretScanningGitRisksSchema = z.object({ }); export type TSecretScanningGitRisks = z.infer; -export type TSecretScanningGitRisksInsert = Omit; -export type TSecretScanningGitRisksUpdate = Partial>; +export type TSecretScanningGitRisksInsert = Omit, TImmutableDBKeys>; +export type TSecretScanningGitRisksUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-snapshot-folders.ts b/backend/src/db/schemas/secret-snapshot-folders.ts index acf11ab0a..3e2853cbe 100644 --- a/backend/src/db/schemas/secret-snapshot-folders.ts +++ b/backend/src/db/schemas/secret-snapshot-folders.ts @@ -17,5 +17,5 @@ export const SecretSnapshotFoldersSchema = z.object({ }); export type TSecretSnapshotFolders = z.infer; -export type TSecretSnapshotFoldersInsert = Omit; -export type TSecretSnapshotFoldersUpdate = Partial>; +export type TSecretSnapshotFoldersInsert = Omit, TImmutableDBKeys>; +export type TSecretSnapshotFoldersUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-snapshot-secrets.ts b/backend/src/db/schemas/secret-snapshot-secrets.ts index 6a83d1155..121c5d56e 100644 --- a/backend/src/db/schemas/secret-snapshot-secrets.ts +++ b/backend/src/db/schemas/secret-snapshot-secrets.ts @@ -17,5 +17,5 @@ export const SecretSnapshotSecretsSchema = z.object({ }); export type TSecretSnapshotSecrets = z.infer; -export type TSecretSnapshotSecretsInsert = Omit; -export type TSecretSnapshotSecretsUpdate = Partial>; +export type TSecretSnapshotSecretsInsert = Omit, TImmutableDBKeys>; +export type TSecretSnapshotSecretsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-snapshots.ts b/backend/src/db/schemas/secret-snapshots.ts index ed255cb77..7f070075f 100644 --- a/backend/src/db/schemas/secret-snapshots.ts +++ b/backend/src/db/schemas/secret-snapshots.ts @@ -17,5 +17,5 @@ export const SecretSnapshotsSchema = z.object({ }); export type TSecretSnapshots = z.infer; -export type TSecretSnapshotsInsert = Omit; -export type TSecretSnapshotsUpdate = Partial>; +export type TSecretSnapshotsInsert = Omit, TImmutableDBKeys>; +export type TSecretSnapshotsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-tag-junction.ts b/backend/src/db/schemas/secret-tag-junction.ts index 1d25574c5..d14384fab 100644 --- a/backend/src/db/schemas/secret-tag-junction.ts +++ b/backend/src/db/schemas/secret-tag-junction.ts @@ -14,5 +14,5 @@ export const SecretTagJunctionSchema = z.object({ }); export type TSecretTagJunction = z.infer; -export type TSecretTagJunctionInsert = Omit; -export type TSecretTagJunctionUpdate = Partial>; +export type TSecretTagJunctionInsert = Omit, TImmutableDBKeys>; +export type TSecretTagJunctionUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-tags.ts b/backend/src/db/schemas/secret-tags.ts index 622c29bd3..f94e1e262 100644 --- a/backend/src/db/schemas/secret-tags.ts +++ b/backend/src/db/schemas/secret-tags.ts @@ -19,5 +19,5 @@ export const SecretTagsSchema = z.object({ }); export type TSecretTags = z.infer; -export type TSecretTagsInsert = Omit; -export type TSecretTagsUpdate = Partial>; +export type TSecretTagsInsert = Omit, TImmutableDBKeys>; +export type TSecretTagsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-version-tag-junction.ts b/backend/src/db/schemas/secret-version-tag-junction.ts index 2c9a24fee..b36e28c72 100644 --- a/backend/src/db/schemas/secret-version-tag-junction.ts +++ b/backend/src/db/schemas/secret-version-tag-junction.ts @@ -14,5 +14,7 @@ export const SecretVersionTagJunctionSchema = z.object({ }); export type TSecretVersionTagJunction = z.infer; -export type TSecretVersionTagJunctionInsert = Omit; -export type TSecretVersionTagJunctionUpdate = Partial>; +export type TSecretVersionTagJunctionInsert = Omit, TImmutableDBKeys>; +export type TSecretVersionTagJunctionUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-versions.ts b/backend/src/db/schemas/secret-versions.ts index d1675e3d2..d60db9b75 100644 --- a/backend/src/db/schemas/secret-versions.ts +++ b/backend/src/db/schemas/secret-versions.ts @@ -36,5 +36,5 @@ export const SecretVersionsSchema = z.object({ }); export type TSecretVersions = z.infer; -export type TSecretVersionsInsert = Omit; -export type TSecretVersionsUpdate = Partial>; +export type TSecretVersionsInsert = Omit, TImmutableDBKeys>; +export type TSecretVersionsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secrets.ts b/backend/src/db/schemas/secrets.ts index 3fe5ad8d8..f261c40bb 100644 --- a/backend/src/db/schemas/secrets.ts +++ b/backend/src/db/schemas/secrets.ts @@ -34,5 +34,5 @@ export const SecretsSchema = z.object({ }); export type TSecrets = z.infer; -export type TSecretsInsert = Omit; -export type TSecretsUpdate = Partial>; +export type TSecretsInsert = Omit, TImmutableDBKeys>; +export type TSecretsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/service-tokens.ts b/backend/src/db/schemas/service-tokens.ts index 24720f3e4..720c8fd6f 100644 --- a/backend/src/db/schemas/service-tokens.ts +++ b/backend/src/db/schemas/service-tokens.ts @@ -25,5 +25,5 @@ export const ServiceTokensSchema = z.object({ }); export type TServiceTokens = z.infer; -export type TServiceTokensInsert = Omit; -export type TServiceTokensUpdate = Partial>; +export type TServiceTokensInsert = Omit, TImmutableDBKeys>; +export type TServiceTokensUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/super-admin.ts b/backend/src/db/schemas/super-admin.ts index b4631195b..958fed0ab 100644 --- a/backend/src/db/schemas/super-admin.ts +++ b/backend/src/db/schemas/super-admin.ts @@ -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; -export type TSuperAdminInsert = Omit; -export type TSuperAdminUpdate = Partial>; +export type TSuperAdminInsert = Omit, TImmutableDBKeys>; +export type TSuperAdminUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/trusted-ips.ts b/backend/src/db/schemas/trusted-ips.ts index 6d9018db3..f9973a843 100644 --- a/backend/src/db/schemas/trusted-ips.ts +++ b/backend/src/db/schemas/trusted-ips.ts @@ -20,5 +20,5 @@ export const TrustedIpsSchema = z.object({ }); export type TTrustedIps = z.infer; -export type TTrustedIpsInsert = Omit; -export type TTrustedIpsUpdate = Partial>; +export type TTrustedIpsInsert = Omit, TImmutableDBKeys>; +export type TTrustedIpsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/user-actions.ts b/backend/src/db/schemas/user-actions.ts index eaa03ba98..89d269847 100644 --- a/backend/src/db/schemas/user-actions.ts +++ b/backend/src/db/schemas/user-actions.ts @@ -16,5 +16,5 @@ export const UserActionsSchema = z.object({ }); export type TUserActions = z.infer; -export type TUserActionsInsert = Omit; -export type TUserActionsUpdate = Partial>; +export type TUserActionsInsert = Omit, TImmutableDBKeys>; +export type TUserActionsUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/user-encryption-keys.ts b/backend/src/db/schemas/user-encryption-keys.ts index 8f35b09fe..693b73b4c 100644 --- a/backend/src/db/schemas/user-encryption-keys.ts +++ b/backend/src/db/schemas/user-encryption-keys.ts @@ -25,5 +25,5 @@ export const UserEncryptionKeysSchema = z.object({ }); export type TUserEncryptionKeys = z.infer; -export type TUserEncryptionKeysInsert = Omit; -export type TUserEncryptionKeysUpdate = Partial>; +export type TUserEncryptionKeysInsert = Omit, TImmutableDBKeys>; +export type TUserEncryptionKeysUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/users.ts b/backend/src/db/schemas/users.ts index cdbb5607a..8f9758b4f 100644 --- a/backend/src/db/schemas/users.ts +++ b/backend/src/db/schemas/users.ts @@ -24,5 +24,5 @@ export const UsersSchema = z.object({ }); export type TUsers = z.infer; -export type TUsersInsert = Omit; -export type TUsersUpdate = Partial>; +export type TUsersInsert = Omit, TImmutableDBKeys>; +export type TUsersUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/webhooks.ts b/backend/src/db/schemas/webhooks.ts index 7abfb3772..44aa8c5da 100644 --- a/backend/src/db/schemas/webhooks.ts +++ b/backend/src/db/schemas/webhooks.ts @@ -25,5 +25,5 @@ export const WebhooksSchema = z.object({ }); export type TWebhooks = z.infer; -export type TWebhooksInsert = Omit; -export type TWebhooksUpdate = Partial>; +export type TWebhooksInsert = Omit, TImmutableDBKeys>; +export type TWebhooksUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/ee/services/license/license-service.ts b/backend/src/ee/services/license/license-service.ts index 6d97b537c..b0bc11e31 100644 --- a/backend/src/ee/services/license/license-service.ts +++ b/backend/src/ee/services/license/license-service.ts @@ -505,6 +505,9 @@ export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }: get isValidLicense() { return isValidLicense; }, + getInstanceType() { + return instanceType; + }, getPlan, updateSubscriptionOrgMemberCount, refreshPlan, diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts index 9e69f0a8f..330f6beca 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts @@ -240,7 +240,7 @@ export const secretRotationQueueFactory = ({ ); }); - telemetryService.sendPostHogEvents({ + await telemetryService.sendPostHogEvents({ event: PostHogEventTypes.SecretRotated, distinctId: "", properties: { diff --git a/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts b/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts index aab8d1218..d8f4e647e 100644 --- a/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts +++ b/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts @@ -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: { diff --git a/backend/src/keystore/keystore.ts b/backend/src/keystore/keystore.ts new file mode 100644 index 000000000..5e2c3aab3 --- /dev/null +++ b/backend/src/keystore/keystore.ts @@ -0,0 +1,20 @@ +import { Redis } from "ioredis"; + +export type TKeyStoreFactory = ReturnType; + +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 }; +}; diff --git a/backend/src/lib/config/env.ts b/backend/src/lib/config/env.ts index 4542c7fc3..655e402df 100644 --- a/backend/src/lib/config/env.ts +++ b/backend/src/lib/config/env.ts @@ -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, diff --git a/backend/src/main.ts b/backend/src/main.ts index fab576d3b..86681ef33 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -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 () => { diff --git a/backend/src/queue/queue-service.ts b/backend/src/queue/queue-service.ts index e11e0b590..45c135b77 100644 --- a/backend/src/queue/queue-service.ts +++ b/backend/src/queue/queue-service.ts @@ -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; diff --git a/backend/src/server/app.ts b/backend/src/server/app.ts index 969d2fe43..556a88d7c 100644 --- a/backend/src/server/app.ts +++ b/backend/src/server/app.ts @@ -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, { diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 7366c7041..a21825633 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -34,6 +34,7 @@ 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 { apiKeyDALFactory } from "@app/services/api-key/api-key-dal"; @@ -96,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"; @@ -112,7 +115,12 @@ 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" }); @@ -159,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); @@ -226,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 }); @@ -263,7 +281,8 @@ export const registerRoutes = async ( userDAL, authService: loginService, serverCfgDAL: superAdminDAL, - orgService + orgService, + keyStore }); const apiKeyService = apiKeyServiceFactory({ apiKeyDAL, userDAL }); @@ -491,9 +510,13 @@ export const registerRoutes = async ( }); 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("services", { login: loginService, diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts index b89e3dc4c..38f948851 100644 --- a/backend/src/server/routes/v1/admin-router.ts +++ b/backend/src/server/routes/v1/admin-router.ts @@ -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: { diff --git a/backend/src/server/routes/v1/identity-router.ts b/backend/src/server/routes/v1/identity-router.ts index a03cde62f..0ec27a98b 100644 --- a/backend/src/server/routes/v1/identity-router.ts +++ b/backend/src/server/routes/v1/identity-router.ts @@ -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: { diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts index 1ccf75e94..ec712a543 100644 --- a/backend/src/server/routes/v1/integration-router.ts +++ b/backend/src/server/routes/v1/integration-router.ts @@ -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: { diff --git a/backend/src/server/routes/v1/invite-org-router.ts b/backend/src/server/routes/v1/invite-org-router.ts index dd2fd8157..5956b53df 100644 --- a/backend/src/server/routes/v1/invite-org-router.ts +++ b/backend/src/server/routes/v1/invite-org-router.ts @@ -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: { diff --git a/backend/src/server/routes/v2/project-router.ts b/backend/src/server/routes/v2/project-router.ts index 62f4c7cf5..fe1254b2b 100644 --- a/backend/src/server/routes/v2/project-router.ts +++ b/backend/src/server/routes/v2/project-router.ts @@ -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: { diff --git a/backend/src/server/routes/v3/secret-router.ts b/backend/src/server/routes/v3/secret-router.ts index cfe4a87d7..6b3dd6041 100644 --- a/backend/src/server/routes/v3/secret-router.ts +++ b/backend/src/server/routes/v3/secret-router.ts @@ -95,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: { @@ -185,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: { @@ -261,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: { @@ -336,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: { @@ -406,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: { @@ -512,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: { @@ -589,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: { @@ -752,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: { @@ -934,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: { @@ -1052,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: { @@ -1172,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: { @@ -1292,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: { @@ -1400,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: { diff --git a/backend/src/services/project-membership/project-membership-service.ts b/backend/src/services/project-membership/project-membership-service.ts index cf538e2c5..014e9fb1b 100644 --- a/backend/src/services/project-membership/project-membership-service.ts +++ b/backend/src/services/project-membership/project-membership-service.ts @@ -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) } diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts index 64dac73f2..2a6a2c75e 100644 --- a/backend/src/services/super-admin/super-admin-service.ts +++ b/backend/src/services/super-admin/super-admin-service.ts @@ -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; orgService: Pick; + keyStore: Pick; }; export type TSuperAdminServiceFactory = ReturnType; @@ -21,26 +23,53 @@ export type TSuperAdminServiceFactory = ReturnType Promise; +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 ({ diff --git a/backend/src/services/telemetry/telemetry-dal.ts b/backend/src/services/telemetry/telemetry-dal.ts new file mode 100644 index 000000000..9fac4f1ef --- /dev/null +++ b/backend/src/services/telemetry/telemetry-dal.ts @@ -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; + +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 }; +}; diff --git a/backend/src/services/telemetry/telemetry-queue.ts b/backend/src/services/telemetry/telemetry-queue.ts new file mode 100644 index 000000000..02e906fe6 --- /dev/null +++ b/backend/src/services/telemetry/telemetry-queue.ts @@ -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; + telemetryDAL: TTelemetryDALFactory; +}; + +export type TTelemetryQueueServiceFactory = ReturnType; + +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 + }; +}; diff --git a/backend/src/services/telemetry/telemetry-service.ts b/backend/src/services/telemetry/telemetry-service.ts index a1a4b78f7..9912e0101 100644 --- a/backend/src/services/telemetry/telemetry-service.ts +++ b/backend/src/services/telemetry/telemetry-service.ts @@ -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; +export type TTelemetryServiceFactoryDep = { + keyStore: Pick; + licenseService: Pick; +}; -// 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); + } } }; diff --git a/backend/src/services/telemetry/telemetry-types.ts b/backend/src/services/telemetry/telemetry-types.ts index 0f92da4da..947403783 100644 --- a/backend/src/services/telemetry/telemetry-types.ts +++ b/backend/src/services/telemetry/telemetry-types.ts @@ -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 ); diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index f95810777..6c3a89a74 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -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 diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 5861a4a0e..f26f17284 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -4,10 +4,12 @@ services: db-migration: container_name: infisical-db-migration depends_on: - - db + db: + condition: service_healthy image: infisical/infisical:latest-postgres env_file: .env command: npm run migration:latest + pull_policy: always networks: - infisical @@ -16,12 +18,13 @@ services: restart: unless-stopped depends_on: db: - condition: service_started + condition: service_healthy redis: condition: service_started db-migration: condition: service_completed_successfully image: infisical/infisical:latest-postgres + pull_policy: always env_file: .env ports: - 80:8080 @@ -52,6 +55,11 @@ services: - pg_data:/data/db networks: - infisical + healthcheck: + test: "pg_isready --username=${POSTGRES_USER} && psql --username=${POSTGRES_USER} --list" + interval: 5s + timeout: 10s + retries: 10 volumes: pg_data: diff --git a/docs/contributing/platform/developing.mdx b/docs/contributing/platform/developing.mdx index 7a43c8250..a6675b6f6 100644 --- a/docs/contributing/platform/developing.mdx +++ b/docs/contributing/platform/developing.mdx @@ -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. - - - ```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= - ``` - - - - The pre-populated environment variable values above are meant to be used in development only. They should never be used in production. - - -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 diff --git a/docs/documentation/platform/ldap.mdx b/docs/documentation/platform/ldap.mdx new file mode 100644 index 000000000..63b2a814b --- /dev/null +++ b/docs/documentation/platform/ldap.mdx @@ -0,0 +1,36 @@ +--- +title: "LDAP" +description: "Log in to Infisical with LDAP" +--- + + + LDAP is a paid feature. + + If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical, + then you should contact team@infisical.com to purchase an enterprise license to use it. + + +You can configure your organization in Infisical to have members authenticate with the platform via [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol); this includes support for Active Directory. + + + + In Infisical, head to your Organization Settings > Authentication > LDAP Configuration and select **Set up LDAP**. + + Next, input your LDAP server settings. + + ![LDAP configuration](/images/platform/ldap/ldap-config.png) + + Here's some guidance for each field: + + - URL: The LDAP server to connect to such as `ldap://ldap.your-org.com`, `ldaps://ldap.myorg.com:636` (for connection over SSL/TLS), etc. + - Bind DN: The distinguished name of object to bind when performing the user search such as `cn=infisical,ou=Users,dc=acme,dc=com`. + - Bind Pass: The password to use along with `Bind DN` when performing the user search. + - Search Base / User DN: Base DN under which to perform user search such as `ou=Users,dc=example,dc=com` + - CA Certificate: The CA certificate to use when verifying the LDAP server certificate. + + + Enabling LDAP allows members in your organization to log into Infisical via LDAP. + + ![LDAP toggle](/images/platform/ldap/ldap-toggle.png) + + \ No newline at end of file diff --git a/docs/documentation/platform/ldap/general.mdx b/docs/documentation/platform/ldap/general.mdx new file mode 100644 index 000000000..b4f772ea3 --- /dev/null +++ b/docs/documentation/platform/ldap/general.mdx @@ -0,0 +1,36 @@ +--- +title: "General LDAP" +description: "Log in to Infisical with LDAP" +--- + + + LDAP is a paid feature. + + If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical, + then you should contact team@infisical.com to purchase an enterprise license to use it. + + +You can configure your organization in Infisical to have members authenticate with the platform via [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol) + + + + In Infisical, head to your Organization Settings > Authentication > LDAP Configuration and select **Set up LDAP**. + + Next, input your LDAP server settings. + + ![LDAP configuration](/images/platform/ldap/ldap-config.png) + + Here's some guidance for each field: + + - URL: The LDAP server to connect to such as `ldap://ldap.your-org.com`, `ldaps://ldap.myorg.com:636` (for connection over SSL/TLS), etc. + - Bind DN: The distinguished name of object to bind when performing the user search such as `cn=infisical,ou=Users,dc=acme,dc=com`. + - Bind Pass: The password to use along with `Bind DN` when performing the user search. + - Search Base / User DN: Base DN under which to perform user search such as `ou=Users,dc=example,dc=com` + - CA Certificate: The CA certificate to use when verifying the LDAP server certificate. + + + Enabling LDAP allows members in your organization to log into Infisical via LDAP. + + ![LDAP toggle](/images/platform/ldap/ldap-toggle.png) + + \ No newline at end of file diff --git a/docs/documentation/platform/ldap/jumpcloud.mdx b/docs/documentation/platform/ldap/jumpcloud.mdx new file mode 100644 index 000000000..b52a75880 --- /dev/null +++ b/docs/documentation/platform/ldap/jumpcloud.mdx @@ -0,0 +1,56 @@ +--- +title: "JumpCloud LDAP" +description: "Configure JumpCloud LDAP for Logging into Infisical" +--- + + + LDAP is a paid feature. + + If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical, + then you should contact team@infisical.com to purchase an enterprise license to use it. + + + + + In JumpCloud, head to USER MANAGEMENT > Users and create a new user via the **Manual user entry** option. This user + will be used as a privileged service account to facilitate Infisical's ability to bind/search the LDAP directory. + + When creating the user, input their **First Name**, **Last Name**, **Username** (required), **Company Email** (required), and **Description**. + Also, create a password for the user. + + Next, under User Security Settings and Permissions > Permission Settings, check the box next to **Enable as LDAP Bind DN**. + + ![LDAP JumpCloud](/images/platform/ldap/jumpcloud/ldap-jumpcloud-enable-bind-dn.png) + + + + In Infisical, head to your Organization Settings > Authentication > LDAP Configuration and select **Set up LDAP**. + + Next, input your JumpCloud LDAP server settings. + + ![LDAP configuration](/images/platform/ldap/ldap-config.png) + + Here's some guidance for each field: + + - URL: The LDAP server to connect to (`ldaps://ldap.jumpcloud.com:636`). + - Bind DN: The distinguished name of object to bind when performing the user search (`uid=,ou=Users,o=,dc=jumpcloud,dc=com`). + - Bind Pass: The password to use along with `Bind DN` when performing the user search. + - Search Base / User DN: Base DN under which to perform user search (`ou=Users,o=,dc=jumpcloud,dc=com`). + - CA Certificate: The CA certificate to use when verifying the LDAP server certificate (instructions to obtain the certificate for JumpCloud [here](https://jumpcloud.com/support/connect-to-ldap-with-tls-ssl)). + + + When filling out the **Bind DN** and **Bind Pass** fields, refer to the username and password of the user created in Step 1. + + Also, for the **Bind DN** and **Search Base / User DN** fields, you'll want to use the organization ID that appears + in your LDAP instance **ORG DN**. + + + + Enabling LDAP allows members in your organization to log into Infisical via LDAP. + + ![LDAP toggle](/images/platform/ldap/ldap-toggle.png) + + + +Resources: +- [JumpCloud Cloud LDAP Guide](https://jumpcloud.com/support/use-cloud-ldap) \ No newline at end of file diff --git a/docs/documentation/platform/ldap/overview.mdx b/docs/documentation/platform/ldap/overview.mdx new file mode 100644 index 000000000..d19095b7c --- /dev/null +++ b/docs/documentation/platform/ldap/overview.mdx @@ -0,0 +1,23 @@ +--- +title: "LDAP Overview" +description: "Log in to Infisical with LDAP" +--- + + LDAP is a paid feature. + + If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical, + then you should contact sales@infisical.com to purchase an enterprise license to use it. + + +You can configure your organization in Infisical to have members authenticate with the platform via [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol) + +To note, configuring LDAP retains the end-to-end encrypted architecture of Infisical because we decouple the authentication and decryption steps; the LDAP server cannot and will not have access to the decryption key needed to decrypt your secrets. + +LDAP providers: + +- Active Directory +- [JumpCloud LDAP](/documentation/platform/ldap/jumpcloud) +- AWS Directory Service +- Foxpass + +Check out the general instructions for configuring LDAP [here](/documentation/platform/ldap/general). diff --git a/docs/documentation/platform/project-upgrade.mdx b/docs/documentation/platform/project-upgrade.mdx new file mode 100644 index 000000000..6c7e509f5 --- /dev/null +++ b/docs/documentation/platform/project-upgrade.mdx @@ -0,0 +1,21 @@ +--- +title: "Enhancing Security and Usability: Project Upgrades" +--- + + +At Infisical, we're constantly striving to elevate the security and usability standards of our platform to better serve our users. +With this commitment in mind, we're excited to introduce our latest addition, non-E2EE projects, aimed at addressing two significant issues while enhancing how clients interact with Infisical programmatically. + +Previously, users encountered a challenge where projects risked becoming inaccessible if the project creator deleted their account. +Additionally, our API lacked the capability to interact with projects without dealing with complex cryptographic operations. +These obstacles made API driven automation and collaboration a painful experience for a majority of our users. + +To overcome these limitations, our upgrade focuses on disabling end-to-end encryption (E2EE) for projects. +While this may raise eyebrows, it's important to understand that this decision is a strategic move to make Infisical easer to use and interact with. + +But what does this mean for our users? Essentially nothing, there are no changes required on your end. +Rest assured, all sensitive data remains encrypted at rest according to the latest industry standards. +Our commitment to security remains unwavering, and this upgrade is a testament to our dedication to delivering on our promises in both security and usability when it comes to secrets management. + +To increase consistency with existing and future integrations, all projects created on Infisical from now on will have end-to-end encryption (E2EE) disabled by default. +This will not only reduce confusion for end users, but will also make the Infisical API seamless to use. diff --git a/docs/images/platform/ldap/jumpcloud/ldap-jumpcloud-enable-bind-dn.png b/docs/images/platform/ldap/jumpcloud/ldap-jumpcloud-enable-bind-dn.png new file mode 100644 index 000000000..b50c1e0be Binary files /dev/null and b/docs/images/platform/ldap/jumpcloud/ldap-jumpcloud-enable-bind-dn.png differ diff --git a/docs/images/platform/ldap/jumpcloud/ldap-jumpcloud-org-dn.png b/docs/images/platform/ldap/jumpcloud/ldap-jumpcloud-org-dn.png new file mode 100644 index 000000000..cd6166b1f Binary files /dev/null and b/docs/images/platform/ldap/jumpcloud/ldap-jumpcloud-org-dn.png differ diff --git a/docs/images/platform/ldap/ldap-config.png b/docs/images/platform/ldap/ldap-config.png new file mode 100644 index 000000000..8d105c1d6 Binary files /dev/null and b/docs/images/platform/ldap/ldap-config.png differ diff --git a/docs/images/platform/ldap/ldap-toggle.png b/docs/images/platform/ldap/ldap-toggle.png new file mode 100644 index 000000000..dcc7ffc96 Binary files /dev/null and b/docs/images/platform/ldap/ldap-toggle.png differ diff --git a/docs/images/self-hosting/applicable-to-all/selfhost-signup.png b/docs/images/self-hosting/applicable-to-all/selfhost-signup.png index ec73105a0..745c32a44 100644 Binary files a/docs/images/self-hosting/applicable-to-all/selfhost-signup.png and b/docs/images/self-hosting/applicable-to-all/selfhost-signup.png differ diff --git a/docs/images/self-hosting/guides/mongo-postgres/mongo-migration.png b/docs/images/self-hosting/guides/mongo-postgres/mongo-migration.png new file mode 100644 index 000000000..b74cd4963 Binary files /dev/null and b/docs/images/self-hosting/guides/mongo-postgres/mongo-migration.png differ diff --git a/docs/mint.json b/docs/mint.json index e55dc5c43..852b93853 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -149,6 +149,14 @@ "documentation/platform/sso/jumpcloud" ] }, + { + "group": "LDAP", + "pages": [ + "documentation/platform/ldap/overview", + "documentation/platform/ldap/jumpcloud", + "documentation/platform/ldap/general" + ] + }, { "group": "SCIM", "pages": [ @@ -165,7 +173,6 @@ "pages": [ "self-hosting/overview", "self-hosting/configuration/requirements", - "self-hosting/configuration/schema-migrations", { "group": "Installation methods", "pages": [ @@ -175,6 +182,13 @@ ] }, "self-hosting/configuration/envars", + { + "group": "Guides", + "pages": [ + "self-hosting/configuration/schema-migrations", + "self-hosting/guides/mongo-to-postgres" + ] + }, "self-hosting/faq" ] }, diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index 333ddba5c..4bb56ebcd 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -4,7 +4,7 @@ description: "Configure environment variables for self-hosted Infisical" --- -Infisical accepts all configurations via environment variables. For a basic self-hosted instance, at least `ENCRYPTION_KEY`, `AUTH_SECRET`, `DB_CONNECTION_URI` and `REDIS_URL` must be defined. +Infisical accepts all configurations via environment variables. For a minimal self-hosted instance, at least `ENCRYPTION_KEY`, `AUTH_SECRET`, `DB_CONNECTION_URI` and `REDIS_URL` must be defined. However, you can configure additional settings to activate more features as needed. ## General platform diff --git a/docs/self-hosting/deployment-options/kubernetes-helm.mdx b/docs/self-hosting/deployment-options/kubernetes-helm.mdx index 072d65487..300cb3db9 100644 --- a/docs/self-hosting/deployment-options/kubernetes-helm.mdx +++ b/docs/self-hosting/deployment-options/kubernetes-helm.mdx @@ -166,7 +166,7 @@ description: "Use Helm chart to install Infisical on your Kubernetes cluster" After deployment, please wait for 2-5 minutes for all pods to reach a running state. Once a significant number of pods are operational, access the IP address revealed through Ingress by your load balancer. You can find the IP address/hostname by executing the command `kubectl get ingress`. - ![self host sign up](images/self-hosting/applicable-to-all/selfhost-signup.png) + ![infisical-selfhost](images/self-hosting/applicable-to-all/selfhost-signup.png) To upgrade your instance of Infisical simply update the docker image tag in your Halm values and rerun the command below. diff --git a/docs/self-hosting/faq.mdx b/docs/self-hosting/faq.mdx index 5bbc426e3..598d408ae 100644 --- a/docs/self-hosting/faq.mdx +++ b/docs/self-hosting/faq.mdx @@ -15,3 +15,7 @@ However, in the event you choose to use Infisical without SSL, you can do so by [Learn more about secure cookies](https://really-simple-ssl.com/definition/what-are-secure-cookies/) + + Follow the step by step guide [here](self-hosting/guides/mongo-to-postgres) to learn how. + + diff --git a/docs/self-hosting/guides/mongo-to-postgres.mdx b/docs/self-hosting/guides/mongo-to-postgres.mdx new file mode 100644 index 000000000..fe3f0aef7 --- /dev/null +++ b/docs/self-hosting/guides/mongo-to-postgres.mdx @@ -0,0 +1,195 @@ +--- +title: "Migrate Mongo to Postgres" +description: "How to migrate from MongoDB to PostgreSQL for Infisical" +--- + +This guide will provide step by step instructions on migrating your Infisical instance running on MongoDB to the newly released PostgreSQL version of Infisical. +The newly released Postgres version of Infisical is the only version of Infisical that will receive feature updates and patches going forward. + + + If you have a small set of secrets, we recommend you to download the secrets and upload them to your new instance of Infisical instead of running the migration script. + + +## Prerequisites + +Before starting the migration, ensure you have the following command line tools installed: + +- [pg_dump](https://www.postgresql.org/docs/current/app-pgrestore.html) +- [pg_restore](https://www.postgresql.org/docs/current/app-pgdump.html) +- [mongodump](https://www.mongodb.com/docs/database-tools/mongodump/) +- [mongorestore](https://www.mongodb.com/docs/database-tools/mongorestore/) +- [Docker](https://docs.docker.com/engine/install/) + +## Prepare for migration + + + + While the migration script will not mutate any MongoDB production data, we recommend you to take a backup of your MongoDB instance if possible. + + + To prevent new data entries during the migration, set your Infisical instance to migration mode by setting the environment variable `MIGRATION_MODE=true` and redeploying your instance. + This mode will block all write operations, only allowing GET requests. It also disables user logins and sets up a migration page to prevent UI interactions. + ![migration mode](/images/self-hosting/guides/mongo-postgres/mongo-migration.png) + + + Start local instances of MongoDB and Postgres. This will be used in later steps to process and transform the data locally. + + To start local instances of the two databases, create a file called `docker-compose.yaml` as shown below. + + ```yaml docker-compose.yaml + version: '3.1' + + services: + mongodb: + image: mongo + restart: always + environment: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: example + ports: + - "27017:27017" + volumes: + - mongodb_data:/data/db + + postgres: + image: postgres + restart: always + environment: + POSTGRES_PASSWORD: example + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + + volumes: + mongodb_data: + postgres_data: + ``` + + Next, run the command below in the same working directory where the `docker-compose.yaml` file resides to start both services. + + ``` + docker-compose up + ``` + + + + +## Dump MongoDB +To speed up the data transformation process, the first step involves transferring the production data from Infisical's MongoDB to a local machine. +This is achieved by creating a dump of the production database and then uploading this dumped data into a local Mongo instance. +By having a running local instance of the production database, we will significantly reduce the time it takes to run the migration script. + + + + + ``` + mongodump --uri= --archive="mongodump-db" --db= --excludeCollection=auditlogs + ``` + + + + ``` + mongorestore --uri=mongodb://root:example@localhost:27017/ --archive="mongodump-db" + ``` + + + +## Start the migration + +Once started, the migration script will transform MongoDB data into an equivalent PostgreSQL format. + + + + Clone the Infisical MongoDB repository. + ``` + git clone https://github.com/Infisical/infisical.git + ``` + + + ``` + cd backend + ``` + + ``` + npm install + ``` + + + ``` + cd pg-migrator + ``` + + ``` + npm install + ``` + + + ``` + npm run migration + ``` + + When executing the above command, you'll be asked to provide the MongoDB connection string for the database containing your production Infisical data. Since our production Mongo data is transferred to a local Mongo instance, you should input the connection string for this local instance. + + ``` + mongodb://root:example@localhost:27017/?authSource=admin + ``` + + + Remember to replace `` with the name of the MongoDB database. If you are not sure the name, you can use [Compass](https://www.mongodb.com/products/tools/compass) to view the available databases. + + + + Next, you will be asked to enter the Postgres connection string for the database where the transformed data should be stored. + Input the connection string of the local Postgres instance that was set up earlier in the guide. + + ``` + postgres://infisical:infisical@localhost/infisical?sslmode=disable + ``` + + + + Once the script has completed, you will notice a new folder has been created called `db` in the `pg-migrator` folder. + This folder contains meta data for schema mapping and can be helpful when debugging migration related issues. + We highly recommend you to make a copy of this folder in case you need assistance from the Infisical team during your migration process. + + + The `db` folder does not contain any sensitive data + + + + +## Finalizing Migration +At this stage, the data from the Mongo instance of Infisical should have been successfully converted into its Postgres equivalent. +The remaining step involves transferring the local Postgres database, which now contains all the migrated data, to your chosen production Postgres environment. +Rather than transferring the data row-by-row from your local machine to the production Postgres database, we will first create a dump file from the local Postgres and then upload this file to your production Postgres instance. + + + + ``` + pg_dump -h localhost -U infisical -Fc -b -v -f dumpfilelocation.sql -d infisical + ``` + + + ``` + pg_restore --clean -v -h -U -d -j 2 dumpfilelocation.sql + ``` + + + Remember to replace ``, ``, `` with the corresponding details of your production Postgres database. + + + + Use a tool like Beekeeper Studio to confirm that the data has been successfully transferred to your production Postgres DB. + + + +## Post-Migration Steps + +After successfully migrating the data to PostgreSQL, you can proceed to deploy Infisical using your preferred deployment method. +Refer to [Infisical's self-hosting documentation](https://infisical.com/docs/self-hosting/overview) for deployment options. +Remember to use your production PostgreSQL connection string for the new deployment and transfer all [environment variables](/self-hosting/configuration/envars) from the MongoDB version of Infisical to the new version (they are all compatible). + +## Additional discussion +- When you visit Infisical's [docker hub](https://hub.docker.com/r/infisical/infisical) page, you will notice that image tags end with `-postgres`. +This is to indicate that this version of Infisical runs on the new Postgres backend. Any image tag that does not end in `postgres` runs on MongoDB. \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c47958a9e..48f90d2ee 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,5 +1,5 @@ { - "name": "npm-proj-1708750287210-0.2958294777207371vFy6Ag", + "name": "frontend", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/frontend/src/components/signup/EnterEmailStep.tsx b/frontend/src/components/signup/EnterEmailStep.tsx index 058c23106..fa26e80b9 100644 --- a/frontend/src/components/signup/EnterEmailStep.tsx +++ b/frontend/src/components/signup/EnterEmailStep.tsx @@ -28,7 +28,7 @@ export default function EnterEmailStep({ incrementStep }: DownloadBackupPDFStepProps): JSX.Element { const { createNotification } = useNotificationContext(); - const { mutateAsync } = useSendVerificationEmail(); + const { mutateAsync, isLoading } = useSendVerificationEmail(); const [emailError, setEmailError] = useState(false); const { t } = useTranslation(); @@ -91,6 +91,8 @@ export default function EnterEmailStep({ className='h-14' colorSchema="primary" variant="outline_bg" + isLoading={isLoading} + isDisabled={isLoading} > {String(t("signup.step1-submit"))} diff --git a/frontend/src/components/utilities/cryptography/crypto.ts b/frontend/src/components/utilities/cryptography/crypto.ts index 0f0e4af22..c0e5d4c21 100644 --- a/frontend/src/components/utilities/cryptography/crypto.ts +++ b/frontend/src/components/utilities/cryptography/crypto.ts @@ -210,7 +210,14 @@ const decryptSymmetric = ({ ciphertext, iv, tag, key }: DecryptSymmetricProps): try { plaintext = aes.decrypt({ ciphertext, iv, tag, secret: key }); } catch (err) { - console.log("Failed to perform decryption"); + console.log("Failed to decrypt with the following parameters", { + ciphertext, + iv, + tag, + key + }); + console.log("Failed to perform decryption", err); + process.exit(1); } diff --git a/frontend/src/components/v2/UpgradeProjectAlert/UpgradeProjectAlert.tsx b/frontend/src/components/v2/UpgradeProjectAlert/UpgradeProjectAlert.tsx index 121f77067..f07a076b4 100644 --- a/frontend/src/components/v2/UpgradeProjectAlert/UpgradeProjectAlert.tsx +++ b/frontend/src/components/v2/UpgradeProjectAlert/UpgradeProjectAlert.tsx @@ -1,4 +1,5 @@ import { useCallback, useState } from "react"; +import Link from "next/link"; import { useRouter } from "next/router"; import { faWarning } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -97,16 +98,31 @@ export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX.
Upgrade your project {membership.role === "admin" ? ( -

- Upgrade your project version to continue receiving the latest improvements and patches. -

+ <> +

+ Upgrade your project version to continue receiving the latest improvements and + patches. +

+ + + Learn more + + + ) : ( -

- Please ask a project admin to upgrade the project. -
- Upgrading the project version is required to continue receiving the latest improvements - and patches. -

+ <> +

+ Please ask a project admin to upgrade the project. +
+ Upgrading the project version is required to continue receiving the latest + improvements and patches. +

+ + + Learn more + + + )} {currentStatus &&

Status: {currentStatus}

}
diff --git a/frontend/src/views/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx b/frontend/src/views/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx index edeadef36..ed7b571e3 100644 --- a/frontend/src/views/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx +++ b/frontend/src/views/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx @@ -90,7 +90,7 @@ export const CreateRotationForm = ({ {WIZARD_STEPS.map(({ title, description }, index) => ( diff --git a/helm-charts/infisical-standalone-postgres/Chart.yaml b/helm-charts/infisical-standalone-postgres/Chart.yaml index e5892d2e3..1eaace01c 100644 --- a/helm-charts/infisical-standalone-postgres/Chart.yaml +++ b/helm-charts/infisical-standalone-postgres/Chart.yaml @@ -7,7 +7,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.0.0 +version: 1.0.5 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm-charts/infisical-standalone-postgres/templates/ingress.yaml b/helm-charts/infisical-standalone-postgres/templates/ingress.yaml new file mode 100644 index 000000000..a059c4f24 --- /dev/null +++ b/helm-charts/infisical-standalone-postgres/templates/ingress.yaml @@ -0,0 +1,50 @@ +{{ if .Values.ingress.enabled }} +{{- $ingress := .Values.ingress }} +{{- if and $ingress.ingressClassName (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey $ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set $ingress.annotations "kubernetes.io/ingress.class" $ingress.ingressClassName}} + {{- end }} +{{- end }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: infisical-ingress + {{- with $ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and $ingress.ingressClassName (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ $ingress.ingressClassName | default "nginx" }} + {{- end }} +{{- if $ingress.tls }} + tls: + {{- range $ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "infisical.fullname" . }} + port: + number: 8080 + - path: /ss-webhook + pathType: Exact + backend: + service: + name: {{ include "infisical.fullname" . }} + port: + number: 8080 + {{- if $ingress.hostName }} + host: {{ $ingress.hostName }} + {{- end }} +{{ end }} \ No newline at end of file diff --git a/helm-charts/infisical-standalone-postgres/values.yaml b/helm-charts/infisical-standalone-postgres/values.yaml index 014bb659d..1b5f2f561 100644 --- a/helm-charts/infisical-standalone-postgres/values.yaml +++ b/helm-charts/infisical-standalone-postgres/values.yaml @@ -24,9 +24,9 @@ infisical: resources: limits: - memory: 210Mi + memory: 350Mi requests: - cpu: 200m + cpu: 350m ingress: enabled: true diff --git a/pg-migrator/src/index.ts b/pg-migrator/src/index.ts index aab8cdba1..9845e9d03 100644 --- a/pg-migrator/src/index.ts +++ b/pg-migrator/src/index.ts @@ -66,7 +66,7 @@ enum SecretEncryptionAlgo { AES_256_GCM = "aes-256-gcm", } -const ENV_SLUG_LENGTH = 15; +const ENV_SLUG_LENGTH = 500; enum SecretKeyEncoding { UTF8 = "utf8", @@ -210,9 +210,9 @@ export const migrateCollection = async < return (await tx .batchInsert(postgresTableName, pgDoc as any) .returning(returnKeys as any)) as Pick< - Tables[K]["base"], - R[number] - >[]; + Tables[K]["base"], + R[number] + >[]; }); await postPgProcessing?.(mongooseDoc, newUserIds); } @@ -230,9 +230,9 @@ export const migrateCollection = async < return (await tx .batchInsert(postgresTableName, pgDoc as any) .returning(returnKeys as any)) as Pick< - Tables[K]["base"], - R[number] - >[]; + Tables[K]["base"], + R[number] + >[]; }); await postPgProcessing?.(mongooseDoc, newUserIds); } @@ -258,9 +258,9 @@ const main = async () => { try { dotenv.config(); - process.env.MONGO_DB_URL = "mongodb://root:example@localhost:27017/test?authSource=admin" + // process.env.MONGO_DB_URL = "mongodb://root:example@localhost:27017/test?authSource=admin" - process.env.POSTGRES_DB_URL = "postgres://infisical:infisical@localhost/infisical?sslmode=disable" + // process.env.POSTGRES_DB_URL = "postgres://infisical:infisical@localhost/infisical?sslmode=disable" process.env.START_FRESH = "true"; const prompt = promptSync({ sigint: true }); @@ -313,7 +313,7 @@ const main = async () => { preProcessing: async (doc) => { if (["64058e0ea5c55c6a8203fed7", "64155f5d75c91bf4e176eb85", "6434ff80b82e04f17008aa13"].includes(doc._id.toString())) { console.log("Skipping duplicate user") - return + return } const id = uuidV4(); @@ -843,9 +843,9 @@ const main = async () => { await folderKv.put(folder.id, id); const parentId = folder?.parentId ? await folderKv.get(folder?.parentId).catch((e) => { - console.log("parent folder not found==>", folder); - throw e; - }) + console.log("parent folder not found==>", folder); + throw e; + }) : null; pgFolder.push({ @@ -1548,8 +1548,8 @@ const main = async () => { returnKeys: ["id"], preProcessing: async (doc) => { // dangling identity - if (!await identityKv.get(doc.identity.toString()).catch(() => null)){ - return + if (!await identityKv.get(doc.identity.toString()).catch(() => null)) { + return } const id = uuidV4(); @@ -1584,8 +1584,8 @@ const main = async () => { returnKeys: ["id"], preProcessing: async (doc) => { // dangling identity - if (!await identityKv.get(doc.identity.toString()).catch(() => null)){ - return + if (!await identityKv.get(doc.identity.toString()).catch(() => null)) { + return } const identityUAId = await identityUaKv.get( @@ -1617,15 +1617,15 @@ const main = async () => { returnKeys: ["id"], preProcessing: async (doc) => { // dangling identity - if (!await identityKv.get(doc.identity.toString()).catch(() => null)){ - return + if (!await identityKv.get(doc.identity.toString()).catch(() => null)) { + return } await identityAccessTokenKv.put(doc._id.toString(), doc._id.toString()); const identityUAClientSecretId = doc?.identityUniversalAuthClientSecret ? await identityUaClientSecKv.get( - doc.identityUniversalAuthClientSecret.toString(), - ) + doc.identityUniversalAuthClientSecret.toString(), + ) : null; const identityId = await identityKv.get(doc.identity.toString()); return { @@ -1652,8 +1652,8 @@ const main = async () => { returnKeys: ["id"], preProcessing: async (doc) => { // dangling identity - if (!await identityKv.get(doc.identity.toString()).catch(() => null)){ - return + if (!await identityKv.get(doc.identity.toString()).catch(() => null)) { + return } const id = uuidV4(); @@ -1687,8 +1687,8 @@ const main = async () => { returnKeys: ["id"], preProcessing: async (doc) => { // dangling identity - if (!await identityKv.get(doc.identity.toString()).catch(() => null)){ - return + if (!await identityKv.get(doc.identity.toString()).catch(() => null)) { + return } const id = uuidV4(); @@ -2317,8 +2317,8 @@ const main = async () => { const statusChangeBy = doc.statusChangeBy ? await projectMembKv - .get(doc.statusChangeBy.toString()) - .catch(() => null) + .get(doc.statusChangeBy.toString()) + .catch(() => null) : null; return { id, @@ -2454,7 +2454,7 @@ const main = async () => { secretCommentCiphertext: commit.newVersion.secretCommentCiphertext || secret.secretCommentCiphertext, - secretVersion, + secretVersion, createdAt: new Date((doc as any).createdAt), updatedAt: new Date((doc as any).updatedAt), };