diff --git a/backend/src/ee/routes/v1/project-role-router.ts b/backend/src/ee/routes/v1/project-role-router.ts index 86f2242e2..f6fd53e5e 100644 --- a/backend/src/ee/routes/v1/project-role-router.ts +++ b/backend/src/ee/routes/v1/project-role-router.ts @@ -30,7 +30,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => { req.permission.type, req.permission.id, req.params.projectId, - req.body + req.body, + req.permission.orgId ); return { role }; } @@ -63,7 +64,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => { req.permission.id, req.params.projectId, req.params.roleId, - req.body + req.body, + req.permission.orgId ); return { role }; } @@ -89,7 +91,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => { req.permission.type, req.permission.id, req.params.projectId, - req.params.roleId + req.params.roleId, + req.permission.orgId ); return { role }; } @@ -117,7 +120,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => { const roles = await server.services.projectRole.listRoles( req.permission.type, req.permission.id, - req.params.projectId + req.params.projectId, + req.permission.orgId ); return { data: { roles } }; } @@ -143,7 +147,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => { handler: async (req) => { const { permissions, membership } = await server.services.projectRole.getUserPermission( req.permission.id, - req.params.projectId + req.params.projectId, + req.permission.orgId ); return { data: { permissions, membership } }; } diff --git a/backend/src/ee/routes/v1/project-router.ts b/backend/src/ee/routes/v1/project-router.ts index 3870123fd..b0f2326ec 100644 --- a/backend/src/ee/routes/v1/project-router.ts +++ b/backend/src/ee/routes/v1/project-router.ts @@ -31,6 +31,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const secretSnapshots = await server.services.snapshot.listSnapshots({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, ...req.query }); @@ -60,6 +61,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const count = await server.services.snapshot.projectSecretSnapshotCount({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, environment: req.query.environment, path: req.query.path @@ -112,6 +114,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { handler: async (req) => { const auditLogs = await server.services.auditLog.listProjectAuditLogs({ actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, ...req.query, auditLogActor: req.query.actor, diff --git a/backend/src/ee/routes/v1/secret-approval-policy-router.ts b/backend/src/ee/routes/v1/secret-approval-policy-router.ts index dda8dbe38..1cae7e3f8 100644 --- a/backend/src/ee/routes/v1/secret-approval-policy-router.ts +++ b/backend/src/ee/routes/v1/secret-approval-policy-router.ts @@ -34,6 +34,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi const approval = await server.services.secretApprovalPolicy.createSecretApprovalPolicy({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.body.workspaceId, ...req.body, name: req.body.name ?? `${req.body.environment}-${nanoid(3)}` @@ -71,6 +72,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi const approval = await server.services.secretApprovalPolicy.updateSecretApprovalPolicy({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, ...req.body, secretPolicyId: req.params.sapId }); @@ -96,6 +98,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi const approval = await server.services.secretApprovalPolicy.deleteSecretApprovalPolicy({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, secretPolicyId: req.params.sapId }); return { approval }; @@ -120,6 +123,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi const approvals = await server.services.secretApprovalPolicy.getSecretApprovalPolicyByProjectId({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.query.workspaceId }); return { approvals }; @@ -146,6 +150,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.query.workspaceId, ...req.query }); diff --git a/backend/src/ee/routes/v1/secret-approval-request-router.ts b/backend/src/ee/routes/v1/secret-approval-request-router.ts index f33e8b0d0..57316f8a9 100644 --- a/backend/src/ee/routes/v1/secret-approval-request-router.ts +++ b/backend/src/ee/routes/v1/secret-approval-request-router.ts @@ -52,6 +52,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv const approvals = await server.services.secretApprovalRequest.getSecretApprovals({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, ...req.query, projectId: req.query.workspaceId }); @@ -80,6 +81,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv const approvals = await server.services.secretApprovalRequest.requestCount({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.query.workspaceId }); return { approvals }; @@ -104,6 +106,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv const { approval } = await server.services.secretApprovalRequest.mergeSecretApprovalRequest({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, approvalId: req.params.id }); return { approval }; @@ -131,6 +134,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv const review = await server.services.secretApprovalRequest.reviewApproval({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, approvalId: req.params.id, status: req.body.status }); @@ -159,6 +163,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv const approval = await server.services.secretApprovalRequest.updateApprovalStatus({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, approvalId: req.params.id, status: req.body.status }); @@ -266,6 +271,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv const approval = await server.services.secretApprovalRequest.getSecretApprovalDetails({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, id: req.params.id }); return { approval }; diff --git a/backend/src/ee/routes/v1/secret-rotation-provider-router.ts b/backend/src/ee/routes/v1/secret-rotation-provider-router.ts index bcaf1ab39..8e9924315 100644 --- a/backend/src/ee/routes/v1/secret-rotation-provider-router.ts +++ b/backend/src/ee/routes/v1/secret-rotation-provider-router.ts @@ -30,6 +30,7 @@ export const registerSecretRotationProviderRouter = async (server: FastifyZodPro const providers = await server.services.secretRotation.getProviderTemplates({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId }); return providers; diff --git a/backend/src/ee/routes/v1/secret-rotation-router.ts b/backend/src/ee/routes/v1/secret-rotation-router.ts index 062c51980..840030c94 100644 --- a/backend/src/ee/routes/v1/secret-rotation-router.ts +++ b/backend/src/ee/routes/v1/secret-rotation-router.ts @@ -40,6 +40,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) = const secretRotation = await server.services.secretRotation.createRotation({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, ...req.body, projectId: req.body.workspaceId }); @@ -73,6 +74,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) = const secretRotation = await server.services.secretRotation.restartById({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, rotationId: req.body.id }); return { secretRotation }; @@ -123,6 +125,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) = const secretRotations = await server.services.secretRotation.getByProjectId({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.query.workspaceId }); return { secretRotations }; @@ -155,6 +158,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) = const secretRotation = await server.services.secretRotation.deleteById({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, rotationId: req.params.id }); return { secretRotation }; diff --git a/backend/src/ee/routes/v1/secret-version-router.ts b/backend/src/ee/routes/v1/secret-version-router.ts index 269ed8636..b1d60315d 100644 --- a/backend/src/ee/routes/v1/secret-version-router.ts +++ b/backend/src/ee/routes/v1/secret-version-router.ts @@ -27,6 +27,7 @@ export const registerSecretVersionRouter = async (server: FastifyZodProvider) => const secretVersions = await server.services.secret.getSecretVersions({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, limit: req.query.limit, offset: req.query.offset, secretId: req.params.secretId diff --git a/backend/src/ee/routes/v1/snapshot-router.ts b/backend/src/ee/routes/v1/snapshot-router.ts index c3b9d2d98..d49f2f88a 100644 --- a/backend/src/ee/routes/v1/snapshot-router.ts +++ b/backend/src/ee/routes/v1/snapshot-router.ts @@ -46,6 +46,7 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => { const secretSnapshot = await server.services.snapshot.getSnapshotData({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, id: req.params.secretSnapshotId }); return { secretSnapshot }; @@ -70,6 +71,7 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => { const secretSnapshot = await server.services.snapshot.rollbackSnapshot({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, id: req.params.secretSnapshotId }); return { secretSnapshot }; diff --git a/backend/src/ee/routes/v1/trusted-ip-router.ts b/backend/src/ee/routes/v1/trusted-ip-router.ts index fd56a2cda..8009cc791 100644 --- a/backend/src/ee/routes/v1/trusted-ip-router.ts +++ b/backend/src/ee/routes/v1/trusted-ip-router.ts @@ -24,7 +24,8 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => { const trustedIps = await server.services.trustedIp.listIpsByProjectId({ projectId: req.params.workspaceId, actor: req.permission.type, - actorId: req.permission.id + actorId: req.permission.id, + actorOrgScope: req.permission.orgId }); return { trustedIps }; } @@ -54,6 +55,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => { projectId: req.params.workspaceId, actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, ...req.body }); await server.services.auditLog.createAuditLog({ @@ -97,6 +99,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => { projectId: req.params.workspaceId, actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, trustedIpId: req.params.trustedIpId, ...req.body }); @@ -137,6 +140,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => { projectId: req.params.workspaceId, actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, trustedIpId: req.params.trustedIpId }); await server.services.auditLog.createAuditLog({ diff --git a/backend/src/ee/services/audit-log/audit-log-service.ts b/backend/src/ee/services/audit-log/audit-log-service.ts index c1d5c6925..3611bc0f6 100644 --- a/backend/src/ee/services/audit-log/audit-log-service.ts +++ b/backend/src/ee/services/audit-log/audit-log-service.ts @@ -30,10 +30,11 @@ export const auditLogServiceFactory = ({ startDate, actor, actorId, + actorOrgScope, projectId, auditLogActor }: TListProjectAuditLogDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); const auditLogs = await auditLogDAL.find({ startDate, diff --git a/backend/src/ee/services/permission/permission-dal.ts b/backend/src/ee/services/permission/permission-dal.ts index b8713f369..d3e9bab65 100644 --- a/backend/src/ee/services/permission/permission-dal.ts +++ b/backend/src/ee/services/permission/permission-dal.ts @@ -13,7 +13,7 @@ export const permissionDALFactory = (db: TDbClient) => { .join(TableName.Organization, `${TableName.OrgMembership}.orgId`, `${TableName.Organization}.id`) .where("userId", userId) .where(`${TableName.OrgMembership}.orgId`, orgId) - .select(`${TableName.Organization}.authEnabled as orgAuthEnabled`) + .select(db.ref("authEnabled").withSchema(TableName.Organization).as("orgAuthEnabled")) .select("permissions") .select(selectAllTableCols(TableName.OrgMembership)) .first(); @@ -32,7 +32,7 @@ export const permissionDALFactory = (db: TDbClient) => { .where("identityId", identityId) .where(`${TableName.IdentityOrgMembership}.orgId`, orgId) .select(selectAllTableCols(TableName.IdentityOrgMembership)) - .select(`${TableName.Organization}.authEnabled as orgAuthEnabled`) + .select(db.ref("authEnabled").withSchema(TableName.Organization).as("orgAuthEnabled")) .select("permissions") .first(); return membership; @@ -45,9 +45,15 @@ export const permissionDALFactory = (db: TDbClient) => { try { const membership = await db(TableName.ProjectMembership) .leftJoin(TableName.ProjectRoles, `${TableName.ProjectMembership}.roleId`, `${TableName.ProjectRoles}.id`) + .join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`) + .join(TableName.Organization, `${TableName.Project}.orgId`, `${TableName.Organization}.id`) .where("userId", userId) .where(`${TableName.ProjectMembership}.projectId`, projectId) .select(selectAllTableCols(TableName.ProjectMembership)) + .select( + db.ref("authEnabled").withSchema(TableName.Organization).as("orgAuthEnabled"), + db.ref("orgId").withSchema(TableName.Project) + ) .select("permissions") .first(); diff --git a/backend/src/ee/services/permission/permission-service.ts b/backend/src/ee/services/permission/permission-service.ts index 1f10fa0fa..f4627321b 100644 --- a/backend/src/ee/services/permission/permission-service.ts +++ b/backend/src/ee/services/permission/permission-service.ts @@ -148,12 +148,15 @@ export const permissionServiceFactory = ({ }; // user permission for a project in an organization - const getUserProjectPermission = async (userId: string, projectId: string) => { + const getUserProjectPermission = async (userId: string, projectId: string, orgScope?: string) => { const membership = await permissionDAL.getProjectPermission(userId, projectId); if (!membership) throw new UnauthorizedError({ name: "User not in project" }); if (membership.role === ProjectMembershipRole.Custom && !membership.permissions) { throw new BadRequestError({ name: "Custom permission not found" }); } + if (membership.orgAuthEnabled && membership.orgId !== orgScope) { + throw new BadRequestError({ name: "Cannot access org-scoped resource" }); + } return { permission: buildProjectPermission(membership.role, membership.permissions), membership @@ -194,17 +197,19 @@ export const permissionServiceFactory = ({ }; }; + // TODO: add support for org scope here const getProjectPermission = async ( type: T, id: string, - projectId: string + projectId: string, + orgScope?: string ): Promise> => { switch (type) { case ActorType.USER: - return getUserProjectPermission(id, projectId) as Promise>; - case ActorType.SERVICE: + return getUserProjectPermission(id, projectId, orgScope) as Promise>; + case ActorType.SERVICE: // how to handle org-scope case here? return getServiceTokenProjectPermission(id, projectId) as Promise>; - case ActorType.IDENTITY: + case ActorType.IDENTITY: // how to handle org-scope case here? return getIdentityProjectPermission(id, projectId) as Promise>; default: throw new UnauthorizedError({ 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 b5688545c..0defae92c 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 @@ -44,6 +44,7 @@ export const secretApprovalPolicyServiceFactory = ({ name, actor, actorId, + actorOrgScope, approvals, approvers, projectId, @@ -53,7 +54,7 @@ export const secretApprovalPolicyServiceFactory = ({ if (approvals > approvers.length) throw new BadRequestError({ message: "Approvals cannot be greater than approvers" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SecretApproval @@ -96,13 +97,19 @@ export const secretApprovalPolicyServiceFactory = ({ name, actorId, actor, + actorOrgScope, approvals, secretPolicyId }: TUpdateSapDTO) => { const secretApprovalPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId); if (!secretApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, secretApprovalPolicy.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + secretApprovalPolicy.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval); const updatedSap = await secretApprovalPolicyDAL.transaction(async (tx) => { @@ -145,11 +152,16 @@ export const secretApprovalPolicyServiceFactory = ({ }; }; - const deleteSecretApprovalPolicy = async ({ secretPolicyId, actor, actorId }: TDeleteSapDTO) => { + const deleteSecretApprovalPolicy = async ({ secretPolicyId, actor, actorId, actorOrgScope }: TDeleteSapDTO) => { const sapPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId); if (!sapPolicy) throw new BadRequestError({ message: "Secret approval policy not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, sapPolicy.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + sapPolicy.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, ProjectPermissionSub.SecretApproval @@ -159,8 +171,8 @@ export const secretApprovalPolicyServiceFactory = ({ return sapPolicy; }; - const getSecretApprovalPolicyByProjectId = async ({ actorId, actor, projectId }: TListSapDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getSecretApprovalPolicyByProjectId = async ({ actorId, actor, actorOrgScope, projectId }: TListSapDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); const sapPolicies = await secretApprovalPolicyDAL.find({ projectId }); @@ -188,10 +200,11 @@ export const secretApprovalPolicyServiceFactory = ({ projectId, actor, actorId, + actorOrgScope, environment, secretPath }: TGetBoardSapDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Secrets, { secretPath, environment }) 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 d1ecd51ed..a55d10efe 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 @@ -73,10 +73,15 @@ export const secretApprovalRequestServiceFactory = ({ secretVersionDAL, secretQueueService }: TSecretApprovalRequestServiceFactoryDep) => { - const requestCount = async ({ projectId, actor, actorId }: TApprovalRequestCountDTO) => { + const requestCount = async ({ projectId, actor, actorId, actorOrgScope }: TApprovalRequestCountDTO) => { if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); - const { membership } = await permissionService.getProjectPermission(actor as ActorType.USER, actorId, projectId); + const { membership } = await permissionService.getProjectPermission( + actor as ActorType.USER, + actorId, + projectId, + actorOrgScope + ); const count = await secretApprovalRequestDAL.findProjectRequestCount(projectId, membership.id); return count; @@ -86,6 +91,7 @@ export const secretApprovalRequestServiceFactory = ({ projectId, actorId, actor, + actorOrgScope, status, environment, committer, @@ -94,7 +100,7 @@ export const secretApprovalRequestServiceFactory = ({ }: TListApprovalsDTO) => { if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); - const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); const approvals = await secretApprovalRequestDAL.findByProjectId({ projectId, committer, @@ -107,7 +113,7 @@ export const secretApprovalRequestServiceFactory = ({ return approvals; }; - const getSecretApprovalDetails = async ({ actor, actorId, id }: TSecretApprovalDetailsDTO) => { + const getSecretApprovalDetails = async ({ actor, actorId, actorOrgScope, id }: TSecretApprovalDetailsDTO) => { if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); const secretApprovalRequest = await secretApprovalRequestDAL.findById(id); @@ -117,7 +123,8 @@ export const secretApprovalRequestServiceFactory = ({ const { membership } = await permissionService.getProjectPermission( actor, actorId, - secretApprovalRequest.projectId + secretApprovalRequest.projectId, + actorOrgScope ); if ( membership.role !== ProjectMembershipRole.Admin && @@ -134,7 +141,7 @@ export const secretApprovalRequestServiceFactory = ({ return { ...secretApprovalRequest, secretPath: secretPath?.[0]?.path || "/", commits: secrets }; }; - const reviewApproval = async ({ approvalId, actor, status, actorId }: TReviewRequestDTO) => { + const reviewApproval = async ({ approvalId, actor, status, actorId, actorOrgScope }: TReviewRequestDTO) => { const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" }); if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); @@ -143,7 +150,8 @@ export const secretApprovalRequestServiceFactory = ({ const { membership } = await permissionService.getProjectPermission( ActorType.USER, actorId, - secretApprovalRequest.projectId + secretApprovalRequest.projectId, + actorOrgScope ); if ( membership.role !== ProjectMembershipRole.Admin && @@ -175,7 +183,7 @@ export const secretApprovalRequestServiceFactory = ({ return reviewStatus; }; - const updateApprovalStatus = async ({ actorId, status, approvalId, actor }: TStatusChangeDTO) => { + const updateApprovalStatus = async ({ actorId, status, approvalId, actor, actorOrgScope }: TStatusChangeDTO) => { const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" }); if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); @@ -184,7 +192,8 @@ export const secretApprovalRequestServiceFactory = ({ const { membership } = await permissionService.getProjectPermission( ActorType.USER, actorId, - secretApprovalRequest.projectId + secretApprovalRequest.projectId, + actorOrgScope ); if ( membership.role !== ProjectMembershipRole.Admin && @@ -207,13 +216,23 @@ export const secretApprovalRequestServiceFactory = ({ return { ...secretApprovalRequest, ...updatedRequest }; }; - const mergeSecretApprovalRequest = async ({ approvalId, actor, actorId }: TMergeSecretApprovalRequestDTO) => { + const mergeSecretApprovalRequest = async ({ + approvalId, + actor, + actorId, + actorOrgScope + }: TMergeSecretApprovalRequestDTO) => { const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId); if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" }); if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" }); const { policy, folderId, projectId } = secretApprovalRequest; - const { membership } = await permissionService.getProjectPermission(ActorType.USER, actorId, projectId); + const { membership } = await permissionService.getProjectPermission( + ActorType.USER, + actorId, + projectId, + actorOrgScope + ); if ( membership.role !== ProjectMembershipRole.Admin && secretApprovalRequest.committerId !== membership.id && @@ -401,6 +420,7 @@ export const secretApprovalRequestServiceFactory = ({ data, actorId, actor, + actorOrgScope, policy, projectId, secretPath, @@ -408,7 +428,12 @@ export const secretApprovalRequestServiceFactory = ({ }: TGenerateSecretApprovalRequestDTO) => { if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); - const { permission, membership } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission, membership } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Secrets, { environment, secretPath }) 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 e10d7fa63..98049bdb9 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-service.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-service.ts @@ -14,13 +14,7 @@ import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/pr import { TSecretRotationDALFactory } from "./secret-rotation-dal"; import { TSecretRotationQueueFactory } from "./secret-rotation-queue"; import { TSecretRotationEncData } from "./secret-rotation-queue/secret-rotation-queue-types"; -import { - TCreateSecretRotationDTO, - TDeleteDTO, - TGetByIdDTO, - TListByProjectIdDTO, - TRestartDTO -} from "./secret-rotation-types"; +import { TCreateSecretRotationDTO, TDeleteDTO, TListByProjectIdDTO, TRestartDTO } from "./secret-rotation-types"; import { rotationTemplates } from "./templates"; type TSecretRotationServiceFactoryDep = { @@ -45,8 +39,8 @@ export const secretRotationServiceFactory = ({ folderDAL, secretDAL }: TSecretRotationServiceFactoryDep) => { - const getProviderTemplates = async ({ actor, actorId, projectId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getProviderTemplates = async ({ actor, actorId, actorOrgScope, projectId }: TProjectPermission) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); return { @@ -59,6 +53,7 @@ export const secretRotationServiceFactory = ({ projectId, actorId, actor, + actorOrgScope, inputs, outputs, interval, @@ -66,7 +61,7 @@ export const secretRotationServiceFactory = ({ secretPath, environment }: TCreateSecretRotationDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SecretRotation @@ -144,23 +139,14 @@ export const secretRotationServiceFactory = ({ return secretRotation; }; - const getById = async ({ rotationId, actor, actorId }: TGetByIdDTO) => { - const [doc] = await secretRotationDAL.find({ id: rotationId }); - if (!doc) throw new BadRequestError({ message: "Rotation not found" }); - - const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId); - ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); - return doc; - }; - - const getByProjectId = async ({ actorId, projectId, actor }: TListByProjectIdDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getByProjectId = async ({ actorId, projectId, actor, actorOrgScope }: TListByProjectIdDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); const doc = await secretRotationDAL.find({ projectId }); return doc; }; - const restartById = async ({ actor, actorId, rotationId }: TRestartDTO) => { + const restartById = async ({ actor, actorId, actorOrgScope, rotationId }: TRestartDTO) => { const doc = await secretRotationDAL.findById(rotationId); if (!doc) throw new BadRequestError({ message: "Rotation not found" }); @@ -171,18 +157,18 @@ export const secretRotationServiceFactory = ({ message: "Failed to add secret rotation due to plan restriction. Upgrade plan to add secret rotation." }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretRotation); await secretRotationQueue.removeFromQueue(doc.id, doc.interval); await secretRotationQueue.addToQueue(doc.id, doc.interval); return doc; }; - const deleteById = async ({ actor, actorId, rotationId }: TDeleteDTO) => { + const deleteById = async ({ actor, actorId, actorOrgScope, rotationId }: TDeleteDTO) => { const doc = await secretRotationDAL.findById(rotationId); if (!doc) throw new BadRequestError({ message: "Rotation not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, ProjectPermissionSub.SecretRotation @@ -197,7 +183,6 @@ export const secretRotationServiceFactory = ({ return { getProviderTemplates, - getById, getByProjectId, createRotation, restartById, diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-types.ts b/backend/src/ee/services/secret-rotation/secret-rotation-types.ts index 52d248765..990bf3eca 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-types.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-types.ts @@ -18,7 +18,3 @@ export type TDeleteDTO = { export type TRestartDTO = { rotationId: string; } & Omit; - -export type TGetByIdDTO = { - rotationId: string; -} & Omit; 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 26148958f..f58b19a85 100644 --- a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts +++ b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts @@ -58,9 +58,10 @@ export const secretSnapshotServiceFactory = ({ projectId, actorId, actor, + actorOrgScope, path }: TProjectSnapshotCountDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); const folder = await folderDAL.findBySecretPath(projectId, environment, path); @@ -75,11 +76,12 @@ export const secretSnapshotServiceFactory = ({ projectId, actorId, actor, + actorOrgScope, path, limit = 20, offset = 0 }: TProjectSnapshotListDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); const folder = await folderDAL.findBySecretPath(projectId, environment, path); @@ -89,10 +91,15 @@ export const secretSnapshotServiceFactory = ({ return snapshots; }; - const getSnapshotData = async ({ actorId, actor, id }: TGetSnapshotDataDTO) => { + const getSnapshotData = async ({ actorId, actor, actorOrgScope, id }: TGetSnapshotDataDTO) => { const snapshot = await snapshotDAL.findSecretSnapshotDataById(id); if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, snapshot.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + snapshot.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); return snapshot; }; @@ -143,11 +150,16 @@ export const secretSnapshotServiceFactory = ({ } }; - const rollbackSnapshot = async ({ id: snapshotId, actor, actorId }: TRollbackSnapshotDTO) => { + const rollbackSnapshot = async ({ id: snapshotId, actor, actorId, actorOrgScope }: TRollbackSnapshotDTO) => { const snapshot = await snapshotDAL.findById(snapshotId); if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, snapshot.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + snapshot.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SecretRollback diff --git a/backend/src/ee/services/trusted-ip/trusted-ip-service.ts b/backend/src/ee/services/trusted-ip/trusted-ip-service.ts index a443a32f0..c2952f09c 100644 --- a/backend/src/ee/services/trusted-ip/trusted-ip-service.ts +++ b/backend/src/ee/services/trusted-ip/trusted-ip-service.ts @@ -26,8 +26,8 @@ export const trustedIpServiceFactory = ({ licenseService, projectDAL }: TTrustedIpServiceFactoryDep) => { - const listIpsByProjectId = async ({ projectId, actor, actorId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const listIpsByProjectId = async ({ projectId, actor, actorId, actorOrgScope }: TProjectPermission) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList); const trustedIps = await trustedIpDAL.find({ projectId @@ -35,8 +35,16 @@ export const trustedIpServiceFactory = ({ return trustedIps; }; - const addProjectIp = async ({ projectId, actorId, actor, ipAddress: ip, comment, isActive }: TCreateIpDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const addProjectIp = async ({ + projectId, + actorId, + actor, + actorOrgScope, + ipAddress: ip, + comment, + isActive + }: TCreateIpDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); const project = await projectDAL.findById(projectId); @@ -65,8 +73,16 @@ export const trustedIpServiceFactory = ({ return { trustedIp, project }; // for audit log }; - const updateProjectIp = async ({ projectId, actorId, actor, ipAddress: ip, comment, trustedIpId }: TUpdateIpDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const updateProjectIp = async ({ + projectId, + actorId, + actor, + actorOrgScope, + ipAddress: ip, + comment, + trustedIpId + }: TUpdateIpDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); const project = await projectDAL.findById(projectId); @@ -97,8 +113,8 @@ export const trustedIpServiceFactory = ({ return { trustedIp, project }; // for audit log }; - const deleteProjectIp = async ({ projectId, actorId, actor, trustedIpId }: TDeleteIpDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteProjectIp = async ({ projectId, actorId, actor, actorOrgScope, trustedIpId }: TDeleteIpDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); const project = await projectDAL.findById(projectId); diff --git a/backend/src/server/plugins/auth/inject-identity.ts b/backend/src/server/plugins/auth/inject-identity.ts index e5f5747e6..7abcd073c 100644 --- a/backend/src/server/plugins/auth/inject-identity.ts +++ b/backend/src/server/plugins/auth/inject-identity.ts @@ -10,18 +10,19 @@ import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-to export type TAuthMode = | { + orgId?: string; authMode: AuthMode.JWT; actor: ActorType.USER; userId: string; tokenVersionId: string; // the session id of token used user: TUsers; - orgId?: string; } | { authMode: AuthMode.API_KEY; actor: ActorType.USER; userId: string; user: TUsers; + orgId?: string; } | { authMode: AuthMode.SERVICE_TOKEN; diff --git a/backend/src/server/routes/v1/bot-router.ts b/backend/src/server/routes/v1/bot-router.ts index 4c6e07ffe..3468556fa 100644 --- a/backend/src/server/routes/v1/bot-router.ts +++ b/backend/src/server/routes/v1/bot-router.ts @@ -29,6 +29,7 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => { const bot = await server.services.projectBot.findBotByProjectId({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.params.projectId }); return { bot }; @@ -68,6 +69,7 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => { const bot = await server.services.projectBot.setBotActiveState({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, botId: req.params.botId, botKey: req.body.botKey, isActive: req.body.isActive diff --git a/backend/src/server/routes/v1/identity-ua.ts b/backend/src/server/routes/v1/identity-ua.ts index fb6917512..371d669a5 100644 --- a/backend/src/server/routes/v1/identity-ua.ts +++ b/backend/src/server/routes/v1/identity-ua.ts @@ -112,10 +112,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => { const identityUniversalAuth = await server.services.identityUa.attachUa({ actor: req.permission.type, actorId: req.permission.id, -<<<<<<< HEAD actorOrgScope: req.permission.orgId, -======= ->>>>>>> origin ...req.body, identityId: req.params.identityId }); @@ -182,10 +179,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => { const identityUniversalAuth = await server.services.identityUa.updateUa({ actor: req.permission.type, actorId: req.permission.id, -<<<<<<< HEAD actorOrgScope: req.permission.orgId, -======= ->>>>>>> origin ...req.body, identityId: req.params.identityId }); @@ -228,10 +222,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => { const identityUniversalAuth = await server.services.identityUa.getIdentityUa({ actor: req.permission.type, actorId: req.permission.id, -<<<<<<< HEAD actorOrgScope: req.permission.orgId, -======= ->>>>>>> origin identityId: req.params.identityId }); @@ -274,10 +265,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => { const { clientSecret, clientSecretData, orgId } = await server.services.identityUa.createUaClientSecret({ actor: req.permission.type, actorId: req.permission.id, -<<<<<<< HEAD actorOrgScope: req.permission.orgId, -======= ->>>>>>> origin identityId: req.params.identityId, ...req.body }); @@ -316,10 +304,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => { const { clientSecrets: clientSecretData, orgId } = await server.services.identityUa.getUaClientSecrets({ actor: req.permission.type, actorId: req.permission.id, -<<<<<<< HEAD actorOrgScope: req.permission.orgId, -======= ->>>>>>> origin identityId: req.params.identityId }); @@ -356,10 +341,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => { const clientSecretData = await server.services.identityUa.revokeUaClientSecret({ actor: req.permission.type, actorId: req.permission.id, -<<<<<<< HEAD actorOrgScope: req.permission.orgId, -======= ->>>>>>> origin identityId: req.params.identityId, clientSecretId: req.params.clientSecretId }); diff --git a/backend/src/server/routes/v1/integration-auth-router.ts b/backend/src/server/routes/v1/integration-auth-router.ts index 1d92813f2..04b18be86 100644 --- a/backend/src/server/routes/v1/integration-auth-router.ts +++ b/backend/src/server/routes/v1/integration-auth-router.ts @@ -53,6 +53,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const integrationAuth = await server.services.integrationAuth.getIntegrationAuth({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId }); return { integrationAuth }; @@ -78,6 +79,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuths({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, integration: req.query.integration, projectId: req.query.projectId }); @@ -115,6 +117,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuthById({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId }); @@ -154,6 +157,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const integrationAuth = await server.services.integrationAuth.oauthExchange({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.body.workspaceId, ...req.body }); @@ -196,6 +200,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const integrationAuth = await server.services.integrationAuth.saveIntegrationToken({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.body.workspaceId, ...req.body }); @@ -242,6 +247,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const apps = await server.services.integrationAuth.getIntegrationApps({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, ...req.query }); @@ -272,6 +278,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const teams = await server.services.integrationAuth.getIntegrationAuthTeams({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId }); return { teams }; @@ -299,6 +306,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const branches = await server.services.integrationAuth.getVercelBranches({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, appId: req.query.appId }); @@ -327,6 +335,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const groups = await server.services.integrationAuth.getChecklyGroups({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, accountId: req.query.accountId }); @@ -352,6 +361,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const orgs = await server.services.integrationAuth.getQoveryOrgs({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId }); return { orgs }; @@ -379,6 +389,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const projects = await server.services.integrationAuth.getQoveryProjects({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, orgId: req.query.orgId }); @@ -407,6 +418,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const environments = await server.services.integrationAuth.getQoveryEnvs({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, projectId: req.query.projectId }); @@ -435,6 +447,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const apps = await server.services.integrationAuth.getQoveryApps({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, environmentId: req.query.environmentId }); @@ -463,6 +476,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const containers = await server.services.integrationAuth.getQoveryContainers({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, environmentId: req.query.environmentId }); @@ -491,6 +505,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const jobs = await server.services.integrationAuth.getQoveryJobs({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, environmentId: req.query.environmentId }); @@ -519,6 +534,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const environments = await server.services.integrationAuth.getRailwayEnvironments({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, appId: req.query.appId }); @@ -547,6 +563,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const services = await server.services.integrationAuth.getRailwayServices({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, appId: req.query.appId }); @@ -582,6 +599,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const workspaces = await server.services.integrationAuth.getBitbucketWorkspaces({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId }); return { workspaces }; @@ -614,6 +632,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const secretGroups = await server.services.integrationAuth.getNorthFlankSecretGroups({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, appId: req.query.appId }); @@ -647,6 +666,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) const buildConfigs = await server.services.integrationAuth.getTeamcityBuildConfigs({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationAuthId, appId: req.query.appId }); diff --git a/backend/src/server/routes/v1/integration-router.ts b/backend/src/server/routes/v1/integration-router.ts index a7df57a54..558ca9ade 100644 --- a/backend/src/server/routes/v1/integration-router.ts +++ b/backend/src/server/routes/v1/integration-router.ts @@ -50,6 +50,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { const { integration, integrationAuth } = await server.services.integration.createIntegration({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.body }); await server.services.auditLog.createAuditLog({ @@ -107,6 +108,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { const integration = await server.services.integration.updateIntegration({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationId, ...req.body }); @@ -132,6 +134,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => { const integration = await server.services.integration.deleteIntegration({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.integrationId }); diff --git a/backend/src/server/routes/v1/organization-router.ts b/backend/src/server/routes/v1/organization-router.ts index 23230d0c7..e66e6e2c2 100644 --- a/backend/src/server/routes/v1/organization-router.ts +++ b/backend/src/server/routes/v1/organization-router.ts @@ -39,7 +39,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => { handler: async (req) => { const organization = await server.services.org.findOrganizationById( req.permission.id, - req.params.organizationId. + req.params.organizationId, req.permission.orgId ); return { organization }; @@ -73,8 +73,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => { onRequest: verifyAuth([AuthMode.JWT]), handler: async (req) => { const users = await server.services.org.findAllOrgMembers( - req.permission.id, - req.params.organizationId, + req.permission.id, + req.params.organizationId, req.permission.orgId ); return { users }; diff --git a/backend/src/server/routes/v1/project-env-router.ts b/backend/src/server/routes/v1/project-env-router.ts index 44be1a3d6..311c3aad6 100644 --- a/backend/src/server/routes/v1/project-env-router.ts +++ b/backend/src/server/routes/v1/project-env-router.ts @@ -30,6 +30,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => { const environment = await server.services.projectEnv.createEnvironment({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, ...req.body }); @@ -79,6 +80,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => { const { environment, old } = await server.services.projectEnv.updateEnvironment({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, id: req.params.id, ...req.body @@ -129,6 +131,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => { const environment = await server.services.projectEnv.deleteEnvironment({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, id: req.params.id }); diff --git a/backend/src/server/routes/v1/project-key-router.ts b/backend/src/server/routes/v1/project-key-router.ts index 482392947..cf20d130c 100644 --- a/backend/src/server/routes/v1/project-key-router.ts +++ b/backend/src/server/routes/v1/project-key-router.ts @@ -30,6 +30,7 @@ export const registerProjectKeyRouter = async (server: FastifyZodProvider) => { projectId: req.params.workspaceId, actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, nonce: req.body.key.nonce, receiverId: req.body.key.userId, encryptedKey: req.body.key.encryptedKey diff --git a/backend/src/server/routes/v1/project-membership-router.ts b/backend/src/server/routes/v1/project-membership-router.ts index 7d28f470a..c12c90cda 100644 --- a/backend/src/server/routes/v1/project-membership-router.ts +++ b/backend/src/server/routes/v1/project-membership-router.ts @@ -35,6 +35,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider const memberships = await server.services.projectMembership.getProjectMemberships({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId }); return { memberships }; @@ -70,6 +71,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider const data = await server.services.projectMembership.addUsersToProject({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, members: req.body.members }); @@ -112,6 +114,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider const membership = await server.services.projectMembership.updateProjectMembership({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, membershipId: req.params.membershipId, role: req.body.role @@ -153,6 +156,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider const membership = await server.services.projectMembership.deleteProjectMembership({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, membershipId: req.params.membershipId }); diff --git a/backend/src/server/routes/v1/project-router.ts b/backend/src/server/routes/v1/project-router.ts index 52f6f53fe..9a13da634 100644 --- a/backend/src/server/routes/v1/project-router.ts +++ b/backend/src/server/routes/v1/project-router.ts @@ -46,6 +46,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const publicKeys = await server.services.projectKey.getProjectPublicKeys({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId }); return { publicKeys }; @@ -81,7 +82,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const users = await server.services.projectMembership.getProjectMemberships({ actorId: req.permission.id, actor: req.permission.type, - projectId: req.params.workspaceId + projectId: req.params.workspaceId, + actorOrgScope: req.permission.orgId }); return { users }; } @@ -122,6 +124,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const workspace = await server.services.project.getAProject({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId }); return { workspace }; @@ -173,6 +176,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const workspace = await server.services.project.deleteProject({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId }); return { workspace }; @@ -201,6 +205,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const workspace = await server.services.project.updateName({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, name: req.body.name }); @@ -233,6 +238,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const workspace = await server.services.project.toggleAutoCapitalization({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, autoCapitalization: req.body.autoCapitalization }); @@ -265,6 +271,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const { invitee, latestKey } = await server.services.projectMembership.inviteUserToProject({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId, email: req.body.email }); @@ -310,6 +317,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const integrations = await server.services.integration.listIntegrationByProject({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId }); return { integrations }; @@ -334,6 +342,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const authorizations = await server.services.integrationAuth.listIntegrationAuthByProjectId({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId }); return { authorizations }; @@ -358,6 +367,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const serviceTokenData = await server.services.serviceToken.getProjectServiceTokens({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, projectId: req.params.workspaceId }); return { serviceTokenData }; diff --git a/backend/src/server/routes/v1/secret-folder-router.ts b/backend/src/server/routes/v1/secret-folder-router.ts index 4a152f52e..a97e51759 100644 --- a/backend/src/server/routes/v1/secret-folder-router.ts +++ b/backend/src/server/routes/v1/secret-folder-router.ts @@ -31,6 +31,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => const folder = await server.services.folder.createFolder({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.body, projectId: req.body.workspaceId, path @@ -80,6 +81,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => const { folder, old } = await server.services.folder.updateFolder({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.body, projectId: req.body.workspaceId, id: req.params.folderId, @@ -129,6 +131,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => const folder = await server.services.folder.deleteFolder({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.body, projectId: req.body.workspaceId, id: req.params.folderId, @@ -174,6 +177,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => const folders = await server.services.folder.getFolders({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.query, projectId: req.query.workspaceId, path diff --git a/backend/src/server/routes/v1/secret-import-router.ts b/backend/src/server/routes/v1/secret-import-router.ts index 80f980a90..96ff906fa 100644 --- a/backend/src/server/routes/v1/secret-import-router.ts +++ b/backend/src/server/routes/v1/secret-import-router.ts @@ -36,6 +36,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => const secretImport = await server.services.secretImport.createImport({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.body, projectId: req.body.workspaceId, data: req.body.import @@ -97,6 +98,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => const secretImport = await server.services.secretImport.updateImport({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.secretImportId, ...req.body, projectId: req.body.workspaceId, @@ -150,6 +152,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => const secretImport = await server.services.secretImport.deleteImport({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.secretImportId, ...req.body, projectId: req.body.workspaceId @@ -201,6 +204,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => const secretImports = await server.services.secretImport.getImports({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.query, projectId: req.query.workspaceId }); @@ -253,6 +257,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) => const importedSecrets = await server.services.secretImport.getSecretsFromImports({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.query, projectId: req.query.workspaceId }); diff --git a/backend/src/server/routes/v1/secret-tag-router.ts b/backend/src/server/routes/v1/secret-tag-router.ts index 3cafb11d2..c6b26a8b2 100644 --- a/backend/src/server/routes/v1/secret-tag-router.ts +++ b/backend/src/server/routes/v1/secret-tag-router.ts @@ -23,6 +23,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => { const workspaceTags = await server.services.secretTag.getProjectTags({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.params.projectId }); return { workspaceTags }; @@ -52,6 +53,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => { const workspaceTag = await server.services.secretTag.createTag({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.params.projectId, ...req.body }); @@ -78,6 +80,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => { const workspaceTag = await server.services.secretTag.deleteTag({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, id: req.params.tagId }); return { workspaceTag }; diff --git a/backend/src/server/routes/v1/webhook-router.ts b/backend/src/server/routes/v1/webhook-router.ts index 2b3e66398..c19313f2b 100644 --- a/backend/src/server/routes/v1/webhook-router.ts +++ b/backend/src/server/routes/v1/webhook-router.ts @@ -47,6 +47,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => { const webhook = await server.services.webhook.createWebhook({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.body.workspaceId, ...req.body }); @@ -92,6 +93,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => { const webhook = await server.services.webhook.updateWebhook({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, id: req.params.webhookId, isDisabled: req.body.isDisabled }); @@ -128,6 +130,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => { const webhook = await server.services.webhook.deleteWebhook({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, id: req.params.webhookId }); @@ -169,6 +172,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => { const webhook = await server.services.webhook.testWebhook({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, id: req.params.webhookId }); return { message: "Successfully tested webhook", webhook }; @@ -200,6 +204,7 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => { const webhooks = await server.services.webhook.listWebhooks({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, ...req.query, projectId: req.query.workspaceId }); diff --git a/backend/src/server/routes/v2/identity-project-router.ts b/backend/src/server/routes/v2/identity-project-router.ts index ea797e0cb..b9488e39b 100644 --- a/backend/src/server/routes/v2/identity-project-router.ts +++ b/backend/src/server/routes/v2/identity-project-router.ts @@ -32,6 +32,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider) const identityMembership = await server.services.identityProject.createProjectIdentity({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, identityId: req.params.identityId, projectId: req.params.projectId, role: req.body.role @@ -62,6 +63,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider) const identityMembership = await server.services.identityProject.updateProjectIdentity({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, identityId: req.params.identityId, projectId: req.params.projectId, role: req.body.role @@ -89,6 +91,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider) const identityMembership = await server.services.identityProject.deleteProjectIdentity({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, identityId: req.params.identityId, projectId: req.params.projectId }); @@ -125,6 +128,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider) const identityMemberships = await server.services.identityProject.listProjectIdentities({ actor: req.permission.type, actorId: req.permission.id, + actorOrgScope: req.permission.orgId, projectId: req.params.projectId }); return { identityMemberships }; diff --git a/backend/src/server/routes/v2/project-router.ts b/backend/src/server/routes/v2/project-router.ts index e90a36060..a3a5267dc 100644 --- a/backend/src/server/routes/v2/project-router.ts +++ b/backend/src/server/routes/v2/project-router.ts @@ -28,7 +28,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { const key = await server.services.projectKey.getLatestProjectKey({ actor: req.permission.type, actorId: req.permission.id, - projectId: req.params.workspaceId + projectId: req.params.workspaceId, + actorOrgScope: req.permission.orgId }); await server.services.auditLog.createAuditLog({ diff --git a/backend/src/server/routes/v2/service-token-router.ts b/backend/src/server/routes/v2/service-token-router.ts index ea9912dda..713d0d644 100644 --- a/backend/src/server/routes/v2/service-token-router.ts +++ b/backend/src/server/routes/v2/service-token-router.ts @@ -92,6 +92,7 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) => const { serviceToken, token } = await server.services.serviceToken.createServiceToken({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, ...req.body, projectId: req.body.workspaceId }); @@ -129,6 +130,7 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) => const serviceTokenData = await server.services.serviceToken.deleteServiceToken({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, id: req.params.serviceTokenId }); diff --git a/backend/src/server/routes/v3/secret-blind-index-router.ts b/backend/src/server/routes/v3/secret-blind-index-router.ts index 17bf4c4eb..32c7cca63 100644 --- a/backend/src/server/routes/v3/secret-blind-index-router.ts +++ b/backend/src/server/routes/v3/secret-blind-index-router.ts @@ -21,7 +21,8 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider) const count = await server.services.secretBlindIndex.getSecretBlindIndexStatus({ projectId: req.params.projectId, actorId: req.permission.id, - actor: req.permission.type + actor: req.permission.type, + actorOrgScope: req.permission.orgId }); return count === 0; } @@ -52,7 +53,8 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider) const secrets = await server.services.secretBlindIndex.getProjectSecrets({ projectId: req.params.projectId, actorId: req.permission.id, - actor: req.permission.type + actor: req.permission.type, + actorOrgScope: req.permission.orgId }); return { secrets }; } @@ -85,7 +87,8 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider) projectId: req.params.projectId, secretsToUpdate: req.body.secretsToUpdate, actorId: req.permission.id, - actor: req.permission.type + actor: req.permission.type, + actorOrgScope: req.permission.orgId }); return { message: "Successfully named workspace secrets" }; } diff --git a/backend/src/server/routes/v3/secret-router.ts b/backend/src/server/routes/v3/secret-router.ts index 01746507f..f7cc1b45b 100644 --- a/backend/src/server/routes/v3/secret-router.ts +++ b/backend/src/server/routes/v3/secret-router.ts @@ -81,6 +81,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const { secrets, imports } = await server.services.secret.getSecretsRaw({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, environment, projectId: workspaceId, path: secretPath, @@ -158,6 +159,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secret = await server.services.secret.getSecretByNameRaw({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, environment, projectId: workspaceId, path: secretPath, @@ -225,6 +227,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secret = await server.services.secret.createSecretRaw({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, environment: req.body.environment, projectId: req.body.workspaceId, secretPath: req.body.secretPath, @@ -293,6 +296,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secret = await server.services.secret.updateSecretRaw({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, environment: req.body.environment, projectId: req.body.workspaceId, secretPath: req.body.secretPath, @@ -357,6 +361,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secret = await server.services.secret.deleteSecretRaw({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, environment: req.body.environment, projectId: req.body.workspaceId, secretPath: req.body.secretPath, @@ -451,6 +456,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const { secrets, imports } = await server.services.secret.getSecrets({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, environment: req.query.environment, projectId: req.query.workspaceId, path: req.query.secretPath, @@ -536,6 +542,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secret = await server.services.secret.getSecretByName({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, environment: req.query.environment, projectId: req.query.workspaceId, path: req.query.secretPath, @@ -646,6 +653,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId, @@ -688,6 +696,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secret = await server.services.secret.createSecret({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, path: secretPath, type, environment: req.body.environment, @@ -811,6 +820,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId @@ -819,6 +829,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId, @@ -863,6 +874,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secret = await server.services.secret.updateSecret({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, path: secretPath, type, environment, @@ -952,6 +964,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId @@ -960,6 +973,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId, @@ -992,6 +1006,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secret = await server.services.secret.deleteSecret({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, path: secretPath, type, environment, @@ -1074,6 +1089,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId @@ -1082,6 +1098,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId, @@ -1110,6 +1127,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secrets = await server.services.secret.createManySecret({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, path: secretPath, environment, projectId, @@ -1192,6 +1210,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId @@ -1200,6 +1219,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId, @@ -1227,6 +1247,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secrets = await server.services.secret.updateManySecret({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, path: secretPath, environment, projectId, @@ -1298,6 +1319,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId @@ -1306,6 +1328,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, secretPath, environment, projectId, @@ -1332,6 +1355,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { const secrets = await server.services.secret.deleteManySecret({ actorId: req.permission.id, actor: req.permission.type, + actorOrgScope: req.permission.orgId, path: req.body.secretPath, environment, projectId, diff --git a/backend/src/services/identity-project/identity-project-service.ts b/backend/src/services/identity-project/identity-project-service.ts index 05e0bd68b..75fddd1db 100644 --- a/backend/src/services/identity-project/identity-project-service.ts +++ b/backend/src/services/identity-project/identity-project-service.ts @@ -32,8 +32,15 @@ export const identityProjectServiceFactory = ({ identityOrgMembershipDAL, projectDAL }: TIdentityProjectServiceFactoryDep) => { - const createProjectIdentity = async ({ identityId, actor, actorId, projectId, role }: TCreateProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const createProjectIdentity = async ({ + identityId, + actor, + actorId, + actorOrgScope, + projectId, + role + }: TCreateProjectIdentityDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Identity); const existingIdentity = await identityProjectDAL.findOne({ identityId, projectId }); @@ -72,8 +79,15 @@ export const identityProjectServiceFactory = ({ return projectIdentity; }; - const updateProjectIdentity = async ({ projectId, identityId, role, actor, actorId }: TUpdateProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const updateProjectIdentity = async ({ + projectId, + identityId, + role, + actor, + actorId, + actorOrgScope + }: TUpdateProjectIdentityDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity); const projectIdentity = await identityProjectDAL.findOne({ identityId, projectId }); @@ -85,7 +99,8 @@ export const identityProjectServiceFactory = ({ const { permission: identityRolePermission } = await permissionService.getProjectPermission( ActorType.IDENTITY, projectIdentity.identityId, - projectIdentity.projectId + projectIdentity.projectId, + actorOrgScope ); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); if (!hasRequiredPriviledges) @@ -115,7 +130,13 @@ export const identityProjectServiceFactory = ({ return updatedProjectIdentity; }; - const deleteProjectIdentity = async ({ identityId, actorId, actor, projectId }: TDeleteProjectIdentityDTO) => { + const deleteProjectIdentity = async ({ + identityId, + actorId, + actor, + actorOrgScope, + projectId + }: TDeleteProjectIdentityDTO) => { const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); if (!identityProjectMembership) throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` }); @@ -123,13 +144,15 @@ export const identityProjectServiceFactory = ({ const { permission } = await permissionService.getProjectPermission( actor, actorId, - identityProjectMembership.projectId + identityProjectMembership.projectId, + actorOrgScope ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity); const { permission: identityRolePermission } = await permissionService.getProjectPermission( ActorType.IDENTITY, identityId, - identityProjectMembership.projectId + identityProjectMembership.projectId, + actorOrgScope ); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); if (!hasRequiredPriviledges) @@ -139,8 +162,8 @@ export const identityProjectServiceFactory = ({ return deletedIdentity; }; - const listProjectIdentities = async ({ projectId, actor, actorId }: TListProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const listProjectIdentities = async ({ projectId, actor, actorId, actorOrgScope }: TListProjectIdentityDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity); const identityMemberhips = await identityProjectDAL.findByProjectId(projectId); diff --git a/backend/src/services/integration-auth/integration-auth-service.ts b/backend/src/services/integration-auth/integration-auth-service.ts index 844e01f3c..2e349e9c5 100644 --- a/backend/src/services/integration-auth/integration-auth-service.ts +++ b/backend/src/services/integration-auth/integration-auth-service.ts @@ -59,27 +59,40 @@ export const integrationAuthServiceFactory = ({ projectBotDAL, projectBotService }: TIntegrationAuthServiceFactoryDep) => { - const listIntegrationAuthByProjectId = async ({ actorId, actor, projectId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const listIntegrationAuthByProjectId = async ({ actorId, actor, actorOrgScope, projectId }: TProjectPermission) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const authorizations = await integrationAuthDAL.find({ projectId }); return authorizations; }; - const getIntegrationAuth = async ({ actor, id, actorId }: TGetIntegrationAuthDTO) => { + const getIntegrationAuth = async ({ actor, id, actorId, actorOrgScope }: TGetIntegrationAuthDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); return integrationAuth; }; - const oauthExchange = async ({ projectId, actorId, actor, integration, url, code }: TOauthExchangeDTO) => { + const oauthExchange = async ({ + projectId, + actorId, + actor, + actorOrgScope, + integration, + url, + code + }: TOauthExchangeDTO) => { if (!Object.values(Integrations).includes(integration as Integrations)) throw new BadRequestError({ message: "Invalid integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); const bot = await projectBotDAL.findOne({ isActive: true, projectId }); @@ -134,6 +147,7 @@ export const integrationAuthServiceFactory = ({ integration, url, actor, + actorOrgScope, accessId, namespace, accessToken @@ -141,7 +155,7 @@ export const integrationAuthServiceFactory = ({ if (!Object.values(Integrations).includes(integration as Integrations)) throw new BadRequestError({ message: "Invalid integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); const bot = await projectBotDAL.findOne({ isActive: true, projectId }); @@ -254,11 +268,23 @@ export const integrationAuthServiceFactory = ({ return { accessId, accessToken }; }; - const getIntegrationApps = async ({ actor, actorId, teamId, id, workspaceSlug }: TIntegrationAuthAppsDTO) => { + const getIntegrationApps = async ({ + actor, + actorId, + actorOrgScope, + teamId, + id, + workspaceSlug + }: TIntegrationAuthAppsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); @@ -274,11 +300,16 @@ export const integrationAuthServiceFactory = ({ return apps; }; - const getIntegrationAuthTeams = async ({ actor, actorId, id }: TIntegrationAuthTeamsDTO) => { + const getIntegrationAuthTeams = async ({ actor, actorId, actorOrgScope, id }: TIntegrationAuthTeamsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); @@ -291,11 +322,16 @@ export const integrationAuthServiceFactory = ({ return teams; }; - const getVercelBranches = async ({ appId, id, actor, actorId }: TIntegrationAuthVercelBranchesDTO) => { + const getVercelBranches = async ({ appId, id, actor, actorId, actorOrgScope }: TIntegrationAuthVercelBranchesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -319,11 +355,22 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getChecklyGroups = async ({ actorId, actor, id, accountId }: TIntegrationAuthChecklyGroupsDTO) => { + const getChecklyGroups = async ({ + actorId, + actor, + actorOrgScope, + id, + accountId + }: TIntegrationAuthChecklyGroupsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -340,11 +387,16 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getQoveryOrgs = async ({ actorId, actor, id }: TIntegrationAuthQoveryOrgsDTO) => { + const getQoveryOrgs = async ({ actorId, actor, actorOrgScope, id }: TIntegrationAuthQoveryOrgsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -361,11 +413,16 @@ export const integrationAuthServiceFactory = ({ return data.results.map(({ name, id: orgId }) => ({ name, orgId })); }; - const getQoveryProjects = async ({ actorId, actor, id, orgId }: TIntegrationAuthQoveryProjectDTO) => { + const getQoveryProjects = async ({ actorId, actor, actorOrgScope, id, orgId }: TIntegrationAuthQoveryProjectDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -384,11 +441,22 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getQoveryEnvs = async ({ projectId, id, actor, actorId }: TIntegrationAuthQoveryEnvironmentsDTO) => { + const getQoveryEnvs = async ({ + projectId, + id, + actor, + actorId, + actorOrgScope + }: TIntegrationAuthQoveryEnvironmentsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -412,11 +480,22 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getQoveryApps = async ({ id, actor, actorId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { + const getQoveryApps = async ({ + id, + actor, + actorId, + actorOrgScope, + environmentId + }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -439,11 +518,22 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getQoveryContainers = async ({ id, actor, actorId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { + const getQoveryContainers = async ({ + id, + actor, + actorId, + actorOrgScope, + environmentId + }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -466,11 +556,22 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getQoveryJobs = async ({ id, actor, actorId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { + const getQoveryJobs = async ({ + id, + actor, + actorId, + actorOrgScope, + environmentId + }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -493,11 +594,22 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getRailwayEnvironments = async ({ id, actor, actorId, appId }: TIntegrationAuthRailwayEnvDTO) => { + const getRailwayEnvironments = async ({ + id, + actor, + actorId, + actorOrgScope, + appId + }: TIntegrationAuthRailwayEnvDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -547,11 +659,23 @@ export const integrationAuthServiceFactory = ({ } return []; }; - const getRailwayServices = async ({ id, actor, actorId, appId }: TIntegrationAuthRailwayServicesDTO) => { + + const getRailwayServices = async ({ + id, + actor, + actorId, + actorOrgScope, + appId + }: TIntegrationAuthRailwayServicesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -620,11 +744,21 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getBitbucketWorkspaces = async ({ actorId, actor, id }: TIntegrationAuthBitbucketWorkspaceDTO) => { + const getBitbucketWorkspaces = async ({ + actorId, + actor, + actorOrgScope, + id + }: TIntegrationAuthBitbucketWorkspaceDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -658,11 +792,22 @@ export const integrationAuthServiceFactory = ({ return workspaces; }; - const getNorthFlankSecretGroups = async ({ id, actor, actorId, appId }: TIntegrationAuthNorthflankSecretGroupDTO) => { + const getNorthFlankSecretGroups = async ({ + id, + actor, + actorId, + actorOrgScope, + appId + }: TIntegrationAuthNorthflankSecretGroupDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -713,11 +858,22 @@ export const integrationAuthServiceFactory = ({ return secretGroups; }; - const getTeamcityBuildConfigs = async ({ appId, id, actorId, actor }: TGetIntegrationAuthTeamCityBuildConfigDTO) => { + const getTeamcityBuildConfigs = async ({ + appId, + id, + actorId, + actorOrgScope, + actor + }: TGetIntegrationAuthTeamCityBuildConfigDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const botKey = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey); @@ -742,19 +898,30 @@ export const integrationAuthServiceFactory = ({ return []; }; - const deleteIntegrationAuths = async ({ projectId, integration, actor, actorId }: TDeleteIntegrationAuthsDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteIntegrationAuths = async ({ + projectId, + integration, + actor, + actorId, + actorOrgScope + }: TDeleteIntegrationAuthsDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); const integrations = await integrationAuthDAL.delete({ integration, projectId }); return integrations; }; - const deleteIntegrationAuthById = async ({ id, actorId, actor }: TDeleteIntegrationAuthByIdDTO) => { + const deleteIntegrationAuthById = async ({ id, actorId, actor, actorOrgScope }: TDeleteIntegrationAuthByIdDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); const delIntegrationAuth = await integrationAuthDAL.transaction(async (tx) => { diff --git a/backend/src/services/integration/integration-service.ts b/backend/src/services/integration/integration-service.ts index b7f74966e..7c5a93ab3 100644 --- a/backend/src/services/integration/integration-service.ts +++ b/backend/src/services/integration/integration-service.ts @@ -31,6 +31,7 @@ export const integrationServiceFactory = ({ const createIntegration = async ({ app, actor, + actorOrgScope, path, appId, owner, @@ -50,7 +51,12 @@ export const integrationServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(integrationAuthId); if (!integrationAuth) throw new BadRequestError({ message: "Integration auth not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integrationAuth.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integrationAuth.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); const folder = await folderDAL.findBySecretPath(integrationAuth.projectId, sourceEnvironment, secretPath); @@ -86,6 +92,7 @@ export const integrationServiceFactory = ({ const updateIntegration = async ({ actorId, actor, + actorOrgScope, targetEnvironment, app, id, @@ -98,7 +105,12 @@ export const integrationServiceFactory = ({ const integration = await integrationDAL.findById(id); if (!integration) throw new BadRequestError({ message: "Integration auth not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integration.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integration.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); const folder = await folderDAL.findBySecretPath(integration.projectId, environment, secretPath); @@ -117,19 +129,24 @@ export const integrationServiceFactory = ({ return updatedIntegration; }; - const deleteIntegration = async ({ actorId, id, actor }: TDeleteIntegrationDTO) => { + const deleteIntegration = async ({ actorId, id, actor, actorOrgScope }: TDeleteIntegrationDTO) => { const integration = await integrationDAL.findById(id); if (!integration) throw new BadRequestError({ message: "Integration auth not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, integration.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + integration.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); const deletedIntegration = await integrationDAL.deleteById(id); return { ...integration, ...deletedIntegration }; }; - const listIntegrationByProject = async ({ actor, actorId, projectId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const listIntegrationByProject = async ({ actor, actorId, actorOrgScope, projectId }: TProjectPermission) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const integrations = await integrationDAL.findByProjectId(projectId); diff --git a/backend/src/services/project-bot/project-bot-service.ts b/backend/src/services/project-bot/project-bot-service.ts index 5478aadfa..a2dc8bfb1 100644 --- a/backend/src/services/project-bot/project-bot-service.ts +++ b/backend/src/services/project-bot/project-bot-service.ts @@ -71,8 +71,8 @@ export const projectBotServiceFactory = ({ projectBotDAL, permissionService }: T }); }; - const findBotByProjectId = async ({ actorId, actor, projectId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const findBotByProjectId = async ({ actorId, actor, actorOrgScope, projectId }: TProjectPermission) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const appCfg = getConfig(); @@ -120,11 +120,11 @@ export const projectBotServiceFactory = ({ projectBotDAL, permissionService }: T return bot; }; - const setBotActiveState = async ({ actor, botId, botKey, actorId, isActive }: TSetActiveStateDTO) => { + const setBotActiveState = async ({ actor, botId, botKey, actorId, actorOrgScope, isActive }: TSetActiveStateDTO) => { const bot = await projectBotDAL.findById(botId); if (!bot) throw new BadRequestError({ message: "Bot not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, bot.projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, bot.projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); if (isActive) { diff --git a/backend/src/services/project-env/project-env-service.ts b/backend/src/services/project-env/project-env-service.ts index 49657204e..8896218bb 100644 --- a/backend/src/services/project-env/project-env-service.ts +++ b/backend/src/services/project-env/project-env-service.ts @@ -27,8 +27,8 @@ export const projectEnvServiceFactory = ({ projectDAL, folderDAL }: TProjectEnvServiceFactoryDep) => { - const createEnvironment = async ({ projectId, actorId, actor, name, slug }: TCreateEnvDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const createEnvironment = async ({ projectId, actorId, actor, actorOrgScope, name, slug }: TCreateEnvDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Environments); const envs = await projectEnvDAL.find({ projectId }); @@ -59,8 +59,17 @@ export const projectEnvServiceFactory = ({ return env; }; - const updateEnvironment = async ({ projectId, slug, actor, actorId, name, id, position }: TUpdateEnvDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const updateEnvironment = async ({ + projectId, + slug, + actor, + actorId, + actorOrgScope, + name, + id, + position + }: TUpdateEnvDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments); const oldEnv = await projectEnvDAL.findOne({ id, projectId }); @@ -85,8 +94,8 @@ export const projectEnvServiceFactory = ({ return { environment: env, old: oldEnv }; }; - const deleteEnvironment = async ({ projectId, actor, actorId, id }: TDeleteEnvDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteEnvironment = async ({ projectId, actor, actorId, actorOrgScope, id }: TDeleteEnvDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Environments); const env = await projectEnvDAL.transaction(async (tx) => { diff --git a/backend/src/services/project-key/project-key-service.ts b/backend/src/services/project-key/project-key-service.ts index e7ebc23ee..685fc0b6b 100644 --- a/backend/src/services/project-key/project-key-service.ts +++ b/backend/src/services/project-key/project-key-service.ts @@ -25,11 +25,12 @@ export const projectKeyServiceFactory = ({ receiverId, actor, actorId, + actorOrgScope, projectId, nonce, encryptedKey }: TUploadProjectKeyDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); const receiverMembership = await projectMembershipDAL.findOne({ @@ -45,14 +46,14 @@ export const projectKeyServiceFactory = ({ await projectKeyDAL.create({ projectId, receiverId, encryptedKey, nonce, senderId: actorId }); }; - const getLatestProjectKey = async ({ actorId, projectId, actor }: TGetLatestProjectKeyDTO) => { - await permissionService.getProjectPermission(actor, actorId, projectId); + const getLatestProjectKey = async ({ actorId, projectId, actor, actorOrgScope }: TGetLatestProjectKeyDTO) => { + await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); const latestKey = await projectKeyDAL.findLatestProjectKey(actorId, projectId); return latestKey; }; - const getProjectPublicKeys = async ({ actor, actorId, projectId }: TGetLatestProjectKeyDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getProjectPublicKeys = async ({ actor, actorId, actorOrgScope, projectId }: TGetLatestProjectKeyDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); return projectKeyDAL.findAllProjectUserPubKeys(projectId); }; diff --git a/backend/src/services/project-membership/project-membership-service.ts b/backend/src/services/project-membership/project-membership-service.ts index 862c19384..1ce536ee8 100644 --- a/backend/src/services/project-membership/project-membership-service.ts +++ b/backend/src/services/project-membership/project-membership-service.ts @@ -48,15 +48,15 @@ export const projectMembershipServiceFactory = ({ projectKeyDAL, licenseService }: TProjectMembershipServiceFactoryDep) => { - const getProjectMemberships = async ({ actorId, actor, projectId }: TGetProjectMembershipDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getProjectMemberships = async ({ actorId, actor, actorOrgScope, projectId }: TGetProjectMembershipDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); return projectMembershipDAL.findAllProjectMembers(projectId); }; - const inviteUserToProject = async ({ actorId, actor, projectId, email }: TInviteUserToProjectDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const inviteUserToProject = async ({ actorId, actor, actorOrgScope, projectId, email }: TInviteUserToProjectDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member); const invitee = await userDAL.findOne({ email }); @@ -112,11 +112,11 @@ export const projectMembershipServiceFactory = ({ return { invitee, latestKey }; }; - const addUsersToProject = async ({ projectId, actorId, actor, members }: TAddUsersToWorkspaceDTO) => { + const addUsersToProject = async ({ projectId, actorId, actor, actorOrgScope, members }: TAddUsersToWorkspaceDTO) => { const project = await projectDAL.findById(projectId); if (!project) throw new BadRequestError({ message: "Project not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member); const orgMembers = await orgDAL.findMembership({ orgId: project.orgId, @@ -172,11 +172,12 @@ export const projectMembershipServiceFactory = ({ const updateProjectMembership = async ({ actorId, actor, + actorOrgScope, projectId, membershipId, role }: TUpdateProjectMembershipDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); const isCustomRole = !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole); @@ -204,8 +205,14 @@ export const projectMembershipServiceFactory = ({ return membership; }; - const deleteProjectMembership = async ({ actorId, actor, projectId, membershipId }: TDeleteProjectMembershipDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteProjectMembership = async ({ + actorId, + actor, + actorOrgScope, + projectId, + membershipId + }: TDeleteProjectMembershipDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member); const membership = await projectMembershipDAL.transaction(async (tx) => { diff --git a/backend/src/services/project-role/project-role-service.ts b/backend/src/services/project-role/project-role-service.ts index 4c0633712..4c2ef1435 100644 --- a/backend/src/services/project-role/project-role-service.ts +++ b/backend/src/services/project-role/project-role-service.ts @@ -28,9 +28,10 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }: actor: ActorType, actorId: string, projectId: string, - data: Omit + data: Omit, + actorOrgScope?: string ) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Role); const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId }); if (existingRole) throw new BadRequestError({ name: "Create Role", message: "Duplicate role" }); @@ -47,9 +48,10 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }: actorId: string, projectId: string, roleId: string, - data: Omit + data: Omit, + actorOrgScope?: string ) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Role); if (data?.slug) { const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId }); @@ -64,8 +66,14 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }: return updatedRole; }; - const deleteRole = async (actor: ActorType, actorId: string, projectId: string, roleId: string) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteRole = async ( + actor: ActorType, + actorId: string, + projectId: string, + roleId: string, + actorOrgScope?: string + ) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role); const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId }); if (!deleteRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); @@ -73,8 +81,8 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }: return deletedRole; }; - const listRoles = async (actor: ActorType, actorId: string, projectId: string) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const listRoles = async (actor: ActorType, actorId: string, projectId: string, actorOrgScope?: string) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role); const customRoles = await projectRoleDAL.find({ projectId }); const roles = [ @@ -127,8 +135,12 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }: return roles; }; - const getUserPermission = async (userId: string, projectId: string) => { - const { permission, membership } = await permissionService.getUserProjectPermission(userId, projectId); + const getUserPermission = async (userId: string, projectId: string, actorOrgScope?: string) => { + const { permission, membership } = await permissionService.getUserProjectPermission( + userId, + projectId, + actorOrgScope + ); return { permissions: packRules(permission.rules), membership }; }; diff --git a/backend/src/services/project/project-service.ts b/backend/src/services/project/project-service.ts index 2e4ee15ca..9ec3b46a3 100644 --- a/backend/src/services/project/project-service.ts +++ b/backend/src/services/project/project-service.ts @@ -106,8 +106,8 @@ export const projectServiceFactory = ({ return newProject; }; - const deleteProject = async ({ actor, actorId, projectId }: TDeleteProjectDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteProject = async ({ actor, actorId, actorOrgScope, projectId }: TDeleteProjectDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project); const deletedProject = await projectDAL.deleteById(projectId); @@ -119,8 +119,8 @@ export const projectServiceFactory = ({ return workspaces; }; - const getAProject = async ({ actorId, projectId, actor }: TGetProjectDTO) => { - await permissionService.getProjectPermission(actor, actorId, projectId); + const getAProject = async ({ actorId, actorOrgScope, projectId, actor }: TGetProjectDTO) => { + await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); return projectDAL.findProjectById(projectId); }; @@ -128,17 +128,18 @@ export const projectServiceFactory = ({ projectId, actor, actorId, + actorOrgScope, autoCapitalization }: TGetProjectDTO & { autoCapitalization: boolean }) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); const updatedProject = await projectDAL.updateById(projectId, { autoCapitalization }); return updatedProject; }; - const updateName = async ({ projectId, actor, actorId, name }: TGetProjectDTO & { name: string }) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const updateName = async ({ projectId, actor, actorId, actorOrgScope, name }: TGetProjectDTO & { name: string }) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); const updatedProject = await projectDAL.updateById(projectId, { name }); diff --git a/backend/src/services/project/project-types.ts b/backend/src/services/project/project-types.ts index 57d385141..eab04d4df 100644 --- a/backend/src/services/project/project-types.ts +++ b/backend/src/services/project/project-types.ts @@ -11,11 +11,13 @@ export type TCreateProjectDTO = { export type TDeleteProjectDTO = { actor: ActorType; actorId: string; + actorOrgScope?: string; projectId: string; }; export type TGetProjectDTO = { actor: ActorType; actorId: string; + actorOrgScope?: string; projectId: string; }; 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 bb565e295..7a019c958 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 @@ -24,8 +24,13 @@ export const secretBlindIndexServiceFactory = ({ permissionService, secretDAL }: TSecretBlindIndexServiceFactoryDep) => { - const getSecretBlindIndexStatus = async ({ actor, projectId, actorId }: TGetProjectBlindIndexStatusDTO) => { - await permissionService.getProjectPermission(actor, actorId, projectId); + const getSecretBlindIndexStatus = async ({ + actor, + projectId, + actorId, + actorOrgScope + }: TGetProjectBlindIndexStatusDTO) => { + await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); const secretCount = await secretBlindIndexDAL.countOfSecretsWithNullSecretBlindIndex(projectId); return Number(secretCount); @@ -45,9 +50,10 @@ export const secretBlindIndexServiceFactory = ({ projectId, actor, actorId, + actorOrgScope, secretsToUpdate }: TUpdateProjectSecretNameDTO) => { - const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); if (membership?.role !== ProjectMembershipRole.Admin) { throw new UnauthorizedError({ message: "User must be admin" }); } diff --git a/backend/src/services/secret-folder/secret-folder-service.ts b/backend/src/services/secret-folder/secret-folder-service.ts index 082674485..e12450d81 100644 --- a/backend/src/services/secret-folder/secret-folder-service.ts +++ b/backend/src/services/secret-folder/secret-folder-service.ts @@ -30,8 +30,16 @@ export const secretFolderServiceFactory = ({ projectEnvDAL, folderVersionDAL }: TSecretFolderServiceFactoryDep) => { - const createFolder = async ({ projectId, actor, actorId, name, environment, path: secretPath }: TCreateFolderDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const createFolder = async ({ + projectId, + actor, + actorId, + actorOrgScope, + name, + environment, + path: secretPath + }: TCreateFolderDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, subject(ProjectPermissionSub.Secrets, { environment, secretPath }) @@ -105,12 +113,13 @@ export const secretFolderServiceFactory = ({ projectId, actor, actorId, + actorOrgScope, name, environment, path: secretPath, id }: TUpdateFolderDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Secrets, { environment, secretPath }) @@ -148,8 +157,16 @@ export const secretFolderServiceFactory = ({ return { folder: newFolder, old: folder }; }; - const deleteFolder = async ({ projectId, actor, actorId, environment, path: secretPath, id }: TDeleteFolderDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteFolder = async ({ + projectId, + actor, + actorId, + actorOrgScope, + environment, + path: secretPath, + id + }: TDeleteFolderDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, subject(ProjectPermissionSub.Secrets, { environment, secretPath }) @@ -171,10 +188,17 @@ export const secretFolderServiceFactory = ({ return folder; }; - const getFolders = async ({ projectId, actor, actorId, environment, path: secretPath }: TGetFolderDTO) => { + const getFolders = async ({ + projectId, + actor, + actorId, + actorOrgScope, + environment, + path: secretPath + }: TGetFolderDTO) => { // folder list is allowed to be read by anyone // permission to check does user has access - await permissionService.getProjectPermission(actor, actorId, projectId); + await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); const env = await projectEnvDAL.findOne({ projectId, slug: environment }); if (!env) throw new BadRequestError({ message: "Environment not found", name: "get folders" }); diff --git a/backend/src/services/secret-import/secret-import-service.ts b/backend/src/services/secret-import/secret-import-service.ts index 57142424f..b763ddb5e 100644 --- a/backend/src/services/secret-import/secret-import-service.ts +++ b/backend/src/services/secret-import/secret-import-service.ts @@ -36,8 +36,16 @@ export const secretImportServiceFactory = ({ folderDAL, secretDAL }: TSecretImportServiceFactoryDep) => { - const createImport = async ({ environment, data, actor, actorId, projectId, path }: TCreateSecretImportDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const createImport = async ({ + environment, + data, + actor, + actorId, + actorOrgScope, + projectId, + path + }: TCreateSecretImportDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); // check if user has permission to import into destination path ForbiddenError.from(permission).throwUnlessCan( @@ -77,8 +85,17 @@ export const secretImportServiceFactory = ({ return { ...secImport, importEnv }; }; - const updateImport = async ({ path, environment, projectId, actor, actorId, data, id }: TUpdateSecretImportDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const updateImport = async ({ + path, + environment, + projectId, + actor, + actorId, + actorOrgScope, + data, + id + }: TUpdateSecretImportDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -115,8 +132,16 @@ export const secretImportServiceFactory = ({ return { ...updatedSecImport, importEnv: importedEnv }; }; - const deleteImport = async ({ path, environment, projectId, actor, actorId, id }: TDeleteSecretImportDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteImport = async ({ + path, + environment, + projectId, + actor, + actorId, + actorOrgScope, + id + }: TDeleteSecretImportDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -137,8 +162,8 @@ export const secretImportServiceFactory = ({ return secImport; }; - const getImports = async ({ path, environment, projectId, actor, actorId }: TGetSecretImportsDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getImports = async ({ path, environment, projectId, actor, actorId, actorOrgScope }: TGetSecretImportsDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -151,8 +176,15 @@ export const secretImportServiceFactory = ({ return secImports; }; - const getSecretsFromImports = async ({ path, environment, projectId, actor, actorId }: TGetSecretsFromImportDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getSecretsFromImports = async ({ + path, + environment, + projectId, + actor, + actorId, + actorOrgScope + }: TGetSecretsFromImportDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) diff --git a/backend/src/services/secret-tag/secret-tag-service.ts b/backend/src/services/secret-tag/secret-tag-service.ts index 361f2d009..2a7ca3242 100644 --- a/backend/src/services/secret-tag/secret-tag-service.ts +++ b/backend/src/services/secret-tag/secret-tag-service.ts @@ -15,8 +15,8 @@ type TSecretTagServiceFactoryDep = { export type TSecretTagServiceFactory = ReturnType; export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSecretTagServiceFactoryDep) => { - const createTag = async ({ name, slug, actor, color, actorId, projectId }: TCreateTagDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const createTag = async ({ name, slug, actor, color, actorId, actorOrgScope, projectId }: TCreateTagDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags); const existingTag = await secretTagDAL.findOne({ slug }); @@ -32,19 +32,19 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe return newTag; }; - const deleteTag = async ({ actorId, actor, id }: TDeleteTagDTO) => { + const deleteTag = async ({ actorId, actor, actorOrgScope, id }: TDeleteTagDTO) => { const tag = await secretTagDAL.findById(id); if (!tag) throw new BadRequestError({ message: "Tag doesn't exist" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, tag.projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, tag.projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Tags); const deletedTag = await secretTagDAL.deleteById(tag.id); return deletedTag; }; - const getProjectTags = async ({ actor, actorId, projectId }: TListProjectTagsDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getProjectTags = async ({ actor, actorId, actorOrgScope, projectId }: TListProjectTagsDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); const tags = await secretTagDAL.find({ projectId }, { sort: [["createdAt", "asc"]] }); diff --git a/backend/src/services/secret/secret-service.ts b/backend/src/services/secret/secret-service.ts index 71086446f..4eb3ea1cc 100644 --- a/backend/src/services/secret/secret-service.ts +++ b/backend/src/services/secret/secret-service.ts @@ -37,7 +37,6 @@ import { TGetSecretsDTO, TGetSecretsRawDTO, TGetSecretVersionsDTO, - TListSecretVersionDTO, TUpdateBulkSecretDTO, TUpdateSecretDTO, TUpdateSecretRawDTO @@ -267,8 +266,16 @@ export const secretServiceFactory = ({ return { secsGroupedByBlindIndex, secrets }; }; - const createSecret = async ({ path, actor, actorId, environment, projectId, ...inputSecret }: TCreateSecretDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const createSecret = async ({ + path, + actor, + actorId, + actorOrgScope, + environment, + projectId, + ...inputSecret + }: TCreateSecretDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -337,8 +344,16 @@ export const secretServiceFactory = ({ return { ...secret[0], environment, workspace: projectId, tags }; }; - const updateSecret = async ({ path, actor, actorId, environment, projectId, ...inputSecret }: TUpdateSecretDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const updateSecret = async ({ + path, + actor, + actorId, + actorOrgScope, + environment, + projectId, + ...inputSecret + }: TUpdateSecretDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -429,8 +444,16 @@ export const secretServiceFactory = ({ return { ...updatedSecret[0], workspace: projectId, environment }; }; - const deleteSecret = async ({ path, actor, actorId, environment, projectId, ...inputSecret }: TDeleteSecretDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const deleteSecret = async ({ + path, + actor, + actorId, + actorOrgScope, + environment, + projectId, + ...inputSecret + }: TDeleteSecretDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -476,8 +499,16 @@ export const secretServiceFactory = ({ return { ...deletedSecret[0], _id: deletedSecret[0].id, workspace: projectId, environment }; }; - const getSecrets = async ({ actorId, path, environment, projectId, actor, includeImports }: TGetSecretsDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getSecrets = async ({ + actorId, + path, + environment, + projectId, + actor, + actorOrgScope, + includeImports + }: TGetSecretsDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -518,6 +549,7 @@ export const secretServiceFactory = ({ const getSecretByName = async ({ actorId, actor, + actorOrgScope, projectId, environment, path, @@ -526,7 +558,7 @@ export const secretServiceFactory = ({ version, includeImports }: TGetASecretDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -595,11 +627,12 @@ export const secretServiceFactory = ({ path, actor, actorId, + actorOrgScope, environment, projectId, secrets: inputSecrets }: TCreateBulkSecretDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -649,11 +682,12 @@ export const secretServiceFactory = ({ path, actor, actorId, + actorOrgScope, environment, projectId, secrets: inputSecrets }: TUpdateBulkSecretDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -721,9 +755,10 @@ export const secretServiceFactory = ({ environment, projectId, actor, - actorId + actorId, + actorOrgScope }: TDeleteBulkSecretDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -762,20 +797,15 @@ export const secretServiceFactory = ({ return secretsDeleted; }; - const listSecretVersionsBySecretId = async ({ actorId, actor, limit, offset, secretId }: TListSecretVersionDTO) => { - const secret = await secretDAL.findById(secretId); - if (!secret) throw new BadRequestError({ message: "Failed to find secret" }); - - const folder = await folderDAL.findById(secret.folderId); - if (!folder) throw new BadRequestError({ message: "Folder not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, folder.projectId); - ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); - - const secretVersions = await secretVersionDAL.find({ secretId }, { limit, offset, sort: [["createdAt", "desc"]] }); - return secretVersions; - }; - - const getSecretsRaw = async ({ projectId, path, actor, actorId, environment, includeImports }: TGetSecretsRawDTO) => { + const getSecretsRaw = async ({ + projectId, + path, + actor, + actorId, + actorOrgScope, + environment, + includeImports + }: TGetSecretsRawDTO) => { const botKey = await projectBotService.getBotKey(projectId); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); @@ -784,6 +814,7 @@ export const secretServiceFactory = ({ projectId, environment, actor, + actorOrgScope, path, includeImports }); @@ -806,6 +837,7 @@ export const secretServiceFactory = ({ environment, projectId, actorId, + actorOrgScope, secretName, includeImports, version @@ -818,6 +850,7 @@ export const secretServiceFactory = ({ projectId, environment, actor, + actorOrgScope, path, secretName, type, @@ -833,6 +866,7 @@ export const secretServiceFactory = ({ projectId, environment, actor, + actorOrgScope, type, secretPath, secretValue, @@ -854,6 +888,7 @@ export const secretServiceFactory = ({ path: secretPath, actor, actorId, + actorOrgScope, secretKeyCiphertext: secretKeyEncrypted.ciphertext, secretKeyIV: secretKeyEncrypted.iv, secretKeyTag: secretKeyEncrypted.tag, @@ -878,6 +913,7 @@ export const secretServiceFactory = ({ projectId, environment, actor, + actorOrgScope, type, secretPath, secretValue, @@ -896,6 +932,7 @@ export const secretServiceFactory = ({ path: secretPath, actor, actorId, + actorOrgScope, secretValueCiphertext: secretValueEncrypted.ciphertext, secretValueIV: secretValueEncrypted.iv, secretValueTag: secretValueEncrypted.tag, @@ -914,6 +951,7 @@ export const secretServiceFactory = ({ projectId, environment, actor, + actorOrgScope, type, secretPath }: TDeleteSecretRawDTO) => { @@ -927,7 +965,8 @@ export const secretServiceFactory = ({ type, path: secretPath, actor, - actorId + actorId, + actorOrgScope }); await snapshotService.performSnapshot(secret.folderId); @@ -936,14 +975,26 @@ export const secretServiceFactory = ({ return decryptSecretRaw(secret, botKey); }; - const getSecretVersions = async ({ actorId, actor, limit = 20, offset = 0, secretId }: TGetSecretVersionsDTO) => { + const getSecretVersions = async ({ + actorId, + actor, + actorOrgScope, + limit = 20, + offset = 0, + secretId + }: TGetSecretVersionsDTO) => { const secret = await secretDAL.findById(secretId); if (!secret) throw new BadRequestError({ message: "Failed to find secret" }); const folder = await folderDAL.findById(secret.folderId); if (!folder) throw new BadRequestError({ message: "Failed to find secret" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, folder.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + folder.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] }); @@ -964,7 +1015,6 @@ export const secretServiceFactory = ({ createSecretRaw, updateSecretRaw, deleteSecretRaw, - listSecretVersionsBySecretId, getSecretVersions, // external services function fnSecretBulkDelete, diff --git a/backend/src/services/secret/secret-types.ts b/backend/src/services/secret/secret-types.ts index 89e16d77b..50f678172 100644 --- a/backend/src/services/secret/secret-types.ts +++ b/backend/src/services/secret/secret-types.ts @@ -128,12 +128,6 @@ export type TDeleteBulkSecretDTO = { }>; } & TProjectPermission; -export type TListSecretVersionDTO = { - secretId: string; - offset?: number; - limit?: number; -} & Omit; - export type TGetSecretsRawDTO = { path: string; environment: string; diff --git a/backend/src/services/service-token/service-token-service.ts b/backend/src/services/service-token/service-token-service.ts index 9a4fd6afe..1c7dfacf3 100644 --- a/backend/src/services/service-token/service-token-service.ts +++ b/backend/src/services/service-token/service-token-service.ts @@ -39,6 +39,7 @@ export const serviceTokenServiceFactory = ({ tag, name, actor, + actorOrgScope, scopes, actorId, projectId, @@ -46,7 +47,7 @@ export const serviceTokenServiceFactory = ({ permissions, encryptedKey }: TCreateServiceTokenDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens); scopes.forEach(({ environment, secretPath }) => { @@ -90,11 +91,16 @@ export const serviceTokenServiceFactory = ({ return { token, serviceToken }; }; - const deleteServiceToken = async ({ actorId, actor, id }: TDeleteServiceTokenDTO) => { + const deleteServiceToken = async ({ actorId, actor, actorOrgScope, id }: TDeleteServiceTokenDTO) => { const serviceToken = await serviceTokenDAL.findById(id); if (!serviceToken) throw new BadRequestError({ message: "Token not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, serviceToken.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + serviceToken.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens); const deletedServiceToken = await serviceTokenDAL.deleteById(id); @@ -113,8 +119,8 @@ export const serviceTokenServiceFactory = ({ return { serviceToken, user: serviceTokenUser }; }; - const getProjectServiceTokens = async ({ actorId, actor, projectId }: TProjectServiceTokensDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const getProjectServiceTokens = async ({ actorId, actor, actorOrgScope, projectId }: TProjectServiceTokensDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens); const tokens = await serviceTokenDAL.find({ projectId }, { sort: [["createdAt", "desc"]] }); diff --git a/backend/src/services/webhook/webhook-service.ts b/backend/src/services/webhook/webhook-service.ts index c208ba472..b05b11029 100644 --- a/backend/src/services/webhook/webhook-service.ts +++ b/backend/src/services/webhook/webhook-service.ts @@ -30,13 +30,14 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer const createWebhook = async ({ actor, actorId, + actorOrgScope, projectId, webhookUrl, environment, secretPath, webhookSecretKey }: TCreateWebhookDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks); const env = await projectEnvDAL.findOne({ projectId, slug: environment }); if (!env) throw new BadRequestError({ message: "Env not found" }); @@ -72,33 +73,48 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer return { ...webhook, projectId, environment: env }; }; - const updateWebhook = async ({ actorId, actor, id, isDisabled }: TUpdateWebhookDTO) => { + const updateWebhook = async ({ actorId, actor, actorOrgScope, id, isDisabled }: TUpdateWebhookDTO) => { const webhook = await webhookDAL.findById(id); if (!webhook) throw new BadRequestError({ message: "Webhook not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + webhook.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks); const updatedWebhook = await webhookDAL.updateById(id, { isDisabled }); return { ...webhook, ...updatedWebhook }; }; - const deleteWebhook = async ({ id, actor, actorId }: TDeleteWebhookDTO) => { + const deleteWebhook = async ({ id, actor, actorId, actorOrgScope }: TDeleteWebhookDTO) => { const webhook = await webhookDAL.findById(id); if (!webhook) throw new BadRequestError({ message: "Webhook not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + webhook.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks); const deletedWebhook = await webhookDAL.deleteById(id); return { ...webhook, ...deletedWebhook }; }; - const testWebhook = async ({ id, actor, actorId }: TTestWebhookDTO) => { + const testWebhook = async ({ id, actor, actorId, actorOrgScope }: TTestWebhookDTO) => { const webhook = await webhookDAL.findById(id); if (!webhook) throw new BadRequestError({ message: "Webhook not found" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + webhook.projectId, + actorOrgScope + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); let webhookError: string | undefined; @@ -118,8 +134,15 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer return { ...webhook, ...updatedWebhook }; }; - const listWebhooks = async ({ actorId, actor, projectId, secretPath, environment }: TListWebhookDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + const listWebhooks = async ({ + actorId, + actor, + actorOrgScope, + projectId, + secretPath, + environment + }: TListWebhookDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgScope); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); return webhookDAL.findAllWebhooks(projectId, environment, secretPath);