diff --git a/backend/src/@types/knex.d.ts b/backend/src/@types/knex.d.ts index 8aa00ec79..be98cd212 100644 --- a/backend/src/@types/knex.d.ts +++ b/backend/src/@types/knex.d.ts @@ -227,6 +227,9 @@ import { TSecretReferences, TSecretReferencesInsert, TSecretReferencesUpdate, + TSecretReferencesV2, + TSecretReferencesV2Insert, + TSecretReferencesV2Update, TSecretRotationOutputs, TSecretRotationOutputsInsert, TSecretRotationOutputsUpdate, @@ -263,6 +266,9 @@ import { TSecretVersionTagJunction, TSecretVersionTagJunctionInsert, TSecretVersionTagJunctionUpdate, + TSecretVersionV2TagJunction, + TSecretVersionV2TagJunctionInsert, + TSecretVersionV2TagJunctionUpdate, TServiceTokens, TServiceTokensInsert, TServiceTokensUpdate, @@ -291,6 +297,17 @@ import { TWebhooksInsert, TWebhooksUpdate } from "@app/db/schemas"; +import { + TSecretV2TagJunction, + TSecretV2TagJunctionInsert, + TSecretV2TagJunctionUpdate +} from "@app/db/schemas/secret-v2-tag-junction"; +import { + TSecretVersionsV2, + TSecretVersionsV2Insert, + TSecretVersionsV2Update +} from "@app/db/schemas/secret-versions-v2"; +import { TSecretsV2, TSecretsV2Insert, TSecretsV2Update } from "@app/db/schemas/secrets-v2"; declare module "knex" { namespace Knex { @@ -645,7 +662,23 @@ declare module "knex/types/tables" { TSecretScanningGitRisksUpdate >; [TableName.TrustedIps]: KnexOriginal.CompositeTableType; + [TableName.SecretV2]: KnexOriginal.CompositeTableType; + [TableName.SecretVersionV2]: KnexOriginal.CompositeTableType< + TSecretVersionsV2, + TSecretVersionsV2Insert, + TSecretVersionsV2Update + >; + [TableName.SecretReferenceV2]: KnexOriginal.CompositeTableType< + TSecretReferencesV2, + TSecretReferencesV2Insert, + TSecretReferencesV2Update + >; // Junction tables + [TableName.SecretV2JnTag]: KnexOriginal.CompositeTableType< + TSecretV2TagJunction, + TSecretV2TagJunctionInsert, + TSecretV2TagJunctionUpdate + >; [TableName.JnSecretTag]: KnexOriginal.CompositeTableType< TSecretTagJunction, TSecretTagJunctionInsert, @@ -656,6 +689,11 @@ declare module "knex/types/tables" { TSecretVersionTagJunctionInsert, TSecretVersionTagJunctionUpdate >; + [TableName.SecretVersionV2Tag]: KnexOriginal.CompositeTableType< + TSecretVersionV2TagJunction, + TSecretVersionV2TagJunctionInsert, + TSecretVersionV2TagJunctionUpdate + >; // KMS service [TableName.KmsServerRootConfig]: KnexOriginal.CompositeTableType< TKmsRootConfig, diff --git a/backend/src/db/migrations/20240716105646_secret-v2.ts b/backend/src/db/migrations/20240716105646_secret-v2.ts new file mode 100644 index 000000000..630f4a61e --- /dev/null +++ b/backend/src/db/migrations/20240716105646_secret-v2.ts @@ -0,0 +1,81 @@ +import { Knex } from "knex"; + +import { SecretType, TableName } from "../schemas"; +import { createJunctionTable, createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils"; + +export async function up(knex: Knex): Promise { + const doesSecretV2TableExist = await knex.schema.hasTable(TableName.SecretV2); + if (!doesSecretV2TableExist) { + await knex.schema.createTable(TableName.SecretV2, (t) => { + t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); + t.integer("version").defaultTo(1).notNullable(); + t.string("type").notNullable().defaultTo(SecretType.Shared); + t.string("key", 500).notNullable(); + t.binary("encryptedValue"); + t.binary("encryptedComment"); + t.string("reminderNote"); + t.integer("reminderRepeatDays"); + t.boolean("skipMultilineEncoding").defaultTo(false); + t.jsonb("metadata"); + t.uuid("userId"); + t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE"); + t.uuid("folderId").notNullable(); + t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE"); + t.timestamps(true, true, true); + }); + } + await createOnUpdateTrigger(knex, TableName.SecretV2); + + // many to many relation between tags + await createJunctionTable(knex, TableName.SecretV2JnTag, TableName.SecretV2, TableName.SecretTag); + + const doesSecretV2VersionTableExist = await knex.schema.hasTable(TableName.SecretVersionV2); + if (!doesSecretV2VersionTableExist) { + await knex.schema.createTable(TableName.SecretVersionV2, (t) => { + t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); + t.integer("version").defaultTo(1).notNullable(); + t.string("type").notNullable().defaultTo(SecretType.Shared); + t.string("key", 500).notNullable(); + t.binary("encryptedValue"); + t.binary("encryptedComment"); + t.string("reminderNote"); + t.integer("reminderRepeatDays"); + t.boolean("skipMultilineEncoding").defaultTo(false); + t.jsonb("metadata"); + // to avoid orphan rows + t.uuid("envId"); + t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE"); + t.uuid("secretId").notNullable(); + t.uuid("folderId").notNullable(); + t.uuid("userId"); + t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE"); + t.timestamps(true, true, true); + }); + } + await createOnUpdateTrigger(knex, TableName.SecretVersionV2); + + if (!(await knex.schema.hasTable(TableName.SecretReferenceV2))) { + await knex.schema.createTable(TableName.SecretReferenceV2, (t) => { + t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); + t.string("environment").notNullable(); + t.string("secretPath").notNullable(); + t.string("secretKey", 500).notNullable(); + t.uuid("secretId").notNullable(); + t.foreign("secretId").references("id").inTable(TableName.SecretV2).onDelete("CASCADE"); + }); + } + + await createJunctionTable(knex, TableName.SecretVersionV2Tag, TableName.SecretVersionV2, TableName.SecretTag); +} + +export async function down(knex: Knex): Promise { + await knex.schema.dropTableIfExists(TableName.SecretV2JnTag); + await knex.schema.dropTableIfExists(TableName.SecretReferenceV2); + + await dropOnUpdateTrigger(knex, TableName.SecretV2); + await knex.schema.dropTableIfExists(TableName.SecretV2); + + await dropOnUpdateTrigger(knex, TableName.SecretVersionV2); + await knex.schema.dropTableIfExists(TableName.SecretVersionV2Tag); + await knex.schema.dropTableIfExists(TableName.SecretVersionV2); +} diff --git a/backend/src/db/schemas/index.ts b/backend/src/db/schemas/index.ts index 06c735cee..f0d43b98f 100644 --- a/backend/src/db/schemas/index.ts +++ b/backend/src/db/schemas/index.ts @@ -74,6 +74,7 @@ export * from "./secret-folder-versions"; export * from "./secret-folders"; export * from "./secret-imports"; export * from "./secret-references"; +export * from "./secret-references-v2"; export * from "./secret-rotation-outputs"; export * from "./secret-rotations"; export * from "./secret-scanning-git-risks"; @@ -83,9 +84,13 @@ export * from "./secret-snapshot-secrets"; export * from "./secret-snapshots"; export * from "./secret-tag-junction"; export * from "./secret-tags"; +export * from "./secret-v2-tag-junction"; export * from "./secret-version-tag-junction"; +export * from "./secret-version-v2-tag-junction"; export * from "./secret-versions"; +export * from "./secret-versions-v2"; export * from "./secrets"; +export * from "./secrets-v2"; export * from "./service-tokens"; export * from "./super-admin"; export * from "./trusted-ips"; diff --git a/backend/src/db/schemas/models.ts b/backend/src/db/schemas/models.ts index 5747fb381..44d0cfd91 100644 --- a/backend/src/db/schemas/models.ts +++ b/backend/src/db/schemas/models.ts @@ -90,9 +90,14 @@ export enum TableName { TrustedIps = "trusted_ips", DynamicSecret = "dynamic_secrets", DynamicSecretLease = "dynamic_secret_leases", + SecretV2 = "secrets_v2", + SecretReferenceV2 = "secret_references_v2", + SecretVersionV2 = "secret_versions_v2", // junction tables with tags + SecretV2JnTag = "secret_v2_tag_junction", JnSecretTag = "secret_tag_junction", SecretVersionTag = "secret_version_tag_junction", + SecretVersionV2Tag = "secret_version_v2_tag_junction", // KMS Service KmsServerRootConfig = "kms_root_config", KmsKey = "kms_keys", diff --git a/backend/src/db/schemas/secret-references-v2.ts b/backend/src/db/schemas/secret-references-v2.ts new file mode 100644 index 000000000..ed339e65c --- /dev/null +++ b/backend/src/db/schemas/secret-references-v2.ts @@ -0,0 +1,20 @@ +// Code generated by automation script, DO NOT EDIT. +// Automated by pulling database and generating zod schema +// To update. Just run npm run generate:schema +// Written by akhilmhdh. + +import { z } from "zod"; + +import { TImmutableDBKeys } from "./models"; + +export const SecretReferencesV2Schema = z.object({ + id: z.string().uuid(), + environment: z.string(), + secretPath: z.string(), + secretKey: z.string(), + secretId: z.string().uuid() +}); + +export type TSecretReferencesV2 = z.infer; +export type TSecretReferencesV2Insert = Omit, TImmutableDBKeys>; +export type TSecretReferencesV2Update = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-v2-tag-junction.ts b/backend/src/db/schemas/secret-v2-tag-junction.ts new file mode 100644 index 000000000..982e11f50 --- /dev/null +++ b/backend/src/db/schemas/secret-v2-tag-junction.ts @@ -0,0 +1,18 @@ +// Code generated by automation script, DO NOT EDIT. +// Automated by pulling database and generating zod schema +// To update. Just run npm run generate:schema +// Written by akhilmhdh. + +import { z } from "zod"; + +import { TImmutableDBKeys } from "./models"; + +export const SecretV2TagJunctionSchema = z.object({ + id: z.string().uuid(), + secrets_v2Id: z.string().uuid(), + secret_tagsId: z.string().uuid() +}); + +export type TSecretV2TagJunction = z.infer; +export type TSecretV2TagJunctionInsert = Omit, TImmutableDBKeys>; +export type TSecretV2TagJunctionUpdate = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secret-version-v2-tag-junction.ts b/backend/src/db/schemas/secret-version-v2-tag-junction.ts new file mode 100644 index 000000000..4679116a0 --- /dev/null +++ b/backend/src/db/schemas/secret-version-v2-tag-junction.ts @@ -0,0 +1,23 @@ +// Code generated by automation script, DO NOT EDIT. +// Automated by pulling database and generating zod schema +// To update. Just run npm run generate:schema +// Written by akhilmhdh. + +import { z } from "zod"; + +import { TImmutableDBKeys } from "./models"; + +export const SecretVersionV2TagJunctionSchema = z.object({ + id: z.string().uuid(), + secret_versions_v2Id: z.string().uuid(), + secret_tagsId: z.string().uuid() +}); + +export type TSecretVersionV2TagJunction = z.infer; +export type TSecretVersionV2TagJunctionInsert = Omit< + z.input, + TImmutableDBKeys +>; +export type TSecretVersionV2TagJunctionUpdate = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/db/schemas/secret-versions-v2.ts b/backend/src/db/schemas/secret-versions-v2.ts new file mode 100644 index 000000000..160ed1c14 --- /dev/null +++ b/backend/src/db/schemas/secret-versions-v2.ts @@ -0,0 +1,33 @@ +// Code generated by automation script, DO NOT EDIT. +// Automated by pulling database and generating zod schema +// To update. Just run npm run generate:schema +// Written by akhilmhdh. + +import { z } from "zod"; + +import { zodBuffer } from "@app/lib/zod"; + +import { TImmutableDBKeys } from "./models"; + +export const SecretVersionsV2Schema = z.object({ + id: z.string().uuid(), + version: z.number().default(1), + type: z.string().default("shared"), + key: z.string(), + encryptedValue: zodBuffer.nullable().optional(), + encryptedComment: zodBuffer.nullable().optional(), + reminderNote: z.string().nullable().optional(), + reminderRepeatDays: z.number().nullable().optional(), + skipMultilineEncoding: z.boolean().default(false).nullable().optional(), + metadata: z.unknown().nullable().optional(), + envId: z.string().uuid().nullable().optional(), + secretId: z.string().uuid(), + folderId: z.string().uuid(), + userId: z.string().uuid().nullable().optional(), + createdAt: z.date(), + updatedAt: z.date() +}); + +export type TSecretVersionsV2 = z.infer; +export type TSecretVersionsV2Insert = Omit, TImmutableDBKeys>; +export type TSecretVersionsV2Update = Partial, TImmutableDBKeys>>; diff --git a/backend/src/db/schemas/secrets-v2.ts b/backend/src/db/schemas/secrets-v2.ts new file mode 100644 index 000000000..18fa3b476 --- /dev/null +++ b/backend/src/db/schemas/secrets-v2.ts @@ -0,0 +1,31 @@ +// Code generated by automation script, DO NOT EDIT. +// Automated by pulling database and generating zod schema +// To update. Just run npm run generate:schema +// Written by akhilmhdh. + +import { z } from "zod"; + +import { zodBuffer } from "@app/lib/zod"; + +import { TImmutableDBKeys } from "./models"; + +export const SecretsV2Schema = z.object({ + id: z.string().uuid(), + version: z.number().default(1), + type: z.string().default("shared"), + key: z.string(), + encryptedValue: zodBuffer.nullable().optional(), + encryptedComment: zodBuffer.nullable().optional(), + reminderNote: z.string().nullable().optional(), + reminderRepeatDays: z.number().nullable().optional(), + skipMultilineEncoding: z.boolean().default(false).nullable().optional(), + metadata: z.unknown().nullable().optional(), + userId: z.string().uuid().nullable().optional(), + folderId: z.string().uuid(), + createdAt: z.date(), + updatedAt: z.date() +}); + +export type TSecretsV2 = z.infer; +export type TSecretsV2Insert = Omit, TImmutableDBKeys>; +export type TSecretsV2Update = Partial, TImmutableDBKeys>>;