diff --git a/backend/e2e-test/routes/v3/secrets.spec.ts b/backend/e2e-test/routes/v3/secrets.spec.ts index ab73a7f1f..e7e271279 100644 --- a/backend/e2e-test/routes/v3/secrets.spec.ts +++ b/backend/e2e-test/routes/v3/secrets.spec.ts @@ -945,7 +945,7 @@ describe.each([{ auth: AuthMode.JWT }, { auth: AuthMode.IDENTITY_ACCESS_TOKEN }] test.each(testRawSecrets)("Bulk create secret raw in path $path", async ({ path, secret }) => { const createSecretReqBody = { - workspaceId: seedData1.project.id, + projectSlug: seedData1.project.slug, environment: seedData1.environment.slug, secretPath: path, secrets: [ @@ -986,7 +986,7 @@ describe.each([{ auth: AuthMode.JWT }, { auth: AuthMode.IDENTITY_ACCESS_TOKEN }] test.each(testRawSecrets)("Bulk update secret raw in path $path", async ({ secret, path }) => { await createRawSecret({ path, ...secret }); const updateSecretReqBody = { - workspaceId: seedData1.project.id, + projectSlug: seedData1.project.slug, environment: seedData1.environment.slug, secretPath: path, secrets: [ @@ -1028,7 +1028,7 @@ describe.each([{ auth: AuthMode.JWT }, { auth: AuthMode.IDENTITY_ACCESS_TOKEN }] await createRawSecret({ path, ...secret }); const deletedSecretReqBody = { - workspaceId: seedData1.project.id, + projectSlug: seedData1.project.slug, environment: seedData1.environment.slug, secretPath: path, secrets: [{ secretKey: secret.key }] diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 4a98f73c8..9dbcc4fb4 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -282,6 +282,7 @@ export const RAW_SECRETS = { }, CREATE: { secretName: "The name of the secret to create.", + projectSlug: "The slug of the project to create the secret in.", environment: "The slug of the environment to create the secret in.", secretComment: "Attach a comment to the secret.", secretPath: "The path to create the secret in.", @@ -307,6 +308,7 @@ export const RAW_SECRETS = { secretValue: "The new value of the secret.", skipMultilineEncoding: "Skip multiline encoding for the secret value.", type: "The type of the secret to update.", + projectSlug: "The slug of the project to update the secret in.", workspaceId: "The ID of the project to update the secret in." }, DELETE: { @@ -314,6 +316,7 @@ export const RAW_SECRETS = { environment: "The slug of the environment where the secret is located.", secretPath: "The path of the secret.", type: "The type of the secret to delete.", + projectSlug: "The slug of the project to delete the secret in.", workspaceId: "The ID of the project where the secret is located." } } as const; diff --git a/backend/src/server/routes/v3/secret-router.ts b/backend/src/server/routes/v3/secret-router.ts index ceecc0805..955aa01be 100644 --- a/backend/src/server/routes/v3/secret-router.ts +++ b/backend/src/server/routes/v3/secret-router.ts @@ -1671,7 +1671,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { } ], body: z.object({ - workspaceId: z.string().trim().describe(RAW_SECRETS.CREATE.workspaceId), + projectSlug: z.string().trim().describe(RAW_SECRETS.CREATE.projectSlug), environment: z.string().trim().describe(RAW_SECRETS.CREATE.environment), secretPath: z .string() @@ -1700,7 +1700,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const { environment, workspaceId: projectId, secretPath, secrets: inputSecrets } = req.body; + const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body; const secrets = await server.services.secret.createManySecretsRaw({ actorId: req.permission.id, @@ -1709,12 +1709,12 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { actorOrgId: req.permission.orgId, secretPath, environment, - projectId, + projectSlug, secrets: inputSecrets }); await server.services.auditLog.createAuditLog({ - projectId: req.body.workspaceId, + projectId: secrets[0].workspace, ...req.auditLogInfo, event: { type: EventType.CREATE_SECRETS, @@ -1735,7 +1735,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { distinctId: getTelemetryDistinctId(req), properties: { numberOfSecrets: secrets.length, - workspaceId: req.body.workspaceId, + workspaceId: secrets[0].workspace, environment: req.body.environment, secretPath: req.body.secretPath, channel: getUserAgentType(req.headers["user-agent"]), @@ -1760,7 +1760,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { } ], body: z.object({ - workspaceId: z.string().trim().describe(RAW_SECRETS.UPDATE.workspaceId), + projectSlug: z.string().trim().describe(RAW_SECRETS.UPDATE.projectSlug), environment: z.string().trim().describe(RAW_SECRETS.UPDATE.environment), secretPath: z .string() @@ -1789,7 +1789,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const { environment, workspaceId: projectId, secretPath, secrets: inputSecrets } = req.body; + const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body; const secrets = await server.services.secret.updateManySecretsRaw({ actorId: req.permission.id, actor: req.permission.type, @@ -1797,12 +1797,12 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { actorOrgId: req.permission.orgId, secretPath, environment, - projectId, + projectSlug, secrets: inputSecrets }); await server.services.auditLog.createAuditLog({ - projectId: req.body.workspaceId, + projectId: secrets[0].workspace, ...req.auditLogInfo, event: { type: EventType.UPDATE_SECRETS, @@ -1823,7 +1823,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { distinctId: getTelemetryDistinctId(req), properties: { numberOfSecrets: secrets.length, - workspaceId: req.body.workspaceId, + workspaceId: secrets[0].workspace, environment: req.body.environment, secretPath: req.body.secretPath, channel: getUserAgentType(req.headers["user-agent"]), @@ -1848,7 +1848,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { } ], body: z.object({ - workspaceId: z.string().trim().describe(RAW_SECRETS.DELETE.workspaceId), + projectSlug: z.string().trim().describe(RAW_SECRETS.DELETE.projectSlug), environment: z.string().trim().describe(RAW_SECRETS.DELETE.environment), secretPath: z .string() @@ -1871,20 +1871,20 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const { environment, workspaceId: projectId, secretPath, secrets: inputSecrets } = req.body; + const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body; const secrets = await server.services.secret.deleteManySecretsRaw({ actorId: req.permission.id, actor: req.permission.type, actorAuthMethod: req.permission.authMethod, actorOrgId: req.permission.orgId, environment, - projectId, + projectSlug, secretPath, secrets: inputSecrets }); await server.services.auditLog.createAuditLog({ - projectId: req.body.workspaceId, + projectId: secrets[0].workspace, ...req.auditLogInfo, event: { type: EventType.DELETE_SECRETS, @@ -1905,7 +1905,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { distinctId: getTelemetryDistinctId(req), properties: { numberOfSecrets: secrets.length, - workspaceId: req.body.workspaceId, + workspaceId: secrets[0].workspace, environment: req.body.environment, secretPath: req.body.secretPath, channel: getUserAgentType(req.headers["user-agent"]), diff --git a/backend/src/services/secret/secret-service.ts b/backend/src/services/secret/secret-service.ts index 9c7c0cbd6..01557f992 100644 --- a/backend/src/services/secret/secret-service.ts +++ b/backend/src/services/secret/secret-service.ts @@ -1041,7 +1041,7 @@ export const secretServiceFactory = ({ const createManySecretsRaw = async ({ actorId, - projectId, + projectSlug, environment, actor, actorOrgId, @@ -1049,6 +1049,10 @@ export const secretServiceFactory = ({ secretPath, secrets: inputSecrets = [] }: TCreateManySecretRawDTO) => { + const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); + if (!project) throw new BadRequestError({ message: "Project not found" }); + const projectId = project.id; + const botKey = await projectBotService.getBotKey(projectId); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); @@ -1088,7 +1092,7 @@ export const secretServiceFactory = ({ const updateManySecretsRaw = async ({ actorId, - projectId, + projectSlug, environment, actor, actorOrgId, @@ -1096,6 +1100,10 @@ export const secretServiceFactory = ({ secretPath, secrets: inputSecrets = [] }: TUpdateManySecretRawDTO) => { + const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); + if (!project) throw new BadRequestError({ message: "Project not found" }); + const projectId = project.id; + const botKey = await projectBotService.getBotKey(projectId); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); @@ -1136,7 +1144,7 @@ export const secretServiceFactory = ({ const deleteManySecretsRaw = async ({ actorId, - projectId, + projectSlug, environment, actor, actorOrgId, @@ -1144,6 +1152,10 @@ export const secretServiceFactory = ({ secretPath, secrets: inputSecrets = [] }: TDeleteManySecretRawDTO) => { + const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); + if (!project) throw new BadRequestError({ message: "Project not found" }); + const projectId = project.id; + const botKey = await projectBotService.getBotKey(projectId); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); diff --git a/backend/src/services/secret/secret-types.ts b/backend/src/services/secret/secret-types.ts index 34b8bc822..c2a0d5cf6 100644 --- a/backend/src/services/secret/secret-types.ts +++ b/backend/src/services/secret/secret-types.ts @@ -181,8 +181,9 @@ export type TDeleteSecretRawDTO = TProjectPermission & { type: SecretType; }; -export type TCreateManySecretRawDTO = TProjectPermission & { +export type TCreateManySecretRawDTO = Omit & { secretPath: string; + projectSlug: string; environment: string; secrets: { secretKey: string; @@ -192,8 +193,9 @@ export type TCreateManySecretRawDTO = TProjectPermission & { }[]; }; -export type TUpdateManySecretRawDTO = TProjectPermission & { +export type TUpdateManySecretRawDTO = Omit & { secretPath: string; + projectSlug: string; environment: string; secrets: { secretKey: string; @@ -203,8 +205,9 @@ export type TUpdateManySecretRawDTO = TProjectPermission & { }[]; }; -export type TDeleteManySecretRawDTO = TProjectPermission & { +export type TDeleteManySecretRawDTO = Omit & { secretPath: string; + projectSlug: string; environment: string; secrets: { secretKey: string;