mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 00:27:30 +00:00
Merge pull request #4745 from Infisical/fix/duplicate-slug-check-in-create-project
[ENG-4007] chore: adds unique slug check when creating project
This commit is contained in:
@@ -10,7 +10,8 @@ import {
|
|||||||
ProjectType,
|
ProjectType,
|
||||||
ProjectVersion,
|
ProjectVersion,
|
||||||
TableName,
|
TableName,
|
||||||
TProjectEnvironments
|
TProjectEnvironments,
|
||||||
|
TProjects
|
||||||
} from "@app/db/schemas";
|
} from "@app/db/schemas";
|
||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||||
@@ -40,7 +41,8 @@ import { TSshHostGroupDALFactory } from "@app/ee/services/ssh-host-group/ssh-hos
|
|||||||
import { PgSqlLock, TKeyStoreFactory } from "@app/keystore/keystore";
|
import { PgSqlLock, TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { crypto } from "@app/lib/crypto/cryptography";
|
import { crypto } from "@app/lib/crypto/cryptography";
|
||||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { DatabaseErrorCode } from "@app/lib/error-codes";
|
||||||
|
import { BadRequestError, DatabaseError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
import { groupBy } from "@app/lib/fn";
|
import { groupBy } from "@app/lib/fn";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { TProjectPermission } from "@app/lib/types";
|
import { TProjectPermission } from "@app/lib/types";
|
||||||
@@ -303,19 +305,34 @@ export const projectServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const project = await projectDAL.create(
|
const slug = projectSlug || slugify(`${workspaceName}-${alphaNumericNanoId(4)}`);
|
||||||
{
|
|
||||||
name: workspaceName,
|
let project: TProjects;
|
||||||
type,
|
try {
|
||||||
description: workspaceDescription,
|
project = await projectDAL.create(
|
||||||
orgId: organization.id,
|
{
|
||||||
slug: projectSlug || slugify(`${workspaceName}-${alphaNumericNanoId(4)}`),
|
name: workspaceName,
|
||||||
kmsSecretManagerKeyId: kmsKeyId,
|
type,
|
||||||
version: ProjectVersion.V3,
|
description: workspaceDescription,
|
||||||
pitVersionLimit: 10
|
orgId: organization.id,
|
||||||
},
|
slug,
|
||||||
tx
|
kmsSecretManagerKeyId: kmsKeyId,
|
||||||
);
|
version: ProjectVersion.V3,
|
||||||
|
pitVersionLimit: 10
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
if (
|
||||||
|
err instanceof DatabaseError &&
|
||||||
|
(err.error as { code: string })?.code === DatabaseErrorCode.UniqueViolation
|
||||||
|
) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `A project with the slug "${slug}" already exists in your organization. Please choose a different name or slug.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
if (type === ProjectType.SSH) {
|
if (type === ProjectType.SSH) {
|
||||||
await bootstrapSshProject({
|
await bootstrapSshProject({
|
||||||
@@ -579,39 +596,36 @@ export const projectServiceFactory = ({
|
|||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
|
||||||
|
|
||||||
if (update.slug) {
|
|
||||||
const existingProject = await projectDAL.findOne({
|
|
||||||
slug: update.slug,
|
|
||||||
orgId: actorOrgId
|
|
||||||
});
|
|
||||||
if (existingProject && existingProject.id !== project.id) {
|
|
||||||
throw new BadRequestError({
|
|
||||||
message: `Failed to update project slug. The project "${existingProject.name}" with the slug "${existingProject.slug}" already exists in your organization. Please choose a unique slug for your project.`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (update.secretDetectionIgnoreValues && !hasRole(ProjectMembershipRole.Admin)) {
|
if (update.secretDetectionIgnoreValues && !hasRole(ProjectMembershipRole.Admin)) {
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Only admins can update secret detection ignore values"
|
message: "Only admins can update secret detection ignore values"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedProject = await projectDAL.updateById(project.id, {
|
try {
|
||||||
name: update.name,
|
const updatedProject = await projectDAL.updateById(project.id, {
|
||||||
description: update.description,
|
name: update.name,
|
||||||
autoCapitalization: update.autoCapitalization,
|
description: update.description,
|
||||||
enforceCapitalization: update.autoCapitalization,
|
autoCapitalization: update.autoCapitalization,
|
||||||
hasDeleteProtection: update.hasDeleteProtection,
|
enforceCapitalization: update.autoCapitalization,
|
||||||
slug: update.slug,
|
hasDeleteProtection: update.hasDeleteProtection,
|
||||||
secretSharing: update.secretSharing,
|
slug: update.slug,
|
||||||
defaultProduct: update.defaultProduct,
|
secretSharing: update.secretSharing,
|
||||||
showSnapshotsLegacy: update.showSnapshotsLegacy,
|
defaultProduct: update.defaultProduct,
|
||||||
secretDetectionIgnoreValues: update.secretDetectionIgnoreValues,
|
showSnapshotsLegacy: update.showSnapshotsLegacy,
|
||||||
pitVersionLimit: update.pitVersionLimit
|
secretDetectionIgnoreValues: update.secretDetectionIgnoreValues,
|
||||||
});
|
pitVersionLimit: update.pitVersionLimit
|
||||||
|
});
|
||||||
|
|
||||||
return updatedProject;
|
return updatedProject;
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof DatabaseError && (err.error as { code: string })?.code === DatabaseErrorCode.UniqueViolation) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `Failed to update project. A project with the slug "${update.slug}" already exists in your organization. Please choose a different slug.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleAutoCapitalization = async ({
|
const toggleAutoCapitalization = async ({
|
||||||
|
|||||||
Reference in New Issue
Block a user