mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 07:30:20 +00:00
improvement: address requested feedback
This commit is contained in:
@@ -13,7 +13,6 @@ export async function up(knex: Knex): Promise<void> {
|
||||
t.jsonb("environments").notNullable();
|
||||
t.uuid("orgId").notNullable().references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
t.unique(["orgId", "name"]);
|
||||
});
|
||||
|
||||
await createOnUpdateTrigger(knex, TableName.ProjectTemplates);
|
||||
|
||||
@@ -13,7 +13,7 @@ export const ProjectTemplatesSchema = z.object({
|
||||
description: z.string().nullable().optional(),
|
||||
roles: z.unknown(),
|
||||
environments: z.unknown(),
|
||||
orgId: z.string().uuid().nullable().optional(),
|
||||
orgId: z.string().uuid(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
});
|
||||
|
||||
@@ -4,16 +4,16 @@ import { z } from "zod";
|
||||
import { ProjectMembershipRole, ProjectTemplatesSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
||||
import {
|
||||
DefaultProjectTemplateIdentifier,
|
||||
ProjectTemplateDefaultEnvironments
|
||||
} from "@app/ee/services/project-template/project-template-constants";
|
||||
import { ProjectTemplateDefaultEnvironments } from "@app/ee/services/project-template/project-template-constants";
|
||||
import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
|
||||
import { ProjectTemplates } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { UnpackedPermissionSchema } from "@app/server/routes/santizedSchemas/permission";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
const MAX_JSON_SIZE_LIMIT_IN_BYTES = 1_048_576; // 1MB
|
||||
|
||||
const SlugSchema = z
|
||||
.string()
|
||||
.trim()
|
||||
@@ -57,6 +57,9 @@ const ProjectTemplateRolesSchema = z
|
||||
.superRefine((roles, ctx) => {
|
||||
if (!roles.length) return;
|
||||
|
||||
if (Buffer.byteLength(JSON.stringify(roles)) > MAX_JSON_SIZE_LIMIT_IN_BYTES)
|
||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Size limit exceeded" });
|
||||
|
||||
if (new Set(roles.map((v) => v.slug)).size !== roles.length)
|
||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Role slugs must be unique" });
|
||||
|
||||
@@ -81,6 +84,9 @@ const ProjectTemplateEnvironmentsSchema = z
|
||||
.array()
|
||||
.min(1)
|
||||
.superRefine((environments, ctx) => {
|
||||
if (Buffer.byteLength(JSON.stringify(environments)) > MAX_JSON_SIZE_LIMIT_IN_BYTES)
|
||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Size limit exceeded" });
|
||||
|
||||
if (new Set(environments.map((v) => v.name)).size !== environments.length)
|
||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Environment names must be unique" });
|
||||
|
||||
@@ -116,7 +122,7 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
||||
handler: async (req) => {
|
||||
const projectTemplates = await server.services.projectTemplate.listProjectTemplatesByOrg(req.permission);
|
||||
|
||||
const auditTemplates = projectTemplates.filter((template) => template.name !== DefaultProjectTemplateIdentifier);
|
||||
const auditTemplates = projectTemplates.filter((template) => !isInfisicalProjectTemplate(template.name));
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
@@ -153,7 +159,7 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const projectTemplate = await server.services.projectTemplate.findProjectTemplatesById(
|
||||
const projectTemplate = await server.services.projectTemplate.findProjectTemplateById(
|
||||
req.params.templateId,
|
||||
req.permission
|
||||
);
|
||||
@@ -182,10 +188,10 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
||||
schema: {
|
||||
description: "Create a project template.",
|
||||
body: z.object({
|
||||
name: SlugSchema.refine((val) => val !== DefaultProjectTemplateIdentifier, {
|
||||
message: `The project template name "${DefaultProjectTemplateIdentifier}" is reserved.`
|
||||
name: SlugSchema.refine((val) => !isInfisicalProjectTemplate(val), {
|
||||
message: `The requested project template name is reserved.`
|
||||
}).describe(ProjectTemplates.CREATE.name),
|
||||
description: z.string().trim().optional().describe(ProjectTemplates.CREATE.description),
|
||||
description: z.string().max(256).trim().optional().describe(ProjectTemplates.CREATE.description),
|
||||
roles: ProjectTemplateRolesSchema.default([]).describe(ProjectTemplates.CREATE.roles),
|
||||
environments: ProjectTemplateEnvironmentsSchema.default(ProjectTemplateDefaultEnvironments).describe(
|
||||
ProjectTemplates.CREATE.environments
|
||||
@@ -224,12 +230,12 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
||||
description: "Update a project template.",
|
||||
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.UPDATE.templateId) }),
|
||||
body: z.object({
|
||||
name: SlugSchema.refine((val) => val !== DefaultProjectTemplateIdentifier, {
|
||||
message: `The project template name "${DefaultProjectTemplateIdentifier}" is reserved.`
|
||||
name: SlugSchema.refine((val) => !isInfisicalProjectTemplate(val), {
|
||||
message: `The requested project template name is reserved.`
|
||||
})
|
||||
.optional()
|
||||
.describe(ProjectTemplates.UPDATE.name),
|
||||
description: z.string().trim().optional().describe(ProjectTemplates.UPDATE.description),
|
||||
description: z.string().max(256).trim().optional().describe(ProjectTemplates.UPDATE.description),
|
||||
roles: ProjectTemplateRolesSchema.optional().describe(ProjectTemplates.UPDATE.roles),
|
||||
environments: ProjectTemplateEnvironmentsSchema.optional().describe(ProjectTemplates.UPDATE.environments)
|
||||
}),
|
||||
|
||||
@@ -1663,7 +1663,7 @@ interface DeleteProjectTemplateEvent {
|
||||
interface ApplyProjectTemplateEvent {
|
||||
type: EventType.APPLY_PROJECT_TEMPLATE;
|
||||
metadata: {
|
||||
templateId: string;
|
||||
template: string;
|
||||
projectId: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
||||
},
|
||||
pkiEst: false,
|
||||
enforceMfa: false,
|
||||
projectTemplates: false
|
||||
projectTemplates: true
|
||||
});
|
||||
|
||||
export const setupLicenseRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
|
||||
|
||||
@@ -1,25 +1,5 @@
|
||||
import { TUnpackedPermission } from "@app/ee/services/project-template/project-template-types";
|
||||
import { getPredefinedRoles } from "@app/services/project-role/project-role-fns";
|
||||
|
||||
export const ProjectTemplateDefaultEnvironments = [
|
||||
{ name: "Development", slug: "dev", position: 1 },
|
||||
{ name: "Staging", slug: "staging", position: 2 },
|
||||
{ name: "Production", slug: "prod", position: 3 }
|
||||
];
|
||||
|
||||
export const DefaultProjectTemplateIdentifier = "default";
|
||||
|
||||
export const getDefaultProjectTemplate = (orgId: string) => ({
|
||||
id: "b11b49a9-09a9-4443-916a-4246f9ff2c69", // random ID to appease zod
|
||||
name: DefaultProjectTemplateIdentifier,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
description: "Infisical's default project template",
|
||||
environments: ProjectTemplateDefaultEnvironments,
|
||||
roles: [...getPredefinedRoles("project-template")].map(({ name, slug, permissions }) => ({
|
||||
name,
|
||||
slug,
|
||||
permissions: permissions as TUnpackedPermission[]
|
||||
})),
|
||||
orgId
|
||||
});
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ProjectTemplateDefaultEnvironments } from "@app/ee/services/project-template/project-template-constants";
|
||||
import {
|
||||
InfisicalProjectTemplate,
|
||||
TUnpackedPermission
|
||||
} from "@app/ee/services/project-template/project-template-types";
|
||||
import { getPredefinedRoles } from "@app/services/project-role/project-role-fns";
|
||||
|
||||
export const getDefaultProjectTemplate = (orgId: string) => ({
|
||||
id: "b11b49a9-09a9-4443-916a-4246f9ff2c69", // random ID to appease zod
|
||||
name: InfisicalProjectTemplate.Default,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
description: "Infisical's default project template",
|
||||
environments: ProjectTemplateDefaultEnvironments,
|
||||
roles: [...getPredefinedRoles("project-template")].map(({ name, slug, permissions }) => ({
|
||||
name,
|
||||
slug,
|
||||
permissions: permissions as TUnpackedPermission[]
|
||||
})),
|
||||
orgId
|
||||
});
|
||||
|
||||
export const isInfisicalProjectTemplate = (template: string) =>
|
||||
Object.values(InfisicalProjectTemplate).includes(template as InfisicalProjectTemplate);
|
||||
@@ -5,7 +5,7 @@ import { TProjectTemplates } from "@app/db/schemas";
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { getDefaultProjectTemplate } from "@app/ee/services/project-template/project-template-constants";
|
||||
import { getDefaultProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
|
||||
import {
|
||||
TCreateProjectTemplateDTO,
|
||||
TProjectTemplateEnvironment,
|
||||
@@ -50,6 +50,13 @@ export const projectTemplateServiceFactory = ({
|
||||
projectTemplateDAL
|
||||
}: TProjectTemplatesServiceFactoryDep) => {
|
||||
const listProjectTemplatesByOrg = async (actor: OrgServiceActor) => {
|
||||
const plan = await licenseService.getPlan(actor.orgId);
|
||||
|
||||
if (!plan.projectTemplates)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to access project templates due to plan restriction. Upgrade plan to access project templates."
|
||||
});
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
@@ -60,13 +67,6 @@ export const projectTemplateServiceFactory = ({
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
const plan = await licenseService.getPlan(actor.orgId);
|
||||
|
||||
if (!plan.projectTemplates)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to access project templates due to plan restriction. Upgrade plan to access project templates."
|
||||
});
|
||||
|
||||
const projectTemplates = await projectTemplateDAL.find({
|
||||
orgId: actor.orgId
|
||||
});
|
||||
@@ -77,17 +77,7 @@ export const projectTemplateServiceFactory = ({
|
||||
];
|
||||
};
|
||||
|
||||
const findProjectTemplatesById = async (id: string, actor: OrgServiceActor) => {
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
actor.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
const findProjectTemplateByName = async (name: string, actor: OrgServiceActor) => {
|
||||
const plan = await licenseService.getPlan(actor.orgId);
|
||||
|
||||
if (!plan.projectTemplates)
|
||||
@@ -95,13 +85,48 @@ export const projectTemplateServiceFactory = ({
|
||||
message: "Failed to access project template due to plan restriction. Upgrade plan to access project templates."
|
||||
});
|
||||
|
||||
const [projectTemplate] = await projectTemplateDAL.find({
|
||||
id,
|
||||
orgId: actor.orgId // ensure from user org
|
||||
});
|
||||
const projectTemplate = await projectTemplateDAL.findOne({ name, orgId: actor.orgId });
|
||||
|
||||
if (!projectTemplate) throw new NotFoundError({ message: `Could not find project template with Name "${name}"` });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
projectTemplate.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
return {
|
||||
...$unpackProjectTemplate(projectTemplate),
|
||||
packedRoles: projectTemplate.roles as TProjectTemplateRole[] // preserve packed for when applying template
|
||||
};
|
||||
};
|
||||
|
||||
const findProjectTemplateById = async (id: string, actor: OrgServiceActor) => {
|
||||
const plan = await licenseService.getPlan(actor.orgId);
|
||||
|
||||
if (!plan.projectTemplates)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to access project template due to plan restriction. Upgrade plan to access project templates."
|
||||
});
|
||||
|
||||
const projectTemplate = await projectTemplateDAL.findById(id);
|
||||
|
||||
if (!projectTemplate) throw new NotFoundError({ message: `Could not find project template with ID ${id}` });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
projectTemplate.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
return {
|
||||
...$unpackProjectTemplate(projectTemplate),
|
||||
packedRoles: projectTemplate.roles as TProjectTemplateRole[] // preserve packed for when applying template
|
||||
@@ -112,6 +137,13 @@ export const projectTemplateServiceFactory = ({
|
||||
{ roles, environments, ...params }: TCreateProjectTemplateDTO,
|
||||
actor: OrgServiceActor
|
||||
) => {
|
||||
const plan = await licenseService.getPlan(actor.orgId);
|
||||
|
||||
if (!plan.projectTemplates)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to create project template due to plan restriction. Upgrade plan to access project templates."
|
||||
});
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
@@ -122,11 +154,16 @@ export const projectTemplateServiceFactory = ({
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
const plan = await licenseService.getPlan(actor.orgId);
|
||||
const isConflictingName = Boolean(
|
||||
await projectTemplateDAL.findOne({
|
||||
name: params.name,
|
||||
orgId: actor.orgId
|
||||
})
|
||||
);
|
||||
|
||||
if (!plan.projectTemplates)
|
||||
if (isConflictingName)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to create project template due to plan restriction. Upgrade plan to access project templates."
|
||||
message: `A project template with the name "${params.name}" already exists.`
|
||||
});
|
||||
|
||||
const projectTemplate = await projectTemplateDAL.create({
|
||||
@@ -144,16 +181,6 @@ export const projectTemplateServiceFactory = ({
|
||||
{ roles, environments, ...params }: TUpdateProjectTemplateDTO,
|
||||
actor: OrgServiceActor
|
||||
) => {
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
actor.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
const plan = await licenseService.getPlan(actor.orgId);
|
||||
|
||||
if (!plan.projectTemplates)
|
||||
@@ -161,7 +188,35 @@ export const projectTemplateServiceFactory = ({
|
||||
message: "Failed to update project template due to plan restriction. Upgrade plan to access project templates."
|
||||
});
|
||||
|
||||
const projectTemplate = await projectTemplateDAL.updateById(id, {
|
||||
const projectTemplate = await projectTemplateDAL.findById(id);
|
||||
|
||||
if (!projectTemplate) throw new NotFoundError({ message: `Could not find project template with ID ${id}` });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
projectTemplate.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
if (params.name && projectTemplate.name !== params.name) {
|
||||
const isConflictingName = Boolean(
|
||||
await projectTemplateDAL.findOne({
|
||||
name: params.name,
|
||||
orgId: projectTemplate.orgId
|
||||
})
|
||||
);
|
||||
|
||||
if (isConflictingName)
|
||||
throw new BadRequestError({
|
||||
message: `A project template with the name "${params.name}" already exists.`
|
||||
});
|
||||
}
|
||||
|
||||
const updatedProjectTemplate = await projectTemplateDAL.updateById(id, {
|
||||
...params,
|
||||
roles: roles
|
||||
? JSON.stringify(roles.map((role) => ({ ...role, permissions: packRules(role.permissions) })))
|
||||
@@ -169,20 +224,10 @@ export const projectTemplateServiceFactory = ({
|
||||
environments: environments ? JSON.stringify(environments) : undefined
|
||||
});
|
||||
|
||||
return $unpackProjectTemplate(projectTemplate);
|
||||
return $unpackProjectTemplate(updatedProjectTemplate);
|
||||
};
|
||||
|
||||
const deleteProjectTemplateById = async (id: string, actor: OrgServiceActor) => {
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
actor.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
const plan = await licenseService.getPlan(actor.orgId);
|
||||
|
||||
if (!plan.projectTemplates)
|
||||
@@ -190,9 +235,23 @@ export const projectTemplateServiceFactory = ({
|
||||
message: "Failed to delete project template due to plan restriction. Upgrade plan to access project templates."
|
||||
});
|
||||
|
||||
const projectTemplate = await projectTemplateDAL.deleteById(id);
|
||||
const projectTemplate = await projectTemplateDAL.findById(id);
|
||||
|
||||
return $unpackProjectTemplate(projectTemplate);
|
||||
if (!projectTemplate) throw new NotFoundError({ message: `Could not find project template with ID ${id}` });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
projectTemplate.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.ProjectTemplates);
|
||||
|
||||
const deletedProjectTemplate = await projectTemplateDAL.deleteById(id);
|
||||
|
||||
return $unpackProjectTemplate(deletedProjectTemplate);
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -200,6 +259,7 @@ export const projectTemplateServiceFactory = ({
|
||||
createProjectTemplate,
|
||||
updateProjectTemplateById,
|
||||
deleteProjectTemplateById,
|
||||
findProjectTemplatesById
|
||||
findProjectTemplateById,
|
||||
findProjectTemplateByName
|
||||
};
|
||||
};
|
||||
|
||||
@@ -22,3 +22,7 @@ export type TCreateProjectTemplateDTO = {
|
||||
export type TUpdateProjectTemplateDTO = Partial<TCreateProjectTemplateDTO>;
|
||||
|
||||
export type TUnpackedPermission = z.infer<typeof UnpackedPermissionSchema>;
|
||||
|
||||
export enum InfisicalProjectTemplate {
|
||||
Default = "default"
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ export const PROJECTS = {
|
||||
organizationSlug: "The slug of the organization to create the project in.",
|
||||
projectName: "The name of the project to create.",
|
||||
slug: "An optional slug for the project.",
|
||||
templateId: "The ID of the project template, if specified, to apply to this project."
|
||||
template: "The name of the project template, if specified, to apply to this project."
|
||||
},
|
||||
DELETE: {
|
||||
workspaceId: "The ID of the project to delete."
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ProjectKeysSchema
|
||||
} from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { InfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-types";
|
||||
import { PROJECTS } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
@@ -170,7 +171,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
.optional()
|
||||
.describe(PROJECTS.CREATE.slug),
|
||||
kmsKeyId: z.string().optional(),
|
||||
templateId: z.string().uuid().optional().describe(PROJECTS.CREATE.templateId)
|
||||
template: z
|
||||
.string()
|
||||
.refine((v) => slugify(v) === v, {
|
||||
message: "Template name must be in slug format"
|
||||
})
|
||||
.optional()
|
||||
.default(InfisicalProjectTemplate.Default)
|
||||
.describe(PROJECTS.CREATE.template)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -188,7 +196,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
workspaceName: req.body.projectName,
|
||||
slug: req.body.slug,
|
||||
kmsKeyId: req.body.kmsKeyId,
|
||||
templateId: req.body.templateId
|
||||
template: req.body.template
|
||||
});
|
||||
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
@@ -201,14 +209,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
if (req.body.templateId) {
|
||||
if (req.body.template) {
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
event: {
|
||||
type: EventType.APPLY_PROJECT_TEMPLATE,
|
||||
metadata: {
|
||||
templateId: req.body.templateId,
|
||||
template: req.body.template,
|
||||
projectId: project.id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/pe
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { TProjectTemplateServiceFactory } from "@app/ee/services/project-template/project-template-service";
|
||||
import { InfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-types";
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
@@ -152,7 +153,7 @@ export const projectServiceFactory = ({
|
||||
kmsKeyId,
|
||||
tx: trx,
|
||||
createDefaultEnvs = true,
|
||||
templateId
|
||||
template = InfisicalProjectTemplate.Default
|
||||
}: TCreateProjectDTO) => {
|
||||
const organization = await orgDAL.findOne({ id: actorOrgId });
|
||||
|
||||
@@ -187,23 +188,19 @@ export const projectServiceFactory = ({
|
||||
}
|
||||
}
|
||||
|
||||
let projectTemplate: Awaited<ReturnType<typeof projectTemplateService.findProjectTemplatesById>> | null = null;
|
||||
let projectTemplate: Awaited<ReturnType<typeof projectTemplateService.findProjectTemplateByName>> | null = null;
|
||||
|
||||
if (templateId) {
|
||||
if (!plan.projectTemplates)
|
||||
throw new BadRequestError({
|
||||
message:
|
||||
"Failed to apply project template due to plan restriction. Upgrade plan to access project templates."
|
||||
switch (template) {
|
||||
case InfisicalProjectTemplate.Default:
|
||||
projectTemplate = null;
|
||||
break;
|
||||
default:
|
||||
projectTemplate = await projectTemplateService.findProjectTemplateByName(template, {
|
||||
id: actorId,
|
||||
orgId: organization.id,
|
||||
type: actor,
|
||||
authMethod: actorAuthMethod
|
||||
});
|
||||
|
||||
projectTemplate = await projectTemplateService.findProjectTemplatesById(templateId, {
|
||||
id: actorId,
|
||||
orgId: organization.id,
|
||||
type: actor,
|
||||
authMethod: actorAuthMethod
|
||||
});
|
||||
|
||||
if (!projectTemplate) throw new NotFoundError({ message: `Project template with ID ${templateId} not found.` });
|
||||
}
|
||||
|
||||
const project = await projectDAL.create(
|
||||
|
||||
@@ -32,7 +32,7 @@ export type TCreateProjectDTO = {
|
||||
slug?: string;
|
||||
kmsKeyId?: string;
|
||||
createDefaultEnvs?: boolean;
|
||||
templateId?: string;
|
||||
template?: string;
|
||||
tx?: Knex;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user