diff --git a/backend/src/db/migrations/20250626101747_default-project-type.ts b/backend/src/db/migrations/20250626101747_default-project-type.ts index 84d439844..58aa23ab7 100644 --- a/backend/src/db/migrations/20250626101747_default-project-type.ts +++ b/backend/src/db/migrations/20250626101747_default-project-type.ts @@ -8,13 +8,13 @@ export async function up(knex: Knex): Promise { if (hasTypeColumn && !hasDefaultTypeColumn) { await knex.schema.alterTable(TableName.Project, (t) => { t.string("type").nullable().alter(); - t.string("defaultType").notNullable().defaultTo(ProjectType.SecretManager); + t.string("defaultProduct").notNullable().defaultTo(ProjectType.SecretManager); }); await knex(TableName.Project).update({ // eslint-disable-next-line // @ts-ignore this is because this field is created later - defaultType: knex.raw(` + defaultProduct: knex.raw(` CASE WHEN "type" IS NULL OR "type" = '' THEN 'secret-manager' ELSE "type" @@ -32,10 +32,10 @@ export async function up(knex: Knex): Promise { } export async function down(knex: Knex): Promise { - const hasDefaultTypeColumn = await knex.schema.hasColumn(TableName.Project, "defaultType"); + const hasDefaultTypeColumn = await knex.schema.hasColumn(TableName.Project, "defaultProduct"); if (hasDefaultTypeColumn) { await knex.schema.alterTable(TableName.Project, (t) => { - t.dropColumn("defaultType"); + t.dropColumn("defaultProduct"); }); } } diff --git a/backend/src/db/schemas/projects.ts b/backend/src/db/schemas/projects.ts index ee8a4cce1..00401575e 100644 --- a/backend/src/db/schemas/projects.ts +++ b/backend/src/db/schemas/projects.ts @@ -30,7 +30,7 @@ export const ProjectsSchema = z.object({ hasDeleteProtection: z.boolean().default(false).nullable().optional(), secretSharing: z.boolean().default(true), showSnapshotsLegacy: z.boolean().default(false), - defaultType: z.string().default("secret-manager") + defaultProduct: z.string().default("secret-manager") }); export type TProjects = z.infer; diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 1e169f58d..4405728b2 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -700,7 +700,8 @@ export const PROJECTS = { slug: "An optional slug for the project. (must be unique within the organization)", hasDeleteProtection: "Enable or disable delete protection for the project.", secretSharing: "Enable or disable secret sharing for the project.", - showSnapshotsLegacy: "Enable or disable legacy snapshots for the project." + showSnapshotsLegacy: "Enable or disable legacy snapshots for the project.", + defaultProduct: "The default product in which the project will open" }, GET_KEY: { workspaceId: "The ID of the project to get the key from." diff --git a/backend/src/server/routes/sanitizedSchemas.ts b/backend/src/server/routes/sanitizedSchemas.ts index 13d7ae2c1..beef663b9 100644 --- a/backend/src/server/routes/sanitizedSchemas.ts +++ b/backend/src/server/routes/sanitizedSchemas.ts @@ -251,7 +251,7 @@ export const SanitizedProjectSchema = ProjectsSchema.pick({ name: true, description: true, type: true, - defaultType: true, + defaultProduct: true, slug: true, autoCapitalization: true, orgId: true, diff --git a/backend/src/server/routes/v1/project-router.ts b/backend/src/server/routes/v1/project-router.ts index 3046f0ae8..80c892a41 100644 --- a/backend/src/server/routes/v1/project-router.ts +++ b/backend/src/server/routes/v1/project-router.ts @@ -11,7 +11,8 @@ import { SecretFoldersSchema, SortDirection, UserEncryptionKeysSchema, - UsersSchema + UsersSchema, + ProjectType } from "@app/db/schemas"; import { ProjectMicrosoftTeamsConfigsSchema } from "@app/db/schemas/project-microsoft-teams-configs"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; @@ -365,7 +366,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { .optional() .describe(PROJECTS.UPDATE.slug), secretSharing: z.boolean().optional().describe(PROJECTS.UPDATE.secretSharing), - showSnapshotsLegacy: z.boolean().optional().describe(PROJECTS.UPDATE.showSnapshotsLegacy) + showSnapshotsLegacy: z.boolean().optional().describe(PROJECTS.UPDATE.showSnapshotsLegacy), + defaultProduct: z.nativeEnum(ProjectType).optional().describe(PROJECTS.UPDATE.defaultProduct) }), response: { 200: z.object({ @@ -384,6 +386,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { name: req.body.name, description: req.body.description, autoCapitalization: req.body.autoCapitalization, + defaultProduct: req.body.defaultProduct, hasDeleteProtection: req.body.hasDeleteProtection, slug: req.body.slug, secretSharing: req.body.secretSharing, diff --git a/backend/src/services/project/project-service.ts b/backend/src/services/project/project-service.ts index b6b4e183f..d79da75ce 100644 --- a/backend/src/services/project/project-service.ts +++ b/backend/src/services/project/project-service.ts @@ -651,6 +651,7 @@ export const projectServiceFactory = ({ hasDeleteProtection: update.hasDeleteProtection, slug: update.slug, secretSharing: update.secretSharing, + defaultProduct: update.defaultProduct, showSnapshotsLegacy: update.showSnapshotsLegacy }); diff --git a/backend/src/services/project/project-types.ts b/backend/src/services/project/project-types.ts index 8ef72492a..5d4578194 100644 --- a/backend/src/services/project/project-types.ts +++ b/backend/src/services/project/project-types.ts @@ -92,6 +92,7 @@ export type TUpdateProjectDTO = { description?: string; autoCapitalization?: boolean; hasDeleteProtection?: boolean; + defaultProduct?: ProjectType; slug?: string; secretSharing?: boolean; showSnapshotsLegacy?: boolean;