diff --git a/Dockerfile.standalone-infisical b/Dockerfile.standalone-infisical index 8ffe7e3de..269cbfcf9 100644 --- a/Dockerfile.standalone-infisical +++ b/Dockerfile.standalone-infisical @@ -95,6 +95,10 @@ RUN mkdir frontend-build # Production stage FROM base AS production RUN apk add --upgrade --no-cache ca-certificates +RUN apk add --no-cache bash curl && curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \ + && apk add infisical=0.31.1 && apk add --no-cache git + RUN addgroup --system --gid 1001 nodejs \ && adduser --system --uid 1001 non-root-user diff --git a/backend/package.json b/backend/package.json index 97e951242..a713728e9 100644 --- a/backend/package.json +++ b/backend/package.json @@ -58,6 +58,7 @@ "migration:latest": "npm run auditlog-migration:latest && knex --knexfile ./src/db/knexfile.ts --client pg migrate:latest", "migration:status": "npm run auditlog-migration:status && knex --knexfile ./src/db/knexfile.ts --client pg migrate:status", "migration:rollback": "npm run auditlog-migration:rollback && knex --knexfile ./src/db/knexfile.ts migrate:rollback", + "migrate:org": "tsx ./scripts/migrate-organization.ts", "seed:new": "tsx ./scripts/create-seed-file.ts", "seed": "knex --knexfile ./src/db/knexfile.ts --client pg seed:run", "db:reset": "npm run migration:rollback -- --all && npm run migration:latest" diff --git a/backend/scripts/migrate-organization.ts b/backend/scripts/migrate-organization.ts new file mode 100644 index 000000000..ca6aa904d --- /dev/null +++ b/backend/scripts/migrate-organization.ts @@ -0,0 +1,84 @@ +/* eslint-disable */ +import promptSync from "prompt-sync"; +import { execSync } from "child_process"; +import path from "path"; +import { existsSync } from "fs"; + +const prompt = promptSync({ + sigint: true +}); + +const exportDb = () => { + const exportHost = prompt("Enter your Postgres Host to migrate from: "); + const exportPort = prompt("Enter your Postgres Port to migrate from [Default = 5432]: ") ?? "5432"; + const exportUser = prompt("Enter your Postgres User to migrate from: [Default = infisical]: ") ?? "infisical"; + const exportPassword = prompt("Enter your Postgres Password to migrate from: "); + const exportDatabase = prompt("Enter your Postgres Database to migrate from [Default = infisical]: ") ?? "infisical"; + + // we do not include the audit_log and secret_sharing entries + execSync( + `PGDATABASE="${exportDatabase}" PGPASSWORD="${exportPassword}" PGHOST="${exportHost}" PGPORT=${exportPort} PGUSER=${exportUser} pg_dump infisical --exclude-table-data="secret_sharing" --exclude-table-data="audit_log*" > ${path.join( + __dirname, + "../src/db/dump.sql" + )}`, + { stdio: "inherit" } + ); +}; + +const importDbForOrg = () => { + const importHost = prompt("Enter your Postgres Host to migrate to: "); + const importPort = prompt("Enter your Postgres Port to migrate to [Default = 5432]: ") ?? "5432"; + const importUser = prompt("Enter your Postgres User to migrate to: [Default = infisical]: ") ?? "infisical"; + const importPassword = prompt("Enter your Postgres Password to migrate to: "); + const importDatabase = prompt("Enter your Postgres Database to migrate to [Default = infisical]: ") ?? "infisical"; + const orgId = prompt("Enter the organization ID to migrate: "); + + if (!existsSync(path.join(__dirname, "../src/db/dump.sql"))) { + console.log("File not found, please export the database first."); + return; + } + + execSync( + `PGDATABASE="${importDatabase}" PGPASSWORD="${importPassword}" PGHOST="${importHost}" PGPORT=${importPort} PGUSER=${importUser} psql -f ${path.join( + __dirname, + "../src/db/dump.sql" + )}` + ); + + execSync( + `PGDATABASE="${importDatabase}" PGPASSWORD="${importPassword}" PGHOST="${importHost}" PGPORT=${importPort} PGUSER=${importUser} psql -c "DELETE FROM public.organizations WHERE id != '${orgId}'"` + ); + + // delete global/instance-level resources not relevant to the organization to migrate + // users + execSync( + `PGDATABASE="${importDatabase}" PGPASSWORD="${importPassword}" PGHOST="${importHost}" PGPORT=${importPort} PGUSER=${importUser} psql -c 'DELETE FROM users WHERE users.id NOT IN (SELECT org_memberships."userId" FROM org_memberships)'` + ); + + // identities + execSync( + `PGDATABASE="${importDatabase}" PGPASSWORD="${importPassword}" PGHOST="${importHost}" PGPORT=${importPort} PGUSER=${importUser} psql -c 'DELETE FROM identities WHERE id NOT IN (SELECT "identityId" FROM identity_org_memberships)'` + ); + + // reset slack configuration in superAdmin + execSync( + `PGDATABASE="${importDatabase}" PGPASSWORD="${importPassword}" PGHOST="${importHost}" PGPORT=${importPort} PGUSER=${importUser} psql -c 'UPDATE super_admin SET "encryptedSlackClientId" = null, "encryptedSlackClientSecret" = null'` + ); + + console.log("Organization migrated successfully."); +}; + +const main = () => { + const action = prompt( + "Enter the action to perform\n 1. Export from existing instance.\n 2. Import org to instance.\n \n Action: " + ); + if (action === "1") { + exportDb(); + } else if (action === "2") { + importDbForOrg(); + } else { + console.log("Invalid action"); + } +}; + +main(); diff --git a/backend/src/db/migrations/20241021114650_add-missing-org-cascade-references.ts b/backend/src/db/migrations/20241021114650_add-missing-org-cascade-references.ts new file mode 100644 index 000000000..7a2cf688b --- /dev/null +++ b/backend/src/db/migrations/20241021114650_add-missing-org-cascade-references.ts @@ -0,0 +1,21 @@ +import { Knex } from "knex"; + +import { TableName } from "../schemas"; + +export async function up(knex: Knex): Promise { + if (await knex.schema.hasColumn(TableName.SamlConfig, "orgId")) { + await knex.schema.alterTable(TableName.SamlConfig, (t) => { + t.dropForeign("orgId"); + t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE"); + }); + } +} + +export async function down(knex: Knex): Promise { + if (await knex.schema.hasColumn(TableName.SamlConfig, "orgId")) { + await knex.schema.alterTable(TableName.SamlConfig, (t) => { + t.dropForeign("orgId"); + t.foreign("orgId").references("id").inTable(TableName.Organization); + }); + } +} diff --git a/backend/src/ee/routes/v1/group-router.ts b/backend/src/ee/routes/v1/group-router.ts index fed6adaba..780e5ec00 100644 --- a/backend/src/ee/routes/v1/group-router.ts +++ b/backend/src/ee/routes/v1/group-router.ts @@ -165,7 +165,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => { querystring: z.object({ offset: z.coerce.number().min(0).max(100).default(0).describe(GROUPS.LIST_USERS.offset), limit: z.coerce.number().min(1).max(100).default(10).describe(GROUPS.LIST_USERS.limit), - username: z.string().optional().describe(GROUPS.LIST_USERS.username) + username: z.string().trim().optional().describe(GROUPS.LIST_USERS.username), + search: z.string().trim().optional().describe(GROUPS.LIST_USERS.search) }), response: { 200: z.object({ diff --git a/backend/src/ee/routes/v1/secret-scanning-router.ts b/backend/src/ee/routes/v1/secret-scanning-router.ts index 2604d7232..89784600a 100644 --- a/backend/src/ee/routes/v1/secret-scanning-router.ts +++ b/backend/src/ee/routes/v1/secret-scanning-router.ts @@ -2,6 +2,8 @@ import { z } from "zod"; import { GitAppOrgSchema, SecretScanningGitRisksSchema } from "@app/db/schemas"; import { SecretScanningRiskStatus } from "@app/ee/services/secret-scanning/secret-scanning-types"; +import { getConfig } from "@app/lib/config/env"; +import { BadRequestError } from "@app/lib/errors"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; @@ -23,6 +25,13 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) = }, onRequest: verifyAuth([AuthMode.JWT]), handler: async (req) => { + const appCfg = getConfig(); + if (!appCfg.SECRET_SCANNING_ORG_WHITELIST?.includes(req.auth.orgId)) { + throw new BadRequestError({ + message: "Secret scanning is temporarily unavailable." + }); + } + const session = await server.services.secretScanning.createInstallationSession({ actor: req.permission.type, actorId: req.permission.id, @@ -30,6 +39,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) = actorOrgId: req.permission.orgId, orgId: req.body.organizationId }); + return session; } }); diff --git a/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts b/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts index 2633a026f..715b88ecf 100644 --- a/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts +++ b/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts @@ -58,7 +58,7 @@ export const accessApprovalPolicyServiceFactory = ({ enforcementLevel }: TCreateAccessApprovalPolicy) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); // If there is a group approver people might be added to the group later to meet the approvers quota const groupApprovers = approvers @@ -89,7 +89,7 @@ export const accessApprovalPolicyServiceFactory = ({ ProjectPermissionSub.SecretApproval ); const env = await projectEnvDAL.findOne({ slug: environment, projectId: project.id }); - if (!env) throw new NotFoundError({ message: "Environment not found" }); + if (!env) throw new NotFoundError({ message: `Environment with slug '${environment}' not found` }); let approverUserIds = userApprovers; if (userApproverNames.length) { @@ -124,7 +124,9 @@ export const accessApprovalPolicyServiceFactory = ({ const verifyAllApprovers = [...approverUserIds]; for (const groupId of groupApprovers) { - usersPromises.push(groupDAL.findAllGroupPossibleMembers({ orgId: actorOrgId, groupId, offset: 0 })); + usersPromises.push( + groupDAL.findAllGroupPossibleMembers({ orgId: actorOrgId, groupId, offset: 0 }).then((group) => group.members) + ); } const verifyGroupApprovers = (await Promise.all(usersPromises)) .flat() @@ -192,7 +194,7 @@ export const accessApprovalPolicyServiceFactory = ({ projectSlug }: TListAccessApprovalPoliciesDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); // Anyone in the project should be able to get the policies. /* const { permission } = */ await permissionService.getProjectPermission( @@ -243,7 +245,9 @@ export const accessApprovalPolicyServiceFactory = ({ throw new BadRequestError({ message: "Approvals cannot be greater than approvers" }); } - if (!accessApprovalPolicy) throw new NotFoundError({ message: "Secret approval policy not found" }); + if (!accessApprovalPolicy) { + throw new NotFoundError({ message: `Secret approval policy with ID '${policyId}' not found` }); + } const { permission } = await permissionService.getProjectPermission( actor, actorId, @@ -327,7 +331,11 @@ export const accessApprovalPolicyServiceFactory = ({ >[] = []; for (const groupId of groupApprovers) { - usersPromises.push(groupDAL.findAllGroupPossibleMembers({ orgId: actorOrgId, groupId, offset: 0 })); + usersPromises.push( + groupDAL + .findAllGroupPossibleMembers({ orgId: actorOrgId, groupId, offset: 0 }) + .then((group) => group.members) + ); } const verifyGroupApprovers = (await Promise.all(usersPromises)) .flat() @@ -376,7 +384,7 @@ export const accessApprovalPolicyServiceFactory = ({ actorOrgId }: TDeleteAccessApprovalPolicy) => { const policy = await accessApprovalPolicyDAL.findById(policyId); - if (!policy) throw new NotFoundError({ message: "Secret approval policy not found" }); + if (!policy) throw new NotFoundError({ message: `Secret approval policy with ID '${policyId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -404,7 +412,7 @@ export const accessApprovalPolicyServiceFactory = ({ }: TGetAccessPolicyCountByEnvironmentDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const { membership } = await permissionService.getProjectPermission( actor, @@ -418,10 +426,10 @@ export const accessApprovalPolicyServiceFactory = ({ } const environment = await projectEnvDAL.findOne({ projectId: project.id, slug: envSlug }); - if (!environment) throw new NotFoundError({ message: "Environment not found" }); + if (!environment) throw new NotFoundError({ message: `Environment with slug '${envSlug}' not found` }); const policies = await accessApprovalPolicyDAL.find({ envId: environment.id, projectId: project.id }); - if (!policies) throw new NotFoundError({ message: "No policies found" }); + if (!policies) throw new NotFoundError({ message: `No policies found in environment with slug '${envSlug}'` }); return { count: policies.length }; }; @@ -437,7 +445,7 @@ export const accessApprovalPolicyServiceFactory = ({ if (!policy) { throw new NotFoundError({ - message: "Cannot find access approval policy" + message: `Cannot find access approval policy with ID ${policyId}` }); } diff --git a/backend/src/ee/services/access-approval-request/access-approval-request-service.ts b/backend/src/ee/services/access-approval-request/access-approval-request-service.ts index 7c1f00a37..160c77cad 100644 --- a/backend/src/ee/services/access-approval-request/access-approval-request-service.ts +++ b/backend/src/ee/services/access-approval-request/access-approval-request-service.ts @@ -99,7 +99,7 @@ export const accessApprovalRequestServiceFactory = ({ }: TCreateAccessApprovalRequestDTO) => { const cfg = getConfig(); const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); // Anyone can create an access approval request. const { membership } = await permissionService.getProjectPermission( @@ -121,13 +121,17 @@ export const accessApprovalRequestServiceFactory = ({ const { envSlug, secretPath, accessTypes } = verifyRequestedPermissions({ permissions: requestedPermissions }); const environment = await projectEnvDAL.findOne({ projectId: project.id, slug: envSlug }); - if (!environment) throw new NotFoundError({ message: "Environment not found" }); + if (!environment) throw new NotFoundError({ message: `Environment with slug '${envSlug}' not found` }); const policy = await accessApprovalPolicyDAL.findOne({ envId: environment.id, secretPath }); - if (!policy) throw new NotFoundError({ message: "No policy matching criteria was found." }); + if (!policy) { + throw new NotFoundError({ + message: `No policy in environment with slug '${environment.slug}' and with secret path '${secretPath}' was found.` + }); + } const approverIds: string[] = []; const approverGroupIds: string[] = []; @@ -147,10 +151,12 @@ export const accessApprovalRequestServiceFactory = ({ const groupUsers = ( await Promise.all( approverGroupIds.map((groupApproverId) => - groupDAL.findAllGroupPossibleMembers({ - orgId: actorOrgId, - groupId: groupApproverId - }) + groupDAL + .findAllGroupPossibleMembers({ + orgId: actorOrgId, + groupId: groupApproverId + }) + .then((group) => group.members) ) ) ).flat(); @@ -264,7 +270,7 @@ export const accessApprovalRequestServiceFactory = ({ actorAuthMethod }: TListApprovalRequestsDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const { membership } = await permissionService.getProjectPermission( actor, @@ -300,7 +306,9 @@ export const accessApprovalRequestServiceFactory = ({ actorOrgId }: TReviewAccessRequestDTO) => { const accessApprovalRequest = await accessApprovalRequestDAL.findById(requestId); - if (!accessApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" }); + if (!accessApprovalRequest) { + throw new NotFoundError({ message: `Secret approval request with ID '${requestId}' not found` }); + } const { policy } = accessApprovalRequest; const { membership, hasRole } = await permissionService.getProjectPermission( @@ -421,7 +429,7 @@ export const accessApprovalRequestServiceFactory = ({ const getCount = async ({ projectSlug, actor, actorAuthMethod, actorId, actorOrgId }: TGetAccessRequestCountDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const { membership } = await permissionService.getProjectPermission( actor, diff --git a/backend/src/ee/services/audit-log-stream/audit-log-stream-service.ts b/backend/src/ee/services/audit-log-stream/audit-log-stream-service.ts index 3172543c7..4f080dac3 100644 --- a/backend/src/ee/services/audit-log-stream/audit-log-stream-service.ts +++ b/backend/src/ee/services/audit-log-stream/audit-log-stream-service.ts @@ -130,7 +130,7 @@ export const auditLogStreamServiceFactory = ({ }); const logStream = await auditLogStreamDAL.findById(id); - if (!logStream) throw new NotFoundError({ message: "Audit log stream not found" }); + if (!logStream) throw new NotFoundError({ message: `Audit log stream with ID '${id}' not found` }); const { orgId } = logStream; const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); @@ -182,7 +182,7 @@ export const auditLogStreamServiceFactory = ({ if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID attached to authentication token" }); const logStream = await auditLogStreamDAL.findById(id); - if (!logStream) throw new NotFoundError({ message: "Audit log stream not found" }); + if (!logStream) throw new NotFoundError({ message: `Audit log stream with ID '${id}' not found` }); const { orgId } = logStream; const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); @@ -194,7 +194,7 @@ export const auditLogStreamServiceFactory = ({ const getById = async ({ id, actor, actorId, actorOrgId, actorAuthMethod }: TGetDetailsAuditLogStreamDTO) => { const logStream = await auditLogStreamDAL.findById(id); - if (!logStream) throw new NotFoundError({ message: "Audit log stream not found" }); + if (!logStream) throw new NotFoundError({ message: `Audit log stream with ID '${id}' not found` }); const { orgId } = logStream; const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); diff --git a/backend/src/ee/services/certificate-authority-crl/certificate-authority-crl-service.ts b/backend/src/ee/services/certificate-authority-crl/certificate-authority-crl-service.ts index c2a8304c2..7282b0a29 100644 --- a/backend/src/ee/services/certificate-authority-crl/certificate-authority-crl-service.ts +++ b/backend/src/ee/services/certificate-authority-crl/certificate-authority-crl-service.ts @@ -34,7 +34,7 @@ export const certificateAuthorityCrlServiceFactory = ({ */ const getCrlById = async (crlId: TGetCrlById) => { const caCrl = await certificateAuthorityCrlDAL.findById(crlId); - if (!caCrl) throw new NotFoundError({ message: "CRL not found" }); + if (!caCrl) throw new NotFoundError({ message: `CRL with ID '${crlId}' not found` }); const ca = await certificateAuthorityDAL.findById(caCrl.caId); @@ -64,7 +64,7 @@ export const certificateAuthorityCrlServiceFactory = ({ */ const getCaCrls = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCrlsDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, diff --git a/backend/src/ee/services/certificate-est/certificate-est-service.ts b/backend/src/ee/services/certificate-est/certificate-est-service.ts index b8e179856..ce3821ae0 100644 --- a/backend/src/ee/services/certificate-est/certificate-est-service.ts +++ b/backend/src/ee/services/certificate-est/certificate-est-service.ts @@ -211,7 +211,7 @@ export const certificateEstServiceFactory = ({ const certTemplate = await certificateTemplateDAL.findById(certificateTemplateId); if (!certTemplate) { throw new NotFoundError({ - message: "Certificate template not found" + message: `Certificate template with ID '${certificateTemplateId}' not found` }); } @@ -236,7 +236,7 @@ export const certificateEstServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(certTemplate.caId); if (!ca) { throw new NotFoundError({ - message: "Certificate Authority not found" + message: `Certificate Authority with ID '${certTemplate.caId}' not found` }); } diff --git a/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts index 306c7ca26..6fc099993 100644 --- a/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts +++ b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts @@ -61,7 +61,7 @@ export const dynamicSecretLeaseServiceFactory = ({ }: TCreateDynamicSecretLeaseDTO) => { const appCfg = getConfig(); const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -84,10 +84,16 @@ export const dynamicSecretLeaseServiceFactory = ({ } const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${path}' in environment with slug '${environmentSlug}' not found` + }); const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id }); - if (!dynamicSecretCfg) throw new NotFoundError({ message: "Dynamic secret not found" }); + if (!dynamicSecretCfg) + throw new NotFoundError({ + message: `Dynamic secret with name '${name}' in folder with path '${path}' not found` + }); const totalLeasesTaken = await dynamicSecretLeaseDAL.countLeasesForDynamicSecret(dynamicSecretCfg.id); if (totalLeasesTaken >= appCfg.MAX_LEASE_LIMIT) @@ -134,7 +140,7 @@ export const dynamicSecretLeaseServiceFactory = ({ leaseId }: TRenewDynamicSecretLeaseDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -157,10 +163,15 @@ export const dynamicSecretLeaseServiceFactory = ({ } const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${path}' in environment with slug '${environmentSlug}' not found` + }); const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId); - if (!dynamicSecretLease) throw new NotFoundError({ message: "Dynamic secret lease not found" }); + if (!dynamicSecretLease) { + throw new NotFoundError({ message: `Dynamic secret lease with ID '${leaseId}' not found` }); + } const dynamicSecretCfg = dynamicSecretLease.dynamicSecret; const selectedProvider = dynamicSecretProviders[dynamicSecretCfg.type as DynamicSecretProviders]; @@ -208,7 +219,7 @@ export const dynamicSecretLeaseServiceFactory = ({ isForced }: TDeleteDynamicSecretLeaseDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -224,10 +235,14 @@ export const dynamicSecretLeaseServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${path}' in environment with slug '${environmentSlug}' not found` + }); const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId); - if (!dynamicSecretLease) throw new NotFoundError({ message: "Dynamic secret lease not found" }); + if (!dynamicSecretLease) + throw new NotFoundError({ message: `Dynamic secret lease with ID '${leaseId}' not found` }); const dynamicSecretCfg = dynamicSecretLease.dynamicSecret; const selectedProvider = dynamicSecretProviders[dynamicSecretCfg.type as DynamicSecretProviders]; @@ -273,7 +288,7 @@ export const dynamicSecretLeaseServiceFactory = ({ actorAuthMethod }: TListDynamicSecretLeasesDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -289,10 +304,16 @@ export const dynamicSecretLeaseServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${path}' in environment with slug '${environmentSlug}' not found` + }); const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id }); - if (!dynamicSecretCfg) throw new NotFoundError({ message: "Dynamic secret not found" }); + if (!dynamicSecretCfg) + throw new NotFoundError({ + message: `Dynamic secret with name '${name}' in folder with path '${path}' not found` + }); const dynamicSecretLeases = await dynamicSecretLeaseDAL.find({ dynamicSecretId: dynamicSecretCfg.id }); return dynamicSecretLeases; @@ -309,7 +330,7 @@ export const dynamicSecretLeaseServiceFactory = ({ actorAuthMethod }: TDetailsDynamicSecretLeaseDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -325,10 +346,11 @@ export const dynamicSecretLeaseServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) throw new NotFoundError({ message: `Folder with path '${path}' not found` }); const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId); - if (!dynamicSecretLease) throw new NotFoundError({ message: "Dynamic secret lease not found" }); + if (!dynamicSecretLease) + throw new NotFoundError({ message: `Dynamic secret lease with ID '${leaseId}' not found` }); return dynamicSecretLease; }; diff --git a/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts b/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts index eec9094cb..2dd4b4fd9 100644 --- a/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts +++ b/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts @@ -66,7 +66,7 @@ export const dynamicSecretServiceFactory = ({ actorAuthMethod }: TCreateDynamicSecretDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -89,7 +89,9 @@ export const dynamicSecretServiceFactory = ({ } const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) { + throw new NotFoundError({ message: `Folder with path '${path}' in environment '${environmentSlug}' not found` }); + } const existingDynamicSecret = await dynamicSecretDAL.findOne({ name, folderId: folder.id }); if (existingDynamicSecret) @@ -134,7 +136,7 @@ export const dynamicSecretServiceFactory = ({ actorAuthMethod }: TUpdateDynamicSecretDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; @@ -158,11 +160,15 @@ export const dynamicSecretServiceFactory = ({ } const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ message: `Folder with path '${path}' in environment '${environmentSlug}' not found` }); const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id }); - if (!dynamicSecretCfg) throw new NotFoundError({ message: "Dynamic secret not found" }); - + if (!dynamicSecretCfg) { + throw new NotFoundError({ + message: `Dynamic secret with name '${name}' in folder '${folder.path}' not found` + }); + } if (newName) { const existingDynamicSecret = await dynamicSecretDAL.findOne({ name: newName, folderId: folder.id }); if (existingDynamicSecret) @@ -213,7 +219,7 @@ export const dynamicSecretServiceFactory = ({ isForced }: TDeleteDynamicSecretDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; @@ -230,10 +236,13 @@ export const dynamicSecretServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ message: `Folder with path '${path}' in environment '${environmentSlug}' not found` }); const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id }); - if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" }); + if (!dynamicSecretCfg) { + throw new NotFoundError({ message: `Dynamic secret with name '${name}' in folder '${folder.path}' not found` }); + } const leases = await dynamicSecretLeaseDAL.find({ dynamicSecretId: dynamicSecretCfg.id }); // when not forced we check with the external system to first remove the things @@ -271,7 +280,7 @@ export const dynamicSecretServiceFactory = ({ actor }: TDetailsDynamicSecretDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -287,10 +296,13 @@ export const dynamicSecretServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ message: `Folder with path '${path}' in environment '${environmentSlug}' not found` }); const dynamicSecretCfg = await dynamicSecretDAL.findOne({ name, folderId: folder.id }); - if (!dynamicSecretCfg) throw new NotFoundError({ message: "Dynamic secret not found" }); + if (!dynamicSecretCfg) { + throw new NotFoundError({ message: `Dynamic secret with name '${name} in folder '${path}' not found` }); + } const decryptedStoredInput = JSON.parse( infisicalSymmetricDecrypt({ keyEncoding: dynamicSecretCfg.keyEncoding as SecretKeyEncoding, @@ -335,7 +347,11 @@ export const dynamicSecretServiceFactory = ({ } const folders = await folderDAL.findBySecretPathMultiEnv(projectId, environmentSlugs, path); - if (!folders.length) throw new NotFoundError({ message: "Folders not found" }); + if (!folders.length) { + throw new NotFoundError({ + message: `Folders with path '${path}' in environments with slugs '${environmentSlugs.join(", ")}' not found` + }); + } const dynamicSecretCfg = await dynamicSecretDAL.find( { $in: { folderId: folders.map((folder) => folder.id) }, $search: search ? { name: `%${search}%` } : undefined }, @@ -369,7 +385,9 @@ export const dynamicSecretServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) { + throw new NotFoundError({ message: `Folder with path '${path}' in environment '${environmentSlug}' not found` }); + } const dynamicSecretCfg = await dynamicSecretDAL.find( { folderId: folder.id, $search: search ? { name: `%${search}%` } : undefined }, @@ -398,7 +416,7 @@ export const dynamicSecretServiceFactory = ({ if (!projectId) { if (!projectSlug) throw new BadRequestError({ message: "Project ID or slug required" }); const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); projectId = project.id; } @@ -415,7 +433,8 @@ export const dynamicSecretServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ message: `Folder with path '${path}' in environment '${environmentSlug}' not found` }); const dynamicSecretCfg = await dynamicSecretDAL.find( { folderId: folder.id, $search: search ? { name: `%${search}%` } : undefined }, @@ -459,7 +478,10 @@ export const dynamicSecretServiceFactory = ({ } const folders = await folderDAL.findBySecretPathMultiEnv(projectId, environmentSlugs, path); - if (!folders.length) throw new NotFoundError({ message: "Folders not found" }); + if (!folders.length) + throw new NotFoundError({ + message: `Folders with path '${path} in environments with slugs '${environmentSlugs.join(", ")}' not found` + }); const dynamicSecretCfg = await dynamicSecretDAL.listDynamicSecretsByFolderIds({ folderIds: folders.map((folder) => folder.id), diff --git a/backend/src/ee/services/external-kms/external-kms-service.ts b/backend/src/ee/services/external-kms/external-kms-service.ts index 9300b42d8..c3b774afd 100644 --- a/backend/src/ee/services/external-kms/external-kms-service.ts +++ b/backend/src/ee/services/external-kms/external-kms-service.ts @@ -145,7 +145,7 @@ export const externalKmsServiceFactory = ({ const kmsName = name ? slugify(name) : undefined; const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id }); - if (!externalKmsDoc) throw new NotFoundError({ message: "External kms not found" }); + if (!externalKmsDoc) throw new NotFoundError({ message: `External KMS with ID '${kmsId}' not found` }); let sanitizedProviderInput = ""; const { encryptor: orgDataKeyEncryptor, decryptor: orgDataKeyDecryptor } = @@ -220,7 +220,7 @@ export const externalKmsServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Kms); const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id }); - if (!externalKmsDoc) throw new NotFoundError({ message: "External kms not found" }); + if (!externalKmsDoc) throw new NotFoundError({ message: `External KMS with ID '${kmsId}' not found` }); const externalKms = await externalKmsDAL.transaction(async (tx) => { const kms = await kmsDAL.deleteById(kmsDoc.id, tx); @@ -258,7 +258,7 @@ export const externalKmsServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Kms); const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id }); - if (!externalKmsDoc) throw new NotFoundError({ message: "External kms not found" }); + if (!externalKmsDoc) throw new NotFoundError({ message: `External KMS with ID '${kmsId}' not found` }); const { decryptor: orgDataKeyDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.Organization, @@ -298,7 +298,7 @@ export const externalKmsServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Kms); const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id }); - if (!externalKmsDoc) throw new NotFoundError({ message: "External kms not found" }); + if (!externalKmsDoc) throw new NotFoundError({ message: `External KMS with ID '${kmsDoc.id}' not found` }); const { decryptor: orgDataKeyDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.Organization, diff --git a/backend/src/ee/services/group/group-dal.ts b/backend/src/ee/services/group/group-dal.ts index 6d4a3df79..5e25f6113 100644 --- a/backend/src/ee/services/group/group-dal.ts +++ b/backend/src/ee/services/group/group-dal.ts @@ -65,16 +65,18 @@ export const groupDALFactory = (db: TDbClient) => { groupId, offset = 0, limit, - username + username, // depreciated in favor of search + search }: { orgId: string; groupId: string; offset?: number; limit?: number; username?: string; + search?: string; }) => { try { - let query = db + const query = db .replicaNode()(TableName.OrgMembership) .where(`${TableName.OrgMembership}.orgId`, orgId) .join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`) @@ -92,31 +94,39 @@ export const groupDALFactory = (db: TDbClient) => { db.ref("username").withSchema(TableName.Users), db.ref("firstName").withSchema(TableName.Users), db.ref("lastName").withSchema(TableName.Users), - db.ref("id").withSchema(TableName.Users).as("userId") + db.ref("id").withSchema(TableName.Users).as("userId"), + db.raw(`count(*) OVER() as total_count`) ) .where({ isGhost: false }) - .offset(offset); + .offset(offset) + .orderBy("firstName", "asc"); if (limit) { - query = query.limit(limit); + void query.limit(limit); } - if (username) { - query = query.andWhere(`${TableName.Users}.username`, "ilike", `%${username}%`); + if (search) { + void query.andWhereRaw(`CONCAT_WS(' ', "firstName", "lastName", "username") ilike '%${search}%'`); + } else if (username) { + void query.andWhere(`${TableName.Users}.username`, "ilike", `%${username}%`); } const members = await query; - return members.map( - ({ email, username: memberUsername, firstName, lastName, userId, groupId: memberGroupId }) => ({ - id: userId, - email, - username: memberUsername, - firstName, - lastName, - isPartOfGroup: !!memberGroupId - }) - ); + return { + members: members.map( + ({ email, username: memberUsername, firstName, lastName, userId, groupId: memberGroupId }) => ({ + id: userId, + email, + username: memberUsername, + firstName, + lastName, + isPartOfGroup: !!memberGroupId + }) + ), + // @ts-expect-error col select is raw and not strongly typed + totalCount: Number(members?.[0]?.total_count ?? 0) + }; } catch (error) { throw new DatabaseError({ error, name: "Find all org members" }); } diff --git a/backend/src/ee/services/group/group-fns.ts b/backend/src/ee/services/group/group-fns.ts index 8d4843624..72d052b29 100644 --- a/backend/src/ee/services/group/group-fns.ts +++ b/backend/src/ee/services/group/group-fns.ts @@ -74,7 +74,7 @@ const addAcceptedUsersToGroup = async ({ if (!ghostUser) { throw new NotFoundError({ - message: "Failed to find project owner" + message: `Failed to find project owner of project with ID '${projectId}'` }); } @@ -82,7 +82,7 @@ const addAcceptedUsersToGroup = async ({ if (!ghostUserLatestKey) { throw new NotFoundError({ - message: "Failed to find project owner's latest key" + message: `Failed to find project owner's latest key in project with ID '${projectId}'` }); } @@ -90,7 +90,7 @@ const addAcceptedUsersToGroup = async ({ if (!bot) { throw new NotFoundError({ - message: "Failed to find project bot" + message: `Failed to find project bot in project with ID '${projectId}'` }); } diff --git a/backend/src/ee/services/group/group-service.ts b/backend/src/ee/services/group/group-service.ts index 9937bc280..2a32bb5d4 100644 --- a/backend/src/ee/services/group/group-service.ts +++ b/backend/src/ee/services/group/group-service.ts @@ -221,7 +221,8 @@ export const groupServiceFactory = ({ actor, actorId, actorAuthMethod, - actorOrgId + actorOrgId, + search }: TListGroupUsersDTO) => { if (!actorOrgId) throw new UnauthorizedError({ message: "No organization ID provided in request" }); @@ -244,17 +245,16 @@ export const groupServiceFactory = ({ message: `Failed to find group with ID ${id}` }); - const users = await groupDAL.findAllGroupPossibleMembers({ + const { members, totalCount } = await groupDAL.findAllGroupPossibleMembers({ orgId: group.orgId, groupId: group.id, offset, limit, - username + username, + search }); - const count = await orgDAL.countAllOrgMembers(group.orgId); - - return { users, totalCount: count }; + return { users: members, totalCount }; }; const addUserToGroup = async ({ id, username, actor, actorId, actorAuthMethod, actorOrgId }: TAddUserToGroupDTO) => { diff --git a/backend/src/ee/services/group/group-types.ts b/backend/src/ee/services/group/group-types.ts index a6c80ef43..a6eb4782b 100644 --- a/backend/src/ee/services/group/group-types.ts +++ b/backend/src/ee/services/group/group-types.ts @@ -38,6 +38,7 @@ export type TListGroupUsersDTO = { offset: number; limit: number; username?: string; + search?: string; } & TGenericPermission; export type TAddUserToGroupDTO = { diff --git a/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts b/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts index f5c1c857a..55d567601 100644 --- a/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts +++ b/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts @@ -65,7 +65,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ ...dto }: TCreateIdentityPrivilegeDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); @@ -137,7 +137,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ actorAuthMethod }: TUpdateIdentityPrivilegeDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); @@ -167,7 +167,11 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ slug, projectMembershipId: identityProjectMembership.id }); - if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" }); + if (!identityPrivilege) { + throw new NotFoundError({ + message: `Identity additional privilege with slug '${slug}' not found for the specified identity with ID '${identityProjectMembership.identityId}'` + }); + } if (data?.slug) { const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({ slug: data.slug, @@ -218,7 +222,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ actorAuthMethod }: TDeleteIdentityPrivilegeDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); @@ -248,7 +252,11 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ slug, projectMembershipId: identityProjectMembership.id }); - if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" }); + if (!identityPrivilege) { + throw new NotFoundError({ + message: `Identity additional privilege with slug '${slug}' not found for the specified identity with ID '${identityProjectMembership.identityId}'` + }); + } const deletedPrivilege = await identityProjectAdditionalPrivilegeDAL.deleteById(identityPrivilege.id); return { @@ -268,7 +276,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ actorAuthMethod }: TGetIdentityPrivilegeDetailsDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); @@ -287,8 +295,11 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ slug, projectMembershipId: identityProjectMembership.id }); - if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" }); - + if (!identityPrivilege) { + throw new NotFoundError({ + message: `Identity additional privilege with slug '${slug}' not found for the specified identity with ID '${identityProjectMembership.identityId}'` + }); + } return { ...identityPrivilege, permissions: unpackPermissions(identityPrivilege.permissions) @@ -304,7 +315,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ projectSlug }: TListIdentityPrivilegesDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); diff --git a/backend/src/ee/services/ldap-config/ldap-config-service.ts b/backend/src/ee/services/ldap-config/ldap-config-service.ts index 7caaa5596..0cbab8c32 100644 --- a/backend/src/ee/services/ldap-config/ldap-config-service.ts +++ b/backend/src/ee/services/ldap-config/ldap-config-service.ts @@ -247,7 +247,11 @@ export const ldapConfigServiceFactory = ({ }; const orgBot = await orgBotDAL.findOne({ orgId }); - if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + if (!orgBot) + throw new NotFoundError({ + message: `Organization bot in organization with ID '${orgId}' not found`, + name: "OrgBotNotFound" + }); const key = infisicalSymmetricDecrypt({ ciphertext: orgBot.encryptedSymmetricKey, iv: orgBot.symmetricKeyIV, @@ -283,10 +287,19 @@ export const ldapConfigServiceFactory = ({ const getLdapCfg = async (filter: { orgId: string; isActive?: boolean; id?: string }) => { const ldapConfig = await ldapConfigDAL.findOne(filter); - if (!ldapConfig) throw new NotFoundError({ message: "Failed to find organization LDAP data" }); + if (!ldapConfig) { + throw new NotFoundError({ + message: `Failed to find organization LDAP data in organization with ID '${filter.orgId}'` + }); + } const orgBot = await orgBotDAL.findOne({ orgId: ldapConfig.orgId }); - if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + if (!orgBot) { + throw new NotFoundError({ + message: `Organization bot not found in organization with ID ${ldapConfig.orgId}`, + name: "OrgBotNotFound" + }); + } const key = infisicalSymmetricDecrypt({ ciphertext: orgBot.encryptedSymmetricKey, @@ -369,7 +382,7 @@ export const ldapConfigServiceFactory = ({ const bootLdap = async (organizationSlug: string) => { const organization = await orgDAL.findOne({ slug: organizationSlug }); - if (!organization) throw new NotFoundError({ message: "Organization not found" }); + if (!organization) throw new NotFoundError({ message: `Organization with slug '${organizationSlug}' not found` }); const ldapConfig = await getLdapCfg({ orgId: organization.id, @@ -426,7 +439,7 @@ export const ldapConfigServiceFactory = ({ }); const organization = await orgDAL.findOrgById(orgId); - if (!organization) throw new NotFoundError({ message: "Organization not found" }); + if (!organization) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); if (userAlias) { await userDAL.transaction(async (tx) => { @@ -700,7 +713,11 @@ export const ldapConfigServiceFactory = ({ orgId }); - if (!ldapConfig) throw new NotFoundError({ message: "Failed to find organization LDAP data" }); + if (!ldapConfig) { + throw new NotFoundError({ + message: `Failed to find organization LDAP data with ID '${ldapConfigId}' in organization with ID ${orgId}` + }); + } const groupMaps = await ldapGroupMapDAL.findLdapGroupMapsByLdapConfigId(ldapConfigId); @@ -747,7 +764,11 @@ export const ldapConfigServiceFactory = ({ } const group = await groupDAL.findOne({ slug: groupSlug, orgId }); - if (!group) throw new NotFoundError({ message: "Failed to find group" }); + if (!group) { + throw new NotFoundError({ + message: `Failed to find group with slug '${groupSlug}' in organization with ID '${orgId}'` + }); + } const groupMap = await ldapGroupMapDAL.create({ ldapConfigId, @@ -781,7 +802,11 @@ export const ldapConfigServiceFactory = ({ orgId }); - if (!ldapConfig) throw new NotFoundError({ message: "Failed to find organization LDAP data" }); + if (!ldapConfig) { + throw new NotFoundError({ + message: `Failed to find organization LDAP data with ID '${ldapConfigId}' in organization with ID ${orgId}` + }); + } const [deletedGroupMap] = await ldapGroupMapDAL.delete({ ldapConfigId: ldapConfig.id, diff --git a/backend/src/ee/services/license/license-service.ts b/backend/src/ee/services/license/license-service.ts index 2f06f35cf..068d947aa 100644 --- a/backend/src/ee/services/license/license-service.ts +++ b/backend/src/ee/services/license/license-service.ts @@ -145,7 +145,7 @@ export const licenseServiceFactory = ({ if (cachedPlan) return JSON.parse(cachedPlan) as TFeatureSet; const org = await orgDAL.findOrgById(orgId); - if (!org) throw new NotFoundError({ message: "Organization not found" }); + if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); const { data: { currentPlan } } = await licenseServerCloudApi.request.get<{ currentPlan: TFeatureSet }>( @@ -204,7 +204,7 @@ export const licenseServiceFactory = ({ const updateSubscriptionOrgMemberCount = async (orgId: string, tx?: Knex) => { if (instanceType === InstanceType.Cloud) { const org = await orgDAL.findOrgById(orgId); - if (!org) throw new NotFoundError({ message: "Organization not found" }); + if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); const quantity = await licenseDAL.countOfOrgMembers(orgId, tx); const quantityIdentities = await licenseDAL.countOrgUsersAndIdentities(orgId, tx); @@ -267,7 +267,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } @@ -341,7 +341,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } const { data } = await licenseServerCloudApi.request.get( @@ -358,7 +358,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } const { data } = await licenseServerCloudApi.request.get( @@ -374,7 +374,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } @@ -399,7 +399,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } const { data } = await licenseServerCloudApi.request.patch( @@ -419,7 +419,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } @@ -446,7 +446,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } const { @@ -475,7 +475,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } @@ -492,7 +492,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } const { @@ -510,7 +510,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } @@ -531,7 +531,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } @@ -548,7 +548,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } @@ -565,7 +565,7 @@ export const licenseServiceFactory = ({ const organization = await orgDAL.findOrgById(orgId); if (!organization) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with ID '${orgId}' not found` }); } diff --git a/backend/src/ee/services/oidc/oidc-config-service.ts b/backend/src/ee/services/oidc/oidc-config-service.ts index b68d5497f..17c1ddaaf 100644 --- a/backend/src/ee/services/oidc/oidc-config-service.ts +++ b/backend/src/ee/services/oidc/oidc-config-service.ts @@ -79,7 +79,7 @@ export const oidcConfigServiceFactory = ({ const org = await orgDAL.findOne({ slug: dto.orgSlug }); if (!org) { throw new NotFoundError({ - message: "Organization not found", + message: `Organization with slug '${dto.orgSlug}' not found`, name: "OrgNotFound" }); } @@ -100,14 +100,17 @@ export const oidcConfigServiceFactory = ({ if (!oidcCfg) { throw new NotFoundError({ - message: "Failed to find organization OIDC configuration" + message: `OIDC configuration for organization with slug '${dto.orgSlug}' not found` }); } // decrypt and return cfg const orgBot = await orgBotDAL.findOne({ orgId: oidcCfg.orgId }); if (!orgBot) { - throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + throw new NotFoundError({ + message: `Organization bot for organization with ID '${oidcCfg.orgId}' not found`, + name: "OrgBotNotFound" + }); } const key = infisicalSymmetricDecrypt({ @@ -174,7 +177,7 @@ export const oidcConfigServiceFactory = ({ }); const organization = await orgDAL.findOrgById(orgId); - if (!organization) throw new NotFoundError({ message: "Organization not found" }); + if (!organization) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); let user: TUsers; if (userAlias) { @@ -366,7 +369,7 @@ export const oidcConfigServiceFactory = ({ if (!org) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with slug '${orgSlug}' not found` }); } @@ -387,7 +390,11 @@ export const oidcConfigServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso); const orgBot = await orgBotDAL.findOne({ orgId: org.id }); - if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + if (!orgBot) + throw new NotFoundError({ + message: `Organization bot for organization with ID '${org.id}' not found`, + name: "OrgBotNotFound" + }); const key = infisicalSymmetricDecrypt({ ciphertext: orgBot.encryptedSymmetricKey, iv: orgBot.symmetricKeyIV, @@ -455,7 +462,7 @@ export const oidcConfigServiceFactory = ({ }); if (!org) { throw new NotFoundError({ - message: "Organization not found" + message: `Organization with slug '${orgSlug}' not found` }); } @@ -561,7 +568,7 @@ export const oidcConfigServiceFactory = ({ if (!org) { throw new NotFoundError({ - message: "Organization not found." + message: `Organization with slug '${orgSlug}' not found` }); } diff --git a/backend/src/ee/services/permission/permission-service.ts b/backend/src/ee/services/permission/permission-service.ts index ea0289ab0..900be4b38 100644 --- a/backend/src/ee/services/permission/permission-service.ts +++ b/backend/src/ee/services/permission/permission-service.ts @@ -64,7 +64,7 @@ export const permissionServiceFactory = ({ permissions as PackRule>>[] ); default: - throw new NotFoundError({ name: "OrgRoleInvalid", message: "Organization role not found" }); + throw new NotFoundError({ name: "OrgRoleInvalid", message: `Organization role '${role}' not found` }); } }) .reduce((curr, prev) => prev.concat(curr), []); @@ -94,7 +94,7 @@ export const permissionServiceFactory = ({ default: throw new NotFoundError({ name: "ProjectRoleInvalid", - message: "Project role not found" + message: `Project role '${role}' not found` }); } }) @@ -145,7 +145,7 @@ export const permissionServiceFactory = ({ const membership = await permissionDAL.getOrgIdentityPermission(identityId, orgId); if (!membership) throw new ForbiddenRequestError({ name: "Identity is not apart of this organization" }); if (membership.role === OrgMembershipRole.Custom && !membership.permissions) { - throw new NotFoundError({ name: "Custom organization permission not found" }); + throw new NotFoundError({ name: `Custom organization permission not found for identity ${identityId}` }); } return { permission: buildOrgPermission([{ role: membership.role, permissions: membership.permissions }]), @@ -179,7 +179,10 @@ export const permissionServiceFactory = ({ const isCustomRole = !Object.values(OrgMembershipRole).includes(role as OrgMembershipRole); if (isCustomRole) { const orgRole = await orgRoleDAL.findOne({ slug: role, orgId }); - if (!orgRole) throw new NotFoundError({ message: "Specified role was not found" }); + if (!orgRole) + throw new NotFoundError({ + message: `Specified role '${role}' was not found in the organization with ID '${orgId}'` + }); return { permission: buildOrgPermission([{ role: OrgMembershipRole.Custom, permissions: orgRole.permissions }]), role: orgRole @@ -264,7 +267,9 @@ export const permissionServiceFactory = ({ ): Promise> => { const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId); if (!identityProjectPermission) - throw new ForbiddenRequestError({ name: "Identity is not a member of the specified project" }); + throw new ForbiddenRequestError({ + name: `Identity is not a member of the specified project with ID '${projectId}'` + }); if ( identityProjectPermission.roles.some( @@ -326,7 +331,7 @@ export const permissionServiceFactory = ({ actorOrgId: string | undefined ) => { const serviceToken = await serviceTokenDAL.findById(serviceTokenId); - if (!serviceToken) throw new NotFoundError({ message: "Service token not found" }); + if (!serviceToken) throw new NotFoundError({ message: `Service token with ID '${serviceTokenId}' not found` }); const serviceTokenProject = await projectDAL.findById(serviceToken.projectId); @@ -337,11 +342,15 @@ export const permissionServiceFactory = ({ } if (serviceToken.projectId !== projectId) { - throw new ForbiddenRequestError({ name: "Service token not a part of the specified project" }); + throw new ForbiddenRequestError({ + name: `Service token not a part of the specified project with ID ${projectId}` + }); } if (serviceTokenProject.orgId !== actorOrgId) { - throw new ForbiddenRequestError({ message: "Service token not a part of the specified organization" }); + throw new ForbiddenRequestError({ + message: `Service token not a part of the specified organization with ID ${actorOrgId}` + }); } const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []); diff --git a/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts b/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts index ea46e132c..1ee27b1a7 100644 --- a/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts +++ b/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts @@ -42,7 +42,8 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ ...dto }: TCreateUserPrivilegeDTO) => { const projectMembership = await projectMembershipDAL.findById(projectMembershipId); - if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" }); + if (!projectMembership) + throw new NotFoundError({ message: `Project membership with ID '${projectMembershipId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -94,14 +95,18 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ ...dto }: TUpdateUserPrivilegeDTO) => { const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId); - if (!userPrivilege) throw new NotFoundError({ message: "User additional privilege not found" }); + if (!userPrivilege) + throw new NotFoundError({ message: `User additional privilege with ID '${privilegeId}' not found` }); const projectMembership = await projectMembershipDAL.findOne({ userId: userPrivilege.userId, projectId: userPrivilege.projectId }); - if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" }); + if (!projectMembership) + throw new NotFoundError({ + message: `Project membership for user with ID '${userPrivilege.userId}' not found in project with ID '${userPrivilege.projectId}'` + }); const { permission } = await permissionService.getProjectPermission( actor, @@ -147,13 +152,17 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ const deleteById = async ({ actorId, actor, actorOrgId, actorAuthMethod, privilegeId }: TDeleteUserPrivilegeDTO) => { const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId); - if (!userPrivilege) throw new NotFoundError({ message: "User additional privilege not found" }); + if (!userPrivilege) + throw new NotFoundError({ message: `User additional privilege with ID '${privilegeId}' not found` }); const projectMembership = await projectMembershipDAL.findOne({ userId: userPrivilege.userId, projectId: userPrivilege.projectId }); - if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" }); + if (!projectMembership) + throw new NotFoundError({ + message: `Project membership for user with ID '${userPrivilege.userId}' not found in project with ID '${userPrivilege.projectId}'` + }); const { permission } = await permissionService.getProjectPermission( actor, @@ -176,13 +185,17 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ actorAuthMethod }: TGetUserPrivilegeDetailsDTO) => { const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId); - if (!userPrivilege) throw new NotFoundError({ message: "User additional privilege not found" }); + if (!userPrivilege) + throw new NotFoundError({ message: `User additional privilege with ID '${privilegeId}' not found` }); const projectMembership = await projectMembershipDAL.findOne({ userId: userPrivilege.userId, projectId: userPrivilege.projectId }); - if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" }); + if (!projectMembership) + throw new NotFoundError({ + message: `Project membership for user with ID '${userPrivilege.userId}' not found in project with ID '${userPrivilege.projectId}'` + }); const { permission } = await permissionService.getProjectPermission( actor, @@ -204,7 +217,8 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ actorAuthMethod }: TListUserPrivilegesDTO) => { const projectMembership = await projectMembershipDAL.findById(projectMembershipId); - if (!projectMembership) throw new NotFoundError({ message: "Project membership not found" }); + if (!projectMembership) + throw new NotFoundError({ message: `Project membership with ID '${projectMembershipId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, diff --git a/backend/src/ee/services/saml-config/saml-config-service.ts b/backend/src/ee/services/saml-config/saml-config-service.ts index 69d3626f0..2930d06f9 100644 --- a/backend/src/ee/services/saml-config/saml-config-service.ts +++ b/backend/src/ee/services/saml-config/saml-config-service.ts @@ -191,7 +191,11 @@ export const samlConfigServiceFactory = ({ const updateQuery: TSamlConfigsUpdate = { authProvider, isActive, lastUsed: null }; const orgBot = await orgBotDAL.findOne({ orgId }); - if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + if (!orgBot) + throw new NotFoundError({ + message: `Organization bot not found for organization with ID '${orgId}'`, + name: "OrgBotNotFound" + }); const key = infisicalSymmetricDecrypt({ ciphertext: orgBot.encryptedSymmetricKey, iv: orgBot.symmetricKeyIV, @@ -257,7 +261,7 @@ export const samlConfigServiceFactory = ({ ssoConfig = await samlConfigDAL.findById(id); } - if (!ssoConfig) throw new NotFoundError({ message: "Failed to find organization SSO data" }); + if (!ssoConfig) throw new NotFoundError({ message: `Failed to find SSO data` }); // when dto is type id means it's internally used if (dto.type === "org") { @@ -283,7 +287,11 @@ export const samlConfigServiceFactory = ({ } = ssoConfig; const orgBot = await orgBotDAL.findOne({ orgId: ssoConfig.orgId }); - if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + if (!orgBot) + throw new NotFoundError({ + message: `Organization bot not found in organization with ID '${ssoConfig.orgId}'`, + name: "OrgBotNotFound" + }); const key = infisicalSymmetricDecrypt({ ciphertext: orgBot.encryptedSymmetricKey, iv: orgBot.symmetricKeyIV, @@ -355,7 +363,7 @@ export const samlConfigServiceFactory = ({ }); const organization = await orgDAL.findOrgById(orgId); - if (!organization) throw new NotFoundError({ message: "Organization not found" }); + if (!organization) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); let user: TUsers; if (userAlias) { diff --git a/backend/src/ee/services/scim/scim-service.ts b/backend/src/ee/services/scim/scim-service.ts index 9165408fa..0f814d2ac 100644 --- a/backend/src/ee/services/scim/scim-service.ts +++ b/backend/src/ee/services/scim/scim-service.ts @@ -183,7 +183,7 @@ export const scimServiceFactory = ({ const deleteScimToken = async ({ scimTokenId, actor, actorId, actorAuthMethod, actorOrgId }: TDeleteScimTokenDTO) => { let scimToken = await scimDAL.findById(scimTokenId); - if (!scimToken) throw new NotFoundError({ message: "Failed to find SCIM token to delete" }); + if (!scimToken) throw new NotFoundError({ message: `SCIM token with ID '${scimTokenId}' not found` }); const { permission } = await permissionService.getOrgPermission( actor, @@ -834,10 +834,12 @@ export const scimServiceFactory = ({ }); } - const users = await groupDAL.findAllGroupPossibleMembers({ - orgId: group.orgId, - groupId: group.id - }); + const users = await groupDAL + .findAllGroupPossibleMembers({ + orgId: group.orgId, + groupId: group.id + }) + .then((g) => g.members); const orgMemberships = await orgDAL.findMembership({ [`${TableName.OrgMembership}.orgId` as "orgId"]: orgId, diff --git a/backend/src/ee/services/secret-approval-policy/secret-approval-policy-service.ts b/backend/src/ee/services/secret-approval-policy/secret-approval-policy-service.ts index 1908e75af..e43a0d801 100644 --- a/backend/src/ee/services/secret-approval-policy/secret-approval-policy-service.ts +++ b/backend/src/ee/services/secret-approval-policy/secret-approval-policy-service.ts @@ -95,7 +95,10 @@ export const secretApprovalPolicyServiceFactory = ({ } const env = await projectEnvDAL.findOne({ slug: environment, projectId }); - if (!env) throw new NotFoundError({ message: "Environment not found" }); + if (!env) + throw new NotFoundError({ + message: `Environment with slug '${environment}' not found in project with ID ${projectId}` + }); const secretApproval = await secretApprovalPolicyDAL.transaction(async (tx) => { const doc = await secretApprovalPolicyDAL.create( @@ -178,7 +181,11 @@ export const secretApprovalPolicyServiceFactory = ({ .filter(Boolean) as string[]; const secretApprovalPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId); - if (!secretApprovalPolicy) throw new NotFoundError({ message: "Secret approval policy not found" }); + if (!secretApprovalPolicy) { + throw new NotFoundError({ + message: `Secret approval policy with ID '${secretPolicyId}' not found` + }); + } const { permission } = await permissionService.getProjectPermission( actor, @@ -271,7 +278,8 @@ export const secretApprovalPolicyServiceFactory = ({ actorOrgId }: TDeleteSapDTO) => { const sapPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId); - if (!sapPolicy) throw new NotFoundError({ message: "Secret approval policy not found" }); + if (!sapPolicy) + throw new NotFoundError({ message: `Secret approval policy with ID '${secretPolicyId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -320,7 +328,11 @@ export const secretApprovalPolicyServiceFactory = ({ const getSecretApprovalPolicy = async (projectId: string, environment: string, path: string) => { const secretPath = removeTrailingSlash(path); const env = await projectEnvDAL.findOne({ slug: environment, projectId }); - if (!env) throw new NotFoundError({ message: "Environment not found" }); + if (!env) { + throw new NotFoundError({ + message: `Environment with slug '${environment}' not found in project with ID ${projectId}` + }); + } const policies = await secretApprovalPolicyDAL.find({ envId: env.id }); if (!policies.length) return; @@ -369,7 +381,7 @@ export const secretApprovalPolicyServiceFactory = ({ if (!sapPolicy) { throw new NotFoundError({ - message: "Cannot find secret approval policy" + message: `Secret approval policy with ID '${sapId}' not found` }); } diff --git a/backend/src/ee/services/secret-approval-request/secret-approval-request-service.ts b/backend/src/ee/services/secret-approval-request/secret-approval-request-service.ts index bbc099956..d38043277 100644 --- a/backend/src/ee/services/secret-approval-request/secret-approval-request-service.ts +++ b/backend/src/ee/services/secret-approval-request/secret-approval-request-service.ts @@ -204,7 +204,8 @@ export const secretApprovalRequestServiceFactory = ({ if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); const secretApprovalRequest = await secretApprovalRequestDAL.findById(id); - if (!secretApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" }); + if (!secretApprovalRequest) + throw new NotFoundError({ message: `Secret approval request with ID '${id}' not found` }); const { projectId } = secretApprovalRequest; const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId); @@ -271,7 +272,7 @@ export const secretApprovalRequestServiceFactory = ({ : undefined })); } else { - if (!botKey) throw new NotFoundError({ message: "Project bot key not found" }); + if (!botKey) throw new NotFoundError({ message: `Project bot key not found`, name: "BotKeyNotFound" }); // CLI depends on this error message. TODO(daniel): Make API check for name BotKeyNotFound instead of message const encrypedSecrets = await secretApprovalRequestSecretDAL.findByRequestId(secretApprovalRequest.id); secrets = encrypedSecrets.map((el) => ({ ...el, @@ -307,7 +308,9 @@ export const secretApprovalRequestServiceFactory = ({ actorOrgId }: TReviewRequestDTO) => { const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); - if (!secretApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" }); + if (!secretApprovalRequest) { + throw new NotFoundError({ message: `Secret approval request with ID '${approvalId}' not found` }); + } if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); const plan = await licenseService.getPlan(actorOrgId); @@ -365,7 +368,9 @@ export const secretApprovalRequestServiceFactory = ({ actorAuthMethod }: TStatusChangeDTO) => { const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); - if (!secretApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" }); + if (!secretApprovalRequest) { + throw new NotFoundError({ message: `Secret approval request with ID '${approvalId}' not found` }); + } if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); const plan = await licenseService.getPlan(actorOrgId); @@ -414,7 +419,8 @@ export const secretApprovalRequestServiceFactory = ({ bypassReason }: TMergeSecretApprovalRequestDTO) => { const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); - if (!secretApprovalRequest) throw new NotFoundError({ message: "Secret approval request not found" }); + if (!secretApprovalRequest) + throw new NotFoundError({ message: `Secret approval request with ID '${approvalId}' not found` }); if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); const plan = await licenseService.getPlan(actorOrgId); @@ -462,7 +468,9 @@ export const secretApprovalRequestServiceFactory = ({ const secretApprovalSecrets = await secretApprovalRequestSecretDAL.findByRequestIdBridgeSecretV2( secretApprovalRequest.id ); - if (!secretApprovalSecrets) throw new NotFoundError({ message: "No secrets found" }); + if (!secretApprovalSecrets) { + throw new NotFoundError({ message: `No secrets found in secret change request with ID '${approvalId}'` }); + } const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, @@ -602,7 +610,9 @@ export const secretApprovalRequestServiceFactory = ({ }); } else { const secretApprovalSecrets = await secretApprovalRequestSecretDAL.findByRequestId(secretApprovalRequest.id); - if (!secretApprovalSecrets) throw new NotFoundError({ message: "No secrets found" }); + if (!secretApprovalSecrets) { + throw new NotFoundError({ message: `No secrets found in secret change request with ID '${approvalId}'` }); + } const conflicts: Array<{ secretId: string; op: SecretOperations }> = []; let secretCreationCommits = secretApprovalSecrets.filter(({ op }) => op === SecretOperations.Create); @@ -610,10 +620,10 @@ export const secretApprovalRequestServiceFactory = ({ const { secsGroupedByBlindIndex: conflictGroupByBlindIndex } = await fnSecretBlindIndexCheckV2({ folderId, secretDAL, - inputSecrets: secretCreationCommits.map(({ secretBlindIndex }) => { + inputSecrets: secretCreationCommits.map(({ secretBlindIndex, secret }) => { if (!secretBlindIndex) { throw new NotFoundError({ - message: "Secret blind index not found" + message: `Secret blind index not found on secret with ID '${secret.id}` }); } return { secretBlindIndex }; @@ -637,10 +647,10 @@ export const secretApprovalRequestServiceFactory = ({ userId: "", inputSecrets: secretUpdationCommits .filter(({ secretBlindIndex, secret }) => secret && secret.secretBlindIndex !== secretBlindIndex) - .map(({ secretBlindIndex }) => { + .map(({ secretBlindIndex, secret }) => { if (!secretBlindIndex) { throw new NotFoundError({ - message: "Secret blind index not found" + message: `Secret blind index not found on secret with ID '${secret.id}` }); } return { secretBlindIndex }; @@ -760,10 +770,10 @@ export const secretApprovalRequestServiceFactory = ({ actorId: "", secretDAL, secretQueueService, - inputSecrets: secretDeletionCommits.map(({ secretBlindIndex }) => { + inputSecrets: secretDeletionCommits.map(({ secretBlindIndex, secret }) => { if (!secretBlindIndex) { throw new NotFoundError({ - message: "Secret blind index not found" + message: `Secret blind index not found on secret with ID '${secret.id}` }); } return { secretBlindIndex, type: SecretType.Shared }; @@ -789,7 +799,9 @@ export const secretApprovalRequestServiceFactory = ({ await snapshotService.performSnapshot(folderId); const [folder] = await folderDAL.findSecretPathByFolderIds(projectId, [folderId]); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) { + throw new NotFoundError({ message: `Folder with ID '${folderId}' not found in project with ID '${projectId}'` }); + } await secretQueueService.syncSecrets({ projectId, secretPath: folder.path, @@ -861,14 +873,18 @@ export const secretApprovalRequestServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", + message: `Folder not found for environment with slug '${environment}' & secret path '${secretPath}'`, name: "GenSecretApproval" }); const folderId = folder.id; const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId }); - if (!blindIndexCfg) throw new NotFoundError({ message: "Blind index not found", name: "Update secret" }); - + if (!blindIndexCfg) { + throw new NotFoundError({ + message: `Blind index not found for project with ID '${projectId}'`, + name: "Update secret" + }); + } const commits: Omit[] = []; const commitTagIds: Record = {}; // for created secret approval change @@ -961,7 +977,9 @@ export const secretApprovalRequestServiceFactory = ({ secretDAL }); const secretsGroupedByBlindIndex = groupBy(secrets, (i) => { - if (!i.secretBlindIndex) throw new NotFoundError({ message: "Secret blind index not found" }); + if (!i.secretBlindIndex) { + throw new NotFoundError({ message: `Secret blind index not found for secret with ID '${i.id}'` }); + } return i.secretBlindIndex; }); const deletedSecretIds = deletedSecrets.map( @@ -972,7 +990,7 @@ export const secretApprovalRequestServiceFactory = ({ ...deletedSecrets.map((el) => { const secretId = secretsGroupedByBlindIndex[keyName2BlindIndex[el.secretName]][0].id; if (!latestSecretVersions[secretId].secretBlindIndex) - throw new NotFoundError({ message: "Secret blind index not found" }); + throw new NotFoundError({ message: `Secret blind index not found for secret with ID '${secretId}'` }); return { op: SecretOperations.Delete as const, ...latestSecretVersions[secretId], @@ -988,7 +1006,7 @@ export const secretApprovalRequestServiceFactory = ({ const tagIds = unique(Object.values(commitTagIds).flat()); const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : []; - if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if (tagIds.length !== tags.length) throw new NotFoundError({ message: "One or more tags not found" }); const secretApprovalRequest = await secretApprovalRequestDAL.transaction(async (tx) => { const doc = await secretApprovalRequestDAL.create( @@ -1054,7 +1072,7 @@ export const secretApprovalRequestServiceFactory = ({ const commitsGroupByBlindIndex = groupBy(approvalCommits, (i) => { if (!i.secretBlindIndex) { - throw new NotFoundError({ message: "Secret blind index not found" }); + throw new NotFoundError({ message: `Secret blind index not found for secret with ID '${i.id}'` }); } return i.secretBlindIndex; }); @@ -1133,7 +1151,7 @@ export const secretApprovalRequestServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", + message: `Folder not found for the environment slug '${environment}' & secret path '${secretPath}'`, name: "GenSecretApproval" }); const folderId = folder.id; @@ -1291,7 +1309,7 @@ export const secretApprovalRequestServiceFactory = ({ const tagIds = unique(Object.values(commitTagIds).flat()); const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : []; - if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if (tagIds.length !== tags.length) throw new NotFoundError({ message: "One or more tags not found" }); const secretApprovalRequest = await secretApprovalRequestDAL.transaction(async (tx) => { const doc = await secretApprovalRequestDAL.create( diff --git a/backend/src/ee/services/secret-replication/secret-replication-service.ts b/backend/src/ee/services/secret-replication/secret-replication-service.ts index 8f74079f7..cdb36f7af 100644 --- a/backend/src/ee/services/secret-replication/secret-replication-service.ts +++ b/backend/src/ee/services/secret-replication/secret-replication-service.ts @@ -295,7 +295,10 @@ export const secretReplicationServiceFactory = ({ const [destinationFolder] = await folderDAL.findSecretPathByFolderIds(projectId, [ destinationSecretImport.folderId ]); - if (!destinationFolder) throw new NotFoundError({ message: "Imported folder not found" }); + if (!destinationFolder) + throw new NotFoundError({ + message: `Imported folder with ID '${destinationSecretImport.folderId}' not found in project with ID ${projectId}` + }); let destinationReplicationFolder = await folderDAL.findOne({ parentId: destinationFolder.id, @@ -506,7 +509,7 @@ export const secretReplicationServiceFactory = ({ return; } - if (!botKey) throw new NotFoundError({ message: "Project bot not found" }); + if (!botKey) throw new NotFoundError({ message: `Bot key not found for project with ID ${projectId}` }); // these are the secrets to be added in replicated folders const sourceLocalSecrets = await secretDAL.find({ folderId: folder.id, type: SecretType.Shared }); const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id }); @@ -545,7 +548,11 @@ export const secretReplicationServiceFactory = ({ const [destinationFolder] = await folderDAL.findSecretPathByFolderIds(projectId, [ destinationSecretImport.folderId ]); - if (!destinationFolder) throw new NotFoundError({ message: "Imported folder not found" }); + if (!destinationFolder) { + throw new NotFoundError({ + message: `Imported folder with ID '${destinationSecretImport.folderId}' not found in project with ID ${projectId}` + }); + } let destinationReplicationFolder = await folderDAL.findOne({ parentId: destinationFolder.id, diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts index 76743ecdb..19976f148 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts @@ -332,7 +332,10 @@ export const secretRotationQueueFactory = ({ ); }); } else { - if (!botKey) throw new NotFoundError({ message: "Project bot not found" }); + if (!botKey) + throw new NotFoundError({ + message: `Project bot not found for project with ID '${secretRotation.projectId}'` + }); const encryptedSecrets = rotationOutputs.map(({ key: outputKey, secretId }) => ({ secretId, value: encryptSymmetric128BitHexKeyUTF8( @@ -372,7 +375,9 @@ export const secretRotationQueueFactory = ({ ); await secretVersionDAL.insertMany( updatedSecrets.map(({ id, updatedAt, createdAt, ...el }) => { - if (!el.secretBlindIndex) throw new NotFoundError({ message: "Secret blind index not found" }); + if (!el.secretBlindIndex) { + throw new NotFoundError({ message: `Secret blind index not found on secret with ID '${id}` }); + } return { ...el, secretId: id, diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-service.ts b/backend/src/ee/services/secret-rotation/secret-rotation-service.ts index 8408463ef..ec4171f2b 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-service.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-service.ts @@ -94,7 +94,11 @@ export const secretRotationServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); - if (!folder) throw new NotFoundError({ message: "Secret path not found" }); + if (!folder) { + throw new NotFoundError({ + message: `Secret path with path '${secretPath}' not found in environment with slug '${environment}'` + }); + } ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Secrets, { environment, secretPath }) @@ -108,14 +112,14 @@ export const secretRotationServiceFactory = ({ $in: { id: Object.values(outputs) } }); if (selectedSecrets.length !== Object.values(outputs).length) - throw new NotFoundError({ message: "Secrets not found" }); + throw new NotFoundError({ message: `Secrets not found in folder with ID '${folder.id}'` }); } else { const selectedSecrets = await secretDAL.find({ folderId: folder.id, $in: { id: Object.values(outputs) } }); if (selectedSecrets.length !== Object.values(outputs).length) - throw new NotFoundError({ message: "Secrets not found" }); + throw new NotFoundError({ message: `Secrets not found in folder with ID '${folder.id}'` }); } const plan = await licenseService.getPlan(project.orgId); @@ -125,7 +129,7 @@ export const secretRotationServiceFactory = ({ }); const selectedTemplate = rotationTemplates.find(({ name }) => name === provider); - if (!selectedTemplate) throw new NotFoundError({ message: "Provider not found" }); + if (!selectedTemplate) throw new NotFoundError({ message: `Provider with name '${provider}' not found` }); const formattedInputs: Record = {}; Object.entries(inputs).forEach(([key, value]) => { const { type } = selectedTemplate.template.inputs.properties[key]; @@ -198,7 +202,7 @@ export const secretRotationServiceFactory = ({ return docs; } - if (!botKey) throw new NotFoundError({ message: "Project bot not found" }); + if (!botKey) throw new NotFoundError({ message: `Project bot not found for project with ID '${projectId}'` }); const docs = await secretRotationDAL.find({ projectId }); return docs.map((el) => ({ ...el, @@ -220,7 +224,7 @@ export const secretRotationServiceFactory = ({ const restartById = async ({ actor, actorId, actorOrgId, actorAuthMethod, rotationId }: TRestartDTO) => { const doc = await secretRotationDAL.findById(rotationId); - if (!doc) throw new NotFoundError({ message: "Rotation not found" }); + if (!doc) throw new NotFoundError({ message: `Rotation with ID '${rotationId}' not found` }); const project = await projectDAL.findById(doc.projectId); const plan = await licenseService.getPlan(project.orgId); @@ -244,7 +248,7 @@ export const secretRotationServiceFactory = ({ const deleteById = async ({ actor, actorId, actorOrgId, actorAuthMethod, rotationId }: TDeleteDTO) => { const doc = await secretRotationDAL.findById(rotationId); - if (!doc) throw new NotFoundError({ message: "Rotation not found" }); + if (!doc) throw new NotFoundError({ message: `Rotation with ID '${rotationId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, diff --git a/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts b/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts index 1b19fd7f5..1907ddd9a 100644 --- a/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts +++ b/backend/src/ee/services/secret-scanning/secret-scanning-queue/secret-scanning-queue.ts @@ -1,6 +1,6 @@ import { ProbotOctokit } from "probot"; -import { OrgMembershipRole } from "@app/db/schemas"; +import { OrgMembershipRole, TableName } from "@app/db/schemas"; import { getConfig } from "@app/lib/config/env"; import { logger } from "@app/lib/logger"; import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue"; @@ -61,7 +61,7 @@ export const secretScanningQueueFactory = ({ const getOrgAdminEmails = async (organizationId: string) => { // get emails of admins const adminsOfWork = await orgMemberDAL.findMembership({ - orgId: organizationId, + [`${TableName.Organization}.id` as string]: organizationId, role: OrgMembershipRole.Admin }); return adminsOfWork.filter((userObject) => userObject.email).map((userObject) => userObject.email as string); diff --git a/backend/src/ee/services/secret-scanning/secret-scanning-service.ts b/backend/src/ee/services/secret-scanning/secret-scanning-service.ts index 913972cd1..945164094 100644 --- a/backend/src/ee/services/secret-scanning/secret-scanning-service.ts +++ b/backend/src/ee/services/secret-scanning/secret-scanning-service.ts @@ -90,7 +90,7 @@ export const secretScanningServiceFactory = ({ const { data: { repositories } } = await octokit.apps.listReposAccessibleToInstallation(); - if (!appCfg.DISABLE_SECRET_SCANNING) { + if (appCfg.SECRET_SCANNING_ORG_WHITELIST?.includes(actorOrgId)) { await Promise.all( repositories.map(({ id, full_name }) => secretScanningQueue.startFullRepoScan({ @@ -164,7 +164,7 @@ export const secretScanningServiceFactory = ({ }); if (!installationLink) return; - if (!appCfg.DISABLE_SECRET_SCANNING) { + if (appCfg.SECRET_SCANNING_ORG_WHITELIST?.includes(installationLink.orgId)) { await secretScanningQueue.startPushEventScan({ commits, pusher: { name: pusher.name, email: pusher.email }, diff --git a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts index de285a0f2..481123896 100644 --- a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts +++ b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts @@ -99,7 +99,11 @@ export const secretSnapshotServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environment, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) { + throw new NotFoundError({ + message: `Folder with path '${path}' not found in environment with slug '${environment}'` + }); + } return snapshotDAL.countOfSnapshotsByFolderId(folder.id); }; @@ -131,7 +135,10 @@ export const secretSnapshotServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environment, path); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${path}' not found in environment with slug '${environment}'` + }); const snapshots = await snapshotDAL.find({ folderId: folder.id }, { limit, offset, sort: [["createdAt", "desc"]] }); return snapshots; @@ -139,7 +146,7 @@ export const secretSnapshotServiceFactory = ({ const getSnapshotData = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TGetSnapshotDataDTO) => { const snapshot = await snapshotDAL.findById(id); - if (!snapshot) throw new NotFoundError({ message: "Snapshot not found" }); + if (!snapshot) throw new NotFoundError({ message: `Snapshot with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, actorId, @@ -173,7 +180,8 @@ export const secretSnapshotServiceFactory = ({ } else { const encryptedSnapshotDetails = await snapshotDAL.findSecretSnapshotDataById(id); const { botKey } = await projectBotService.getBotKey(snapshot.projectId); - if (!botKey) throw new NotFoundError({ message: "Project bot not found" }); + if (!botKey) + throw new NotFoundError({ message: `Project bot key not found for project with ID '${snapshot.projectId}'` }); snapshotDetails = { ...encryptedSnapshotDetails, secretVersions: encryptedSnapshotDetails.secretVersions.map((el) => ({ @@ -225,7 +233,7 @@ export const secretSnapshotServiceFactory = ({ try { if (!licenseService.isValidLicense) throw new InternalServerError({ message: "Invalid license" }); const folder = await folderDAL.findById(folderId); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) throw new NotFoundError({ message: `Folder with ID '${folderId}' not found` }); const shouldUseSecretV2Bridge = folder.projectVersion === 3; if (shouldUseSecretV2Bridge) { @@ -311,7 +319,7 @@ export const secretSnapshotServiceFactory = ({ actorOrgId }: TRollbackSnapshotDTO) => { const snapshot = await snapshotDAL.findById(snapshotId); - if (!snapshot) throw new NotFoundError({ message: "Snapshot not found" }); + if (!snapshot) throw new NotFoundError({ message: `Snapshot with ID '${snapshotId}' not found` }); const shouldUseBridge = snapshot.projectVersion === 3; const { permission } = await permissionService.getProjectPermission( diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 0d519ab8c..ecc8870d3 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -18,7 +18,8 @@ export const GROUPS = { id: "The id of the group to list users for", offset: "The offset to start from. If you enter 10, it will start from the 10th user.", limit: "The number of users to return.", - username: "The username to search for." + username: "The username to search for.", + search: "The text string that user email or name will be filtered by." }, ADD_USER: { id: "The id of the group to add the user to.", diff --git a/backend/src/lib/config/env.ts b/backend/src/lib/config/env.ts index 2b7a3a733..60f4b74a9 100644 --- a/backend/src/lib/config/env.ts +++ b/backend/src/lib/config/env.ts @@ -142,6 +142,7 @@ const envSchema = z SECRET_SCANNING_WEBHOOK_SECRET: zpStr(z.string().optional()), SECRET_SCANNING_GIT_APP_ID: zpStr(z.string().optional()), SECRET_SCANNING_PRIVATE_KEY: zpStr(z.string().optional()), + SECRET_SCANNING_ORG_WHITELIST: zpStr(z.string().optional()), // LICENSE LICENSE_SERVER_URL: zpStr(z.string().optional().default("https://portal.infisical.com")), LICENSE_SERVER_KEY: zpStr(z.string().optional()), @@ -177,7 +178,8 @@ const envSchema = z Boolean(data.SECRET_SCANNING_GIT_APP_ID) && Boolean(data.SECRET_SCANNING_PRIVATE_KEY) && Boolean(data.SECRET_SCANNING_WEBHOOK_SECRET), - samlDefaultOrgSlug: data.DEFAULT_SAML_ORG_SLUG + samlDefaultOrgSlug: data.DEFAULT_SAML_ORG_SLUG, + SECRET_SCANNING_ORG_WHITELIST: data.SECRET_SCANNING_ORG_WHITELIST?.split(",") })); let envCfg: Readonly>; diff --git a/backend/src/lib/errors/index.ts b/backend/src/lib/errors/index.ts index 01d1c8b8e..0818cfe7d 100644 --- a/backend/src/lib/errors/index.ts +++ b/backend/src/lib/errors/index.ts @@ -71,6 +71,13 @@ export class BadRequestError extends Error { } } +export class RateLimitError extends Error { + constructor({ message }: { message?: string }) { + super(message || "Rate limit exceeded"); + this.name = "RateLimitExceeded"; + } +} + export class NotFoundError extends Error { name: string; diff --git a/backend/src/server/config/rateLimiter.ts b/backend/src/server/config/rateLimiter.ts index bdbf80371..176d44183 100644 --- a/backend/src/server/config/rateLimiter.ts +++ b/backend/src/server/config/rateLimiter.ts @@ -2,6 +2,7 @@ import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-lim import { Redis } from "ioredis"; import { getConfig } from "@app/lib/config/env"; +import { RateLimitError } from "@app/lib/errors"; export const globalRateLimiterCfg = (): RateLimitPluginOptions => { const appCfg = getConfig(); @@ -10,6 +11,11 @@ export const globalRateLimiterCfg = (): RateLimitPluginOptions => { : null; return { + errorResponseBuilder: (_, context) => { + throw new RateLimitError({ + message: `Rate limit exceeded. Please try again in ${context.after}` + }); + }, timeWindow: 60 * 1000, max: 600, redis, diff --git a/backend/src/server/plugins/error-handler.ts b/backend/src/server/plugins/error-handler.ts index 76bfa9023..be8665a84 100644 --- a/backend/src/server/plugins/error-handler.ts +++ b/backend/src/server/plugins/error-handler.ts @@ -10,6 +10,7 @@ import { GatewayTimeoutError, InternalServerError, NotFoundError, + RateLimitError, ScimRequestError, UnauthorizedError } from "@app/lib/errors"; @@ -27,7 +28,8 @@ enum HttpStatusCodes { Forbidden = 403, // eslint-disable-next-line @typescript-eslint/no-shadow InternalServerError = 500, - GatewayTimeout = 504 + GatewayTimeout = 504, + TooManyRequests = 429 } export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider) => { @@ -69,6 +71,12 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider message: error.message, error: error.name }); + } else if (error instanceof RateLimitError) { + void res.status(HttpStatusCodes.TooManyRequests).send({ + statusCode: HttpStatusCodes.TooManyRequests, + message: error.message, + error: error.name + }); } else if (error instanceof ScimRequestError) { void res.status(error.status).send({ schemas: error.schemas, diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 326b283f5..68df7f2d9 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -225,9 +225,7 @@ export const registerRoutes = async ( }: { auditLogDb?: Knex; db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory; keyStore: TKeyStoreFactory } ) => { const appCfg = getConfig(); - if (!appCfg.DISABLE_SECRET_SCANNING) { - await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" }); - } + await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" }); // db layers const userDAL = userDALFactory(db); diff --git a/backend/src/services/api-key/api-key-service.ts b/backend/src/services/api-key/api-key-service.ts index df69372b5..96fb90026 100644 --- a/backend/src/services/api-key/api-key-service.ts +++ b/backend/src/services/api-key/api-key-service.ts @@ -45,7 +45,7 @@ export const apiKeyServiceFactory = ({ apiKeyDAL, userDAL }: TApiKeyServiceFacto const deleteApiKey = async (userId: string, apiKeyId: string) => { const [apiKeyData] = await apiKeyDAL.delete({ id: apiKeyId, userId }); - if (!apiKeyData) throw new NotFoundError({ message: "API key not found" }); + if (!apiKeyData) throw new NotFoundError({ message: `API key with ID '${apiKeyId}' not found` }); return formatApiKey(apiKeyData); }; diff --git a/backend/src/services/auth-token/auth-token-service.ts b/backend/src/services/auth-token/auth-token-service.ts index 28302052e..321abb5b3 100644 --- a/backend/src/services/auth-token/auth-token-service.ts +++ b/backend/src/services/auth-token/auth-token-service.ts @@ -156,7 +156,7 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL, orgMembershipDAL }: TAu } const user = await userDAL.findById(session.userId); - if (!user || !user.isAccepted) throw new NotFoundError({ message: "User not found" }); + if (!user || !user.isAccepted) throw new NotFoundError({ message: `User with ID '${session.userId}' not found` }); if (token.organizationId) { const orgMembership = await orgMembershipDAL.findOne({ diff --git a/backend/src/services/certificate-authority/certificate-authority-fns.ts b/backend/src/services/certificate-authority/certificate-authority-fns.ts index 65ba57f07..efb582d88 100644 --- a/backend/src/services/certificate-authority/certificate-authority-fns.ts +++ b/backend/src/services/certificate-authority/certificate-authority-fns.ts @@ -113,10 +113,10 @@ export const getCaCredentials = async ({ kmsService }: TGetCaCredentialsDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const caSecret = await certificateAuthoritySecretDAL.findOne({ caId }); - if (!caSecret) throw new NotFoundError({ message: "CA secret not found" }); + if (!caSecret) throw new NotFoundError({ message: `CA secret for CA with ID '${caId}' not found` }); const keyId = await getProjectKmsCertificateKeyId({ projectId: ca.projectId, @@ -165,7 +165,7 @@ export const getCaCertChains = async ({ kmsService }: TGetCaCertChainsDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const keyId = await getProjectKmsCertificateKeyId({ projectId: ca.projectId, @@ -256,7 +256,7 @@ export const rebuildCaCrl = async ({ kmsService }: TRebuildCaCrlDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id }); diff --git a/backend/src/services/certificate-authority/certificate-authority-queue.ts b/backend/src/services/certificate-authority/certificate-authority-queue.ts index 5be67dea4..8c6d3906d 100644 --- a/backend/src/services/certificate-authority/certificate-authority-queue.ts +++ b/backend/src/services/certificate-authority/certificate-authority-queue.ts @@ -76,7 +76,7 @@ export const certificateAuthorityQueueFactory = ({ logger.info(`secretReminderQueue.process: [secretDocument=${caId}]`); const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id }); diff --git a/backend/src/services/certificate-authority/certificate-authority-service.ts b/backend/src/services/certificate-authority/certificate-authority-service.ts index 309a30fb0..06efcf9e3 100644 --- a/backend/src/services/certificate-authority/certificate-authority-service.ts +++ b/backend/src/services/certificate-authority/certificate-authority-service.ts @@ -122,7 +122,7 @@ export const certificateAuthorityServiceFactory = ({ actorOrgId }: TCreateCaDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -290,7 +290,7 @@ export const certificateAuthorityServiceFactory = ({ */ const getCaById = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -321,7 +321,7 @@ export const certificateAuthorityServiceFactory = ({ actorOrgId }: TUpdateCaDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -346,7 +346,7 @@ export const certificateAuthorityServiceFactory = ({ */ const deleteCaById = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteCaDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -371,7 +371,7 @@ export const certificateAuthorityServiceFactory = ({ */ const getCaCsr = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCsrDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -430,7 +430,7 @@ export const certificateAuthorityServiceFactory = ({ */ const renewCaCert = async ({ caId, notAfter, actorId, actorAuthMethod, actor, actorOrgId }: TRenewCaCertDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" }); @@ -702,7 +702,7 @@ export const certificateAuthorityServiceFactory = ({ const getCaCerts = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCertsDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -736,7 +736,7 @@ export const certificateAuthorityServiceFactory = ({ */ const getCaCert = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCertDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" }); const { permission } = await permissionService.getProjectPermission( @@ -778,7 +778,7 @@ export const certificateAuthorityServiceFactory = ({ }); if (!caCert) { - throw new NotFoundError({ message: "CA certificate not found" }); + throw new NotFoundError({ message: `Ca certificate with ID '${caCertId}' not found for CA with ID '${caId}'` }); } const ca = await certificateAuthorityDAL.findById(caId); @@ -963,7 +963,7 @@ export const certificateAuthorityServiceFactory = ({ certificateChain }: TImportCertToCaDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1115,7 +1115,7 @@ export const certificateAuthorityServiceFactory = ({ certificateTemplate = await certificateTemplateDAL.getById(certificateTemplateId); if (!certificateTemplate) { throw new NotFoundError({ - message: "Certificate template not found" + message: `Certificate template with ID '${certificateTemplateId}' not found` }); } @@ -1124,7 +1124,7 @@ export const certificateAuthorityServiceFactory = ({ } if (!ca) { - throw new NotFoundError({ message: "CA not found" }); + throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); } const { permission } = await permissionService.getProjectPermission( @@ -1442,7 +1442,7 @@ export const certificateAuthorityServiceFactory = ({ certificateTemplate = await certificateTemplateDAL.getById(certificateTemplateId); if (!certificateTemplate) { throw new NotFoundError({ - message: "Certificate template not found" + message: `Certificate template with ID '${certificateTemplateId}' not found` }); } @@ -1451,7 +1451,7 @@ export const certificateAuthorityServiceFactory = ({ } if (!ca) { - throw new NotFoundError({ message: "CA not found" }); + throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); } if (!dto.isInternal) { @@ -1484,7 +1484,7 @@ export const certificateAuthorityServiceFactory = ({ // check PKI collection if (pkiCollectionId) { const pkiCollection = await pkiCollectionDAL.findById(pkiCollectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${pkiCollectionId}' not found` }); if (pkiCollection.projectId !== ca.projectId) throw new BadRequestError({ message: "Invalid PKI collection" }); } @@ -1810,7 +1810,7 @@ export const certificateAuthorityServiceFactory = ({ actorOrgId }: TGetCaCertificateTemplatesDTO) => { const ca = await certificateAuthorityDAL.findById(caId); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, diff --git a/backend/src/services/certificate-template/certificate-template-service.ts b/backend/src/services/certificate-template/certificate-template-service.ts index 3e7f80e85..cbe893719 100644 --- a/backend/src/services/certificate-template/certificate-template-service.ts +++ b/backend/src/services/certificate-template/certificate-template-service.ts @@ -64,7 +64,7 @@ export const certificateTemplateServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) { throw new NotFoundError({ - message: "CA not found" + message: `CA with ID ${caId} not found` }); } const { permission } = await permissionService.getProjectPermission( @@ -98,7 +98,7 @@ export const certificateTemplateServiceFactory = ({ const certificateTemplate = await certificateTemplateDAL.getById(id, tx); if (!certificateTemplate) { throw new NotFoundError({ - message: "Certificate template not found" + message: `Certificate template with ID ${id} not found` }); } @@ -124,7 +124,7 @@ export const certificateTemplateServiceFactory = ({ const certTemplate = await certificateTemplateDAL.getById(id); if (!certTemplate) { throw new NotFoundError({ - message: "Certificate template not found." + message: `Certificate template with ID ${id} not found` }); } @@ -169,7 +169,7 @@ export const certificateTemplateServiceFactory = ({ const updatedTemplate = await certificateTemplateDAL.getById(id, tx); if (!updatedTemplate) { throw new NotFoundError({ - message: "Certificate template not found" + message: `Certificate template with ID ${id} not found` }); } @@ -181,7 +181,7 @@ export const certificateTemplateServiceFactory = ({ const certTemplate = await certificateTemplateDAL.getById(id); if (!certTemplate) { throw new NotFoundError({ - message: "Certificate template not found." + message: `Certificate template with ID ${id} not found` }); } @@ -207,7 +207,7 @@ export const certificateTemplateServiceFactory = ({ const certTemplate = await certificateTemplateDAL.getById(id); if (!certTemplate) { throw new NotFoundError({ - message: "Certificate template not found." + message: `Certificate template with ID ${id} not found` }); } @@ -247,7 +247,7 @@ export const certificateTemplateServiceFactory = ({ const certTemplate = await certificateTemplateDAL.getById(certificateTemplateId); if (!certTemplate) { throw new NotFoundError({ - message: "Certificate template not found." + message: `Certificate template with ID ${certificateTemplateId} not found` }); } @@ -324,7 +324,7 @@ export const certificateTemplateServiceFactory = ({ const certTemplate = await certificateTemplateDAL.getById(certificateTemplateId); if (!certTemplate) { throw new NotFoundError({ - message: "Certificate template not found." + message: `Certificate template with ID ${certificateTemplateId} not found` }); } @@ -347,7 +347,7 @@ export const certificateTemplateServiceFactory = ({ if (!originalCaEstConfig) { throw new NotFoundError({ - message: "EST configuration not found" + message: `EST configuration with certificate template ID ${certificateTemplateId} not found` }); } @@ -403,7 +403,7 @@ export const certificateTemplateServiceFactory = ({ const certTemplate = await certificateTemplateDAL.getById(certificateTemplateId); if (!certTemplate) { throw new NotFoundError({ - message: "Certificate template not found." + message: `Certificate template with ID ${certificateTemplateId} not found` }); } @@ -428,7 +428,7 @@ export const certificateTemplateServiceFactory = ({ if (!estConfig) { throw new NotFoundError({ - message: "EST configuration not found" + message: `EST configuration with certificate template ID ${certificateTemplateId} not found` }); } diff --git a/backend/src/services/cmek/cmek-service.ts b/backend/src/services/cmek/cmek-service.ts index 1f9c19dc9..c172f6d3c 100644 --- a/backend/src/services/cmek/cmek-service.ts +++ b/backend/src/services/cmek/cmek-service.ts @@ -46,7 +46,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService }: TC const updateCmekById = async ({ keyId, ...data }: TUpdabteCmekByIdDTO, actor: FastifyRequest["permission"]) => { const key = await kmsDAL.findById(keyId); - if (!key) throw new NotFoundError({ message: "Key not found" }); + if (!key) throw new NotFoundError({ message: `Key with ID ${keyId} not found` }); if (!key.projectId || key.isReserved) throw new BadRequestError({ message: "Key is not customer managed" }); @@ -68,7 +68,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService }: TC const deleteCmekById = async (keyId: string, actor: FastifyRequest["permission"]) => { const key = await kmsDAL.findById(keyId); - if (!key) throw new NotFoundError({ message: "Key not found" }); + if (!key) throw new NotFoundError({ message: `Key with ID ${keyId} not found` }); if (!key.projectId || key.isReserved) throw new BadRequestError({ message: "Key is not customer managed" }); @@ -109,7 +109,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService }: TC const cmekEncrypt = async ({ keyId, plaintext }: TCmekEncryptDTO, actor: FastifyRequest["permission"]) => { const key = await kmsDAL.findById(keyId); - if (!key) throw new NotFoundError({ message: "Key not found" }); + if (!key) throw new NotFoundError({ message: `Key with ID ${keyId} not found` }); if (!key.projectId || key.isReserved) throw new BadRequestError({ message: "Key is not customer managed" }); @@ -135,7 +135,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService }: TC const cmekDecrypt = async ({ keyId, ciphertext }: TCmekDecryptDTO, actor: FastifyRequest["permission"]) => { const key = await kmsDAL.findById(keyId); - if (!key) throw new NotFoundError({ message: "Key not found" }); + if (!key) throw new NotFoundError({ message: `Key with ID ${keyId} not found` }); if (!key.projectId || key.isReserved) throw new BadRequestError({ message: "Key is not customer managed" }); diff --git a/backend/src/services/group-project/group-project-service.ts b/backend/src/services/group-project/group-project-service.ts index acd059f87..896afe93d 100644 --- a/backend/src/services/group-project/group-project-service.ts +++ b/backend/src/services/group-project/group-project-service.ts @@ -169,7 +169,7 @@ export const groupProjectServiceFactory = ({ if (!ghostUser) { throw new NotFoundError({ - message: "Failed to find project owner" + message: `Failed to find project owner of project with name ${project.name}` }); } @@ -177,7 +177,7 @@ export const groupProjectServiceFactory = ({ if (!ghostUserLatestKey) { throw new NotFoundError({ - message: "Failed to find project owner's latest key" + message: `Failed to find project owner's latest key in project with name ${project.name}` }); } @@ -185,7 +185,7 @@ export const groupProjectServiceFactory = ({ if (!bot) { throw new NotFoundError({ - message: "Failed to find project bot" + message: `Failed to find project bot in project with name ${project.name}` }); } @@ -425,7 +425,7 @@ export const groupProjectServiceFactory = ({ if (!groupMembership) { throw new NotFoundError({ - message: "Cannot find group membership" + message: `Group membership with ID ${groupId} not found in project with ID ${projectId}` }); } diff --git a/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts b/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts index 6ef37eba3..e9c80419b 100644 --- a/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts +++ b/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts @@ -154,7 +154,7 @@ export const identityAwsAuthServiceFactory = ({ actorOrgId }: TAttachAwsAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity.authMethod) throw new BadRequestError({ message: "Failed to add AWS Auth to already configured identity" @@ -233,7 +233,7 @@ export const identityAwsAuthServiceFactory = ({ actorOrgId }: TUpdateAwsAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH) throw new BadRequestError({ message: "Failed to update AWS Auth" @@ -292,7 +292,7 @@ export const identityAwsAuthServiceFactory = ({ const getAwsAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAwsAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH) throw new BadRequestError({ message: "The identity does not have AWS Auth attached" @@ -319,7 +319,7 @@ export const identityAwsAuthServiceFactory = ({ actorOrgId }: TRevokeAwsAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH) throw new BadRequestError({ message: "The identity does not have aws auth" diff --git a/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts b/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts index cbda504db..9267725fb 100644 --- a/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts +++ b/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts @@ -125,7 +125,7 @@ export const identityAzureAuthServiceFactory = ({ actorOrgId }: TAttachAzureAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity.authMethod) throw new BadRequestError({ message: "Failed to add Azure Auth to already configured identity" @@ -203,7 +203,7 @@ export const identityAzureAuthServiceFactory = ({ actorOrgId }: TUpdateAzureAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH) throw new BadRequestError({ message: "Failed to update Azure Auth" @@ -265,7 +265,7 @@ export const identityAzureAuthServiceFactory = ({ const getAzureAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAzureAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH) throw new BadRequestError({ message: "The identity does not have Azure Auth attached" @@ -293,7 +293,7 @@ export const identityAzureAuthServiceFactory = ({ actorOrgId }: TRevokeAzureAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH) throw new BadRequestError({ message: "The identity does not have azure auth" diff --git a/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts b/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts index 14e4dcd3f..b78f06fa3 100644 --- a/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts +++ b/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts @@ -167,7 +167,7 @@ export const identityGcpAuthServiceFactory = ({ actorOrgId }: TAttachGcpAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity.authMethod) throw new BadRequestError({ message: "Failed to add GCP Auth to already configured identity" @@ -247,7 +247,7 @@ export const identityGcpAuthServiceFactory = ({ actorOrgId }: TUpdateGcpAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH) throw new BadRequestError({ message: "Failed to update GCP Auth" @@ -310,7 +310,7 @@ export const identityGcpAuthServiceFactory = ({ const getGcpAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetGcpAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH) throw new BadRequestError({ message: "The identity does not have GCP Auth attached" @@ -338,7 +338,7 @@ export const identityGcpAuthServiceFactory = ({ actorOrgId }: TRevokeGcpAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH) throw new BadRequestError({ message: "The identity does not have gcp auth" diff --git a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts index 83a02d079..b324d9046 100644 --- a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts +++ b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts @@ -72,10 +72,19 @@ export const identityKubernetesAuthServiceFactory = ({ const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityKubernetesAuth.identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Identity organization membership not found" }); + if (!identityMembershipOrg) { + throw new NotFoundError({ + message: `Identity organization membership for identity with ID '${identityKubernetesAuth.identityId}' not found` + }); + } const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId }); - if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + if (!orgBot) { + throw new NotFoundError({ + message: `Organization bot not found for organization with ID ${identityMembershipOrg.orgId}`, + name: "OrgBotNotFound" + }); + } const key = infisicalSymmetricDecrypt({ ciphertext: orgBot.encryptedSymmetricKey, @@ -250,7 +259,7 @@ export const identityKubernetesAuthServiceFactory = ({ actorOrgId }: TAttachKubernetesAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity.authMethod) throw new BadRequestError({ message: "Failed to add Kubernetes Auth to already configured identity" @@ -394,7 +403,7 @@ export const identityKubernetesAuthServiceFactory = ({ actorOrgId }: TUpdateKubernetesAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH) throw new BadRequestError({ message: "Failed to update Kubernetes Auth" @@ -451,8 +460,12 @@ export const identityKubernetesAuthServiceFactory = ({ }; const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId }); - if (!orgBot) throw new NotFoundError({ message: "Org bot not found", name: "OrgBotNotFound" }); - + if (!orgBot) { + throw new NotFoundError({ + message: `Organization bot not found for organization with ID ${identityMembershipOrg.orgId}`, + name: "OrgBotNotFound" + }); + } const key = infisicalSymmetricDecrypt({ ciphertext: orgBot.encryptedSymmetricKey, iv: orgBot.symmetricKeyIV, @@ -518,7 +531,7 @@ export const identityKubernetesAuthServiceFactory = ({ actorOrgId }: TGetKubernetesAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH) throw new BadRequestError({ message: "The identity does not have Kubernetes Auth attached" @@ -536,7 +549,11 @@ export const identityKubernetesAuthServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId }); - if (!orgBot) throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + if (!orgBot) + throw new NotFoundError({ + message: `Organization bot not found for organization with ID ${identityMembershipOrg.orgId}`, + name: "OrgBotNotFound" + }); const key = infisicalSymmetricDecrypt({ ciphertext: orgBot.encryptedSymmetricKey, @@ -579,7 +596,7 @@ export const identityKubernetesAuthServiceFactory = ({ actorOrgId }: TRevokeKubernetesAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH) throw new BadRequestError({ message: "The identity does not have kubernetes auth" diff --git a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts index 7c481f788..be09c4777 100644 --- a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts +++ b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts @@ -68,12 +68,17 @@ export const identityOidcAuthServiceFactory = ({ identityId: identityOidcAuth.identityId }); if (!identityMembershipOrg) { - throw new NotFoundError({ message: "Identity organization membership not found" }); + throw new NotFoundError({ + message: `Identity organization membership for identity with ID '${identityOidcAuth.identityId}' not found` + }); } const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId }); if (!orgBot) { - throw new NotFoundError({ message: "Organization bot was not found", name: "OrgBotNotFound" }); + throw new NotFoundError({ + message: `Organization bot not found for organization with ID '${identityMembershipOrg.orgId}'`, + name: "OrgBotNotFound" + }); } const key = infisicalSymmetricDecrypt({ @@ -221,7 +226,7 @@ export const identityOidcAuthServiceFactory = ({ }: TAttachOidcAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); if (!identityMembershipOrg) { - throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); } if (identityMembershipOrg.identity.authMethod) throw new BadRequestError({ @@ -360,7 +365,7 @@ export const identityOidcAuthServiceFactory = ({ }: TUpdateOidcAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); if (!identityMembershipOrg) { - throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); } if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.OIDC_AUTH) { @@ -422,7 +427,10 @@ export const identityOidcAuthServiceFactory = ({ const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId }); if (!orgBot) { - throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + throw new NotFoundError({ + message: `Organization bot not found for organization with ID '${identityMembershipOrg.orgId}'`, + name: "OrgBotNotFound" + }); } const key = infisicalSymmetricDecrypt({ @@ -460,7 +468,7 @@ export const identityOidcAuthServiceFactory = ({ const getOidcAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetOidcAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); if (!identityMembershipOrg) { - throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); } if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.OIDC_AUTH) { @@ -482,7 +490,10 @@ export const identityOidcAuthServiceFactory = ({ const orgBot = await orgBotDAL.findOne({ orgId: identityMembershipOrg.orgId }); if (!orgBot) { - throw new NotFoundError({ message: "Organization bot not found", name: "OrgBotNotFound" }); + throw new NotFoundError({ + message: `Organization bot not found for organization with ID ${identityMembershipOrg.orgId}`, + name: "OrgBotNotFound" + }); } const key = infisicalSymmetricDecrypt({ diff --git a/backend/src/services/identity-project/identity-project-service.ts b/backend/src/services/identity-project/identity-project-service.ts index 13a319df9..a49b15c1b 100644 --- a/backend/src/services/identity-project/identity-project-service.ts +++ b/backend/src/services/identity-project/identity-project-service.ts @@ -66,7 +66,7 @@ export const identityProjectServiceFactory = ({ const existingIdentity = await identityProjectDAL.findOne({ identityId, projectId }); if (existingIdentity) throw new BadRequestError({ - message: `Identity with id ${identityId} already exists in project with id ${projectId}` + message: `Identity with ID ${identityId} already exists in project with ID ${projectId}` }); const project = await projectDAL.findById(projectId); @@ -76,7 +76,7 @@ export const identityProjectServiceFactory = ({ }); if (!identityOrgMembership) throw new NotFoundError({ - message: `Failed to find identity with id ${identityId}` + message: `Failed to find identity with ID ${identityId}` }); for await (const { role: requestedRoleChange } of roles) { @@ -104,7 +104,7 @@ export const identityProjectServiceFactory = ({ }) : []; if (customRoles.length !== customInputRoles.length) - throw new NotFoundError({ message: "Custom project roles not found" }); + throw new NotFoundError({ message: "One or more custom project roles not found" }); const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug); const projectIdentity = await identityProjectDAL.transaction(async (tx) => { @@ -166,7 +166,7 @@ export const identityProjectServiceFactory = ({ const projectIdentity = await identityProjectDAL.findOne({ identityId, projectId }); if (!projectIdentity) throw new NotFoundError({ - message: `Identity with id ${identityId} doesn't exists in project with id ${projectId}` + message: `Identity with ID ${identityId} doesn't exists in project with ID ${projectId}` }); for await (const { role: requestedRoleChange } of roles) { @@ -192,7 +192,7 @@ export const identityProjectServiceFactory = ({ }) : []; if (customRoles.length !== customInputRoles.length) - throw new NotFoundError({ message: "Custom project roles not found" }); + throw new NotFoundError({ message: "One or more custom project roles not found" }); const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug); @@ -237,8 +237,9 @@ export const identityProjectServiceFactory = ({ projectId }: TDeleteProjectIdentityDTO) => { const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); - if (!identityProjectMembership) - throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); + if (!identityProjectMembership) { + throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); + } const { permission } = await permissionService.getProjectPermission( actor, @@ -314,7 +315,10 @@ export const identityProjectServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity); const [identityMembership] = await identityProjectDAL.findByProjectId(projectId, { identityId }); - if (!identityMembership) throw new NotFoundError({ message: `Membership not found for identity ${identityId}` }); + if (!identityMembership) + throw new NotFoundError({ + message: `Project membership for identity with ID '${identityId} in project with ID '${projectId}' not found` + }); return identityMembership; }; diff --git a/backend/src/services/identity-token-auth/identity-token-auth-service.ts b/backend/src/services/identity-token-auth/identity-token-auth-service.ts index b6eacd0d7..aa02cd94a 100644 --- a/backend/src/services/identity-token-auth/identity-token-auth-service.ts +++ b/backend/src/services/identity-token-auth/identity-token-auth-service.ts @@ -64,7 +64,7 @@ export const identityTokenAuthServiceFactory = ({ actorOrgId }: TAttachTokenAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity.authMethod) throw new BadRequestError({ message: "Failed to add Token Auth to already configured identity" @@ -136,7 +136,7 @@ export const identityTokenAuthServiceFactory = ({ actorOrgId }: TUpdateTokenAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) throw new BadRequestError({ message: "Failed to update Token Auth" @@ -196,7 +196,7 @@ export const identityTokenAuthServiceFactory = ({ const getTokenAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetTokenAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) throw new BadRequestError({ message: "The identity does not have Token Auth attached" @@ -224,7 +224,7 @@ export const identityTokenAuthServiceFactory = ({ actorOrgId }: TRevokeTokenAuthDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) throw new BadRequestError({ message: "The identity does not have Token Auth" @@ -269,7 +269,7 @@ export const identityTokenAuthServiceFactory = ({ name }: TCreateTokenAuthTokenDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) throw new BadRequestError({ message: "The identity does not have Token Auth" @@ -343,7 +343,7 @@ export const identityTokenAuthServiceFactory = ({ actorOrgId }: TGetTokenAuthTokensDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) throw new BadRequestError({ message: "The identity does not have Token Auth" @@ -376,9 +376,11 @@ export const identityTokenAuthServiceFactory = ({ actorOrgId }: TUpdateTokenAuthTokenDTO) => { const foundToken = await identityAccessTokenDAL.findById(tokenId); - if (!foundToken) throw new NotFoundError({ message: "Failed to find token" }); + if (!foundToken) throw new NotFoundError({ message: `Token with ID ${tokenId} not found` }); const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: foundToken.identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) { + throw new NotFoundError({ message: `Failed to find identity with ID ${foundToken.identityId}` }); + } if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) throw new BadRequestError({ message: "The identity does not have Token Auth" @@ -431,7 +433,7 @@ export const identityTokenAuthServiceFactory = ({ }); if (!identityAccessToken) throw new NotFoundError({ - message: "Failed to find token" + message: `Token with ID ${tokenId} not found or already revoked` }); const identityOrgMembership = await identityOrgMembershipDAL.findOne({ @@ -439,7 +441,7 @@ export const identityTokenAuthServiceFactory = ({ }); if (!identityOrgMembership) { - throw new NotFoundError({ message: "No identity organization membership found" }); + throw new NotFoundError({ message: `Failed to find identity with ID ${identityAccessToken.identityId}` }); } const { permission } = await permissionService.getOrgPermission( diff --git a/backend/src/services/identity-ua/identity-ua-service.ts b/backend/src/services/identity-ua/identity-ua-service.ts index 757afa4d2..aed9425d2 100644 --- a/backend/src/services/identity-ua/identity-ua-service.ts +++ b/backend/src/services/identity-ua/identity-ua-service.ts @@ -155,7 +155,7 @@ export const identityUaServiceFactory = ({ actorOrgId }: TAttachUaDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity.authMethod) throw new BadRequestError({ message: "Failed to add universal auth to already configured identity" @@ -246,7 +246,7 @@ export const identityUaServiceFactory = ({ actorOrgId }: TUpdateUaDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) throw new BadRequestError({ message: "Failed to updated universal auth" @@ -320,7 +320,7 @@ export const identityUaServiceFactory = ({ const getIdentityUniversalAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetUaDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) throw new BadRequestError({ message: "The identity does not have universal auth" @@ -347,7 +347,7 @@ export const identityUaServiceFactory = ({ actorOrgId }: TRevokeUaDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) throw new BadRequestError({ message: "The identity does not have universal auth" @@ -392,7 +392,7 @@ export const identityUaServiceFactory = ({ numUsesLimit }: TCreateUaClientSecretDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) throw new BadRequestError({ message: "The identity does not have universal auth" @@ -452,7 +452,7 @@ export const identityUaServiceFactory = ({ identityId }: TGetUaClientSecretsDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) throw new BadRequestError({ message: "The identity does not have universal auth" @@ -499,7 +499,7 @@ export const identityUaServiceFactory = ({ clientSecretId }: TGetUniversalAuthClientSecretByIdDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) throw new BadRequestError({ message: "The identity does not have universal auth" @@ -538,7 +538,7 @@ export const identityUaServiceFactory = ({ clientSecretId }: TRevokeUaClientSecretDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityMembershipOrg) throw new NotFoundError({ message: "Failed to find identity" }); + if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) throw new BadRequestError({ message: "The identity does not have universal auth" diff --git a/backend/src/services/integration-auth/integration-app-list.ts b/backend/src/services/integration-auth/integration-app-list.ts index 44ac825c7..d0324e58e 100644 --- a/backend/src/services/integration-auth/integration-app-list.ts +++ b/backend/src/services/integration-auth/integration-app-list.ts @@ -1259,6 +1259,6 @@ export const getApps = async ({ }); default: - throw new NotFoundError({ message: "integration not found" }); + throw new NotFoundError({ message: `Integration '${integration}' not found` }); } }; diff --git a/backend/src/services/integration-auth/integration-auth-service.ts b/backend/src/services/integration-auth/integration-auth-service.ts index 728e417cf..7efc485e0 100644 --- a/backend/src/services/integration-auth/integration-auth-service.ts +++ b/backend/src/services/integration-auth/integration-auth-service.ts @@ -110,7 +110,7 @@ export const integrationAuthServiceFactory = ({ const getIntegrationAuth = async ({ actor, id, actorId, actorAuthMethod, actorOrgId }: TGetIntegrationAuthDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -195,7 +195,7 @@ export const integrationAuthServiceFactory = ({ updateDoc.encryptedAccess = accessToken; } } else { - if (!botKey) throw new NotFoundError({ message: "Project bot key not found" }); + if (!botKey) throw new NotFoundError({ message: `Project bot key for project with ID '${projectId}' not found` }); if (tokenExchange.refreshToken) { const refreshEncToken = encryptSymmetric128BitHexKeyUTF8(tokenExchange.refreshToken, botKey); updateDoc.refreshIV = refreshEncToken.iv; @@ -317,7 +317,7 @@ export const integrationAuthServiceFactory = ({ } } } else { - if (!botKey) throw new NotFoundError({ message: "Project bot key not found" }); + if (!botKey) throw new NotFoundError({ message: `Project bot key for project with ID '${projectId}' not found` }); if (refreshToken) { const tokenDetails = await exchangeRefresh( integration, @@ -496,7 +496,7 @@ export const integrationAuthServiceFactory = ({ workspaceSlug }: TIntegrationAuthAppsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -530,7 +530,7 @@ export const integrationAuthServiceFactory = ({ id }: TIntegrationAuthTeamsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -560,7 +560,7 @@ export const integrationAuthServiceFactory = ({ actorOrgId }: TIntegrationAuthVercelBranchesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -601,7 +601,7 @@ export const integrationAuthServiceFactory = ({ accountId }: TIntegrationAuthChecklyGroupsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -629,7 +629,7 @@ export const integrationAuthServiceFactory = ({ const getGithubOrgs = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TIntegrationAuthGithubOrgsDTO) => { const appCfg = getConfig(); const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -703,7 +703,7 @@ export const integrationAuthServiceFactory = ({ repoName }: TIntegrationAuthGithubEnvsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -750,7 +750,7 @@ export const integrationAuthServiceFactory = ({ const getQoveryOrgs = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TIntegrationAuthQoveryOrgsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -784,7 +784,7 @@ export const integrationAuthServiceFactory = ({ region }: TIntegrationAuthAwsKmsKeyDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -842,7 +842,7 @@ export const integrationAuthServiceFactory = ({ orgId }: TIntegrationAuthQoveryProjectDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -878,7 +878,7 @@ export const integrationAuthServiceFactory = ({ actorOrgId }: TIntegrationAuthQoveryEnvironmentsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -919,7 +919,7 @@ export const integrationAuthServiceFactory = ({ environmentId }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -959,7 +959,7 @@ export const integrationAuthServiceFactory = ({ environmentId }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -999,7 +999,7 @@ export const integrationAuthServiceFactory = ({ environmentId }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID ${id} not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1038,7 +1038,7 @@ export const integrationAuthServiceFactory = ({ actorOrgId }: TIntegrationAuthHerokuPipelinesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1078,7 +1078,7 @@ export const integrationAuthServiceFactory = ({ appId }: TIntegrationAuthRailwayEnvDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1146,7 +1146,7 @@ export const integrationAuthServiceFactory = ({ appId }: TIntegrationAuthRailwayServicesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1220,7 +1220,7 @@ export const integrationAuthServiceFactory = ({ id }: TIntegrationAuthBitbucketWorkspaceDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1269,7 +1269,7 @@ export const integrationAuthServiceFactory = ({ appId }: TIntegrationAuthNorthflankSecretGroupDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1337,7 +1337,7 @@ export const integrationAuthServiceFactory = ({ actor }: TGetIntegrationAuthTeamCityBuildConfigDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1399,7 +1399,7 @@ export const integrationAuthServiceFactory = ({ actorOrgId }: TDeleteIntegrationAuthByIdDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); - if (!integrationAuth) throw new NotFoundError({ message: "Failed to find integration" }); + if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1412,7 +1412,7 @@ export const integrationAuthServiceFactory = ({ const delIntegrationAuth = await integrationAuthDAL.transaction(async (tx) => { const doc = await integrationAuthDAL.deleteById(integrationAuth.id, tx); - if (!doc) throw new NotFoundError({ message: "Faled to find integration" }); + if (!doc) throw new NotFoundError({ message: `Integration auth with ID '${integrationAuth.id}' not found` }); await integrationDAL.delete({ integrationAuthId: doc.id }, tx); return doc; }); @@ -1431,7 +1431,7 @@ export const integrationAuthServiceFactory = ({ }: TDuplicateGithubIntegrationAuthDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) { - throw new NotFoundError({ message: "Failed to find integration" }); + throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); } const { permission: sourcePermission } = await permissionService.getProjectPermission( diff --git a/backend/src/services/integration-auth/integration-delete-secret.ts b/backend/src/services/integration-auth/integration-delete-secret.ts index 7cf77cb26..8036ac7b9 100644 --- a/backend/src/services/integration-auth/integration-delete-secret.ts +++ b/backend/src/services/integration-auth/integration-delete-secret.ts @@ -314,7 +314,7 @@ export const deleteIntegrationSecrets = async ({ if (!folder) { throw new NotFoundError({ - message: "Folder not found." + message: `Folder with path '${integration.secretPath}' not found in environment with slug '${integration.environment.slug}'` }); } diff --git a/backend/src/services/integration/integration-service.ts b/backend/src/services/integration/integration-service.ts index 47a92c384..9b5ff0cf9 100644 --- a/backend/src/services/integration/integration-service.ts +++ b/backend/src/services/integration/integration-service.ts @@ -76,7 +76,8 @@ export const integrationServiceFactory = ({ targetEnvironmentId }: TCreateIntegrationDTO) => { const integrationAuth = await integrationAuthDAL.findById(integrationAuthId); - if (!integrationAuth) throw new NotFoundError({ message: "Integration auth not found" }); + if (!integrationAuth) + throw new NotFoundError({ message: `Integration auth with ID '${integrationAuthId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -93,7 +94,11 @@ export const integrationServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(integrationAuth.projectId, sourceEnvironment, secretPath); - if (!folder) throw new NotFoundError({ message: "Folder path not found" }); + if (!folder) { + throw new NotFoundError({ + message: `Folder with path '${secretPath}' not found in environment with slug'${sourceEnvironment}'` + }); + } const integration = await integrationDAL.create({ envId: folder.envId, @@ -145,7 +150,7 @@ export const integrationServiceFactory = ({ metadata }: TUpdateIntegrationDTO) => { const integration = await integrationDAL.findById(id); - if (!integration) throw new NotFoundError({ message: "Integration auth not found" }); + if (!integration) throw new NotFoundError({ message: `Integration with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -167,7 +172,11 @@ export const integrationServiceFactory = ({ } const folder = await folderDAL.findBySecretPath(integration.projectId, newEnvironment, newSecretPath); - if (!folder) throw new NotFoundError({ message: "Folder path not found" }); + if (!folder) { + throw new NotFoundError({ + message: `Folder with path '${newSecretPath}' not found in environment with slug '${newEnvironment}'` + }); + } const updatedIntegration = await integrationDAL.updateById(id, { envId: folder.envId, @@ -200,7 +209,7 @@ export const integrationServiceFactory = ({ if (!integration) { throw new NotFoundError({ - message: "Integration not found" + message: `Integration with ID '${id}' not found` }); } @@ -215,7 +224,7 @@ export const integrationServiceFactory = ({ if (!integration) { throw new NotFoundError({ - message: "Integration not found" + message: `Integration with ID '${id}' not found` }); } @@ -231,7 +240,7 @@ export const integrationServiceFactory = ({ shouldDeleteIntegrationSecrets }: TDeleteIntegrationDTO) => { const integration = await integrationDAL.findById(id); - if (!integration) throw new NotFoundError({ message: "Integration auth not found" }); + if (!integration) throw new NotFoundError({ message: `Integration with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -285,7 +294,7 @@ export const integrationServiceFactory = ({ const syncIntegration = async ({ id, actorId, actor, actorOrgId, actorAuthMethod }: TSyncIntegrationDTO) => { const integration = await integrationDAL.findById(id); if (!integration) { - throw new NotFoundError({ message: "Integration not found" }); + throw new NotFoundError({ message: `Integration with ID '${id}' not found` }); } const { permission } = await permissionService.getProjectPermission( diff --git a/backend/src/services/kms/kms-service.ts b/backend/src/services/kms/kms-service.ts index e1166d8c0..1b5c282a6 100644 --- a/backend/src/services/kms/kms-service.ts +++ b/backend/src/services/kms/kms-service.ts @@ -164,7 +164,7 @@ export const kmsServiceFactory = ({ let org = await orgDAL.findById(orgId, trx); if (!org) { - throw new NotFoundError({ message: "Org not found" }); + throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); } if (!org.kmsDefaultKeyId) { @@ -247,7 +247,7 @@ export const kmsServiceFactory = ({ const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId, tx); if (!kmsDoc) { - throw new NotFoundError({ message: "KMS ID not found" }); + throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); } if (kmsDoc.externalKms) { @@ -315,7 +315,7 @@ export const kmsServiceFactory = ({ const encryptWithKmsKey = async ({ kmsId }: Omit, tx?: Knex) => { const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId, tx); if (!kmsDoc) { - throw new NotFoundError({ message: "KMS ID not found" }); + throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); } if (kmsDoc.externalKms) { @@ -382,7 +382,7 @@ export const kmsServiceFactory = ({ let org = await orgDAL.findById(orgId, trx); if (!org) { - throw new NotFoundError({ message: "Org not found" }); + throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); } if (!org.kmsEncryptedDataKey) { @@ -460,7 +460,7 @@ export const kmsServiceFactory = ({ const getProjectSecretManagerKmsKeyId = async (projectId: string, trx?: Knex) => { let project = await projectDAL.findById(projectId, trx); if (!project) { - throw new NotFoundError({ message: "Project not found" }); + throw new NotFoundError({ message: `Project with ID '${projectId}' not found` }); } if (!project.kmsSecretManagerKeyId) { @@ -650,12 +650,12 @@ export const kmsServiceFactory = ({ const project = await projectDAL.findById(projectId); if (!project) { throw new NotFoundError({ - message: "Project not found." + message: `Project with ID '${projectId}' not found` }); } const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId); if (!kmsDoc) { - throw new NotFoundError({ message: "KMS ID not found." }); + throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); } if (kmsDoc.orgId !== project.orgId) { @@ -702,7 +702,7 @@ export const kmsServiceFactory = ({ const project = await projectDAL.findById(projectId); if (!project) { throw new NotFoundError({ - message: "Project not found" + message: `Project with ID '${projectId}' not found` }); } @@ -730,7 +730,7 @@ export const kmsServiceFactory = ({ const project = await projectDAL.findById(projectId); if (!project) { throw new NotFoundError({ - message: "Project not found" + message: `Project with ID '${projectId}' not found` }); } @@ -785,7 +785,7 @@ export const kmsServiceFactory = ({ if (!kms.id) { throw new NotFoundError({ - message: "KMS not found" + message: `KMS with ID '${kmsKeyId}' not found` }); } const { id, name, orgId, isExternal } = kms; diff --git a/backend/src/services/org-admin/org-admin-service.ts b/backend/src/services/org-admin/org-admin-service.ts index ac318e9e1..c9f792978 100644 --- a/backend/src/services/org-admin/org-admin-service.ts +++ b/backend/src/services/org-admin/org-admin-service.ts @@ -90,7 +90,7 @@ export const orgAdminServiceFactory = ({ ); const project = await projectDAL.findById(projectId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with ID '${projectId}' not found` }); if (project.version === ProjectVersion.V1) { throw new BadRequestError({ message: "Please upgrade your project on your dashboard" }); @@ -120,21 +120,21 @@ export const orgAdminServiceFactory = ({ const ghostUser = await projectDAL.findProjectGhostUser(projectId); if (!ghostUser) { throw new NotFoundError({ - message: "Failed to find project owner" + message: `Project owner of project with ID '${projectId}' not found` }); } const ghostUserLatestKey = await projectKeyDAL.findLatestProjectKey(ghostUser.id, projectId); if (!ghostUserLatestKey) { throw new NotFoundError({ - message: "Failed to find project owner's latest key" + message: `Project owner's latest key of project with ID '${projectId}' not found` }); } const bot = await projectBotDAL.findOne({ projectId }); if (!bot) { throw new NotFoundError({ - message: "Failed to find project bot" + message: `Project bot for project with ID '${projectId}' not found` }); } @@ -146,7 +146,8 @@ export const orgAdminServiceFactory = ({ }); const userEncryptionKey = await userDAL.findUserEncKeyByUserId(actorId); - if (!userEncryptionKey) throw new NotFoundError({ message: "User encryption key not found" }); + if (!userEncryptionKey) + throw new NotFoundError({ message: `User encryption key for user with ID '${actorId}' not found` }); const [newWsMember] = assignWorkspaceKeysToMembers({ decryptKey: ghostUserLatestKey, userPrivateKey: botPrivateKey, diff --git a/backend/src/services/org/org-role-fns.ts b/backend/src/services/org/org-role-fns.ts index f460e18a4..5bff1e324 100644 --- a/backend/src/services/org/org-role-fns.ts +++ b/backend/src/services/org/org-role-fns.ts @@ -5,7 +5,7 @@ import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal"; const RESERVED_ORG_ROLE_SLUGS = Object.values(OrgMembershipRole).filter((role) => role !== "custom"); -export const isCustomOrgRole = (roleSlug: string) => !RESERVED_ORG_ROLE_SLUGS.includes(roleSlug as OrgMembershipRole); +export const isCustomOrgRole = (roleSlug: string) => !RESERVED_ORG_ROLE_SLUGS.find((r) => r === roleSlug); // this is only for updating an org export const getDefaultOrgMembershipRoleForUpdateOrg = async ({ @@ -27,7 +27,12 @@ export const getDefaultOrgMembershipRoleForUpdateOrg = async ({ }); const customRole = await orgRoleDAL.findOne({ slug: membershipRoleSlug, orgId }); - if (!customRole) throw new NotFoundError({ name: "UpdateOrg", message: "Organization role not found" }); + if (!customRole) { + throw new NotFoundError({ + name: "UpdateOrg", + message: `Organization role with slug '${membershipRoleSlug}' not found` + }); + } // use ID for default role return customRole.id; diff --git a/backend/src/services/org/org-role-service.ts b/backend/src/services/org/org-role-service.ts index f11d53aa0..1243055eb 100644 --- a/backend/src/services/org/org-role-service.ts +++ b/backend/src/services/org/org-role-service.ts @@ -100,7 +100,7 @@ export const orgRoleServiceFactory = ({ } default: { const role = await orgRoleDAL.findOne({ id: roleId, orgId }); - if (!role) throw new NotFoundError({ message: "Organization role not found" }); + if (!role) throw new NotFoundError({ message: `Organization role with ID '${roleId}' not found` }); return role; } } @@ -125,7 +125,7 @@ export const orgRoleServiceFactory = ({ { id: roleId, orgId }, { ...data, permissions: data.permissions ? JSON.stringify(data.permissions) : undefined } ); - if (!updatedRole) throw new NotFoundError({ message: "Organization role not found" }); + if (!updatedRole) throw new NotFoundError({ message: `Organization role with ID '${roleId}' not found` }); return updatedRole; }; @@ -143,7 +143,7 @@ export const orgRoleServiceFactory = ({ if (!org) throw new NotFoundError({ - message: "Failed to find organization" + message: `Organization with ID '${orgId}' not found` }); if (org.defaultMembershipRole === roleId) @@ -163,7 +163,8 @@ export const orgRoleServiceFactory = ({ }); const [deletedRole] = await orgRoleDAL.delete({ id: roleId, orgId }); - if (!deletedRole) throw new NotFoundError({ message: "Organization role not found", name: "Update role" }); + if (!deletedRole) + throw new NotFoundError({ message: `Organization role with ID '${roleId}' not found`, name: "UpdateRole" }); return deletedRole; }; diff --git a/backend/src/services/org/org-service.ts b/backend/src/services/org/org-service.ts index 27e62304d..a751efe39 100644 --- a/backend/src/services/org/org-service.ts +++ b/backend/src/services/org/org-service.ts @@ -138,7 +138,7 @@ export const orgServiceFactory = ({ ) => { await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); const org = await orgDAL.findOrgById(orgId); - if (!org) throw new NotFoundError({ message: "Organization not found" }); + if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); return org; }; /* @@ -313,7 +313,7 @@ export const orgServiceFactory = ({ if (!samlCfg && !oidcCfg) throw new NotFoundError({ - message: "No enforceable SSO config found" + message: `SAML or OIDC configuration for organization with ID '${orgId}' not found` }); } @@ -335,7 +335,7 @@ export const orgServiceFactory = ({ defaultMembershipRole, enforceMfa }); - if (!org) throw new NotFoundError({ message: "Organization not found" }); + if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); return org; }; /* @@ -449,7 +449,8 @@ export const orgServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Member); const foundMembership = await orgMembershipDAL.findById(membershipId); - if (!foundMembership) throw new NotFoundError({ message: "Failed to find organization membership" }); + if (!foundMembership) + throw new NotFoundError({ message: `Organization membership with ID ${membershipId} not found` }); if (foundMembership.orgId !== orgId) throw new UnauthorizedError({ message: "Updated org member doesn't belong to the organization" }); if (foundMembership.userId === userId) @@ -645,8 +646,12 @@ export const orgServiceFactory = ({ const orgRole = isCustomOrgRole ? OrgMembershipRole.Custom : organizationRoleSlug; if (isCustomOrgRole) { const customRole = await orgRoleDAL.findOne({ slug: organizationRoleSlug, orgId }); - if (!customRole) - throw new NotFoundError({ name: "InviteUser", message: "Custom organization role not found" }); + if (!customRole) { + throw new NotFoundError({ + name: "InviteUser", + message: `Custom organization role with slug '${orgRole}' not found` + }); + } roleId = customRole.id; } @@ -804,7 +809,7 @@ export const orgServiceFactory = ({ if (!bot) { throw new NotFoundError({ name: "InviteUser", - message: "Failed to find project bot" + message: `Failed to find project bot for project with ID '${projectId}'` }); } @@ -812,7 +817,7 @@ export const orgServiceFactory = ({ if (!ghostUserLatestKey) { throw new NotFoundError({ name: "InviteUser", - message: "Failed to find project owner's latest key" + message: `Failed to find project owner's latest key for project with ID '${projectId}'` }); } @@ -1001,7 +1006,7 @@ export const orgServiceFactory = ({ const membership = await orgMembershipDAL.findOrgMembershipById(membershipId); if (!membership) { - throw new NotFoundError({ message: "Organization membership not found" }); + throw new NotFoundError({ message: `Organization membership with ID '${membershipId}' not found` }); } if (membership.orgId !== orgId) { throw new ForbiddenRequestError({ message: "Membership does not belong to organization" }); @@ -1047,7 +1052,7 @@ export const orgServiceFactory = ({ const membership = await orgMembershipDAL.findOrgMembershipById(orgMembershipId); if (!membership) { - throw new NotFoundError({ message: "Organization membership not found" }); + throw new NotFoundError({ message: `Organization membership with ID '${orgMembershipId}' not found` }); } if (membership.orgId !== orgId) throw new NotFoundError({ message: "Failed to find organization membership" }); diff --git a/backend/src/services/pki-alert/pki-alert-service.ts b/backend/src/services/pki-alert/pki-alert-service.ts index 07af806b3..1e7d26825 100644 --- a/backend/src/services/pki-alert/pki-alert-service.ts +++ b/backend/src/services/pki-alert/pki-alert-service.ts @@ -84,7 +84,7 @@ export const pkiAlertServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.PkiAlerts); const pkiCollection = await pkiCollectionDAL.findById(pkiCollectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${pkiCollectionId}' not found` }); if (pkiCollection.projectId !== projectId) throw new ForbiddenRequestError({ message: "PKI collection does not belong to the specified project." }); @@ -100,7 +100,7 @@ export const pkiAlertServiceFactory = ({ const getPkiAlertById = async ({ alertId, actorId, actorAuthMethod, actor, actorOrgId }: TGetAlertByIdDTO) => { const alert = await pkiAlertDAL.findById(alertId); - if (!alert) throw new NotFoundError({ message: "Alert not found" }); + if (!alert) throw new NotFoundError({ message: `Alert with ID '${alertId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -126,7 +126,7 @@ export const pkiAlertServiceFactory = ({ actorOrgId }: TUpdateAlertDTO) => { let alert = await pkiAlertDAL.findById(alertId); - if (!alert) throw new NotFoundError({ message: "Alert not found" }); + if (!alert) throw new NotFoundError({ message: `Alert with ID '${alertId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -140,7 +140,7 @@ export const pkiAlertServiceFactory = ({ if (pkiCollectionId) { const pkiCollection = await pkiCollectionDAL.findById(pkiCollectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${pkiCollectionId}' not found` }); if (pkiCollection.projectId !== alert.projectId) { throw new ForbiddenRequestError({ message: "PKI collection does not belong to the specified project." }); } @@ -158,7 +158,7 @@ export const pkiAlertServiceFactory = ({ const deletePkiAlert = async ({ alertId, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteAlertDTO) => { let alert = await pkiAlertDAL.findById(alertId); - if (!alert) throw new NotFoundError({ message: "Alert not found" }); + if (!alert) throw new NotFoundError({ message: `Alert with ID '${alertId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, diff --git a/backend/src/services/pki-collection/pki-collection-service.ts b/backend/src/services/pki-collection/pki-collection-service.ts index f2a3fa0c4..ef849c54f 100644 --- a/backend/src/services/pki-collection/pki-collection-service.ts +++ b/backend/src/services/pki-collection/pki-collection-service.ts @@ -80,7 +80,7 @@ export const pkiCollectionServiceFactory = ({ actorOrgId }: TGetPkiCollectionByIdDTO) => { const pkiCollection = await pkiCollectionDAL.findById(collectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -104,7 +104,7 @@ export const pkiCollectionServiceFactory = ({ actorOrgId }: TUpdatePkiCollectionDTO) => { let pkiCollection = await pkiCollectionDAL.findById(collectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -131,7 +131,7 @@ export const pkiCollectionServiceFactory = ({ actorOrgId }: TDeletePkiCollectionDTO) => { let pkiCollection = await pkiCollectionDAL.findById(collectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -160,7 +160,7 @@ export const pkiCollectionServiceFactory = ({ actorOrgId }: TGetPkiCollectionItems) => { const pkiCollection = await pkiCollectionDAL.findById(collectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -203,7 +203,7 @@ export const pkiCollectionServiceFactory = ({ itemId }: TAddItemToPkiCollectionDTO) => { const pkiCollection = await pkiCollectionDAL.findById(collectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -235,7 +235,7 @@ export const pkiCollectionServiceFactory = ({ projectId: pkiCollection.projectId }); - if (!ca) throw new NotFoundError({ message: "CA not found" }); + if (!ca) throw new NotFoundError({ message: `CA with ID '${itemId}' not found` }); pkiCollectionItem = await pkiCollectionItemDAL.create({ pkiCollectionId: collectionId, @@ -261,7 +261,7 @@ export const pkiCollectionServiceFactory = ({ }, id: itemId }); - if (!certificate) throw new NotFoundError({ message: "Certificate not found" }); + if (!certificate) throw new NotFoundError({ message: `Certificate with ID '${itemId}' not found` }); pkiCollectionItem = await pkiCollectionItemDAL.create({ pkiCollectionId: collectionId, @@ -289,14 +289,14 @@ export const pkiCollectionServiceFactory = ({ itemId }: TRemoveItemFromPkiCollectionDTO) => { const pkiCollection = await pkiCollectionDAL.findById(collectionId); - if (!pkiCollection) throw new NotFoundError({ message: "PKI collection not found" }); + if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); let pkiCollectionItem = await pkiCollectionItemDAL.findOne({ pkiCollectionId: collectionId, id: itemId }); - if (!pkiCollectionItem) throw new NotFoundError({ message: "PKI collection item not found" }); + if (!pkiCollectionItem) throw new NotFoundError({ message: `PKI collection item with ID '${itemId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, diff --git a/backend/src/services/project-bot/project-bot-fns.ts b/backend/src/services/project-bot/project-bot-fns.ts index 315ef2e0d..a8e507bc7 100644 --- a/backend/src/services/project-bot/project-bot-fns.ts +++ b/backend/src/services/project-bot/project-bot-fns.ts @@ -28,7 +28,7 @@ export const getBotKeyFnFactory = ( const project = await projectDAL.findById(projectId); if (!project) throw new NotFoundError({ - message: "Project not found during bot lookup. Are you sure you are using the correct project ID?" + message: `Project with ID '${projectId}' not found during bot lookup. Are you sure you are using the correct project ID?` }); if (project.version === 3 && !shouldGetBotKey) { @@ -39,8 +39,11 @@ export const getBotKeyFnFactory = ( if (!bot || !bot.isActive || !bot.encryptedProjectKey || !bot.encryptedProjectKeyNonce) { // trying to set bot automatically const projectV1Keys = await projectBotDAL.findProjectUserWorkspaceKey(projectId); - if (!projectV1Keys) throw new NotFoundError({ message: "Bot not found. Please ask admin user to login" }); - + if (!projectV1Keys) { + throw new NotFoundError({ + message: `Project bot not found for project with ID '${projectId}'. Please ask an administrator to log-in to the Infisical Console.` + }); + } let userPrivateKey = ""; if ( projectV1Keys?.serverEncryptedPrivateKey && diff --git a/backend/src/services/project-bot/project-bot-service.ts b/backend/src/services/project-bot/project-bot-service.ts index 6a6178c9f..5d7f78c1b 100644 --- a/backend/src/services/project-bot/project-bot-service.ts +++ b/backend/src/services/project-bot/project-bot-service.ts @@ -91,7 +91,7 @@ export const projectBotServiceFactory = ({ const bot = await projectBotDAL.findProjectByBotId(botId); return bot; } catch (e) { - throw new NotFoundError({ message: "Failed to find bot by ID" }); + throw new NotFoundError({ message: `Project bot with ID '${botId}' not found` }); } }; @@ -105,7 +105,7 @@ export const projectBotServiceFactory = ({ isActive }: TSetActiveStateDTO) => { const bot = await projectBotDAL.findById(botId); - if (!bot) throw new NotFoundError({ message: "Bot not found" }); + if (!bot) throw new NotFoundError({ message: `Project bot with ID '${botId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -119,7 +119,7 @@ export const projectBotServiceFactory = ({ const project = await projectBotDAL.findProjectByBotId(botId); if (!project) { - throw new NotFoundError({ message: "Failed to find project by bot ID" }); + throw new NotFoundError({ message: `Project not found for bot with ID '${botId}'` }); } if (project.version === ProjectVersion.V2) { @@ -128,7 +128,9 @@ export const projectBotServiceFactory = ({ if (isActive) { if (!botKey?.nonce || !botKey?.encryptedKey) { - throw new NotFoundError({ message: "Bot key not found, failed to set bot active" }); + throw new NotFoundError({ + message: `Bot key not found for bot in project with ID '${botId}'. Failed to set bot state to active.` + }); } const doc = await projectBotDAL.updateById(botId, { isActive: true, @@ -136,7 +138,8 @@ export const projectBotServiceFactory = ({ encryptedProjectKeyNonce: botKey.nonce, senderId: actorId }); - if (!doc) throw new BadRequestError({ message: "Failed to update bot active state" }); + if (!doc) + throw new BadRequestError({ message: `Project bot with ID '${botId}' not found. Failed to update bot.` }); return doc; } @@ -145,7 +148,7 @@ export const projectBotServiceFactory = ({ encryptedProjectKey: null, encryptedProjectKeyNonce: null }); - if (!doc) throw new BadRequestError({ message: "Failed to update bot active state" }); + if (!doc) throw new BadRequestError({ message: `Project bot with ID '${botId}' not found. Failed to update bot.` }); return doc; }; diff --git a/backend/src/services/project-env/project-env-service.ts b/backend/src/services/project-env/project-env-service.ts index 67bdd867a..a54e8de43 100644 --- a/backend/src/services/project-env/project-env-service.ts +++ b/backend/src/services/project-env/project-env-service.ts @@ -153,8 +153,11 @@ export const projectEnvServiceFactory = ({ } const oldEnv = await projectEnvDAL.findOne({ id, projectId }); - if (!oldEnv) throw new NotFoundError({ message: "Environment not found", name: "UpdateEnvironment" }); - + if (!oldEnv) { + throw new NotFoundError({ + message: `Environment with id '${id}' in project with ID '${projectId}' not found` + }); + } if (slug) { const existingEnv = await projectEnvDAL.findOne({ slug, projectId }); if (existingEnv && existingEnv.id !== id) { @@ -216,7 +219,7 @@ export const projectEnvServiceFactory = ({ const [doc] = await projectEnvDAL.delete({ id, projectId }, tx); if (!doc) throw new NotFoundError({ - message: "Environment doesn't exist", + message: `Environment with id '${id}' in project with ID '${projectId}' not found`, name: "DeleteEnvironment" }); @@ -240,7 +243,7 @@ export const projectEnvServiceFactory = ({ if (!environment) { throw new NotFoundError({ - message: "Environment does not exist" + message: `Environment with ID '${id}' not found` }); } diff --git a/backend/src/services/project-membership/project-membership-service.ts b/backend/src/services/project-membership/project-membership-service.ts index dc063d76d..71b01d615 100644 --- a/backend/src/services/project-membership/project-membership-service.ts +++ b/backend/src/services/project-membership/project-membership-service.ts @@ -129,7 +129,7 @@ export const projectMembershipServiceFactory = ({ ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); const [membership] = await projectMembershipDAL.findAllProjectMembers(projectId, { username }); - if (!membership) throw new NotFoundError({ message: `Project membership not found for user ${username}` }); + if (!membership) throw new NotFoundError({ message: `Project membership not found for user '${username}'` }); return membership; }; @@ -143,7 +143,7 @@ export const projectMembershipServiceFactory = ({ sendEmails = true }: TAddUsersToWorkspaceDTO) => { const project = await projectDAL.findById(projectId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with ID '${projectId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -259,7 +259,7 @@ export const projectMembershipServiceFactory = ({ }) : []; if (customRoles.length !== customInputRoles.length) { - throw new NotFoundError({ message: "Custom project roles not found" }); + throw new NotFoundError({ message: "One or more custom roles not found" }); } const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug); @@ -352,7 +352,7 @@ export const projectMembershipServiceFactory = ({ if (!project) { throw new NotFoundError({ - message: "Project not found" + message: `Project with ID '${projectId}' not found` }); } @@ -426,7 +426,7 @@ export const projectMembershipServiceFactory = ({ } const project = await projectDAL.findById(projectId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with ID '${projectId}' not found` }); if (project.version === ProjectVersion.V1) { throw new BadRequestError({ @@ -437,7 +437,7 @@ export const projectMembershipServiceFactory = ({ const projectMembers = await projectMembershipDAL.findAllProjectMembers(projectId); if (!projectMembers?.length) { - throw new NotFoundError({ message: "Failed to find project members" }); + throw new NotFoundError({ message: `Project members not found for project with ID '${projectId}'` }); } if (projectMembers.length < 2) { diff --git a/backend/src/services/project-role/project-role-service.ts b/backend/src/services/project-role/project-role-service.ts index 49c4f81c9..1fda78e32 100644 --- a/backend/src/services/project-role/project-role-service.ts +++ b/backend/src/services/project-role/project-role-service.ts @@ -43,7 +43,7 @@ export const projectRoleServiceFactory = ({ }: TProjectRoleServiceFactoryDep) => { const createRole = async ({ projectSlug, data, actor, actorId, actorAuthMethod, actorOrgId }: TCreateRoleDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -75,7 +75,7 @@ export const projectRoleServiceFactory = ({ roleSlug }: TGetRoleBySlugDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -92,7 +92,7 @@ export const projectRoleServiceFactory = ({ } const customRole = await projectRoleDAL.findOne({ slug: roleSlug, projectId }); - if (!customRole) throw new NotFoundError({ message: "Project role not found" }); + if (!customRole) throw new NotFoundError({ message: `Project role with slug '${roleSlug}' not found` }); return { ...customRole, permissions: unpackPermissions(customRole.permissions) }; }; @@ -106,7 +106,7 @@ export const projectRoleServiceFactory = ({ data }: TUpdateRoleDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -131,13 +131,17 @@ export const projectRoleServiceFactory = ({ permissions: data.permissions ? data.permissions : undefined } ); - if (!updatedRole) throw new NotFoundError({ message: "Project role not found", name: "Update role" }); + if (!updatedRole) { + throw new NotFoundError({ + message: `Project role with ID '${roleId}' in project with ID '${projectId}' not found` + }); + } return { ...updatedRole, permissions: unpackPermissions(updatedRole.permissions) }; }; const deleteRole = async ({ actor, actorId, actorAuthMethod, actorOrgId, projectSlug, roleId }: TDeleteRoleDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; const { permission } = await permissionService.getProjectPermission( @@ -166,7 +170,12 @@ export const projectRoleServiceFactory = ({ } const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId }); - if (!deletedRole) throw new NotFoundError({ message: "Project role not found", name: "Delete role" }); + if (!deletedRole) { + throw new NotFoundError({ + message: `Project role with ID '${roleId}' in project with ID '${projectId}' not found`, + name: "DeleteRole" + }); + } return { ...deletedRole, permissions: unpackPermissions(deletedRole.permissions) }; }; diff --git a/backend/src/services/project/project-dal.ts b/backend/src/services/project/project-dal.ts index 69cd8933f..4e7425326 100644 --- a/backend/src/services/project/project-dal.ts +++ b/backend/src/services/project/project-dal.ts @@ -186,7 +186,7 @@ export const projectDALFactory = (db: TDbClient) => { })?.[0]; if (!project) { - throw new NotFoundError({ message: "Project not found" }); + throw new NotFoundError({ message: `Project with ID '${id}' not found` }); } return project; @@ -235,7 +235,7 @@ export const projectDALFactory = (db: TDbClient) => { })?.[0]; if (!project) { - throw new NotFoundError({ message: "Project not found" }); + throw new NotFoundError({ message: `Project with slug '${slug}' not found` }); } return project; @@ -295,7 +295,7 @@ export const projectDALFactory = (db: TDbClient) => { .first(); if (!project) { - throw new NotFoundError({ message: "Project not found" }); + throw new NotFoundError({ message: `Project with ID '${projectId}' not found` }); } return { diff --git a/backend/src/services/project/project-fns.ts b/backend/src/services/project/project-fns.ts index 217f289dd..92d0dfc39 100644 --- a/backend/src/services/project/project-fns.ts +++ b/backend/src/services/project/project-fns.ts @@ -75,7 +75,7 @@ export const getProjectKmsCertificateKeyId = async ({ const keyId = await projectDAL.transaction(async (tx) => { const project = await projectDAL.findOne({ id: projectId }, tx); if (!project) { - throw new NotFoundError({ message: "Project not found" }); + throw new NotFoundError({ message: `Project with ID '${projectId}' not found` }); } if (!project.kmsCertificateKeyId) { diff --git a/backend/src/services/project/project-service.ts b/backend/src/services/project/project-service.ts index d99212744..49198fcb1 100644 --- a/backend/src/services/project/project-service.ts +++ b/backend/src/services/project/project-service.ts @@ -327,7 +327,7 @@ export const projectServiceFactory = ({ // If identity org membership not found, throw error if (!identityOrgMembership) { throw new NotFoundError({ - message: `Failed to find identity with id ${actorId}` + message: `Failed to find identity with id '${actorId}'` }); } @@ -496,7 +496,7 @@ export const projectServiceFactory = ({ const project = await projectDAL.findProjectBySlug(workspaceSlug, actorOrgId); if (!project) { throw new NotFoundError({ - message: "Project not found" + message: `Project with slug '${workspaceSlug}' not found` }); } @@ -527,7 +527,7 @@ export const projectServiceFactory = ({ const project = await projectDAL.findProjectBySlug(workspaceSlug, actorOrgId); if (!project) { throw new NotFoundError({ - message: "Project not found." + message: `Project with slug '${workspaceSlug}' not found` }); } @@ -634,7 +634,7 @@ export const projectServiceFactory = ({ if (!project) { throw new NotFoundError({ - message: `Project with id ${projectId} not found` + message: `Project with ID '${projectId}' not found` }); } @@ -933,7 +933,7 @@ export const projectServiceFactory = ({ const project = await projectDAL.findById(projectId); if (!project) { throw new NotFoundError({ - message: "Project not found" + message: `Project with ID '${projectId}' not found` }); } @@ -967,14 +967,21 @@ export const projectServiceFactory = ({ const project = await projectDAL.findById(projectId); if (!project) { throw new NotFoundError({ - message: "Project not found" + message: `Project with ID '${projectId}' not found` }); } const slackIntegration = await slackIntegrationDAL.findByIdWithWorkflowIntegrationDetails(slackIntegrationId); + if (!slackIntegration) { throw new NotFoundError({ - message: "Slack integration not found" + message: `Slack integration with ID '${slackIntegrationId}' not found` + }); + } + + if (slackIntegration.orgId !== actorOrgId) { + throw new ForbiddenRequestError({ + message: "Selected slack integration is not in the same organization" }); } diff --git a/backend/src/services/secret-blind-index/secret-blind-index-service.ts b/backend/src/services/secret-blind-index/secret-blind-index-service.ts index 6f603a693..57746307a 100644 --- a/backend/src/services/secret-blind-index/secret-blind-index-service.ts +++ b/backend/src/services/secret-blind-index/secret-blind-index-service.ts @@ -79,13 +79,15 @@ export const secretBlindIndexServiceFactory = ({ } const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId }); - if (!blindIndexCfg) throw new NotFoundError({ message: "Blind index not found", name: "CreateSecret" }); + if (!blindIndexCfg) + throw new NotFoundError({ message: `Blind index for project with ID '${projectId}' not found` }); const secrets = await secretBlindIndexDAL.findSecretsByProjectId( projectId, secretsToUpdate.map(({ secretId }) => secretId) ); - if (secrets.length !== secretsToUpdate.length) throw new NotFoundError({ message: "Secret not found" }); + if (secrets.length !== secretsToUpdate.length) + throw new NotFoundError({ message: "One or more secrets to update not found" }); const operations = await Promise.all( secretsToUpdate.map(async ({ secretName, secretId: id }) => { diff --git a/backend/src/services/secret-folder/secret-folder-service.ts b/backend/src/services/secret-folder/secret-folder-service.ts index b16d90b6b..8eeef1a22 100644 --- a/backend/src/services/secret-folder/secret-folder-service.ts +++ b/backend/src/services/secret-folder/secret-folder-service.ts @@ -76,7 +76,11 @@ export const secretFolderServiceFactory = ({ } const env = await projectEnvDAL.findOne({ projectId, slug: environment }); - if (!env) throw new NotFoundError({ message: "Environment not found", name: "Create folder" }); + if (!env) { + throw new NotFoundError({ + message: `Environment with slug '${environment}' in project with ID '${projectId}' not found` + }); + } const folder = await folderDAL.transaction(async (tx) => { // the logic is simple we need to avoid creating same folder in same path multiple times @@ -86,7 +90,11 @@ export const secretFolderServiceFactory = ({ const pathWithFolder = path.join(secretPath, name); const parentFolder = await folderDAL.findClosestFolder(projectId, environment, pathWithFolder, tx); // no folder found is not possible root should be their - if (!parentFolder) throw new NotFoundError({ message: "Secret path not found" }); + if (!parentFolder) { + throw new NotFoundError({ + message: `Folder with path '${pathWithFolder}' in environment with slug '${environment}' not found` + }); + } // exact folder if (parentFolder.path === pathWithFolder) return parentFolder; @@ -149,7 +157,7 @@ export const secretFolderServiceFactory = ({ }: TUpdateManyFoldersDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); if (!project) { - throw new NotFoundError({ message: "Project not found" }); + throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); } const { permission } = await permissionService.getProjectPermission( @@ -184,12 +192,18 @@ export const secretFolderServiceFactory = ({ const parentFolder = await folderDAL.findBySecretPath(project.id, environment, secretPath); if (!parentFolder) { - throw new NotFoundError({ message: "Secret path not found", name: "Batch update folder" }); + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found`, + name: "UpdateManyFolders" + }); } const env = await projectEnvDAL.findOne({ projectId: project.id, slug: environment }); if (!env) { - throw new NotFoundError({ message: "Environment not found", name: "Batch update folder" }); + throw new NotFoundError({ + message: `Environment with slug '${environment}' in project with ID '${project.id}' not found`, + name: "UpdateManyFolders" + }); } const folder = await folderDAL .findOne({ envId: env.id, id, parentId: parentFolder.id }) @@ -198,7 +212,10 @@ export const secretFolderServiceFactory = ({ .catch(() => folderDAL.findOne({ envId: env.id, name: id, parentId: parentFolder.id })); if (!folder) { - throw new NotFoundError({ message: "Folder not found" }); + throw new NotFoundError({ + message: `Folder with id '${id}' in environment with slug '${env.slug}' not found`, + name: "UpdateManyFolders" + }); } if (name !== folder.name) { // ensure that new folder name is unique @@ -231,7 +248,10 @@ export const secretFolderServiceFactory = ({ tx ); if (!doc) { - throw new NotFoundError({ message: "Folder not found", name: "Batch update folder" }); + throw new NotFoundError({ + message: `Failed to update folder with id '${id}', not found`, + name: "UpdateManyFolders" + }); } return { oldFolder: folder, newFolder: doc }; @@ -283,17 +303,23 @@ export const secretFolderServiceFactory = ({ } const parentFolder = await folderDAL.findBySecretPath(projectId, environment, secretPath); - if (!parentFolder) throw new NotFoundError({ message: "Secret path not found" }); + if (!parentFolder) + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found`, + name: "UpdateFolder" + }); const env = await projectEnvDAL.findOne({ projectId, slug: environment }); - if (!env) throw new NotFoundError({ message: "Environment not found", name: "Update folder" }); + if (!env) { + throw new NotFoundError({ message: `Environment with slug '${environment}' not found`, name: "UpdateFolder" }); + } const folder = await folderDAL .findOne({ envId: env.id, id, parentId: parentFolder.id, isReserved: false }) // now folder api accepts id based change // this is for cli backward compatiability and when cli removes this, we will remove this logic .catch(() => folderDAL.findOne({ envId: env.id, name: id, parentId: parentFolder.id })); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) throw new NotFoundError({ message: `Folder with ID '${id}' not found`, name: "UpdateFolder" }); if (name !== folder.name) { // ensure that new folder name is unique const folderToCheck = await folderDAL.findOne({ @@ -305,7 +331,7 @@ export const secretFolderServiceFactory = ({ if (folderToCheck) { throw new BadRequestError({ message: "Folder with specified name already exists", - name: "Update folder" + name: "UpdateFolder" }); } } @@ -325,7 +351,7 @@ export const secretFolderServiceFactory = ({ }, tx ); - if (!doc) throw new NotFoundError({ message: "Folder not found", name: "Update folder" }); + if (!doc) throw new NotFoundError({ message: `Failed to update folder with ID '${id}'`, name: "UpdateFolder" }); return doc; }); @@ -367,11 +393,14 @@ export const secretFolderServiceFactory = ({ } const env = await projectEnvDAL.findOne({ projectId, slug: environment }); - if (!env) throw new NotFoundError({ message: "Environment not found", name: "Create folder" }); + if (!env) throw new NotFoundError({ message: `Environment with slug '${environment}' not found` }); const folder = await folderDAL.transaction(async (tx) => { const parentFolder = await folderDAL.findBySecretPath(projectId, environment, secretPath, tx); - if (!parentFolder) throw new NotFoundError({ message: "Secret path not found" }); + if (!parentFolder) + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); const [doc] = await folderDAL.delete( { @@ -382,7 +411,7 @@ export const secretFolderServiceFactory = ({ }, tx ); - if (!doc) throw new NotFoundError({ message: "Folder not found", name: "Delete folder" }); + if (!doc) throw new NotFoundError({ message: `Failed to delete folder with ID '${idOrName}', not found` }); return doc; }); @@ -409,7 +438,7 @@ export const secretFolderServiceFactory = ({ await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId); const env = await projectEnvDAL.findOne({ projectId, slug: environment }); - if (!env) throw new NotFoundError({ message: "Environment not found", name: "get folders" }); + if (!env) throw new NotFoundError({ message: `Environment with slug '${environment}' not found` }); const parentFolder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!parentFolder) return []; @@ -448,7 +477,10 @@ export const secretFolderServiceFactory = ({ const envs = await projectEnvDAL.findBySlugs(projectId, environments); if (!envs.length) - throw new NotFoundError({ message: "Environment(s) not found", name: "get project folder count" }); + throw new NotFoundError({ + message: `Environments '${environments.join(", ")}' not found`, + name: "GetFoldersMultiEnv" + }); const parentFolders = await folderDAL.findBySecretPathMultiEnv(projectId, environments, secretPath); if (!parentFolders.length) return []; @@ -479,8 +511,7 @@ export const secretFolderServiceFactory = ({ const envs = await projectEnvDAL.findBySlugs(projectId, environments); - if (!envs.length) - throw new NotFoundError({ message: "Environment(s) not found", name: "get project folder count" }); + if (!envs.length) throw new NotFoundError({ message: `Environments '${environments.join(", ")}' not found` }); const parentFolders = await folderDAL.findBySecretPathMultiEnv(projectId, environments, secretPath); if (!parentFolders.length) return 0; @@ -502,7 +533,7 @@ export const secretFolderServiceFactory = ({ const getFolderById = async ({ actor, actorId, actorOrgId, actorAuthMethod, id }: TGetFolderByIdDTO) => { const folder = await folderDAL.findById(id); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) throw new NotFoundError({ message: `Folder with ID '${id}' not found` }); // folder list is allowed to be read by anyone // permission to check does user has access await permissionService.getProjectPermission(actor, actorId, folder.projectId, actorAuthMethod, actorOrgId); @@ -510,7 +541,9 @@ export const secretFolderServiceFactory = ({ const [folderWithPath] = await folderDAL.findSecretPathByFolderIds(folder.projectId, [folder.id]); if (!folderWithPath) { - throw new NotFoundError({ message: "Folder path not found" }); + throw new NotFoundError({ + message: `Folder with ID '${folder.id}' in project with ID '${folder.projectId}' not found` + }); } return { diff --git a/backend/src/services/secret-import/secret-import-service.ts b/backend/src/services/secret-import/secret-import-service.ts index 5551b0180..fad32a67a 100644 --- a/backend/src/services/secret-import/secret-import-service.ts +++ b/backend/src/services/secret-import/secret-import-service.ts @@ -107,10 +107,17 @@ export const secretImportServiceFactory = ({ await projectDAL.checkProjectUpgradeStatus(projectId); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); - if (!folder) throw new NotFoundError({ message: "Folder not found", name: "Create import" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); const [importEnv] = await projectEnvDAL.findBySlugs(projectId, [data.environment]); - if (!importEnv) throw new NotFoundError({ error: "Imported env not found", name: "Create import" }); + if (!importEnv) { + throw new NotFoundError({ + error: `Imported environment with slug '${data.environment}' in project with ID '${projectId}' not found` + }); + } const sourceFolder = await folderDAL.findBySecretPath(projectId, data.environment, data.path); if (sourceFolder) { @@ -119,7 +126,7 @@ export const secretImportServiceFactory = ({ importEnv: folder.environment.id, importPath: secretPath }); - if (existingImport) throw new NotFoundError({ message: "Cyclic import not allowed" }); + if (existingImport) throw new BadRequestError({ message: `Cyclic import not allowed` }); } const secImport = await secretImportDAL.transaction(async (tx) => { @@ -195,7 +202,11 @@ export const secretImportServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); - if (!folder) throw new NotFoundError({ message: "Folder not found", name: "Update import" }); + if (!folder) { + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); + } const secImpDoc = await secretImportDAL.findOne({ folderId: folder.id, id }); if (!secImpDoc) throw ERR_SEC_IMP_NOT_FOUND; @@ -203,7 +214,11 @@ export const secretImportServiceFactory = ({ const importedEnv = data.environment // this is get env information of new one or old one ? (await projectEnvDAL.findBySlugs(projectId, [data.environment]))?.[0] : await projectEnvDAL.findById(secImpDoc.importEnv); - if (!importedEnv) throw new NotFoundError({ error: "Imported env not found", name: "Create import" }); + if (!importedEnv) { + throw new NotFoundError({ + error: `Imported environment with slug '${data.environment}' in project with ID '${projectId}' not found` + }); + } const sourceFolder = await folderDAL.findBySecretPath( projectId, @@ -216,7 +231,7 @@ export const secretImportServiceFactory = ({ importEnv: folder.environment.id, importPath: secretPath }); - if (existingImport) throw new NotFoundError({ message: "Cyclic import not allowed" }); + if (existingImport) throw new BadRequestError({ message: "Cyclic import not allowed" }); } const updatedSecImport = await secretImportDAL.transaction(async (tx) => { @@ -281,11 +296,14 @@ export const secretImportServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); - if (!folder) throw new NotFoundError({ message: "Folder not found", name: "Delete import" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); const secImport = await secretImportDAL.transaction(async (tx) => { const [doc] = await secretImportDAL.delete({ folderId: folder.id, id }, tx); - if (!doc) throw new NotFoundError({ message: "Secret import not found" }); + if (!doc) throw new NotFoundError({ message: `Secret import with folder ID '${id}' not found` }); if (doc.isReplication) { const replicationFolderPath = path.join(secretPath, getReplicationFolderName(doc.id)); const replicatedFolder = await folderDAL.findBySecretPath(projectId, environment, replicationFolderPath, tx); @@ -307,7 +325,11 @@ export const secretImportServiceFactory = ({ } const importEnv = await projectEnvDAL.findById(doc.importEnv); - if (!importEnv) throw new NotFoundError({ error: "Imported env not found" }); + if (!importEnv) { + throw new NotFoundError({ + error: `Imported environment with ID '${doc.importEnv}' in project with ID '${projectId}' not found` + }); + } return { ...doc, importEnv }; }); @@ -354,13 +376,18 @@ export const secretImportServiceFactory = ({ } const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) { + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); + } const [secretImportDoc] = await secretImportDAL.find({ folderId: folder.id, [`${TableName.SecretImport}.id` as "id"]: secretImportDocId }); - if (!secretImportDoc) throw new NotFoundError({ message: "Failed to find secret import" }); + if (!secretImportDoc) + throw new NotFoundError({ message: `Secret import with ID '${secretImportDocId}' not found` }); if (!secretImportDoc.isReplication) throw new BadRequestError({ message: "Import is not in replication mode" }); @@ -418,7 +445,10 @@ export const secretImportServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); - if (!folder) throw new NotFoundError({ message: "Folder not found", name: "Get imports" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); const count = await secretImportDAL.getProjectImportCount({ folderId: folder.id, search }); @@ -450,7 +480,10 @@ export const secretImportServiceFactory = ({ ); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); - if (!folder) throw new NotFoundError({ message: "Folder not found" }); + if (!folder) + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); const secImports = await secretImportDAL.find({ folderId: folder.id, search, limit, offset }); return secImports; @@ -466,18 +499,22 @@ export const secretImportServiceFactory = ({ const importDoc = await secretImportDAL.findById(importId); if (!importDoc) { - throw new NotFoundError({ message: "Secret import not found" }); + throw new NotFoundError({ message: `Secret import with ID '${importId}' not found` }); } // the folder to import into const folder = await folderDAL.findById(importDoc.folderId); - if (!folder) throw new NotFoundError({ message: "Secret import folder not found" }); + if (!folder) throw new NotFoundError({ message: `Secret import folder with ID '${importDoc.folderId}' not found` }); // the folder to import into, with path const [folderWithPath] = await folderDAL.findSecretPathByFolderIds(folder.projectId, [folder.id]); - if (!folderWithPath) throw new NotFoundError({ message: "Folder path not found" }); + if (!folderWithPath) { + throw new NotFoundError({ + message: `Folder with ID '${folder.id}' in project with ID ${folder.projectId} not found` + }); + } const { permission } = await permissionService.getProjectPermission( actor, @@ -500,7 +537,11 @@ export const secretImportServiceFactory = ({ slug: folder.environment.envSlug }); - if (!importIntoEnv) throw new NotFoundError({ message: "Environment to import into not found" }); + if (!importIntoEnv) { + throw new NotFoundError({ + message: `Environment with slug '${folder.environment.envSlug}' in project with ID ${folder.projectId} not found` + }); + } return { ...importDoc, @@ -606,7 +647,7 @@ export const secretImportServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot not found for project with ID '${projectId}'. Please upgrade your project.`, name: "bot_not_found_error" }); diff --git a/backend/src/services/secret-sharing/secret-sharing-service.ts b/backend/src/services/secret-sharing/secret-sharing-service.ts index 0f7ee20b4..6e03bba22 100644 --- a/backend/src/services/secret-sharing/secret-sharing-service.ts +++ b/backend/src/services/secret-sharing/secret-sharing-service.ts @@ -199,7 +199,7 @@ export const secretSharingServiceFactory = ({ if (!sharedSecret) throw new NotFoundError({ - message: "Shared secret not found" + message: `Shared secret with ID '${sharedSecretId}' not found` }); const { accessType, expiresAt, expiresAfterViews } = sharedSecret; diff --git a/backend/src/services/secret-tag/secret-tag-service.ts b/backend/src/services/secret-tag/secret-tag-service.ts index c4427e75f..6cae3997a 100644 --- a/backend/src/services/secret-tag/secret-tag-service.ts +++ b/backend/src/services/secret-tag/secret-tag-service.ts @@ -47,7 +47,7 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe const updateTag = async ({ actorId, actor, actorOrgId, actorAuthMethod, id, color, slug }: TUpdateTagDTO) => { const tag = await secretTagDAL.findById(id); - if (!tag) throw new NotFoundError({ message: "Tag not found" }); + if (!tag) throw new NotFoundError({ message: `Tag with ID '${id}' not found` }); if (slug) { const existingTag = await secretTagDAL.findOne({ slug, projectId: tag.projectId }); @@ -69,7 +69,7 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe const deleteTag = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteTagDTO) => { const tag = await secretTagDAL.findById(id); - if (!tag) throw new NotFoundError({ message: "Tag not found" }); + if (!tag) throw new NotFoundError({ message: `Tag with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -86,7 +86,7 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe const getTagById = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TGetTagByIdDTO) => { const tag = await secretTagDAL.findById(id); - if (!tag) throw new NotFoundError({ message: "Tag not found" }); + if (!tag) throw new NotFoundError({ message: `Tag with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -102,7 +102,7 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe const getTagBySlug = async ({ actorId, actor, actorOrgId, actorAuthMethod, slug, projectId }: TGetTagBySlugDTO) => { const tag = await secretTagDAL.findOne({ projectId, slug }); - if (!tag) throw new NotFoundError({ message: "Tag not found" }); + if (!tag) throw new NotFoundError({ message: `Tag with slug '${slug}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts index 1ae7ce6dc..32fc55285 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts @@ -342,7 +342,9 @@ export const recursivelyGetSecretPaths = async ({ }); if (!env) { - throw new NotFoundError({ message: `'${environment}' environment not found in project with ID ${projectId}` }); + throw new NotFoundError({ + message: `Environment with slug '${environment}' in project with ID ${projectId} not found` + }); } // Fetch all folders in env once with a single query diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts index 0d2797800..53c9c43ef 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts @@ -118,8 +118,8 @@ export const secretV2BridgeServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found`, + name: "CreateSecret" }); const folderId = folder.id; @@ -144,7 +144,8 @@ export const secretV2BridgeServiceFactory = ({ // validate tags // fetch all tags and if not same count throw error meaning one was invalid tags const tags = inputSecret.tagIds ? await secretTagDAL.find({ projectId, $in: { id: inputSecret.tagIds } }) : []; - if ((inputSecret.tagIds || []).length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if ((inputSecret.tagIds || []).length !== tags.length) + throw new NotFoundError({ message: "One or more tags not found" }); const { secretName, type, ...el } = inputSecret; const references = getAllNestedSecretReferences(inputSecret.secretValue); @@ -240,7 +241,7 @@ export const secretV2BridgeServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found`, name: "UpdateSecret" }); const folderId = folder.id; @@ -262,7 +263,8 @@ export const secretV2BridgeServiceFactory = ({ folderId, userId: actorId }); - if (!personalSecretToModify) throw new NotFoundError({ message: "Secret not found" }); + if (!personalSecretToModify) + throw new NotFoundError({ message: `Personal secret with name ${inputSecret.secretName} not found` }); secretId = personalSecretToModify.id; secret = personalSecretToModify; } else { @@ -271,7 +273,8 @@ export const secretV2BridgeServiceFactory = ({ type: SecretType.Shared, folderId }); - if (!sharedSecretToModify) throw new NotFoundError({ message: "Secret not found" }); + if (!sharedSecretToModify) + throw new NotFoundError({ message: `Secret with name ${inputSecret.secretName} not found` }); secretId = sharedSecretToModify.id; secret = sharedSecretToModify; } @@ -288,7 +291,8 @@ export const secretV2BridgeServiceFactory = ({ // validate tags // fetch all tags and if not same count throw error meaning one was invalid tags const tags = inputSecret.tagIds ? await secretTagDAL.find({ projectId, $in: { id: inputSecret.tagIds } }) : []; - if ((inputSecret.tagIds || []).length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if ((inputSecret.tagIds || []).length !== tags.length) + throw new NotFoundError({ message: "One or more tags not found" }); const { secretName, secretValue } = inputSecret; @@ -394,8 +398,8 @@ export const secretV2BridgeServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Delete secret" + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found`, + name: "DeleteSecret" }); const folderId = folder.id; @@ -413,7 +417,11 @@ export const secretV2BridgeServiceFactory = ({ userId: actorId }) }); - if (!secretToDelete) throw new NotFoundError({ message: "Secret not found" }); + if (!secretToDelete) + throw new NotFoundError({ + message: `Secret with name '${inputSecret.secretName}' not found`, + name: "DeleteSecret" + }); const deletedSecret = await secretDAL.transaction(async (tx) => fnSecretBulkDelete({ @@ -800,8 +808,8 @@ export const secretV2BridgeServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${path}' in environment with slug '${environment}' not found`, + name: "GetSecretByName" }); const folderId = folder.id; @@ -885,7 +893,7 @@ export const secretV2BridgeServiceFactory = ({ } } } - if (!secret) throw new NotFoundError({ message: "Secret not found" }); + if (!secret) throw new NotFoundError({ message: `Secret with name '${secretName}' not found` }); let secretValue = secret.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: secret.encryptedValue }).toString() @@ -935,8 +943,8 @@ export const secretV2BridgeServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found`, + name: "CreateManySecret" }); const folderId = folder.id; @@ -953,7 +961,7 @@ export const secretV2BridgeServiceFactory = ({ // get all tags const sanitizedTagIds = inputSecrets.flatMap(({ tagIds = [] }) => tagIds); const tags = sanitizedTagIds.length ? await secretTagDAL.findManyTagsById(projectId, sanitizedTagIds) : []; - if (tags.length !== sanitizedTagIds.length) throw new NotFoundError({ message: "Tag not found" }); + if (tags.length !== sanitizedTagIds.length) throw new NotFoundError({ message: "One or more tags not found" }); const { encryptor: secretManagerEncryptor, decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId }); @@ -1040,8 +1048,8 @@ export const secretV2BridgeServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Update secret" + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found`, + name: "UpdateManySecret" }); const folderId = folder.id; @@ -1076,7 +1084,7 @@ export const secretV2BridgeServiceFactory = ({ // get all tags const sanitizedTagIds = inputSecrets.flatMap(({ tagIds = [] }) => tagIds); const tags = sanitizedTagIds.length ? await secretTagDAL.findManyTagsById(projectId, sanitizedTagIds) : []; - if (tags.length !== sanitizedTagIds.length) throw new NotFoundError({ message: "Tag not found" }); + if (tags.length !== sanitizedTagIds.length) throw new NotFoundError({ message: "One or more tags not found" }); const { encryptor: secretManagerEncryptor, decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId }); @@ -1172,8 +1180,8 @@ export const secretV2BridgeServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found`, + name: "DeleteManySecret" }); const folderId = folder.id; @@ -1186,7 +1194,7 @@ export const secretV2BridgeServiceFactory = ({ ); if (secretsToDelete.length !== inputSecrets.length) throw new NotFoundError({ - message: `One or more secrets does not exist: ${secretsToDelete.map((el) => el.key).join(",")}` + message: `One or more secrets does not exist: ${secretsToDelete.map((el) => el.key).join(", ")}` }); const secretsDeleted = await secretDAL.transaction(async (tx) => @@ -1236,10 +1244,10 @@ export const secretV2BridgeServiceFactory = ({ secretId }: TGetSecretVersionsDTO) => { const secret = await secretDAL.findById(secretId); - if (!secret) throw new NotFoundError({ message: "Failed to find secret" }); + if (!secret) throw new NotFoundError({ message: `Secret with ID '${secretId}' not found` }); const folder = await folderDAL.findById(secret.folderId); - if (!folder) throw new NotFoundError({ message: "Failed to find secret" }); + if (!folder) throw new NotFoundError({ message: `Folder with ID '${secret.folderId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -1345,7 +1353,7 @@ export const secretV2BridgeServiceFactory = ({ const sourceFolder = await folderDAL.findBySecretPath(projectId, sourceEnvironment, sourceSecretPath); if (!sourceFolder) { throw new NotFoundError({ - message: "Source path does not exist." + message: `Source folder with path '${sourceSecretPath}' in environment with slug '${sourceEnvironment}' not found` }); } @@ -1357,7 +1365,7 @@ export const secretV2BridgeServiceFactory = ({ if (!destinationFolder) { throw new NotFoundError({ - message: "Destination path does not exist." + message: `Destination folder with path '${destinationSecretPath}' in environment with slug '${destinationEnvironment}' not found` }); } diff --git a/backend/src/services/secret/secret-fns.ts b/backend/src/services/secret/secret-fns.ts index 1d0b89b46..70a4182cd 100644 --- a/backend/src/services/secret/secret-fns.ts +++ b/backend/src/services/secret/secret-fns.ts @@ -152,7 +152,9 @@ export const recursivelyGetSecretPaths = ({ }); if (!env) { - throw new NotFoundError({ message: `'${environment}' environment not found in project with ID ${projectId}` }); + throw new NotFoundError({ + message: `Environment with slug '${environment}' in project with ID '${projectId}' not found` + }); } // Fetch all folders in env once with a single query @@ -758,7 +760,7 @@ export const createManySecretsRawFnFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", + message: `Folder with path '${secretPath}' not found in environment with slug '${environment}'`, name: "Create secret" }); const folderId = folder.id; @@ -798,7 +800,7 @@ export const createManySecretsRawFnFactory = ({ // get all tags const tagIds = inputSecrets.flatMap(({ tags = [] }) => tags); const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : []; - if (tags.length !== tagIds.length) throw new NotFoundError({ message: "Tag not found" }); + if (tags.length !== tagIds.length) throw new NotFoundError({ message: "One or more tags not found" }); const newSecrets = await secretDAL.transaction(async (tx) => fnSecretV2BridgeBulkInsert({ @@ -834,7 +836,7 @@ export const createManySecretsRawFnFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot not found for project with ID '${projectId}'. Please upgrade your project.`, name: "bot_not_found_error" }); const inputSecrets = secrets.map((secret) => { @@ -865,7 +867,7 @@ export const createManySecretsRawFnFactory = ({ // get all tags const tagIds = inputSecrets.flatMap(({ tags = [] }) => tags); const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : []; - if (tags.length !== tagIds.length) throw new NotFoundError({ message: "Tag not found" }); + if (tags.length !== tagIds.length) throw new NotFoundError({ message: "One or more tags not found" }); const newSecrets = await secretDAL.transaction(async (tx) => fnSecretBulkInsert({ @@ -918,8 +920,8 @@ export const updateManySecretsRawFnFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Update secret" + message: `Folder with path '${secretPath}' not found in environment with slug '${environment}'`, + name: "UpdateSecret" }); const folderId = folder.id; if (shouldUseSecretV2Bridge) { @@ -977,7 +979,7 @@ export const updateManySecretsRawFnFactory = ({ const tagIds = inputSecrets.flatMap(({ tags = [] }) => tags); const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : []; - if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if (tagIds.length !== tags.length) throw new NotFoundError({ message: "One or more tags not found" }); const updatedSecrets = await secretDAL.transaction(async (tx) => fnSecretV2BridgeBulkUpdate({ @@ -999,7 +1001,7 @@ export const updateManySecretsRawFnFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot not found for project with ID '${projectId}'. Please upgrade your project.`, name: "bot_not_found_error" }); const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId }); @@ -1046,7 +1048,7 @@ export const updateManySecretsRawFnFactory = ({ const tagIds = inputSecrets.flatMap(({ tags = [] }) => tags); const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : []; - if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if (tagIds.length !== tags.length) throw new NotFoundError({ message: "One or more tags not found" }); // now find any secret that needs to update its name // same process as above diff --git a/backend/src/services/secret/secret-queue.ts b/backend/src/services/secret/secret-queue.ts index 4076b179f..688a196aa 100644 --- a/backend/src/services/secret/secret-queue.ts +++ b/backend/src/services/secret/secret-queue.ts @@ -1048,7 +1048,7 @@ export const secretQueueFactory = ({ return; } - if (!botKey) throw new NotFoundError({ message: "Project bot not found" }); + if (!botKey) throw new NotFoundError({ message: `Project bot not found for project ${projectId}` }); await projectDAL.updateById(projectId, { upgradeStatus: ProjectUpgradeStatus.InProgress }); const { encryptor: secretManagerEncryptor } = await kmsService.createCipherPairWithDataKey({ diff --git a/backend/src/services/secret/secret-service.ts b/backend/src/services/secret/secret-service.ts index 9d3037ec0..ea8c2a4a9 100644 --- a/backend/src/services/secret/secret-service.ts +++ b/backend/src/services/secret/secret-service.ts @@ -153,7 +153,12 @@ export const secretServiceFactory = ({ const appCfg = getConfig(); const secretBlindIndexDoc = await secretBlindIndexDAL.findOne({ projectId }); - if (!secretBlindIndexDoc) throw new NotFoundError({ message: "Blind index not found", name: "Create secret" }); + if (!secretBlindIndexDoc) { + throw new NotFoundError({ + message: `Blind index for project with ID '${projectId}' not found`, + name: "CreateSecret" + }); + } const secretBlindIndex = await buildSecretBlindIndexFromName({ secretName, @@ -164,7 +169,7 @@ export const secretServiceFactory = ({ ciphertext: secretBlindIndexDoc.encryptedSaltCipherText, iv: secretBlindIndexDoc.saltIV }); - if (!secretBlindIndex) throw new NotFoundError({ message: "Secret not found" }); + if (!secretBlindIndex) throw new NotFoundError({ message: `Secret with name '${secretName}' not found` }); return secretBlindIndex; }; @@ -195,13 +200,18 @@ export const secretServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${path}' in environment with slug '${environment}' not found`, + name: "CreateSecret" }); const folderId = folder.id; const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId }); - if (!blindIndexCfg) throw new NotFoundError({ message: "Blind index not found", name: "CreateSecret" }); + if (!blindIndexCfg) { + throw new NotFoundError({ + message: `Blind index for project with ID '${projectId}' not found`, + name: "CreateSecret" + }); + } if (ActorType.USER !== actor && inputSecret.type === SecretType.Personal) { throw new BadRequestError({ message: "Must be user to create personal secret" }); @@ -232,7 +242,8 @@ export const secretServiceFactory = ({ // validate tags // fetch all tags and if not same count throw error meaning one was invalid tags const tags = inputSecret.tags ? await secretTagDAL.findManyTagsById(projectId, inputSecret.tags) : []; - if ((inputSecret.tags || []).length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if ((inputSecret.tags || []).length !== tags.length) + throw new NotFoundError({ message: "One or more tags not found" }); const { secretName, type, ...el } = inputSecret; const references = await getSecretReference(projectId); @@ -308,13 +319,17 @@ export const secretServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${path}' in environment with slug '${environment}' not found`, + name: "CreateSecret" }); const folderId = folder.id; const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId }); - if (!blindIndexCfg) throw new NotFoundError({ message: "Blind index not found", name: "CreateSecret" }); + if (!blindIndexCfg) + throw new NotFoundError({ + message: `Blind index for project with ID '${projectId}' not found`, + name: "CreateSecret" + }); if (ActorType.USER !== actor && inputSecret.type === SecretType.Personal) { throw new BadRequestError({ message: "Must be user to create personal secret" }); @@ -354,7 +369,8 @@ export const secretServiceFactory = ({ }); const tags = inputSecret.tags ? await secretTagDAL.findManyTagsById(projectId, inputSecret.tags) : []; - if ((inputSecret.tags || []).length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if ((inputSecret.tags || []).length !== tags.length) + throw new NotFoundError({ message: "One or more tags not found" }); const { secretName, ...el } = inputSecret; @@ -441,13 +457,17 @@ export const secretServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${path}' in environment with slug '${environment}' not found`, + name: "DeleteSecret" }); const folderId = folder.id; const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId }); - if (!blindIndexCfg) throw new NotFoundError({ message: "Blind index not found", name: "CreateSecret" }); + if (!blindIndexCfg) + throw new NotFoundError({ + message: `Blind index for project with ID '${projectId}' not found`, + name: "DeleteSecret" + }); if (ActorType.USER !== actor && inputSecret.type === SecretType.Personal) { throw new BadRequestError({ message: "Must be user to create personal secret" }); @@ -624,8 +644,8 @@ export const secretServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${path}' in environment with slug '${environment}' not found`, + name: "GetSecretByName" }); const folderId = folder.id; @@ -694,7 +714,7 @@ export const secretServiceFactory = ({ } } } - if (!secret) throw new NotFoundError({ message: "Secret not found" }); + if (!secret) throw new NotFoundError({ message: `Secret with name '${secretName}' not found` }); return { ...secret, workspace: projectId, environment, secretPath: path }; }; @@ -726,8 +746,8 @@ export const secretServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${path}' in environment with slug '${environment}' not found`, + name: "CreateManySecret" }); const folderId = folder.id; @@ -745,7 +765,7 @@ export const secretServiceFactory = ({ // get all tags const tagIds = inputSecrets.flatMap(({ tags = [] }) => tags); const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : []; - if (tags.length !== tagIds.length) throw new NotFoundError({ message: "Tag not found" }); + if (tags.length !== tagIds.length) throw new NotFoundError({ message: "One or more tags not found" }); const references = await getSecretReference(projectId); const newSecrets = await secretDAL.transaction(async (tx) => @@ -811,8 +831,8 @@ export const secretServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Update secret" + message: `Folder with path '${path}' in environment with slug '${environment}' not found`, + name: "UpdateManySecret" }); const folderId = folder.id; @@ -841,7 +861,7 @@ export const secretServiceFactory = ({ // get all tags const tagIds = inputSecrets.flatMap(({ tags = [] }) => tags); const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : []; - if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" }); + if (tagIds.length !== tags.length) throw new NotFoundError({ message: "One or more tags not found" }); const references = await getSecretReference(projectId); const secrets = await secretDAL.transaction(async (tx) => @@ -917,13 +937,17 @@ export const secretServiceFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) throw new NotFoundError({ - message: "Folder not found for the given environment slug & secret path", - name: "Create secret" + message: `Folder with path '${path}' in environment with slug '${environment}' not found`, + name: "DeleteManySecret" }); const folderId = folder.id; const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId }); - if (!blindIndexCfg) throw new NotFoundError({ message: "Blind index not found", name: "Update secret" }); + if (!blindIndexCfg) + throw new NotFoundError({ + message: `Blind index for project with ID '${projectId}' not found`, + name: "DeleteManySecret" + }); const { keyName2BlindIndex } = await fnSecretBlindIndexCheck({ inputSecrets, @@ -1110,7 +1134,7 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); @@ -1274,7 +1298,7 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); const decryptedSecret = decryptSecretRaw(encryptedSecret, botKey); @@ -1370,7 +1394,7 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(secretName, botKey); @@ -1512,7 +1536,7 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); @@ -1638,7 +1662,7 @@ export const secretServiceFactory = ({ } if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); if (policy) { @@ -1694,7 +1718,7 @@ export const secretServiceFactory = ({ // pick either project slug or projectid if (!optionalProjectId && projectSlug) { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); projectId = project.id; } @@ -1742,7 +1766,7 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); const sanitizedSecrets = inputSecrets.map( @@ -1821,7 +1845,7 @@ export const secretServiceFactory = ({ let projectId = optionalProjectId as string; if (!optionalProjectId && projectSlug) { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); projectId = project.id; } @@ -1868,7 +1892,7 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); const sanitizedSecrets = inputSecrets.map( @@ -1959,7 +1983,7 @@ export const secretServiceFactory = ({ let projectId = optionalProjectId as string; if (!optionalProjectId && projectSlug) { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - if (!project) throw new NotFoundError({ message: "Project not found" }); + if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); projectId = project.id; } @@ -2000,7 +2024,7 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); @@ -2066,12 +2090,13 @@ export const secretServiceFactory = ({ if (secretVersionV2) return secretVersionV2; const secret = await secretDAL.findById(secretId); - if (!secret) throw new NotFoundError({ message: "Failed to find secret" }); + if (!secret) throw new NotFoundError({ message: `Secret with ID '${secretId}' not found` }); const folder = await folderDAL.findById(secret.folderId); - if (!folder) throw new NotFoundError({ message: "Failed to find secret" }); + if (!folder) throw new NotFoundError({ message: `Folder with ID '${secret.folderId}' not found` }); const { botKey } = await projectBotService.getBotKey(folder.projectId); - if (!botKey) throw new NotFoundError({ message: "Project bot not found" }); + if (!botKey) + throw new NotFoundError({ message: `Project bot for project with ID '${folder.projectId}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -2136,12 +2161,14 @@ export const secretServiceFactory = ({ }); if (!secret) { - throw new NotFoundError({ message: "Secret not found" }); + throw new NotFoundError({ message: `Secret with name '${secretName}' not found` }); } const folder = await folderDAL.findBySecretPath(project.id, environment, secretPath); if (!folder) { - throw new NotFoundError({ message: "Folder not found" }); + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); } const tags = await secretTagDAL.find({ @@ -2238,12 +2265,14 @@ export const secretServiceFactory = ({ }); if (!secret) { - throw new NotFoundError({ message: "Secret not found" }); + throw new NotFoundError({ message: `Secret with name '${secretName}' not found` }); } const folder = await folderDAL.findBySecretPath(project.id, environment, secretPath); if (!folder) { - throw new NotFoundError({ message: "Folder not found" }); + throw new NotFoundError({ + message: `Folder with path '${secretPath}' in environment with slug '${environment}' not found` + }); } const tags = await secretTagDAL.find({ @@ -2337,7 +2366,7 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${projectId}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); @@ -2378,7 +2407,7 @@ export const secretServiceFactory = ({ const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); if (!project) { throw new NotFoundError({ - message: "Project not found." + message: `Project with slug '${projectSlug}' not found` }); } if (project.version === 3) { @@ -2423,7 +2452,7 @@ export const secretServiceFactory = ({ const { botKey } = await projectBotService.getBotKey(project.id); if (!botKey) { throw new NotFoundError({ - message: "Project bot not found. Please upgrade your project.", + message: `Project bot for project with ID '${project.id}' not found. Please upgrade your project.`, name: "bot_not_found_error" }); } @@ -2431,7 +2460,7 @@ export const secretServiceFactory = ({ const sourceFolder = await folderDAL.findBySecretPath(project.id, sourceEnvironment, sourceSecretPath); if (!sourceFolder) { throw new NotFoundError({ - message: "Source path does not exist." + message: `Source folder with path '${sourceSecretPath}' in environment with slug '${sourceEnvironment}' not found` }); } @@ -2443,7 +2472,7 @@ export const secretServiceFactory = ({ if (!destinationFolder) { throw new NotFoundError({ - message: "Destination path does not exist." + message: `Destination folder with path '${destinationSecretPath}' in environment with slug '${destinationEnvironment}' not found` }); } diff --git a/backend/src/services/secret/secret-version-dal.ts b/backend/src/services/secret/secret-version-dal.ts index 394cecab0..8e77858a5 100644 --- a/backend/src/services/secret/secret-version-dal.ts +++ b/backend/src/services/secret/secret-version-dal.ts @@ -72,7 +72,7 @@ export const secretVersionDALFactory = (db: TDbClient) => { ); if (existingSecretVersions.length !== data.length) { - throw new NotFoundError({ message: "Some of the secret versions do not exist" }); + throw new NotFoundError({ message: "One or more secret versions not found" }); } if (data.length === 0) return []; diff --git a/backend/src/services/service-token/service-token-service.ts b/backend/src/services/service-token/service-token-service.ts index 5ecbcf54d..fe2c1c0d2 100644 --- a/backend/src/services/service-token/service-token-service.ts +++ b/backend/src/services/service-token/service-token-service.ts @@ -75,7 +75,8 @@ export const serviceTokenServiceFactory = ({ // validates env const scopeEnvs = [...new Set(scopes.map(({ environment }) => environment))]; const inputEnvs = await projectEnvDAL.findBySlugs(projectId, scopeEnvs); - if (inputEnvs.length !== scopeEnvs.length) throw new NotFoundError({ message: "Environment not found" }); + if (inputEnvs.length !== scopeEnvs.length) + throw new NotFoundError({ message: `One or more selected environments not found` }); const secret = crypto.randomBytes(16).toString("hex"); const secretHash = await bcrypt.hash(secret, appCfg.SALT_ROUNDS); @@ -106,7 +107,7 @@ export const serviceTokenServiceFactory = ({ const deleteServiceToken = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteServiceTokenDTO) => { const serviceToken = await serviceTokenDAL.findById(id); - if (!serviceToken) throw new NotFoundError({ message: "Token not found" }); + if (!serviceToken) throw new NotFoundError({ message: `Service token with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -122,13 +123,15 @@ export const serviceTokenServiceFactory = ({ }; const getServiceToken = async ({ actor, actorId }: TGetServiceTokenInfoDTO) => { - if (actor !== ActorType.SERVICE) throw new NotFoundError({ message: "Service token not found" }); + if (actor !== ActorType.SERVICE) + throw new NotFoundError({ message: `Service token with ID '${actorId}' not found` }); const serviceToken = await serviceTokenDAL.findById(actorId); - if (!serviceToken) throw new NotFoundError({ message: "Token not found" }); + if (!serviceToken) throw new NotFoundError({ message: `Service token with ID '${actorId}' not found` }); const serviceTokenUser = await userDAL.findById(serviceToken.createdBy); - if (!serviceTokenUser) throw new NotFoundError({ message: "Service token user not found" }); + if (!serviceTokenUser) + throw new NotFoundError({ message: `Service token with ID ${serviceToken.id} has no associated creator` }); return { serviceToken, user: serviceTokenUser }; }; @@ -157,10 +160,10 @@ export const serviceTokenServiceFactory = ({ const [, tokenIdentifier, tokenSecret] = <[string, string, string]>token.split(".", 3); const serviceToken = await serviceTokenDAL.findById(tokenIdentifier); - if (!serviceToken) throw new NotFoundError({ message: "Service token not found" }); + if (!serviceToken) throw new NotFoundError({ message: `Service token with ID '${tokenIdentifier}' not found` }); const project = await projectDAL.findById(serviceToken.projectId); - if (!project) throw new NotFoundError({ message: "Service token project not found" }); + if (!project) throw new NotFoundError({ message: `Project with ID '${serviceToken.projectId}' not found` }); if (serviceToken.expiresAt && new Date(serviceToken.expiresAt) < new Date()) { await serviceTokenDAL.deleteById(serviceToken.id); diff --git a/backend/src/services/slack/slack-service.ts b/backend/src/services/slack/slack-service.ts index 43d7bb176..9c1460c37 100644 --- a/backend/src/services/slack/slack-service.ts +++ b/backend/src/services/slack/slack-service.ts @@ -110,7 +110,7 @@ export const slackServiceFactory = ({ if (!slackIntegration) { throw new NotFoundError({ - message: "Slack integration not found" + message: `Slack integration with ID ${id} not found` }); } @@ -260,7 +260,7 @@ export const slackServiceFactory = ({ if (!slackIntegration) { throw new NotFoundError({ - message: "Slack integration not found" + message: `Slack integration with ID ${id} not found` }); } @@ -347,7 +347,7 @@ export const slackServiceFactory = ({ const slackIntegration = await slackIntegrationDAL.findByIdWithWorkflowIntegrationDetails(id); if (!slackIntegration) { throw new NotFoundError({ - message: "Slack integration not found." + message: `Slack integration with ID ${id} not found` }); } @@ -385,7 +385,7 @@ export const slackServiceFactory = ({ const slackIntegration = await slackIntegrationDAL.findByIdWithWorkflowIntegrationDetails(id); if (!slackIntegration) { throw new NotFoundError({ - message: "Slack integration not found" + message: `Slack integration with ID ${id} not found` }); } @@ -428,7 +428,7 @@ export const slackServiceFactory = ({ const slackIntegration = await slackIntegrationDAL.findByIdWithWorkflowIntegrationDetails(id); if (!slackIntegration) { throw new NotFoundError({ - message: "Slack integration not found" + message: `Slack integration with ID ${id} not found` }); } diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts index a3acd6751..7c02d0e23 100644 --- a/backend/src/services/super-admin/super-admin-service.ts +++ b/backend/src/services/super-admin/super-admin-service.ts @@ -260,7 +260,7 @@ export const superAdminServiceFactory = ({ const serverCfg = await serverCfgDAL.findById(ADMIN_CONFIG_DB_UUID); if (!serverCfg) { - throw new NotFoundError({ name: "Admin config", message: "Admin config not found" }); + throw new NotFoundError({ name: "AdminConfig", message: "Admin config not found" }); } let clientId = ""; diff --git a/backend/src/services/user/user-service.ts b/backend/src/services/user/user-service.ts index bdf73dd74..b8cf3c7a8 100644 --- a/backend/src/services/user/user-service.ts +++ b/backend/src/services/user/user-service.ts @@ -55,7 +55,7 @@ export const userServiceFactory = ({ }: TUserServiceFactoryDep) => { const sendEmailVerificationCode = async (username: string) => { const user = await userDAL.findOne({ username }); - if (!user) throw new NotFoundError({ name: "Failed to find user" }); + if (!user) throw new NotFoundError({ name: `User with username '${username}' not found` }); if (!user.email) throw new BadRequestError({ name: "Failed to send email verification code due to no email on user" }); if (user.isEmailVerified) @@ -78,7 +78,7 @@ export const userServiceFactory = ({ const verifyEmailVerificationCode = async (username: string, code: string) => { const user = await userDAL.findOne({ username }); - if (!user) throw new NotFoundError({ name: "Failed to find user" }); + if (!user) throw new NotFoundError({ name: `User with username '${username}' not found` }); if (!user.email) throw new BadRequestError({ name: "Failed to verify email verification code due to no email on user" }); if (user.isEmailVerified) @@ -193,10 +193,10 @@ export const userServiceFactory = ({ const updateAuthMethods = async (userId: string, authMethods: AuthMethod[]) => { const user = await userDAL.findById(userId); - if (!user) throw new NotFoundError({ message: "User not found" }); + if (!user) throw new NotFoundError({ message: `User with ID '${userId}' not found`, name: "UpdateAuthMethods" }); if (user.authMethods?.includes(AuthMethod.LDAP) || authMethods.includes(AuthMethod.LDAP)) { - throw new BadRequestError({ message: "LDAP auth method cannot be updated", name: "Update auth methods" }); + throw new BadRequestError({ message: "LDAP auth method cannot be updated", name: "UpdateAuthMethods" }); } const updatedUser = await userDAL.updateById(userId, { authMethods }); @@ -205,7 +205,7 @@ export const userServiceFactory = ({ const getMe = async (userId: string) => { const user = await userDAL.findUserEncKeyByUserId(userId); - if (!user) throw new NotFoundError({ message: "User not found" }); + if (!user) throw new NotFoundError({ message: `User with ID '${userId}' not found`, name: "GetMe" }); return user; }; @@ -246,7 +246,7 @@ export const userServiceFactory = ({ const getUserPrivateKey = async (userId: string) => { const user = await userDAL.findUserEncKeyByUserId(userId); if (!user?.serverEncryptedPrivateKey || !user.serverEncryptedPrivateKeyIV || !user.serverEncryptedPrivateKeyTag) { - throw new NotFoundError({ message: "Private key not found. Please login again" }); + throw new NotFoundError({ message: `Private key for user with ID '${userId}' not found` }); } const privateKey = infisicalSymmetricDecrypt({ ciphertext: user.serverEncryptedPrivateKey, diff --git a/backend/src/services/webhook/webhook-fns.ts b/backend/src/services/webhook/webhook-fns.ts index 151c69632..ffa4b4a04 100644 --- a/backend/src/services/webhook/webhook-fns.ts +++ b/backend/src/services/webhook/webhook-fns.ts @@ -172,7 +172,11 @@ export const fnTriggerWebhook = async ({ await webhookDAL.transaction(async (tx) => { const env = await projectEnvDAL.findOne({ projectId, slug: environment }, tx); - if (!env) throw new NotFoundError({ message: "Environment not found" }); + if (!env) { + throw new NotFoundError({ + message: `Environment with slug '${environment}' in project with ID '${projectId}' not found` + }); + } if (successWebhooks.length) { await webhookDAL.update( { envId: env.id, $in: { id: successWebhooks } }, diff --git a/backend/src/services/webhook/webhook-service.ts b/backend/src/services/webhook/webhook-service.ts index 0bf72d56e..a959d904c 100644 --- a/backend/src/services/webhook/webhook-service.ts +++ b/backend/src/services/webhook/webhook-service.ts @@ -54,7 +54,10 @@ export const webhookServiceFactory = ({ ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks); const env = await projectEnvDAL.findOne({ projectId, slug: environment }); - if (!env) throw new NotFoundError({ message: "Environment not found" }); + if (!env) + throw new NotFoundError({ + message: `Environment with slug '${environment}' in project with ID '${projectId}' not found` + }); const insertDoc: TWebhooksInsert = { url: "", // deprecated - we are moving away from plaintext URLs @@ -88,7 +91,7 @@ export const webhookServiceFactory = ({ const updateWebhook = async ({ actorId, actor, actorOrgId, actorAuthMethod, id, isDisabled }: TUpdateWebhookDTO) => { const webhook = await webhookDAL.findById(id); - if (!webhook) throw new NotFoundError({ message: "Webhook not found" }); + if (!webhook) throw new NotFoundError({ message: `Webhook with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -105,7 +108,7 @@ export const webhookServiceFactory = ({ const deleteWebhook = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TDeleteWebhookDTO) => { const webhook = await webhookDAL.findById(id); - if (!webhook) throw new NotFoundError({ message: "Webhook not found" }); + if (!webhook) throw new NotFoundError({ message: `Webhook with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, @@ -122,7 +125,7 @@ export const webhookServiceFactory = ({ const testWebhook = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TTestWebhookDTO) => { const webhook = await webhookDAL.findById(id); - if (!webhook) throw new NotFoundError({ message: "Webhook not found" }); + if (!webhook) throw new NotFoundError({ message: `Webhook with ID '${id}' not found` }); const { permission } = await permissionService.getProjectPermission( actor, diff --git a/cli/test/.snapshots/test-TestUniversalAuth_SecretsGetWrongEnvironment b/cli/test/.snapshots/test-TestUniversalAuth_SecretsGetWrongEnvironment index c3811bd22..1ae9820aa 100644 --- a/cli/test/.snapshots/test-TestUniversalAuth_SecretsGetWrongEnvironment +++ b/cli/test/.snapshots/test-TestUniversalAuth_SecretsGetWrongEnvironment @@ -1,4 +1,4 @@ -error: CallGetRawSecretsV3: Unsuccessful response [GET https://app.infisical.com/api/v3/secrets/raw?environment=invalid-env&include_imports=true&recursive=true&secretPath=%2F&workspaceId=bef697d4-849b-4a75-b284-0922f87f8ba2] [status-code=500] [response={"statusCode":500,"error":"Internal Server Error","message":"'invalid-env' environment not found in project with ID bef697d4-849b-4a75-b284-0922f87f8ba2"}] +error: CallGetRawSecretsV3: Unsuccessful response [GET https://app.infisical.com/api/v3/secrets/raw?environment=invalid-env&expandSecretReferences=true&include_imports=true&recursive=true&secretPath=%2F&workspaceId=bef697d4-849b-4a75-b284-0922f87f8ba2] [status-code=404] [response={"statusCode":404,"message":"'invalid-env' environment not found in project with ID bef697d4-849b-4a75-b284-0922f87f8ba2","error":"NotFound"}] If this issue continues, get support at https://infisical.com/slack diff --git a/docs/documentation/platform/organization.mdx b/docs/documentation/platform/organization.mdx index 5e75f1a3b..f1c62ff37 100644 --- a/docs/documentation/platform/organization.mdx +++ b/docs/documentation/platform/organization.mdx @@ -16,8 +16,10 @@ as well as create a new project. The **Settings** page lets you manage information about your organization including: -- Name: The name of your organization. -- Incident contacts: Emails that should be alerted if anything abnormal is detected within the organization. +- **Name**: The name of your organization. +- **Slug**: The slug of your organization. +- **Default Organization Member Role**: The role assigned to users when joining your organization unless otherwise specified. +- **Incident Contacts**: Emails that should be alerted if anything abnormal is detected within the organization. ![organization settings general](../../images/platform/organization/organization-settings-general.png) diff --git a/docs/documentation/platform/scim/azure.mdx b/docs/documentation/platform/scim/azure.mdx index 2c48e386d..74a6c2030 100644 --- a/docs/documentation/platform/scim/azure.mdx +++ b/docs/documentation/platform/scim/azure.mdx @@ -28,6 +28,13 @@ Prerequisites: ![SCIM copy token](/images/platform/scim/scim-copy-token.png) + + In Azure, navigate to Enterprise Application > Users and Groups. Add any users and/or groups to your application that you would like + to be provisioned over to Infisical. + + ![SCIM Azure Users and Groups](/images/platform/scim/azure/scim-azure-add-users-and-groups.png) + + In Azure, head to your Enterprise Application > Provisioning > Overview and press **Get started**. diff --git a/docs/documentation/platform/scim/group-mappings.mdx b/docs/documentation/platform/scim/group-mappings.mdx new file mode 100644 index 000000000..acce52e1e --- /dev/null +++ b/docs/documentation/platform/scim/group-mappings.mdx @@ -0,0 +1,26 @@ +--- +title: "SCIM Group Mappings" +description: "Learn how to enhance your SCIM implementation using group mappings" +--- + + + SCIM provisioning, and by extension group mapping, is a paid feature. + + If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical, + then you should contact sales@infisical.com to purchase an enterprise license to use it. + + +## SCIM Group to Organization Role Mapping + +By default, when users are provisioned via SCIM, they will be assigned the default organization role configured in [Organization General Settings](/documentation/platform/organization#settings). + +For more precise control over membership roles, you can set up SCIM Group to Organization Role Mappings. This enables you to assign specific roles based on the group from which a user is provisioned. + +![SCIM Group Mapping](/images/platform/scim/scim-group-mapping.png) + +To configure a mapping, simply enter the SCIM group's name and select the role you would like users to be assigned from this group. Be sure +to tap **Update Mappings** once complete. + + + SCIM Group Mappings only apply when users are first provisioned. Previously provisioned users will not be affected, allowing you to customize user roles after they are added. + diff --git a/docs/images/platform/organization/organization-settings-general.png b/docs/images/platform/organization/organization-settings-general.png index 2c60090fe..affcf32ff 100644 Binary files a/docs/images/platform/organization/organization-settings-general.png and b/docs/images/platform/organization/organization-settings-general.png differ diff --git a/docs/images/platform/scim/azure/scim-azure-add-users-and-groups.png b/docs/images/platform/scim/azure/scim-azure-add-users-and-groups.png new file mode 100644 index 000000000..ec8b4428a Binary files /dev/null and b/docs/images/platform/scim/azure/scim-azure-add-users-and-groups.png differ diff --git a/docs/images/platform/scim/scim-group-mapping.png b/docs/images/platform/scim/scim-group-mapping.png new file mode 100644 index 000000000..76baa8d8d Binary files /dev/null and b/docs/images/platform/scim/scim-group-mapping.png differ diff --git a/docs/mint.json b/docs/mint.json index 0d7553b56..662d008ff 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -249,7 +249,8 @@ "documentation/platform/scim/overview", "documentation/platform/scim/okta", "documentation/platform/scim/azure", - "documentation/platform/scim/jumpcloud" + "documentation/platform/scim/jumpcloud", + "documentation/platform/scim/group-mappings" ] } ] diff --git a/docs/sdks/languages/go.mdx b/docs/sdks/languages/go.mdx index 2d5164b36..18fabf64e 100644 --- a/docs/sdks/languages/go.mdx +++ b/docs/sdks/languages/go.mdx @@ -11,22 +11,23 @@ If you're working with Go Lang, the official [Infisical Go SDK](https://github.c - [Package](https://pkg.go.dev/github.com/infisical/go-sdk) - [Github Repository](https://github.com/infisical/go-sdk) -## Basic Usage +# Basic Usage ```go package main import ( - "fmt" - "os" - - infisical "github.com/infisical/go-sdk" + "fmt" + "os" + "context" + infisical "github.com/infisical/go-sdk" ) func main() { - client := infisical.NewInfisicalClient(infisical.Config{ + client := infisical.NewInfisicalClient(context.Background(), infisical.Config{ SiteUrl: "https://app.infisical.com", // Optional, default is https://app.infisical.com + AutoTokenRefresh: true, // Wether or not to let the SDK handle the access token lifecycle. Defaults to true if not specified. }) _, err = client.Auth().UniversalAuthLogin("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET") @@ -64,32 +65,68 @@ This example demonstrates how to use the Infisical Go SDK in a simple Go applica ```console $ go get github.com/infisical/go-sdk ``` + # Configuration Import the SDK and create a client instance. ```go -client := infisical.NewInfisicalClient(infisical.Config{ +client := infisical.NewInfisicalClient(context.Background(), infisical.Config{ SiteUrl: "https://app.infisical.com", // Optional, default is https://api.infisical.com }) ``` -### ClientSettings methods +### Configuration Options - - The URL of the Infisical API. Default is `https://api.infisical.com`. + + The URL of the Infisical API.. - + Optionally set the user agent that will be used for HTTP requests. _(Not recommended)_ + + + Whether or not to let the SDK handle the access token lifecycle. Defaults to true if not specified. + + + + Whether or not to suppress logs such as warnings from the token refreshing process. Defaults to false if not specified. + -### Authentication +# Automatic token refreshing + +The Infisical Go SDK supports automatic token refreshing. After using one of the auth methods such as Universal Auth, the SDK will automatically renew and re-authenticate when needed. +This behavior is enabled by default, but you can opt-out by setting `AutoTokenRefresh` to `false` in the client settings. + +```go + client := infisical.NewInfisicalClient(context.Background(), infisical.Config{ + AutoTokenRefresh: false, // <- Disable automatic token refreshing + }) +``` + +When using automatic token refreshing it's important to understand how your application uses the Infiiscal client. If you are instantiating new instances of the client often, it's important to cancel the context when the client is no longer needed to avoid the token refreshing process from running indefinitely. + +```go + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() // Cancel the context when the client is no longer needed + + client := infisical.NewInfisicalClient(ctx, infisical.Config{ + AutoTokenRefresh: true, + }) + + // Use the client +``` + +This is only necessary if you are creating multiple instances of the client, and those instances are deleted or otherwise removed throughout the application lifecycle. +If you are only creating one instance of the client, and it will be used throughout the lifetime of your application, you don't need to worry about this. + +# Authentication The SDK supports a variety of authentication methods. The most common authentication method is Universal Auth, which uses a client ID and client secret to authenticate. @@ -222,9 +259,12 @@ if err != nil { } ``` -## Working with Secrets +## Working With Secrets -### client.Secrets().List(options) +### List Secrets +`client.Secrets().List(options)` + +Retrieve all secrets within the Infisical project and environment that client is connected to. ```go secrets, err := client.Secrets().List(infisical.ListSecretsOptions{ @@ -235,9 +275,7 @@ secrets, err := client.Secrets().List(infisical.ListSecretsOptions{ }) ``` -Retrieve all secrets within the Infisical project and environment that client is connected to - -#### Parameters +### Parameters @@ -272,7 +310,11 @@ Retrieve all secrets within the Infisical project and environment that client is -### client.Secrets().Retrieve(options) +### +### Retrieve Secret +`client.Secrets().Retrieve(options)` + +Retrieve a secret from Infisical. By default `Secrets().Retrieve()` fetches and returns a shared secret. ```go secret, err := client.Secrets().Retrieve(infisical.RetrieveSecretOptions{ @@ -282,11 +324,7 @@ secret, err := client.Secrets().Retrieve(infisical.RetrieveSecretOptions{ }) ``` -Retrieve a secret from Infisical. - -By default, `Secrets().Retrieve()` fetches and returns a shared secret. - -#### Parameters +### Parameters @@ -308,7 +346,11 @@ By default, `Secrets().Retrieve()` fetches and returns a shared secret. -### client.Secrets().Create(options) +### +### Create Secret +`client.Secrets().Create(options)` + +Create a new secret in Infisical. ```go secret, err := client.Secrets().Create(infisical.CreateSecretOptions{ @@ -321,9 +363,8 @@ secret, err := client.Secrets().Create(infisical.CreateSecretOptions{ }) ``` -Create a new secret in Infisical. -#### Parameters +### Parameters @@ -351,7 +392,12 @@ Create a new secret in Infisical. -### client.Secrets().Update(options) +### +### Update Secret + +`client.Secrets().Update(options)` + +Update an existing secret in Infisical. ```go secret, err := client.Secrets().Update(infisical.UpdateSecretOptions{ @@ -363,9 +409,7 @@ secret, err := client.Secrets().Update(infisical.UpdateSecretOptions{ }) ``` -Update an existing secret in Infisical. - -#### Parameters +### Parameters @@ -393,7 +437,11 @@ Update an existing secret in Infisical. -### client.Secrets().Delete(options) +### +### Delete Secret +`client.Secrets().Delete(options)` + +Delete a secret in Infisical. ```go secret, err := client.Secrets().Delete(infisical.DeleteSecretOptions{ @@ -403,9 +451,7 @@ secret, err := client.Secrets().Delete(infisical.DeleteSecretOptions{ }) ``` -Delete a secret in Infisical. - -#### Parameters +### Parameters @@ -427,10 +473,14 @@ Delete a secret in Infisical. -## Working with folders +## Working With folders -### client.Folders().List(options) +### +### List Folders +`client.Folders().List(options)` + +Retrieve all within the Infisical project and environment that client is connected to. ```go folders, err := client.Folders().List(infisical.ListFoldersOptions{ @@ -440,9 +490,7 @@ folders, err := client.Folders().List(infisical.ListFoldersOptions{ }) ``` -Retrieve all within the Infisical project and environment that client is connected to. - -#### Parameters +### Parameters @@ -461,7 +509,11 @@ Retrieve all within the Infisical project and environment that client is connect -### client.Folders().Create(options) +### +### Create Folder +`client.Folders().Create(options)` + +Create a new folder in Infisical. ```go folder, err := client.Folders().Create(infisical.CreateFolderOptions{ @@ -472,9 +524,7 @@ folder, err := client.Folders().Create(infisical.CreateFolderOptions{ }) ``` -Create a new folder in Infisical. - -#### Parameters +### Parameters @@ -494,8 +544,11 @@ Create a new folder in Infisical. +### +### Update Folder +`client.Folders().Update(options)` -### client.Folders().Update(options) +Update an existing folder in Infisical. ```go folder, err := client.Folders().Update(infisical.UpdateFolderOptions{ @@ -507,9 +560,7 @@ folder, err := client.Folders().Update(infisical.UpdateFolderOptions{ }) ``` -Update an existing folder in Infisical. - -#### Parameters +### Parameters @@ -531,7 +582,11 @@ Update an existing folder in Infisical. -### client.Folders().Delete(options) +### +### Delete Folder +`client.Folders().Delete(options)` + +Delete a folder in Infisical. ```go deletedFolder, err := client.Folders().Delete(infisical.DeleteFolderOptions{ @@ -544,9 +599,7 @@ deletedFolder, err := client.Folders().Delete(infisical.DeleteFolderOptions{ }) ``` -Delete a folder in Infisical. - -#### Parameters +### Parameters @@ -567,4 +620,6 @@ Delete a folder in Infisical. The path from where the folder should be deleted. - \ No newline at end of file + + + diff --git a/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx b/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx index acbcdcb2d..a2fde465d 100644 --- a/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx +++ b/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx @@ -115,7 +115,10 @@ export const CreateTagModal = ({ isOpen, onToggle }: Props): JSX.Element => { formState: { isSubmitting }, handleSubmit } = useForm({ - resolver: zodResolver(createTagSchema) + resolver: zodResolver(createTagSchema), + defaultValues: { + color: secretTagsColors[0].hex + } }); const { currentWorkspace } = useWorkspace(); diff --git a/frontend/src/components/v2/Checkbox/Checkbox.tsx b/frontend/src/components/v2/Checkbox/Checkbox.tsx index 8c7472b26..751a026c3 100644 --- a/frontend/src/components/v2/Checkbox/Checkbox.tsx +++ b/frontend/src/components/v2/Checkbox/Checkbox.tsx @@ -1,5 +1,5 @@ import { ReactNode } from "react"; -import { faCheck } from "@fortawesome/free-solid-svg-icons"; +import { faCheck, faMinus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; import { twMerge } from "tailwind-merge"; @@ -15,6 +15,7 @@ export type CheckboxProps = Omit< isRequired?: boolean; checkIndicatorBg?: string | undefined; isError?: boolean; + isIndeterminate?: boolean; }; export const Checkbox = ({ @@ -26,6 +27,7 @@ export const Checkbox = ({ isRequired, checkIndicatorBg, isError, + isIndeterminate, ...props }: CheckboxProps): JSX.Element => { return ( @@ -45,7 +47,11 @@ export const Checkbox = ({ id={id} > - + {isIndeterminate ? ( + + ) : ( + + )}