From 342ba8f2f08f0c80f2639a36dde40447cc001e9c Mon Sep 17 00:00:00 2001 From: x032205 Date: Sun, 14 Sep 2025 02:06:12 -0400 Subject: [PATCH] fix: approval policy org check --- .../access-approval-policy-service.ts | 36 ++++++++++++++++- .../secret-approval-policy-service.ts | 39 +++++++++++++++++++ backend/src/server/routes/index.ts | 1 + 3 files changed, 74 insertions(+), 2 deletions(-) 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 95d1a9877..74f0813f7 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 @@ -162,7 +162,7 @@ export const accessApprovalPolicyServiceFactory = ({ if (invalidUsernames.length) { throw new BadRequestError({ - message: `Invalid approver user: ${invalidUsernames.join(", ")}` + message: `Invalid approver user: ${invalidUsernames.map((i) => i.username).join(", ")}` }); } @@ -173,6 +173,22 @@ export const accessApprovalPolicyServiceFactory = ({ })) ); } + + if (approverUserIds.length > 0) { + const allApproverUserIds = approverUserIds.map((au) => au.id); + const approverMembers = await orgMembershipDAL.find({ + $in: { userId: allApproverUserIds }, + orgId: actorOrgId + }); + + if (approverMembers.length !== allApproverUserIds.length) { + const approverMemberUserIds = new Set(approverMembers.map((member) => member.userId as string)); + const userIdsNotInOrg = allApproverUserIds.filter((id) => !approverMemberUserIds.has(id)); + throw new BadRequestError({ + message: `Some approvers are not in the organization: ${userIdsNotInOrg.join(", ")}` + }); + } + } let groupBypassers: string[] = []; let bypasserUserIds: string[] = []; @@ -488,7 +504,7 @@ export const accessApprovalPolicyServiceFactory = ({ if (invalidUsernames.length) { throw new BadRequestError({ - message: `Invalid approver user: ${invalidUsernames.join(", ")}` + message: `Invalid approver user: ${invalidUsernames.map((i) => i.username).join(", ")}` }); } @@ -499,6 +515,22 @@ export const accessApprovalPolicyServiceFactory = ({ })) ); } + + if (approverUserIds.length > 0) { + const allApproverUserIds = approverUserIds.map((au) => au.id); + const approverMembers = await orgMembershipDAL.find({ + $in: { userId: allApproverUserIds }, + orgId: actorOrgId + }); + + if (approverMembers.length !== allApproverUserIds.length) { + const approverMemberUserIds = new Set(approverMembers.map((member) => member.userId as string)); + const userIdsNotInOrg = allApproverUserIds.filter((id) => !approverMemberUserIds.has(id)); + throw new BadRequestError({ + message: `Some approvers are not in the organization: ${userIdsNotInOrg.join(", ")}` + }); + } + } await accessApprovalPolicyApproverDAL.insertMany( approverUserIds.map((el) => ({ approverUserId: el.id, 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 96757dc22..475ba9e70 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 @@ -7,6 +7,7 @@ import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { removeTrailingSlash } from "@app/lib/fn"; import { containsGlobPatterns } from "@app/lib/picomatch"; +import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal"; import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal"; import { TUserDALFactory } from "@app/services/user/user-dal"; @@ -39,6 +40,7 @@ type TSecretApprovalPolicyServiceFactoryDep = { secretApprovalPolicyDAL: TSecretApprovalPolicyDALFactory; projectEnvDAL: Pick; userDAL: Pick; + orgMembershipDAL: Pick; secretApprovalPolicyApproverDAL: TSecretApprovalPolicyApproverDALFactory; secretApprovalPolicyBypasserDAL: TSecretApprovalPolicyBypasserDALFactory; licenseService: Pick; @@ -56,6 +58,7 @@ export const secretApprovalPolicyServiceFactory = ({ secretApprovalPolicyEnvironmentDAL, projectEnvDAL, userDAL, + orgMembershipDAL, licenseService, secretApprovalRequestDAL }: TSecretApprovalPolicyServiceFactoryDep) => { @@ -233,6 +236,24 @@ export const secretApprovalPolicyServiceFactory = ({ userApproverIds = userApproverIds.concat(approverUsers.map((user) => user.id)); } + if (userApproverIds.length > 0) { + const approverMembers = await orgMembershipDAL.find( + { + $in: { userId: userApproverIds }, + orgId: actorOrgId + }, + { tx } + ); + + if (approverMembers.length !== userApproverIds.length) { + const approverMemberUserIds = new Set(approverMembers.map((member) => member.userId as string)); + const userIdsNotInOrg = userApproverIds.filter((id) => !approverMemberUserIds.has(id)); + throw new BadRequestError({ + message: `Some approvers are not in the organization: ${userIdsNotInOrg.join(", ")}` + }); + } + } + await secretApprovalPolicyApproverDAL.insertMany( userApproverIds.map((approverUserId) => ({ approverUserId, @@ -425,6 +446,24 @@ export const secretApprovalPolicyServiceFactory = ({ userApproverIds = userApproverIds.concat(approverUsers.map((user) => user.id)); } + if (userApproverIds.length > 0) { + const approverMembers = await orgMembershipDAL.find( + { + $in: { userId: userApproverIds }, + orgId: actorOrgId + }, + { tx } + ); + + if (approverMembers.length !== userApproverIds.length) { + const approverMemberUserIds = new Set(approverMembers.map((member) => member.userId as string)); + const userIdsNotInOrg = userApproverIds.filter((id) => !approverMemberUserIds.has(id)); + throw new BadRequestError({ + message: `Some approvers are not in the organization: ${userIdsNotInOrg.join(", ")}` + }); + } + } + await secretApprovalPolicyApproverDAL.insertMany( userApproverIds.map((approverUserId) => ({ approverUserId, diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index eccad2956..83a2a35f7 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -604,6 +604,7 @@ export const registerRoutes = async ( secretApprovalPolicyDAL, licenseService, userDAL, + orgMembershipDAL, secretApprovalRequestDAL }); const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL, orgMembershipDAL });