diff --git a/backend/src/db/schemas/models.ts b/backend/src/db/schemas/models.ts index dac713cd9..c991b913d 100644 --- a/backend/src/db/schemas/models.ts +++ b/backend/src/db/schemas/models.ts @@ -215,3 +215,12 @@ export enum ProjectType { KMS = "kms", SSH = "ssh" } + +export enum ActionProjectType { + SecretManager = ProjectType.SecretManager, + CertificateManager = ProjectType.CertificateManager, + KMS = ProjectType.KMS, + SSH = ProjectType.SSH, + // project operations that happen on all types + Any = "any" +} diff --git a/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts b/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts index 72de6810a..2313cdec8 100644 --- a/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts +++ b/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; @@ -87,14 +87,14 @@ export const accessApprovalPolicyServiceFactory = ({ if (!groupApprovers && approvals > userApprovers.length + userApproverNames.length) throw new BadRequestError({ message: "Approvals cannot be greater than approvers" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -193,7 +193,14 @@ export const accessApprovalPolicyServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); // Anyone in the project should be able to get the policies. - await permissionService.getProjectPermission(actor, actorId, project.id, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId: project.id, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const accessApprovalPolicies = await accessApprovalPolicyDAL.find({ projectId: project.id, deletedAt: null }); return accessApprovalPolicies; @@ -237,14 +244,14 @@ export const accessApprovalPolicyServiceFactory = ({ if (!accessApprovalPolicy) { throw new NotFoundError({ message: `Secret approval policy with ID '${policyId}' not found` }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - accessApprovalPolicy.projectId, + projectId: accessApprovalPolicy.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval); @@ -321,14 +328,14 @@ export const accessApprovalPolicyServiceFactory = ({ const policy = await accessApprovalPolicyDAL.findById(policyId); if (!policy) throw new NotFoundError({ message: `Secret approval policy with ID '${policyId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - policy.projectId, + projectId: policy.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, ProjectPermissionSub.SecretApproval @@ -372,13 +379,14 @@ export const accessApprovalPolicyServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); - const { membership } = await permissionService.getProjectPermission( + const { membership } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!membership) { throw new ForbiddenRequestError({ message: "You are not a member of this project" }); } @@ -411,13 +419,14 @@ export const accessApprovalPolicyServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - policy.projectId, + projectId: policy.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); diff --git a/backend/src/ee/services/access-approval-request/access-approval-request-service.ts b/backend/src/ee/services/access-approval-request/access-approval-request-service.ts index 87ae6074c..163b97256 100644 --- a/backend/src/ee/services/access-approval-request/access-approval-request-service.ts +++ b/backend/src/ee/services/access-approval-request/access-approval-request-service.ts @@ -1,7 +1,7 @@ import slugify from "@sindresorhus/slugify"; import ms from "ms"; -import { ProjectMembershipRole } from "@app/db/schemas"; +import { ActionProjectType, ProjectMembershipRole } from "@app/db/schemas"; import { getConfig } from "@app/lib/config/env"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { alphaNumericNanoId } from "@app/lib/nanoid"; @@ -100,13 +100,14 @@ export const accessApprovalRequestServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); // Anyone can create an access approval request. - const { membership } = await permissionService.getProjectPermission( + const { membership } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!membership) { throw new ForbiddenRequestError({ message: "You are not a member of this project" }); } @@ -273,13 +274,14 @@ export const accessApprovalRequestServiceFactory = ({ const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); - const { membership } = await permissionService.getProjectPermission( + const { membership } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!membership) { throw new ForbiddenRequestError({ message: "You are not a member of this project" }); } @@ -318,13 +320,14 @@ export const accessApprovalRequestServiceFactory = ({ }); } - const { membership, hasRole } = await permissionService.getProjectPermission( + const { membership, hasRole } = await permissionService.getProjectPermission({ actor, actorId, - accessApprovalRequest.projectId, + projectId: accessApprovalRequest.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!membership) { throw new ForbiddenRequestError({ message: "You are not a member of this project" }); @@ -422,13 +425,14 @@ export const accessApprovalRequestServiceFactory = ({ const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); - const { membership } = await permissionService.getProjectPermission( + const { membership } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!membership) { throw new ForbiddenRequestError({ message: "You are not a member of this project" }); } 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 747c53c1a..e51c08fbe 100644 --- a/backend/src/ee/services/audit-log/audit-log-service.ts +++ b/backend/src/ee/services/audit-log/audit-log-service.ts @@ -1,5 +1,6 @@ import { ForbiddenError } from "@casl/ability"; +import { ActionProjectType } from "@app/db/schemas"; import { getConfig } from "@app/lib/config/env"; import { BadRequestError } from "@app/lib/errors"; @@ -26,13 +27,14 @@ export const auditLogServiceFactory = ({ const listAuditLogs = async ({ actorAuthMethod, actorId, actorOrgId, actor, filter }: TListProjectAuditLogDTO) => { // Filter logs for specific project if (filter.projectId) { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - filter.projectId, + projectId: filter.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); } else { // Organization-wide logs diff --git a/backend/src/ee/services/certificate-authority-crl/certificate-authority-crl-service.ts b/backend/src/ee/services/certificate-authority-crl/certificate-authority-crl-service.ts index 7282b0a29..b8f4ce663 100644 --- a/backend/src/ee/services/certificate-authority-crl/certificate-authority-crl-service.ts +++ b/backend/src/ee/services/certificate-authority-crl/certificate-authority-crl-service.ts @@ -1,6 +1,7 @@ import { ForbiddenError } from "@casl/ability"; import * as x509 from "@peculiar/x509"; +import { ActionProjectType } from "@app/db/schemas"; import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; @@ -66,13 +67,14 @@ export const certificateAuthorityCrlServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, diff --git a/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts index 81e76ff71..830c1aa57 100644 --- a/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts +++ b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts @@ -1,7 +1,7 @@ import { ForbiddenError, subject } from "@casl/ability"; import ms from "ms"; -import { ProjectType, SecretKeyEncoding } from "@app/db/schemas"; +import { ActionProjectType, SecretKeyEncoding } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { @@ -67,14 +67,14 @@ export const dynamicSecretLeaseServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.Lease, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -147,14 +147,14 @@ export const dynamicSecretLeaseServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.Lease, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -227,14 +227,14 @@ export const dynamicSecretLeaseServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.Lease, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -297,13 +297,14 @@ export const dynamicSecretLeaseServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.Lease, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -339,13 +340,14 @@ export const dynamicSecretLeaseServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.Lease, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) diff --git a/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts b/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts index db60b3e57..631d5b6ba 100644 --- a/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts +++ b/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError, subject } from "@casl/ability"; -import { ProjectType, SecretKeyEncoding } from "@app/db/schemas"; +import { ActionProjectType, SecretKeyEncoding } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { @@ -73,14 +73,14 @@ export const dynamicSecretServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.CreateRootCredential, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -145,14 +145,14 @@ export const dynamicSecretServiceFactory = ({ const projectId = project.id; - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.EditRootCredential, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -229,14 +229,14 @@ export const dynamicSecretServiceFactory = ({ const projectId = project.id; - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.DeleteRootCredential, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -290,13 +290,14 @@ export const dynamicSecretServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); const projectId = project.id; - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.ReadRootCredential, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -340,13 +341,14 @@ export const dynamicSecretServiceFactory = ({ isInternal }: TListDynamicSecretsMultiEnvDTO) => { if (!isInternal) { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); // verify user has access to each env in request environmentSlugs.forEach((environmentSlug) => @@ -383,13 +385,14 @@ export const dynamicSecretServiceFactory = ({ search, projectId }: TGetDynamicSecretsCountDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.ReadRootCredential, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -431,13 +434,14 @@ export const dynamicSecretServiceFactory = ({ projectId = project.id; } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionDynamicSecretActions.ReadRootCredential, subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path }) @@ -462,13 +466,14 @@ export const dynamicSecretServiceFactory = ({ { folderMappings, filters, projectId }: TListDynamicSecretsByFolderMappingsDTO, actor: OrgServiceActor ) => { - const { permission } = await permissionService.getProjectPermission( - actor.type, - actor.id, + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, projectId, - actor.authMethod, - actor.orgId - ); + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.SecretManager + }); const userAccessibleFolderMappings = folderMappings.filter(({ path, environment }) => permission.can( @@ -507,13 +512,14 @@ export const dynamicSecretServiceFactory = ({ ...params }: TListDynamicSecretsMultiEnvDTO) => { if (!isInternal) { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); // verify user has access to each env in request environmentSlugs.forEach((environmentSlug) => diff --git a/backend/src/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service.ts b/backend/src/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service.ts index b1c40a879..3a38c0d65 100644 --- a/backend/src/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service.ts +++ b/backend/src/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service.ts @@ -2,7 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability"; import { packRules } from "@casl/ability/extra"; import ms from "ms"; -import { TableName } from "@app/db/schemas"; +import { ActionProjectType, TableName } from "@app/db/schemas"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { unpackPermissions } from "@app/server/routes/santizedSchemas/permission"; @@ -55,24 +55,26 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({ if (!identityProjectMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Identity, { identityId }) ); - const { permission: targetIdentityPermission } = await permissionService.getProjectPermission( - ActorType.IDENTITY, - identityId, - identityProjectMembership.projectId, + const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({ + actor: ActorType.IDENTITY, + actorId: identityId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); // we need to validate that the privilege given is not higher than the assigning users permission // @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules @@ -135,24 +137,26 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({ message: `Failed to find identity with membership ${identityPrivilege.projectMembershipId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId }) ); - const { permission: targetIdentityPermission } = await permissionService.getProjectPermission( - ActorType.IDENTITY, - identityProjectMembership.identityId, - identityProjectMembership.projectId, + const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({ + actor: ActorType.IDENTITY, + actorId: identityProjectMembership.identityId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); // we need to validate that the privilege given is not higher than the assigning users permission // @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules @@ -215,24 +219,26 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({ message: `Failed to find identity with membership ${identityPrivilege.projectMembershipId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId }) ); - const { permission: identityRolePermission } = await permissionService.getProjectPermission( - ActorType.IDENTITY, - identityProjectMembership.identityId, - identityProjectMembership.projectId, + const { permission: identityRolePermission } = await permissionService.getProjectPermission({ + actor: ActorType.IDENTITY, + actorId: identityProjectMembership.identityId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); if (!hasRequiredPriviledges) throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" }); @@ -260,13 +266,14 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({ message: `Failed to find identity with membership ${identityPrivilege.projectMembershipId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId }) @@ -294,13 +301,14 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({ const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); if (!identityProjectMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId }) @@ -329,13 +337,14 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({ const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); if (!identityProjectMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Identity, { identityId: identityProjectMembership.identityId }) diff --git a/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts b/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts index 127de1383..16c0cc212 100644 --- a/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts +++ b/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts @@ -2,6 +2,7 @@ import { ForbiddenError, MongoAbility, RawRuleOf, subject } from "@casl/ability" import { PackRule, packRules, unpackRules } from "@casl/ability/extra"; import ms from "ms"; +import { ActionProjectType } from "@app/db/schemas"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { UnpackedPermissionSchema } from "@app/server/routes/santizedSchemas/permission"; @@ -62,25 +63,27 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ if (!identityProjectMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Identity, { identityId }) ); - const { permission: targetIdentityPermission } = await permissionService.getProjectPermission( - ActorType.IDENTITY, - identityId, - identityProjectMembership.projectId, + const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({ + actor: ActorType.IDENTITY, + actorId: identityId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); // we need to validate that the privilege given is not higher than the assigning users permission // @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules @@ -143,26 +146,28 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ if (!identityProjectMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Identity, { identityId }) ); - const { permission: targetIdentityPermission } = await permissionService.getProjectPermission( - ActorType.IDENTITY, - identityProjectMembership.identityId, - identityProjectMembership.projectId, + const { permission: targetIdentityPermission } = await permissionService.getProjectPermission({ + actor: ActorType.IDENTITY, + actorId: identityProjectMembership.identityId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); // we need to validate that the privilege given is not higher than the assigning users permission // @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules @@ -242,25 +247,27 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ if (!identityProjectMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Identity, { identityId }) ); - const { permission: identityRolePermission } = await permissionService.getProjectPermission( - ActorType.IDENTITY, - identityProjectMembership.identityId, - identityProjectMembership.projectId, + const { permission: identityRolePermission } = await permissionService.getProjectPermission({ + actor: ActorType.IDENTITY, + actorId: identityProjectMembership.identityId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); if (!hasRequiredPriviledges) throw new ForbiddenRequestError({ message: "Failed to edit more privileged identity" }); @@ -299,13 +306,14 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); if (!identityProjectMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Identity, { identityId }) @@ -341,13 +349,14 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({ const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); if (!identityProjectMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, diff --git a/backend/src/ee/services/permission/permission-service-types.ts b/backend/src/ee/services/permission/permission-service-types.ts index 620e7a61c..570e2b6b1 100644 --- a/backend/src/ee/services/permission/permission-service-types.ts +++ b/backend/src/ee/services/permission/permission-service-types.ts @@ -1,3 +1,6 @@ +import { ActionProjectType } from "@app/db/schemas"; +import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type"; + export type TBuildProjectPermissionDTO = { permissions?: unknown; role: string; @@ -7,3 +10,34 @@ export type TBuildOrgPermissionDTO = { permissions?: unknown; role: string; }[]; + +export type TGetUserProjectPermissionArg = { + userId: string; + projectId: string; + authMethod: ActorAuthMethod; + actionProjectType: ActionProjectType; + userOrgId?: string; +}; + +export type TGetIdentityProjectPermissionArg = { + identityId: string; + projectId: string; + identityOrgId?: string; + actionProjectType: ActionProjectType; +}; + +export type TGetServiceTokenProjectPermissionArg = { + serviceTokenId: string; + projectId: string; + actorOrgId?: string; + actionProjectType: ActionProjectType; +}; + +export type TGetProjectPermissionArg = { + actor: ActorType; + actorId: string; + projectId: string; + actorAuthMethod: ActorAuthMethod; + actorOrgId?: string; + actionProjectType: ActionProjectType; +}; diff --git a/backend/src/ee/services/permission/permission-service.ts b/backend/src/ee/services/permission/permission-service.ts index 79103bd2f..ddaf55d9d 100644 --- a/backend/src/ee/services/permission/permission-service.ts +++ b/backend/src/ee/services/permission/permission-service.ts @@ -4,9 +4,9 @@ import { MongoQuery } from "@ucast/mongo2js"; import handlebars from "handlebars"; import { + ActionProjectType, OrgMembershipRole, ProjectMembershipRole, - ProjectType, ServiceTokenScopes, TIdentityProjectMemberships, TProjectMemberships @@ -23,7 +23,14 @@ import { TServiceTokenDALFactory } from "@app/services/service-token/service-tok import { orgAdminPermissions, orgMemberPermissions, orgNoAccessPermissions, OrgPermissionSet } from "./org-permission"; import { TPermissionDALFactory } from "./permission-dal"; import { escapeHandlebarsMissingMetadata, validateOrgSSO } from "./permission-fns"; -import { TBuildOrgPermissionDTO, TBuildProjectPermissionDTO } from "./permission-service-types"; +import { + TBuildOrgPermissionDTO, + TBuildProjectPermissionDTO, + TGetIdentityProjectPermissionArg, + TGetProjectPermissionArg, + TGetServiceTokenProjectPermissionArg, + TGetUserProjectPermissionArg +} from "./permission-service-types"; import { buildServiceTokenProjectPermission, projectAdminPermissions, @@ -193,12 +200,13 @@ export const permissionServiceFactory = ({ }; // user permission for a project in an organization - const getUserProjectPermission = async ( - userId: string, - projectId: string, - authMethod: ActorAuthMethod, - userOrgId?: string - ): Promise> => { + const getUserProjectPermission = async ({ + userId, + projectId, + authMethod, + userOrgId, + actionProjectType + }: TGetUserProjectPermissionArg): Promise> => { const userProjectPermission = await permissionDAL.getProjectPermission(userId, projectId); if (!userProjectPermission) throw new ForbiddenRequestError({ name: "User not a part of the specified project" }); @@ -219,6 +227,12 @@ export const permissionServiceFactory = ({ validateOrgSSO(authMethod, userProjectPermission.orgAuthEnforced); + if (actionProjectType !== ActionProjectType.Any && actionProjectType !== userProjectPermission.projectType) { + throw new BadRequestError({ + message: `The project is of type ${userProjectPermission.projectType}. Operations of type ${actionProjectType} are not allowed.` + }); + } + // join two permissions and pass to build the final permission set const rolePermissions = userProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || []; const additionalPrivileges = @@ -256,13 +270,6 @@ export const permissionServiceFactory = ({ return { permission, membership: userProjectPermission, - ForbidOnInvalidProjectType: (productType: ProjectType) => { - if (productType !== userProjectPermission.projectType) { - throw new BadRequestError({ - message: `The project is of type ${userProjectPermission.projectType}. Operations of type ${productType} are not allowed.` - }); - } - }, hasRole: (role: string) => userProjectPermission.roles.findIndex( ({ role: slug, customRoleSlug }) => role === slug || slug === customRoleSlug @@ -270,11 +277,12 @@ export const permissionServiceFactory = ({ }; }; - const getIdentityProjectPermission = async ( - identityId: string, - projectId: string, - identityOrgId: string | undefined - ): Promise> => { + const getIdentityProjectPermission = async ({ + identityId, + projectId, + identityOrgId, + actionProjectType + }: TGetIdentityProjectPermissionArg): Promise> => { const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId); if (!identityProjectPermission) throw new ForbiddenRequestError({ @@ -293,6 +301,12 @@ export const permissionServiceFactory = ({ throw new ForbiddenRequestError({ name: "Identity is not a member of the specified organization" }); } + if (actionProjectType !== ActionProjectType.Any && actionProjectType !== identityProjectPermission.projectType) { + throw new BadRequestError({ + message: `The project is of type ${identityProjectPermission.projectType}. Operations of type ${actionProjectType} are not allowed.` + }); + } + const rolePermissions = identityProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || []; const additionalPrivileges = @@ -331,13 +345,6 @@ export const permissionServiceFactory = ({ return { permission, membership: identityProjectPermission, - ForbidOnInvalidProjectType: (productType: ProjectType) => { - if (productType !== identityProjectPermission.projectType) { - throw new BadRequestError({ - message: `The project is of type ${identityProjectPermission.projectType}. Operations of type ${productType} are not allowed.` - }); - } - }, hasRole: (role: string) => identityProjectPermission.roles.findIndex( ({ role: slug, customRoleSlug }) => role === slug || slug === customRoleSlug @@ -345,11 +352,12 @@ export const permissionServiceFactory = ({ }; }; - const getServiceTokenProjectPermission = async ( - serviceTokenId: string, - projectId: string, - actorOrgId: string | undefined - ) => { + const getServiceTokenProjectPermission = async ({ + serviceTokenId, + projectId, + actorOrgId, + actionProjectType + }: TGetServiceTokenProjectPermissionArg) => { const serviceToken = await serviceTokenDAL.findById(serviceTokenId); if (!serviceToken) throw new NotFoundError({ message: `Service token with ID '${serviceTokenId}' not found` }); @@ -373,17 +381,16 @@ export const permissionServiceFactory = ({ }); } + if (actionProjectType !== ActionProjectType.Any && actionProjectType !== serviceTokenProject.type) { + throw new BadRequestError({ + message: `The project is of type ${serviceTokenProject.type}. Operations of type ${actionProjectType} are not allowed.` + }); + } + const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []); return { permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions), - membership: undefined, - ForbidOnInvalidProjectType: (productType: ProjectType) => { - if (productType !== serviceTokenProject.type) { - throw new BadRequestError({ - message: `The project is of type ${serviceTokenProject.type}. Operations of type ${productType} are not allowed.` - }); - } - } + membership: undefined }; }; @@ -392,7 +399,6 @@ export const permissionServiceFactory = ({ permission: MongoAbility; membership: undefined; hasRole: (arg: string) => boolean; - ForbidOnInvalidProjectType: (type: ProjectType) => void; } // service token doesn't have both membership and roles : { permission: MongoAbility; @@ -402,7 +408,6 @@ export const permissionServiceFactory = ({ roles: Array<{ role: string }>; }; hasRole: (role: string) => boolean; - ForbidOnInvalidProjectType: (type: ProjectType) => void; }; const getProjectPermissions = async (projectId: string) => { @@ -522,20 +527,37 @@ export const permissionServiceFactory = ({ }; }; - const getProjectPermission = async ( - type: T, - id: string, - projectId: string, - actorAuthMethod: ActorAuthMethod, - actorOrgId: string | undefined - ): Promise> => { - switch (type) { + const getProjectPermission = async ({ + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId, + actionProjectType + }: TGetProjectPermissionArg): Promise> => { + switch (actor) { case ActorType.USER: - return getUserProjectPermission(id, projectId, actorAuthMethod, actorOrgId) as Promise>; + return getUserProjectPermission({ + userId: actorId, + projectId, + authMethod: actorAuthMethod, + userOrgId: actorOrgId, + actionProjectType + }) as Promise>; case ActorType.SERVICE: - return getServiceTokenProjectPermission(id, projectId, actorOrgId) as Promise>; + return getServiceTokenProjectPermission({ + serviceTokenId: actorId, + projectId, + actorOrgId, + actionProjectType + }) as Promise>; case ActorType.IDENTITY: - return getIdentityProjectPermission(id, projectId, actorOrgId) as Promise>; + return getIdentityProjectPermission({ + identityId: actorId, + projectId, + identityOrgId: actorOrgId, + actionProjectType + }) as Promise>; default: throw new BadRequestError({ message: "Invalid actor provided", diff --git a/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts b/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts index 86d8e652a..14586d5e2 100644 --- a/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts +++ b/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts @@ -2,7 +2,7 @@ import { ForbiddenError, MongoAbility, RawRuleOf } from "@casl/ability"; import { PackRule, packRules, unpackRules } from "@casl/ability/extra"; import ms from "ms"; -import { TableName } from "@app/db/schemas"; +import { ActionProjectType, TableName } from "@app/db/schemas"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { UnpackedPermissionSchema } from "@app/server/routes/santizedSchemas/permission"; @@ -55,21 +55,23 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ if (!projectMembership) throw new NotFoundError({ message: `Project membership with ID ${projectMembershipId} found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectMembership.projectId, + projectId: projectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); - const { permission: targetUserPermission } = await permissionService.getProjectPermission( - ActorType.USER, - projectMembership.userId, - projectMembership.projectId, + const { permission: targetUserPermission } = await permissionService.getProjectPermission({ + actor: ActorType.USER, + actorId: projectMembership.userId, + projectId: projectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); // we need to validate that the privilege given is not higher than the assigning users permission // @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules @@ -140,21 +142,23 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ message: `Project membership for user with ID '${userPrivilege.userId}' not found in project with ID '${userPrivilege.projectId}'` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectMembership.projectId, + projectId: projectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); - const { permission: targetUserPermission } = await permissionService.getProjectPermission( - ActorType.USER, - projectMembership.userId, - projectMembership.projectId, + const { permission: targetUserPermission } = await permissionService.getProjectPermission({ + actor: ActorType.USER, + actorId: projectMembership.userId, + projectId: projectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); // we need to validate that the privilege given is not higher than the assigning users permission // @ts-expect-error this is expected error because of one being really accurate rule definition other being a bit more broader. Both are valid casl rules @@ -224,13 +228,14 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ message: `Project membership for user with ID '${userPrivilege.userId}' not found in project with ID '${userPrivilege.projectId}'` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectMembership.projectId, + projectId: projectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); const deletedPrivilege = await projectUserAdditionalPrivilegeDAL.deleteById(userPrivilege.id); @@ -260,13 +265,14 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ message: `Project membership for user with ID '${userPrivilege.userId}' not found in project with ID '${userPrivilege.projectId}'` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectMembership.projectId, + projectId: projectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); return { @@ -286,13 +292,14 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({ if (!projectMembership) throw new NotFoundError({ message: `Project membership with ID ${projectMembershipId} not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectMembership.projectId, + projectId: projectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); const userPrivileges = await projectUserAdditionalPrivilegeDAL.find( 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 b0de6ad75..189ba5c1f 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 @@ -1,7 +1,7 @@ import { ForbiddenError } from "@casl/ability"; import picomatch from "picomatch"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; @@ -79,14 +79,14 @@ export const secretApprovalPolicyServiceFactory = ({ if (!groupApprovers.length && approvals > approvers.length) throw new BadRequestError({ message: "Approvals cannot be greater than approvers" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SecretApproval @@ -193,14 +193,14 @@ export const secretApprovalPolicyServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - secretApprovalPolicy.projectId, + projectId: secretApprovalPolicy.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval); const plan = await licenseService.getPlan(actorOrgId); @@ -288,14 +288,14 @@ export const secretApprovalPolicyServiceFactory = ({ if (!sapPolicy) throw new NotFoundError({ message: `Secret approval policy with ID '${secretPolicyId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - sapPolicy.projectId, + projectId: sapPolicy.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, ProjectPermissionSub.SecretApproval @@ -328,13 +328,14 @@ export const secretApprovalPolicyServiceFactory = ({ actorAuthMethod, projectId }: TListSapDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); const sapPolicies = await secretApprovalPolicyDAL.find({ projectId, deletedAt: null }); @@ -372,7 +373,14 @@ export const secretApprovalPolicyServiceFactory = ({ environment, secretPath }: TGetBoardSapDTO) => { - await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); return getSecretApprovalPolicy(projectId, environment, secretPath); }; @@ -392,13 +400,14 @@ export const secretApprovalPolicyServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - sapPolicy.projectId, + projectId: sapPolicy.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); 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 76cf35ca0..5b5ea6ce3 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 @@ -1,8 +1,8 @@ import { ForbiddenError, subject } from "@casl/ability"; import { + ActionProjectType, ProjectMembershipRole, - ProjectType, SecretEncryptionAlgo, SecretKeyEncoding, SecretType, @@ -147,13 +147,14 @@ export const secretApprovalRequestServiceFactory = ({ const requestCount = async ({ projectId, actor, actorId, actorOrgId, actorAuthMethod }: TApprovalRequestCountDTO) => { if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); - await permissionService.getProjectPermission( - actor as ActorType.USER, + await permissionService.getProjectPermission({ + actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const count = await secretApprovalRequestDAL.findProjectRequestCount(projectId, actorId); return count; @@ -173,7 +174,14 @@ export const secretApprovalRequestServiceFactory = ({ }: TListApprovalsDTO) => { if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); - await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const { shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId); if (shouldUseSecretV2Bridge) { @@ -216,13 +224,14 @@ export const secretApprovalRequestServiceFactory = ({ const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId); const { policy } = secretApprovalRequest; - const { hasRole } = await permissionService.getProjectPermission( + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if ( !hasRole(ProjectMembershipRole.Admin) && secretApprovalRequest.committerUserId !== actorId && @@ -336,13 +345,14 @@ export const secretApprovalRequestServiceFactory = ({ }); } - const { hasRole } = await permissionService.getProjectPermission( - ActorType.USER, + const { hasRole } = await permissionService.getProjectPermission({ + actor: ActorType.USER, actorId, - secretApprovalRequest.projectId, + projectId: secretApprovalRequest.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if ( !hasRole(ProjectMembershipRole.Admin) && secretApprovalRequest.committerUserId !== actorId && @@ -402,13 +412,14 @@ export const secretApprovalRequestServiceFactory = ({ }); } - const { hasRole } = await permissionService.getProjectPermission( - ActorType.USER, + const { hasRole } = await permissionService.getProjectPermission({ + actor: ActorType.USER, actorId, - secretApprovalRequest.projectId, + projectId: secretApprovalRequest.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if ( !hasRole(ProjectMembershipRole.Admin) && secretApprovalRequest.committerUserId !== actorId && @@ -458,13 +469,14 @@ export const secretApprovalRequestServiceFactory = ({ }); } - const { hasRole } = await permissionService.getProjectPermission( - ActorType.USER, + const { hasRole } = await permissionService.getProjectPermission({ + actor: ActorType.USER, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if ( !hasRole(ProjectMembershipRole.Admin) && @@ -889,14 +901,14 @@ export const secretApprovalRequestServiceFactory = ({ }: TGenerateSecretApprovalRequestDTO) => { if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Secrets, { environment, secretPath }) @@ -1170,14 +1182,14 @@ export const secretApprovalRequestServiceFactory = ({ if (actor === ActorType.SERVICE || actor === ActorType.Machine) throw new BadRequestError({ message: "Cannot use service token or machine token over protected branches" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) throw new NotFoundError({ 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 7031d8d12..c456e1581 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-service.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-service.ts @@ -1,7 +1,7 @@ import { ForbiddenError, subject } from "@casl/ability"; import Ajv from "ajv"; -import { ProjectType, ProjectVersion, TableName } from "@app/db/schemas"; +import { ActionProjectType, ProjectVersion, TableName } from "@app/db/schemas"; import { decryptSymmetric128BitHexKeyUTF8, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { TProjectPermission } from "@app/lib/types"; @@ -53,14 +53,14 @@ export const secretRotationServiceFactory = ({ actorAuthMethod, projectId }: TProjectPermission) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); return { @@ -82,14 +82,14 @@ export const secretRotationServiceFactory = ({ secretPath, environment }: TCreateSecretRotationDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SecretRotation @@ -191,13 +191,14 @@ export const secretRotationServiceFactory = ({ }; const getByProjectId = async ({ actorId, projectId, actor, actorOrgId, actorAuthMethod }: TListByProjectIdDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId); if (shouldUseSecretV2Bridge) { @@ -236,14 +237,14 @@ export const secretRotationServiceFactory = ({ message: "Failed to add secret rotation due to plan restriction. Upgrade plan to add secret rotation." }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - doc.projectId, + projectId: project.id, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretRotation); await secretRotationQueue.removeFromQueue(doc.id, doc.interval); await secretRotationQueue.addToQueue(doc.id, doc.interval); @@ -254,14 +255,14 @@ export const secretRotationServiceFactory = ({ const doc = await secretRotationDAL.findById(rotationId); if (!doc) throw new NotFoundError({ message: `Rotation with ID '${rotationId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - doc.projectId, + projectId: doc.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, ProjectPermissionSub.SecretRotation 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 2526facb7..2e4ed0f93 100644 --- a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts +++ b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError, subject } from "@casl/ability"; -import { ProjectType, TableName, TSecretTagJunctionInsert, TSecretV2TagJunctionInsert } from "@app/db/schemas"; +import { ActionProjectType, TableName, TSecretTagJunctionInsert, TSecretV2TagJunctionInsert } from "@app/db/schemas"; import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto"; import { InternalServerError, NotFoundError } from "@app/lib/errors"; import { groupBy } from "@app/lib/fn"; @@ -83,13 +83,14 @@ export const secretSnapshotServiceFactory = ({ actorAuthMethod, path }: TProjectSnapshotCountDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); // We need to check if the user has access to the secrets in the folder. If we don't do this, a user could theoretically access snapshot secret values even if they don't have read access to the secrets in the folder. @@ -119,13 +120,14 @@ export const secretSnapshotServiceFactory = ({ limit = 20, offset = 0 }: TProjectSnapshotListDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); // We need to check if the user has access to the secrets in the folder. If we don't do this, a user could theoretically access snapshot secret values even if they don't have read access to the secrets in the folder. @@ -147,13 +149,14 @@ export const secretSnapshotServiceFactory = ({ const getSnapshotData = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TGetSnapshotDataDTO) => { const snapshot = await snapshotDAL.findById(id); if (!snapshot) throw new NotFoundError({ message: `Snapshot with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - snapshot.projectId, + projectId: snapshot.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); const shouldUseBridge = snapshot.projectVersion === 3; @@ -322,14 +325,14 @@ export const secretSnapshotServiceFactory = ({ if (!snapshot) throw new NotFoundError({ message: `Snapshot with ID '${snapshotId}' not found` }); const shouldUseBridge = snapshot.projectVersion === 3; - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - snapshot.projectId, + projectId: snapshot.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SecretRollback diff --git a/backend/src/ee/services/ssh-certificate-template/ssh-certificate-template-service.ts b/backend/src/ee/services/ssh-certificate-template/ssh-certificate-template-service.ts index a31b9b858..30c50cc9e 100644 --- a/backend/src/ee/services/ssh-certificate-template/ssh-certificate-template-service.ts +++ b/backend/src/ee/services/ssh-certificate-template/ssh-certificate-template-service.ts @@ -1,7 +1,7 @@ import { ForbiddenError } from "@casl/ability"; import ms from "ms"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; @@ -54,15 +54,15 @@ export const sshCertificateTemplateServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SshCertificateTemplates @@ -127,15 +127,15 @@ export const sshCertificateTemplateServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - certTemplate.projectId, + projectId: certTemplate.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, ProjectPermissionSub.SshCertificateTemplates @@ -196,15 +196,15 @@ export const sshCertificateTemplateServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - certificateTemplate.projectId, + projectId: certificateTemplate.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, ProjectPermissionSub.SshCertificateTemplates @@ -223,15 +223,15 @@ export const sshCertificateTemplateServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - certTemplate.projectId, + projectId: certTemplate.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateTemplates diff --git a/backend/src/ee/services/ssh/ssh-certificate-authority-service.ts b/backend/src/ee/services/ssh/ssh-certificate-authority-service.ts index 0b408c9dd..d7ca511e4 100644 --- a/backend/src/ee/services/ssh/ssh-certificate-authority-service.ts +++ b/backend/src/ee/services/ssh/ssh-certificate-authority-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { TSshCertificateAuthorityDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-dal"; @@ -65,15 +65,15 @@ export const sshCertificateAuthorityServiceFactory = ({ actor, actorOrgId }: TCreateSshCaDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SshCertificateAuthorities @@ -118,15 +118,15 @@ export const sshCertificateAuthorityServiceFactory = ({ const ca = await sshCertificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `SSH CA with ID '${caId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateAuthorities @@ -187,15 +187,15 @@ export const sshCertificateAuthorityServiceFactory = ({ const ca = await sshCertificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `SSH CA with ID '${caId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, ProjectPermissionSub.SshCertificateAuthorities @@ -226,15 +226,15 @@ export const sshCertificateAuthorityServiceFactory = ({ const ca = await sshCertificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `SSH CA with ID '${caId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, ProjectPermissionSub.SshCertificateAuthorities @@ -268,15 +268,15 @@ export const sshCertificateAuthorityServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - sshCertificateTemplate.projectId, + projectId: sshCertificateTemplate.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SshCertificates @@ -390,15 +390,15 @@ export const sshCertificateAuthorityServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - sshCertificateTemplate.projectId, + projectId: sshCertificateTemplate.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.SshCertificates @@ -488,15 +488,15 @@ export const sshCertificateAuthorityServiceFactory = ({ const ca = await sshCertificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `SSH CA with ID '${caId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateTemplates 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 ecd2b3070..c407bdc82 100644 --- a/backend/src/ee/services/trusted-ip/trusted-ip-service.ts +++ b/backend/src/ee/services/trusted-ip/trusted-ip-service.ts @@ -1,5 +1,6 @@ import { ForbiddenError } from "@casl/ability"; +import { ActionProjectType } from "@app/db/schemas"; import { BadRequestError } from "@app/lib/errors"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { TProjectPermission } from "@app/lib/types"; @@ -27,13 +28,14 @@ export const trustedIpServiceFactory = ({ projectDAL }: TTrustedIpServiceFactoryDep) => { const listIpsByProjectId = async ({ projectId, actor, actorId, actorAuthMethod, actorOrgId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList); const trustedIps = await trustedIpDAL.find({ projectId @@ -51,13 +53,14 @@ export const trustedIpServiceFactory = ({ comment, isActive }: TCreateIpDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); const project = await projectDAL.findById(projectId); @@ -96,13 +99,14 @@ export const trustedIpServiceFactory = ({ comment, trustedIpId }: TUpdateIpDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); const project = await projectDAL.findById(projectId); @@ -141,13 +145,14 @@ export const trustedIpServiceFactory = ({ actorAuthMethod, trustedIpId }: TDeleteIpDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); const project = await projectDAL.findById(projectId); diff --git a/backend/src/server/routes/v1/dashboard-router.ts b/backend/src/server/routes/v1/dashboard-router.ts index 372fd04a1..d96c45f04 100644 --- a/backend/src/server/routes/v1/dashboard-router.ts +++ b/backend/src/server/routes/v1/dashboard-router.ts @@ -1,7 +1,7 @@ import { ForbiddenError, subject } from "@casl/ability"; import { z } from "zod"; -import { SecretFoldersSchema, SecretImportsSchema, SecretTagsSchema } from "@app/db/schemas"; +import { ActionProjectType, SecretFoldersSchema, SecretImportsSchema, SecretTagsSchema } from "@app/db/schemas"; import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types"; import { ProjectPermissionDynamicSecretActions, @@ -220,13 +220,14 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => { totalCount: totalFolderCount ?? 0 }; - const { permission } = await server.services.permission.getProjectPermission( - req.permission.type, - req.permission.id, + const { permission } = await server.services.permission.getProjectPermission({ + actor: req.permission.type, + actorId: req.permission.id, projectId, - req.permission.authMethod, - req.permission.orgId - ); + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + actionProjectType: ActionProjectType.SecretManager + }); const allowedDynamicSecretEnvironments = // filter envs user has access to environments.filter((environment) => diff --git a/backend/src/services/certificate-authority/certificate-authority-service.ts b/backend/src/services/certificate-authority/certificate-authority-service.ts index f61a39a00..42efc4f29 100644 --- a/backend/src/services/certificate-authority/certificate-authority-service.ts +++ b/backend/src/services/certificate-authority/certificate-authority-service.ts @@ -5,7 +5,7 @@ import crypto, { KeyObject } from "crypto"; import ms from "ms"; import { z } from "zod"; -import { ProjectType, TCertificateAuthorities, TCertificateTemplates } from "@app/db/schemas"; +import { ActionProjectType, ProjectType, TCertificateAuthorities, TCertificateTemplates } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { getConfig } from "@app/lib/config/env"; @@ -136,14 +136,14 @@ export const certificateAuthorityServiceFactory = ({ projectId = certManagerProjectFromSplit.id; } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -305,13 +305,14 @@ export const certificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, ProjectPermissionSub.CertificateAuthorities @@ -336,14 +337,14 @@ export const certificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -362,14 +363,14 @@ export const certificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, @@ -388,13 +389,14 @@ export const certificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -449,14 +451,14 @@ export const certificateAuthorityServiceFactory = ({ if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -720,13 +722,14 @@ export const certificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, @@ -755,13 +758,14 @@ export const certificateAuthorityServiceFactory = ({ if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, @@ -835,14 +839,14 @@ export const certificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: "CA not found" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -982,14 +986,14 @@ export const certificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -1145,14 +1149,14 @@ export const certificateAuthorityServiceFactory = ({ throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Certificates); @@ -1474,14 +1478,14 @@ export const certificateAuthorityServiceFactory = ({ } if (!dto.isInternal) { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( - dto.actor, - dto.actorId, - ca.projectId, - dto.actorAuthMethod, - dto.actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + const { permission } = await permissionService.getProjectPermission({ + actor: dto.actor, + actorId: dto.actorId, + projectId: ca.projectId, + actorAuthMethod: dto.actorAuthMethod, + actorOrgId: dto.actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -1832,13 +1836,14 @@ export const certificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.findById(caId); if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, diff --git a/backend/src/services/certificate-template/certificate-template-service.ts b/backend/src/services/certificate-template/certificate-template-service.ts index c8224d28f..9a5cd9269 100644 --- a/backend/src/services/certificate-template/certificate-template-service.ts +++ b/backend/src/services/certificate-template/certificate-template-service.ts @@ -2,7 +2,7 @@ import { ForbiddenError } from "@casl/ability"; import * as x509 from "@peculiar/x509"; import bcrypt from "bcrypt"; -import { ProjectType, TCertificateTemplateEstConfigsUpdate } from "@app/db/schemas"; +import { ActionProjectType, TCertificateTemplateEstConfigsUpdate } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; @@ -67,14 +67,14 @@ export const certificateTemplateServiceFactory = ({ message: `CA with ID ${caId} not found` }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -129,14 +129,14 @@ export const certificateTemplateServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - certTemplate.projectId, + projectId: certTemplate.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -187,14 +187,14 @@ export const certificateTemplateServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - certTemplate.projectId, + projectId: certTemplate.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, @@ -214,13 +214,14 @@ export const certificateTemplateServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - certTemplate.projectId, + projectId: certTemplate.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, @@ -255,14 +256,14 @@ export const certificateTemplateServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - certTemplate.projectId, + projectId: certTemplate.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -340,14 +341,14 @@ export const certificateTemplateServiceFactory = ({ }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - certTemplate.projectId, + projectId: certTemplate.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -422,13 +423,14 @@ export const certificateTemplateServiceFactory = ({ } if (!dto.isInternal) { - const { permission } = await permissionService.getProjectPermission( - dto.actor, - dto.actorId, - certTemplate.projectId, - dto.actorAuthMethod, - dto.actorOrgId - ); + const { permission } = await permissionService.getProjectPermission({ + actor: dto.actor, + actorId: dto.actorId, + projectId: certTemplate.projectId, + actorAuthMethod: dto.actorAuthMethod, + actorOrgId: dto.actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, diff --git a/backend/src/services/certificate/certificate-service.ts b/backend/src/services/certificate/certificate-service.ts index 3a96ecf91..0ca0d64c6 100644 --- a/backend/src/services/certificate/certificate-service.ts +++ b/backend/src/services/certificate/certificate-service.ts @@ -1,7 +1,7 @@ import { ForbiddenError } from "@casl/ability"; import * as x509 from "@peculiar/x509"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType } from "@app/db/schemas"; import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; @@ -50,14 +50,14 @@ export const certificateServiceFactory = ({ const cert = await certificateDAL.findOne({ serialNumber }); const ca = await certificateAuthorityDAL.findById(cert.caId); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Certificates); @@ -74,14 +74,14 @@ export const certificateServiceFactory = ({ const cert = await certificateDAL.findOne({ serialNumber }); const ca = await certificateAuthorityDAL.findById(cert.caId); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Certificates); @@ -109,14 +109,14 @@ export const certificateServiceFactory = ({ const cert = await certificateDAL.findOne({ serialNumber }); const ca = await certificateAuthorityDAL.findById(cert.caId); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Certificates); @@ -156,13 +156,14 @@ export const certificateServiceFactory = ({ const cert = await certificateDAL.findOne({ serialNumber }); const ca = await certificateAuthorityDAL.findById(cert.caId); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - ca.projectId, + projectId: ca.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Certificates); diff --git a/backend/src/services/cmek/cmek-service.ts b/backend/src/services/cmek/cmek-service.ts index 4f14cab66..775367e6e 100644 --- a/backend/src/services/cmek/cmek-service.ts +++ b/backend/src/services/cmek/cmek-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType, ProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionCmekActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; @@ -34,14 +34,14 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj projectId = cmekProjectFromSplit.id; } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( - actor.type, - actor.id, + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, projectId, - actor.authMethod, - actor.orgId - ); - ForbidOnInvalidProjectType(ProjectType.KMS); + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.KMS + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Create, ProjectPermissionSub.Cmek); const cmek = await kmsService.generateKmsKey({ @@ -60,14 +60,14 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj if (!key.projectId || key.isReserved) throw new BadRequestError({ message: "Key is not customer managed" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( - actor.type, - actor.id, - key.projectId, - actor.authMethod, - actor.orgId - ); - ForbidOnInvalidProjectType(ProjectType.KMS); + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId: key.projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.KMS + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Edit, ProjectPermissionSub.Cmek); @@ -83,14 +83,14 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj if (!key.projectId || key.isReserved) throw new BadRequestError({ message: "Key is not customer managed" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( - actor.type, - actor.id, - key.projectId, - actor.authMethod, - actor.orgId - ); - ForbidOnInvalidProjectType(ProjectType.KMS); + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId: key.projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.KMS + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Delete, ProjectPermissionSub.Cmek); @@ -109,13 +109,14 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj projectId = cmekProjectFromSplit.id; } - const { permission } = await permissionService.getProjectPermission( - actor.type, - actor.id, + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, projectId, - actor.authMethod, - actor.orgId - ); + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.KMS + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek); @@ -133,15 +134,15 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj if (key.isDisabled) throw new BadRequestError({ message: "Key is disabled" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( - actor.type, - actor.id, - key.projectId, - actor.authMethod, - actor.orgId - ); + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId: key.projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.KMS + }); - ForbidOnInvalidProjectType(ProjectType.KMS); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Encrypt, ProjectPermissionSub.Cmek); const encrypt = await kmsService.encryptWithKmsKey({ kmsId: keyId }); @@ -160,14 +161,14 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj if (key.isDisabled) throw new BadRequestError({ message: "Key is disabled" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( - actor.type, - actor.id, - key.projectId, - actor.authMethod, - actor.orgId - ); - ForbidOnInvalidProjectType(ProjectType.KMS); + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId: key.projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.KMS + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Decrypt, ProjectPermissionSub.Cmek); diff --git a/backend/src/services/group-project/group-project-service.ts b/backend/src/services/group-project/group-project-service.ts index 896afe93d..1084dcdd9 100644 --- a/backend/src/services/group-project/group-project-service.ts +++ b/backend/src/services/group-project/group-project-service.ts @@ -1,7 +1,7 @@ import { ForbiddenError } from "@casl/ability"; import ms from "ms"; -import { ProjectMembershipRole, SecretKeyEncoding } from "@app/db/schemas"; +import { ActionProjectType, ProjectMembershipRole, SecretKeyEncoding } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; @@ -69,13 +69,14 @@ export const groupProjectServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` }); if (project.version < 2) throw new BadRequestError({ message: `Failed to add group to E2EE project` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Groups); const group = await groupDAL.findOne({ orgId: actorOrgId, id: groupId }); @@ -237,13 +238,14 @@ export const groupProjectServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Groups); const group = await groupDAL.findOne({ orgId: actorOrgId, id: groupId }); @@ -339,13 +341,14 @@ export const groupProjectServiceFactory = ({ const groupProjectMembership = await groupProjectDAL.findOne({ groupId: group.id, projectId: project.id }); if (!groupProjectMembership) throw new NotFoundError({ message: `Failed to find group with ID ${groupId}` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Groups); const deletedProjectGroup = await groupProjectDAL.transaction(async (tx) => { @@ -383,13 +386,14 @@ export const groupProjectServiceFactory = ({ throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Groups); const groupMemberships = await groupProjectDAL.findByProjectId(project.id); @@ -410,13 +414,14 @@ export const groupProjectServiceFactory = ({ throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Groups); const [groupMembership] = await groupProjectDAL.findByProjectId(project.id, { diff --git a/backend/src/services/identity-project/identity-project-service.ts b/backend/src/services/identity-project/identity-project-service.ts index a2524a0b9..36b9b0562 100644 --- a/backend/src/services/identity-project/identity-project-service.ts +++ b/backend/src/services/identity-project/identity-project-service.ts @@ -1,7 +1,7 @@ import { ForbiddenError, subject } from "@casl/ability"; import ms from "ms"; -import { ProjectMembershipRole } from "@app/db/schemas"; +import { ActionProjectType, ProjectMembershipRole } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; @@ -54,13 +54,14 @@ export const identityProjectServiceFactory = ({ projectId, roles }: TCreateProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, subject(ProjectPermissionSub.Identity, { @@ -159,13 +160,14 @@ export const identityProjectServiceFactory = ({ actorAuthMethod, actorOrgId }: TUpdateProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Identity, { identityId }) @@ -254,25 +256,27 @@ export const identityProjectServiceFactory = ({ throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - identityProjectMembership.projectId, + projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, subject(ProjectPermissionSub.Identity, { identityId }) ); - const { permission: identityRolePermission } = await permissionService.getProjectPermission( - ActorType.IDENTITY, - identityId, - identityProjectMembership.projectId, + const { permission: identityRolePermission } = await permissionService.getProjectPermission({ + actor: ActorType.IDENTITY, + actorId: identityId, + projectId: identityProjectMembership.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); if (!isAtLeastAsPrivileged(permission, identityRolePermission)) throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" }); @@ -292,13 +296,14 @@ export const identityProjectServiceFactory = ({ orderDirection, search }: TListProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity); const identityMemberships = await identityProjectDAL.findByProjectId(projectId, { @@ -322,13 +327,14 @@ export const identityProjectServiceFactory = ({ actorOrgId, identityId }: TGetProjectIdentityByIdentityIdDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, diff --git a/backend/src/services/integration-auth/integration-auth-service.ts b/backend/src/services/integration-auth/integration-auth-service.ts index e2957be98..d96643a19 100644 --- a/backend/src/services/integration-auth/integration-auth-service.ts +++ b/backend/src/services/integration-auth/integration-auth-service.ts @@ -5,7 +5,7 @@ import { Client as OctopusClient, SpaceRepository as OctopusSpaceRepository } fr import AWS from "aws-sdk"; import { - ProjectType, + ActionProjectType, SecretEncryptionAlgo, SecretKeyEncoding, TIntegrationAuths, @@ -97,13 +97,14 @@ export const integrationAuthServiceFactory = ({ actorAuthMethod, projectId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const authorizations = await integrationAuthDAL.find({ projectId }); return authorizations; @@ -114,13 +115,14 @@ export const integrationAuthServiceFactory = ({ return Promise.all( authorizations.filter(async (auth) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - auth.projectId, + projectId: auth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); return permission.can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); }) @@ -131,13 +133,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); return integrationAuth; }; @@ -156,14 +159,14 @@ export const integrationAuthServiceFactory = ({ if (!Object.values(Integrations).includes(integration as Integrations)) throw new BadRequestError({ message: "Invalid integration" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); const tokenExchange = await exchangeCode({ integration, code, url, installationId }); @@ -266,14 +269,14 @@ export const integrationAuthServiceFactory = ({ if (!Object.values(Integrations).includes(integration as Integrations)) throw new BadRequestError({ message: "Invalid integration" }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); const updateDoc: TIntegrationAuthsInsert = { @@ -401,13 +404,14 @@ export const integrationAuthServiceFactory = ({ throw new NotFoundError({ message: `Integration auth with id ${integrationAuthId} not found.` }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); const { projectId } = integrationAuth; @@ -662,13 +666,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(integrationAuth.projectId); @@ -696,13 +701,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); @@ -726,13 +732,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -767,13 +774,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -795,13 +803,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); @@ -869,13 +878,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -916,13 +926,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -950,13 +961,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessId, accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1008,13 +1020,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1044,13 +1057,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1085,13 +1099,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1125,13 +1140,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1165,13 +1181,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID ${id} not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1204,13 +1221,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1244,13 +1262,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1312,13 +1331,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1386,13 +1406,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1436,13 +1457,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1484,13 +1506,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1552,13 +1575,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1593,13 +1617,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1705,13 +1730,14 @@ export const integrationAuthServiceFactory = ({ actorAuthMethod, actorOrgId }: TDeleteIntegrationAuthsDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); const integrations = await integrationAuthDAL.delete({ integration, projectId }); @@ -1728,13 +1754,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); const delIntegrationAuth = await integrationAuthDAL.transaction(async (tx) => { @@ -1761,26 +1788,28 @@ export const integrationAuthServiceFactory = ({ throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); } - const { permission: sourcePermission } = await permissionService.getProjectPermission( + const { permission: sourcePermission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(sourcePermission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.Integrations ); - const { permission: targetPermission } = await permissionService.getProjectPermission( + const { permission: targetPermission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(targetPermission).throwUnlessCan( ProjectPermissionActions.Create, @@ -1806,13 +1835,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); @@ -1846,13 +1876,14 @@ export const integrationAuthServiceFactory = ({ const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { accessToken } = await getIntegrationAccessToken(integrationAuth, shouldUseSecretV2Bridge, botKey); diff --git a/backend/src/services/integration/integration-service.ts b/backend/src/services/integration/integration-service.ts index 36a4156e7..35994433a 100644 --- a/backend/src/services/integration/integration-service.ts +++ b/backend/src/services/integration/integration-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError, subject } from "@casl/ability"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { NotFoundError } from "@app/lib/errors"; @@ -81,14 +81,14 @@ export const integrationServiceFactory = ({ if (!integrationAuth) throw new NotFoundError({ message: `Integration auth with ID '${integrationAuthId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integrationAuth.projectId, + projectId: integrationAuth.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan( @@ -160,14 +160,14 @@ export const integrationServiceFactory = ({ const integration = await integrationDAL.findById(id); if (!integration) throw new NotFoundError({ message: `Integration with ID '${id}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integration.projectId, + projectId: integration.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); const newEnvironment = environment || integration.environment.slug; @@ -227,13 +227,14 @@ export const integrationServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integration?.projectId || "", + projectId: integration.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); if (!integration) { @@ -254,13 +255,14 @@ export const integrationServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integration?.projectId || "", + projectId: integration.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const integrationAuth = await integrationAuthDAL.findById(integration.integrationAuthId); @@ -296,14 +298,14 @@ export const integrationServiceFactory = ({ const integration = await integrationDAL.findById(id); if (!integration) throw new NotFoundError({ message: `Integration with ID '${id}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integration.projectId, + projectId: integration.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); const integrationAuth = await integrationAuthDAL.findById(integration.integrationAuthId); @@ -333,13 +335,14 @@ export const integrationServiceFactory = ({ actorAuthMethod, projectId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const integrations = await integrationDAL.findByProjectId(projectId); @@ -352,13 +355,14 @@ export const integrationServiceFactory = ({ throw new NotFoundError({ message: `Integration with ID '${id}' not found` }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - integration.projectId, + projectId: integration.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); await secretQueueService.syncIntegrations({ diff --git a/backend/src/services/org/org-service.ts b/backend/src/services/org/org-service.ts index 73b8c04e5..f660f511f 100644 --- a/backend/src/services/org/org-service.ts +++ b/backend/src/services/org/org-service.ts @@ -5,6 +5,7 @@ import jwt from "jsonwebtoken"; import { Knex } from "knex"; import { + ActionProjectType, OrgMembershipRole, OrgMembershipStatus, ProjectMembershipRole, @@ -773,13 +774,14 @@ export const orgServiceFactory = ({ // if there exist no project membership we set is as given by the request for await (const project of projectsToInvite) { const projectId = project.id; - const { permission: projectPermission } = await permissionService.getProjectPermission( + const { permission: projectPermission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(projectPermission).throwUnlessCan( ProjectPermissionActions.Create, ProjectPermissionSub.Member diff --git a/backend/src/services/pki-alert/pki-alert-service.ts b/backend/src/services/pki-alert/pki-alert-service.ts index f002c393b..0ddc0f3ae 100644 --- a/backend/src/services/pki-alert/pki-alert-service.ts +++ b/backend/src/services/pki-alert/pki-alert-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType, ProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; @@ -86,14 +86,14 @@ export const pkiAlertServiceFactory = ({ projectId = certManagerProjectFromSplit.id; } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.PkiAlerts); @@ -116,13 +116,14 @@ export const pkiAlertServiceFactory = ({ const alert = await pkiAlertDAL.findById(alertId); if (!alert) throw new NotFoundError({ message: `Alert with ID '${alertId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - alert.projectId, + projectId: alert.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.PkiAlerts); return alert; @@ -142,14 +143,14 @@ export const pkiAlertServiceFactory = ({ let alert = await pkiAlertDAL.findById(alertId); if (!alert) throw new NotFoundError({ message: `Alert with ID '${alertId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - alert.projectId, + projectId: alert.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.PkiAlerts); @@ -175,14 +176,14 @@ export const pkiAlertServiceFactory = ({ let alert = await pkiAlertDAL.findById(alertId); if (!alert) throw new NotFoundError({ message: `Alert with ID '${alertId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - alert.projectId, + projectId: alert.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.PkiAlerts); alert = await pkiAlertDAL.deleteById(alertId); diff --git a/backend/src/services/pki-collection/pki-collection-service.ts b/backend/src/services/pki-collection/pki-collection-service.ts index 93b3b65b6..bee3ee621 100644 --- a/backend/src/services/pki-collection/pki-collection-service.ts +++ b/backend/src/services/pki-collection/pki-collection-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { ProjectType, TPkiCollectionItems } from "@app/db/schemas"; +import { ActionProjectType, ProjectType, TPkiCollectionItems } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; @@ -62,14 +62,14 @@ export const pkiCollectionServiceFactory = ({ projectId = certManagerProjectFromSplit.id; } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -95,13 +95,14 @@ export const pkiCollectionServiceFactory = ({ const pkiCollection = await pkiCollectionDAL.findById(collectionId); if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - pkiCollection.projectId, + projectId: pkiCollection.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.PkiCollections); return pkiCollection; @@ -119,14 +120,14 @@ export const pkiCollectionServiceFactory = ({ let pkiCollection = await pkiCollectionDAL.findById(collectionId); if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - pkiCollection.projectId, + projectId: pkiCollection.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.PkiCollections); pkiCollection = await pkiCollectionDAL.updateById(collectionId, { @@ -147,14 +148,14 @@ export const pkiCollectionServiceFactory = ({ let pkiCollection = await pkiCollectionDAL.findById(collectionId); if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - pkiCollection.projectId, + projectId: pkiCollection.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, @@ -177,13 +178,14 @@ export const pkiCollectionServiceFactory = ({ const pkiCollection = await pkiCollectionDAL.findById(collectionId); if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - pkiCollection.projectId, + projectId: pkiCollection.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.PkiCollections); @@ -220,14 +222,14 @@ export const pkiCollectionServiceFactory = ({ const pkiCollection = await pkiCollectionDAL.findById(collectionId); if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${collectionId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - pkiCollection.projectId, + projectId: pkiCollection.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -314,14 +316,14 @@ export const pkiCollectionServiceFactory = ({ if (!pkiCollectionItem) throw new NotFoundError({ message: `PKI collection item with ID '${itemId}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - pkiCollection.projectId, + projectId: pkiCollection.projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, diff --git a/backend/src/services/project-bot/project-bot-service.ts b/backend/src/services/project-bot/project-bot-service.ts index 5d7f78c1b..dc69cbf99 100644 --- a/backend/src/services/project-bot/project-bot-service.ts +++ b/backend/src/services/project-bot/project-bot-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { ProjectVersion } from "@app/db/schemas"; +import { ActionProjectType, ProjectVersion } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { generateAsymmetricKeyPair } from "@app/lib/crypto"; @@ -41,13 +41,14 @@ export const projectBotServiceFactory = ({ botKey, publicKey }: TFindBotByProjectIdDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const bot = await projectBotDAL.transaction(async (tx) => { @@ -107,13 +108,14 @@ export const projectBotServiceFactory = ({ const bot = await projectBotDAL.findById(botId); if (!bot) throw new NotFoundError({ message: `Project bot with ID '${botId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - bot.projectId, + projectId: bot.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); const project = await projectBotDAL.findProjectByBotId(botId); diff --git a/backend/src/services/project-env/project-env-service.ts b/backend/src/services/project-env/project-env-service.ts index 5c3fdba32..f9935df54 100644 --- a/backend/src/services/project-env/project-env-service.ts +++ b/backend/src/services/project-env/project-env-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; @@ -42,14 +42,14 @@ export const projectEnvServiceFactory = ({ name, slug }: TCreateEnvDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Environments); const lock = await keyStore @@ -131,14 +131,14 @@ export const projectEnvServiceFactory = ({ id, position }: TUpdateEnvDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments); const lock = await keyStore @@ -195,14 +195,14 @@ export const projectEnvServiceFactory = ({ }; const deleteEnvironment = async ({ projectId, actor, actorId, actorOrgId, actorAuthMethod, id }: TDeleteEnvDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Environments); const lock = await keyStore @@ -251,13 +251,14 @@ export const projectEnvServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - environment.projectId, + projectId: environment.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Environments); diff --git a/backend/src/services/project-key/project-key-service.ts b/backend/src/services/project-key/project-key-service.ts index 70c8365ee..b56c0a43e 100644 --- a/backend/src/services/project-key/project-key-service.ts +++ b/backend/src/services/project-key/project-key-service.ts @@ -1,5 +1,6 @@ import { ForbiddenError } from "@casl/ability"; +import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError } from "@app/lib/errors"; @@ -31,13 +32,14 @@ export const projectKeyServiceFactory = ({ nonce, encryptedKey }: TUploadProjectKeyDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); const receiverMembership = await projectMembershipDAL.findOne({ @@ -60,7 +62,14 @@ export const projectKeyServiceFactory = ({ actorOrgId, actorAuthMethod }: TGetLatestProjectKeyDTO) => { - await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.Any + }); const latestKey = await projectKeyDAL.findLatestProjectKey(actorId, projectId); return latestKey; }; @@ -72,13 +81,14 @@ export const projectKeyServiceFactory = ({ actorAuthMethod, projectId }: TGetLatestProjectKeyDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); 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 b4826b54b..fd1382dcf 100644 --- a/backend/src/services/project-membership/project-membership-service.ts +++ b/backend/src/services/project-membership/project-membership-service.ts @@ -2,7 +2,7 @@ import { ForbiddenError } from "@casl/ability"; import ms from "ms"; -import { ProjectMembershipRole, ProjectVersion, TableName } from "@app/db/schemas"; +import { ActionProjectType, ProjectMembershipRole, ProjectVersion, TableName } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; @@ -78,13 +78,14 @@ export const projectMembershipServiceFactory = ({ includeGroupMembers, projectId }: TGetProjectMembershipDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); const projectMembers = await projectMembershipDAL.findAllProjectMembers(projectId); @@ -121,13 +122,14 @@ export const projectMembershipServiceFactory = ({ projectId, username }: TGetProjectMembershipByUsernameDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); const [membership] = await projectMembershipDAL.findAllProjectMembers(projectId, { username }); @@ -143,13 +145,14 @@ export const projectMembershipServiceFactory = ({ projectId, id }: TGetProjectMembershipByIdDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member); const [membership] = await projectMembershipDAL.findAllProjectMembers(projectId, { id }); @@ -169,13 +172,14 @@ export const projectMembershipServiceFactory = ({ const project = await projectDAL.findById(projectId); if (!project) throw new NotFoundError({ message: `Project with ID '${projectId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member); const orgMembers = await orgDAL.findMembership({ [`${TableName.OrgMembership}.orgId` as "orgId"]: project.orgId, @@ -249,13 +253,14 @@ export const projectMembershipServiceFactory = ({ membershipId, roles }: TUpdateProjectMembershipDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member); const membershipUser = await userDAL.findUserByProjectMembershipId(membershipId); @@ -348,13 +353,14 @@ export const projectMembershipServiceFactory = ({ projectId, membershipId }: TDeleteProjectMembershipOldDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member); const member = await userDAL.findUserByProjectMembershipId(membershipId); @@ -383,13 +389,14 @@ export const projectMembershipServiceFactory = ({ emails, usernames }: TDeleteProjectMembershipsDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member); const project = await projectDAL.findById(projectId); diff --git a/backend/src/services/project-role/project-role-service.ts b/backend/src/services/project-role/project-role-service.ts index 55564bc17..09bc6460d 100644 --- a/backend/src/services/project-role/project-role-service.ts +++ b/backend/src/services/project-role/project-role-service.ts @@ -1,7 +1,7 @@ import { ForbiddenError, MongoAbility, RawRuleOf } from "@casl/ability"; import { PackRule, packRules, unpackRules } from "@casl/ability/extra"; -import { ProjectMembershipRole, TableName } from "@app/db/schemas"; +import { ActionProjectType, ProjectMembershipRole, TableName } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, @@ -58,13 +58,14 @@ export const projectRoleServiceFactory = ({ projectId = filter.projectId; } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Role); const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId }); if (existingRole) { @@ -95,13 +96,14 @@ export const projectRoleServiceFactory = ({ projectId = filter.projectId; } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role); if (roleSlug !== "custom" && Object.values(ProjectMembershipRole).includes(roleSlug as ProjectMembershipRole)) { const predefinedRole = getPredefinedRoles(projectId, roleSlug as ProjectMembershipRole)[0]; @@ -117,13 +119,14 @@ export const projectRoleServiceFactory = ({ const projectRole = await projectRoleDAL.findById(roleId); if (!projectRole) throw new NotFoundError({ message: "Project role not found", name: "Delete role" }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectRole.projectId, + projectId: projectRole.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Role); if (data?.slug) { @@ -144,13 +147,14 @@ export const projectRoleServiceFactory = ({ const deleteRole = async ({ actor, actorId, actorAuthMethod, actorOrgId, roleId }: TDeleteRoleDTO) => { const projectRole = await projectRoleDAL.findById(roleId); if (!projectRole) throw new NotFoundError({ message: "Project role not found", name: "Delete role" }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - projectRole.projectId, + projectId: projectRole.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role); const identityRole = await identityProjectMembershipRoleDAL.findOne({ customRoleId: roleId }); @@ -185,13 +189,14 @@ export const projectRoleServiceFactory = ({ projectId = filter.projectId; } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role); const customRoles = await projectRoleDAL.find( { projectId }, @@ -208,12 +213,13 @@ export const projectRoleServiceFactory = ({ actorAuthMethod: ActorAuthMethod, actorOrgId: string | undefined ) => { - const { permission, membership } = await permissionService.getUserProjectPermission( + const { permission, membership } = await permissionService.getUserProjectPermission({ userId, projectId, - actorAuthMethod, - actorOrgId - ); + authMethod: actorAuthMethod, + userOrgId: actorOrgId, + actionProjectType: ActionProjectType.Any + }); 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 fc302c4c8..2d5b492f1 100644 --- a/backend/src/services/project/project-service.ts +++ b/backend/src/services/project/project-service.ts @@ -1,7 +1,13 @@ import { ForbiddenError } from "@casl/ability"; import slugify from "@sindresorhus/slugify"; -import { ProjectMembershipRole, ProjectType, ProjectVersion, TProjectEnvironments } from "@app/db/schemas"; +import { + ActionProjectType, + ProjectMembershipRole, + ProjectType, + ProjectVersion, + TProjectEnvironments +} from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; @@ -427,13 +433,14 @@ export const projectServiceFactory = ({ const deleteProject = async ({ actor, actorId, actorOrgId, actorAuthMethod, filter }: TDeleteProjectDTO) => { const project = await projectDAL.findProjectByFilter(filter); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project); const deletedProject = await projectDAL.transaction(async (tx) => { @@ -510,20 +517,28 @@ export const projectServiceFactory = ({ const getAProject = async ({ actorId, actorOrgId, actorAuthMethod, filter, actor }: TGetProjectDTO) => { const project = await projectDAL.findProjectByFilter(filter); - await permissionService.getProjectPermission(actor, actorId, project.id, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId: project.id, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.Any + }); return project; }; const updateProject = async ({ actor, actorId, actorOrgId, actorAuthMethod, update, filter }: TUpdateProjectDTO) => { const project = await projectDAL.findProjectByFilter(filter); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); const updatedProject = await projectDAL.updateById(project.id, { @@ -542,13 +557,14 @@ export const projectServiceFactory = ({ actorAuthMethod, autoCapitalization }: TToggleProjectAutoCapitalizationDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); const updatedProject = await projectDAL.updateById(projectId, { autoCapitalization }); @@ -570,13 +586,14 @@ export const projectServiceFactory = ({ }); } - const { hasRole } = await permissionService.getProjectPermission( + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); if (!hasRole(ProjectMembershipRole.Admin)) throw new ForbiddenRequestError({ @@ -601,13 +618,14 @@ export const projectServiceFactory = ({ }); } - const { hasRole } = await permissionService.getProjectPermission( + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); if (!hasRole(ProjectMembershipRole.Admin)) { throw new ForbiddenRequestError({ @@ -633,13 +651,14 @@ export const projectServiceFactory = ({ actorAuthMethod, name }: TUpdateProjectNameDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); const updatedProject = await projectDAL.updateById(projectId, { name }); @@ -654,13 +673,14 @@ export const projectServiceFactory = ({ actorOrgId, userPrivateKey }: TUpgradeProjectDTO) => { - const { permission, hasRole } = await permissionService.getProjectPermission( + const { permission, hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project); @@ -691,13 +711,14 @@ export const projectServiceFactory = ({ actorOrgId, actorId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); const project = await projectDAL.findProjectById(projectId); @@ -736,13 +757,14 @@ export const projectServiceFactory = ({ projectId = certManagerProjectFromSplit.id; } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, @@ -786,14 +808,14 @@ export const projectServiceFactory = ({ projectId = certManagerProjectFromSplit.id; } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Certificates); @@ -841,14 +863,14 @@ export const projectServiceFactory = ({ projectId = certManagerProjectFromSplit.id; } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.PkiAlerts); @@ -877,14 +899,14 @@ export const projectServiceFactory = ({ if (certManagerProjectFromSplit) { projectId = certManagerProjectFromSplit.id; } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.PkiCollections); @@ -914,14 +936,14 @@ export const projectServiceFactory = ({ projectId = certManagerProjectFromSplit.id; } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.CertificateManager); + actorOrgId, + actionProjectType: ActionProjectType.CertificateManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, @@ -945,15 +967,15 @@ export const projectServiceFactory = ({ actor, projectId }: TListProjectSshCasDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateAuthorities @@ -981,15 +1003,15 @@ export const projectServiceFactory = ({ actor, projectId }: TListProjectSshCertificatesDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificates); const cas = await sshCertificateAuthorityDAL.find({ @@ -1020,15 +1042,15 @@ export const projectServiceFactory = ({ actor, projectId }: TListProjectSshCertificateTemplatesDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SSH + }); - ForbidOnInvalidProjectType(ProjectType.SSH); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateTemplates @@ -1055,13 +1077,14 @@ export const projectServiceFactory = ({ actorAuthMethod, actorOrgId }: TUpdateProjectKmsDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Kms); @@ -1082,13 +1105,14 @@ export const projectServiceFactory = ({ actorAuthMethod, actorOrgId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Kms); @@ -1111,13 +1135,14 @@ export const projectServiceFactory = ({ actorOrgId, backup }: TLoadProjectKmsBackupDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Kms); @@ -1133,13 +1158,14 @@ export const projectServiceFactory = ({ }; const getProjectKmsKeys = async ({ projectId, actor, actorId, actorAuthMethod, actorOrgId }: TGetProjectKmsKey) => { - const { membership } = await permissionService.getProjectPermission( + const { membership } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); if (!membership) { throw new ForbiddenRequestError({ message: "You are not a member of this project" }); @@ -1165,13 +1191,14 @@ export const projectServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Settings); @@ -1213,13 +1240,14 @@ export const projectServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); 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 57746307a..1cbbbcbb8 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 @@ -1,4 +1,4 @@ -import { ProjectMembershipRole } from "@app/db/schemas"; +import { ActionProjectType, ProjectMembershipRole } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; @@ -31,7 +31,14 @@ export const secretBlindIndexServiceFactory = ({ actorAuthMethod, actorOrgId }: TGetProjectBlindIndexStatusDTO) => { - await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const secretCount = await secretBlindIndexDAL.countOfSecretsWithNullSecretBlindIndex(projectId); return Number(secretCount); @@ -44,13 +51,14 @@ export const secretBlindIndexServiceFactory = ({ actorOrgId, actor }: TGetProjectSecretsDTO) => { - const { hasRole } = await permissionService.getProjectPermission( + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!hasRole(ProjectMembershipRole.Admin)) { throw new ForbiddenRequestError({ message: "Insufficient privileges, user must be admin" }); } @@ -67,13 +75,14 @@ export const secretBlindIndexServiceFactory = ({ actorOrgId, secretsToUpdate }: TUpdateProjectSecretNameDTO) => { - const { hasRole } = await permissionService.getProjectPermission( + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!hasRole(ProjectMembershipRole.Admin)) { throw new ForbiddenRequestError({ message: "Insufficient privileges, 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 99bd81d6d..04eac4586 100644 --- a/backend/src/services/secret-folder/secret-folder-service.ts +++ b/backend/src/services/secret-folder/secret-folder-service.ts @@ -2,7 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability"; import path from "path"; import { v4 as uuidv4, validate as uuidValidate } from "uuid"; -import { ProjectType, TSecretFoldersInsert } from "@app/db/schemas"; +import { ActionProjectType, TSecretFoldersInsert } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/secret-snapshot-service"; @@ -52,14 +52,14 @@ export const secretFolderServiceFactory = ({ environment, path: secretPath }: TCreateFolderDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -151,14 +151,14 @@ export const secretFolderServiceFactory = ({ throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); folders.forEach(({ environment, path: secretPath }) => { ForbiddenError.from(permission).throwUnlessCan( @@ -261,14 +261,14 @@ export const secretFolderServiceFactory = ({ path: secretPath, id }: TUpdateFolderDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -342,14 +342,14 @@ export const secretFolderServiceFactory = ({ path: secretPath, idOrName }: TDeleteFolderDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, @@ -399,7 +399,14 @@ export const secretFolderServiceFactory = ({ }: TGetFolderDTO) => { // folder list is allowed to be read by anyone // permission to check does user has access - await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const env = await projectEnvDAL.findOne({ projectId, slug: environment }); if (!env) throw new NotFoundError({ message: `Environment with slug '${environment}' not found` }); @@ -436,7 +443,14 @@ export const secretFolderServiceFactory = ({ }: Omit & { environments: string[] }) => { // folder list is allowed to be read by anyone // permission to check does user has access - await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const envs = await projectEnvDAL.findBySlugs(projectId, environments); @@ -471,7 +485,14 @@ export const secretFolderServiceFactory = ({ }: Omit & { environments: string[] }) => { // folder list is allowed to be read by anyone // permission to check does user has access - await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const envs = await projectEnvDAL.findBySlugs(projectId, environments); @@ -500,7 +521,14 @@ export const secretFolderServiceFactory = ({ if (!folder) throw new NotFoundError({ message: `Folder with ID '${id}' not found` }); // folder list is allowed to be read by anyone // permission to check does user has access - await permissionService.getProjectPermission(actor, actorId, folder.projectId, actorAuthMethod, actorOrgId); + await permissionService.getProjectPermission({ + actor, + actorId, + projectId: folder.projectId, + actorAuthMethod, + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const [folderWithPath] = await folderDAL.findSecretPathByFolderIds(folder.projectId, [folder.id]); @@ -522,7 +550,14 @@ export const secretFolderServiceFactory = ({ ) => { // folder list is allowed to be read by anyone // permission to check does user have access - await permissionService.getProjectPermission(actor.type, actor.id, projectId, actor.authMethod, actor.orgId); + await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.SecretManager + }); const envs = await projectEnvDAL.findBySlugs(projectId, environments); diff --git a/backend/src/services/secret-import/secret-import-service.ts b/backend/src/services/secret-import/secret-import-service.ts index 3a62fb48a..e8fde04d1 100644 --- a/backend/src/services/secret-import/secret-import-service.ts +++ b/backend/src/services/secret-import/secret-import-service.ts @@ -2,7 +2,7 @@ import path from "node:path"; import { ForbiddenError, subject } from "@casl/ability"; -import { ProjectType, TableName } from "@app/db/schemas"; +import { ActionProjectType, TableName } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; @@ -73,14 +73,14 @@ export const secretImportServiceFactory = ({ isReplication, path: secretPath }: TCreateSecretImportDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); // check if user has permission to import into destination path ForbiddenError.from(permission).throwUnlessCan( @@ -192,14 +192,14 @@ export const secretImportServiceFactory = ({ data, id }: TUpdateSecretImportDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -288,14 +288,14 @@ export const secretImportServiceFactory = ({ actorAuthMethod, id }: TDeleteSecretImportDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, @@ -362,13 +362,14 @@ export const secretImportServiceFactory = ({ path: secretPath, id: secretImportDocId }: TResyncSecretImportReplicationDTO) => { - const { permission, membership } = await permissionService.getProjectPermission( + const { permission, membership } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); // check if user has permission to import into destination path ForbiddenError.from(permission).throwUnlessCan( @@ -441,13 +442,14 @@ export const secretImportServiceFactory = ({ actorOrgId, search }: TGetSecretImportsDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.SecretImports, { environment, secretPath }) @@ -476,13 +478,14 @@ export const secretImportServiceFactory = ({ limit, offset }: TGetSecretImportsDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.SecretImports, { environment, secretPath }) @@ -525,13 +528,14 @@ export const secretImportServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - folder.projectId, + projectId: folder.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, @@ -573,13 +577,14 @@ export const secretImportServiceFactory = ({ actorId, actorOrgId }: TGetSecretsFromImportDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.SecretImports, { environment, secretPath }) @@ -610,13 +615,14 @@ export const secretImportServiceFactory = ({ actorId, actorOrgId }: TGetSecretsFromImportDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.SecretImports, { environment, secretPath }) diff --git a/backend/src/services/secret-tag/secret-tag-service.ts b/backend/src/services/secret-tag/secret-tag-service.ts index 02d2b5af0..0a154a4be 100644 --- a/backend/src/services/secret-tag/secret-tag-service.ts +++ b/backend/src/services/secret-tag/secret-tag-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { ProjectType } from "@app/db/schemas"; +import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; @@ -24,15 +24,15 @@ export type TSecretTagServiceFactory = ReturnType { const createTag = async ({ slug, actor, color, actorId, actorOrgId, actorAuthMethod, projectId }: TCreateTagDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags); - ForbidOnInvalidProjectType(ProjectType.SecretManager); const existingTag = await secretTagDAL.findOne({ slug, projectId }); if (existingTag) throw new BadRequestError({ message: "Tag already exist" }); @@ -56,15 +56,15 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe if (existingTag && existingTag.id !== tag.id) throw new BadRequestError({ message: "Tag already exist" }); } - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - tag.projectId, + projectId: tag.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Tags); - ForbidOnInvalidProjectType(ProjectType.SecretManager); const updatedTag = await secretTagDAL.updateById(tag.id, { color, slug }); return updatedTag; @@ -74,15 +74,15 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe const tag = await secretTagDAL.findById(id); if (!tag) throw new NotFoundError({ message: `Tag with ID '${id}' not found` }); - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - tag.projectId, + projectId: tag.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Tags); - ForbidOnInvalidProjectType(ProjectType.SecretManager); const deletedTag = await secretTagDAL.deleteById(tag.id); return deletedTag; @@ -92,13 +92,14 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe const tag = await secretTagDAL.findById(id); if (!tag) throw new NotFoundError({ message: `Tag with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - tag.projectId, + projectId: tag.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); return { ...tag, name: tag.slug }; @@ -108,26 +109,28 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe const tag = await secretTagDAL.findOne({ projectId, slug }); if (!tag) throw new NotFoundError({ message: `Tag with slug '${slug}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - tag.projectId, + projectId: tag.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); return { ...tag, name: tag.slug }; }; const getProjectTags = async ({ actor, actorId, actorOrgId, actorAuthMethod, projectId }: TListProjectTagsDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); const tags = await secretTagDAL.find({ projectId }, { sort: [["createdAt", "asc"]] }); diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts index a0f93626d..e9e04dbd8 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts @@ -1,7 +1,7 @@ import { ForbiddenError, PureAbility, subject } from "@casl/ability"; import { z } from "zod"; -import { ProjectMembershipRole, ProjectType, SecretsV2Schema, SecretType, TableName } from "@app/db/schemas"; +import { ActionProjectType, ProjectMembershipRole, SecretsV2Schema, SecretType, TableName } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service"; @@ -192,14 +192,14 @@ export const secretV2BridgeServiceFactory = ({ secretMetadata, ...inputSecret }: TCreateSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) @@ -320,14 +320,14 @@ export const secretV2BridgeServiceFactory = ({ secretMetadata, ...inputSecret }: TUpdateSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (inputSecret.newSecretName === "") { throw new BadRequestError({ message: "New secret name cannot be empty" }); @@ -509,14 +509,14 @@ export const secretV2BridgeServiceFactory = ({ secretPath, ...inputSecret }: TDeleteSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) @@ -611,13 +611,14 @@ export const secretV2BridgeServiceFactory = ({ isInternal?: boolean; }) => { if (!isInternal) { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); } @@ -657,13 +658,14 @@ export const secretV2BridgeServiceFactory = ({ | "environment" | "search" >) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); @@ -740,13 +742,14 @@ export const secretV2BridgeServiceFactory = ({ environments: string[]; isInternal?: boolean; }) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!isInternal) { ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); } @@ -789,13 +792,14 @@ export const secretV2BridgeServiceFactory = ({ expandSecretReferences: shouldExpandSecretReferences, ...params }: TGetSecretsDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets); @@ -942,13 +946,14 @@ export const secretV2BridgeServiceFactory = ({ includeImports, expandSecretReferences: shouldExpandSecretReferences }: TGetASecretDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const folder = await folderDAL.findBySecretPath(projectId, environment, path); if (!folder) @@ -1098,14 +1103,14 @@ export const secretV2BridgeServiceFactory = ({ projectId, secrets: inputSecrets }: TCreateManySecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) @@ -1243,14 +1248,14 @@ export const secretV2BridgeServiceFactory = ({ secretPath, secrets: inputSecrets }: TUpdateManySecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) @@ -1454,14 +1459,14 @@ export const secretV2BridgeServiceFactory = ({ actorAuthMethod, actorOrgId }: TDeleteManySecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) @@ -1566,13 +1571,14 @@ export const secretV2BridgeServiceFactory = ({ const folder = await folderDAL.findById(secret.folderId); if (!folder) throw new NotFoundError({ message: `Folder with ID '${secret.folderId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - folder.projectId, + projectId: folder.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, @@ -1598,14 +1604,14 @@ export const secretV2BridgeServiceFactory = ({ actorOrgId, actorAuthMethod }: TBackFillSecretReferencesDTO) => { - const { hasRole, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!hasRole(ProjectMembershipRole.Admin)) throw new ForbiddenRequestError({ message: "Only admins are allowed to take this action" }); @@ -1646,14 +1652,14 @@ export const secretV2BridgeServiceFactory = ({ actorAuthMethod, actorOrgId }: TMoveSecretsDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); const sourceFolder = await folderDAL.findBySecretPath(projectId, sourceEnvironment, sourceSecretPath); if (!sourceFolder) { @@ -2004,13 +2010,14 @@ export const secretV2BridgeServiceFactory = ({ secretName, actorAuthMethod }: TGetSecretReferencesTreeDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, diff --git a/backend/src/services/secret/secret-fns.ts b/backend/src/services/secret/secret-fns.ts index 29d381bfa..1775d1f44 100644 --- a/backend/src/services/secret/secret-fns.ts +++ b/backend/src/services/secret/secret-fns.ts @@ -3,6 +3,7 @@ import { subject } from "@casl/ability"; import path from "path"; import { + ActionProjectType, SecretEncryptionAlgo, SecretKeyEncoding, SecretType, @@ -176,13 +177,14 @@ export const recursivelyGetSecretPaths = ({ folderId: p.folderId })); - const { permission } = await permissionService.getProjectPermission( - auth.actor, - auth.actorId, + const { permission } = await permissionService.getProjectPermission({ + actor: auth.actor, + actorId: auth.actorId, projectId, - auth.actorAuthMethod, - auth.actorOrgId - ); + actorAuthMethod: auth.actorAuthMethod, + actorOrgId: auth.actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); // Filter out paths that the user does not have permission to access, and paths that are not in the current path const allowedPaths = paths.filter( diff --git a/backend/src/services/secret/secret-service.ts b/backend/src/services/secret/secret-service.ts index 91e4ef969..66e53c612 100644 --- a/backend/src/services/secret/secret-service.ts +++ b/backend/src/services/secret/secret-service.ts @@ -3,8 +3,8 @@ import { ForbiddenError, subject } from "@casl/ability"; import { + ActionProjectType, ProjectMembershipRole, - ProjectType, ProjectUpgradeStatus, SecretEncryptionAlgo, SecretKeyEncoding, @@ -191,14 +191,14 @@ export const secretServiceFactory = ({ projectId, ...inputSecret }: TCreateSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, @@ -309,14 +309,14 @@ export const secretServiceFactory = ({ projectId, ...inputSecret }: TUpdateSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -454,14 +454,14 @@ export const secretServiceFactory = ({ projectId, ...inputSecret }: TDeleteSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, @@ -551,13 +551,14 @@ export const secretServiceFactory = ({ includeImports, recursive }: TGetSecretsDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); let paths: { folderId: string; path: string }[] = []; @@ -658,13 +659,14 @@ export const secretServiceFactory = ({ version, includeImports }: TGetASecretDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Read, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -757,14 +759,14 @@ export const secretServiceFactory = ({ projectId, secrets: inputSecrets }: TCreateBulkSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Create, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -844,14 +846,14 @@ export const secretServiceFactory = ({ projectId, secrets: inputSecrets }: TUpdateBulkSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -953,14 +955,14 @@ export const secretServiceFactory = ({ actorAuthMethod, actorOrgId }: TDeleteBulkSecretDTO) => { - const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); - ForbidOnInvalidProjectType(ProjectType.SecretManager); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, subject(ProjectPermissionSub.Secrets, { environment, secretPath: path }) @@ -2229,13 +2231,14 @@ export const secretServiceFactory = ({ if (!botKey) throw new NotFoundError({ message: `Project bot for project with ID '${folder.projectId}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - folder.projectId, + projectId: folder.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] }); return secretVersions.map((el) => @@ -2264,13 +2267,14 @@ export const secretServiceFactory = ({ actorId }: TAttachSecretTagsDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -2369,13 +2373,14 @@ export const secretServiceFactory = ({ actorId }: TAttachSecretTagsDTO) => { const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Edit, @@ -2475,13 +2480,14 @@ export const secretServiceFactory = ({ actorOrgId, actorAuthMethod }: TBackFillSecretReferencesDTO) => { - const { hasRole } = await permissionService.getProjectPermission( + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!hasRole(ProjectMembershipRole.Admin)) throw new ForbiddenRequestError({ message: "Only admins are allowed to take this action" }); @@ -2559,13 +2565,14 @@ export const secretServiceFactory = ({ }); } - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - project.id, + projectId: project.id, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan( ProjectPermissionActions.Delete, @@ -2947,13 +2954,14 @@ export const secretServiceFactory = ({ actorOrgId, actorAuthMethod }: TStartSecretsV2MigrationDTO) => { - const { hasRole } = await permissionService.getProjectPermission( + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); if (!hasRole(ProjectMembershipRole.Admin)) throw new ForbiddenRequestError({ message: "Only admins are allowed to take this action" }); @@ -2975,13 +2983,14 @@ export const secretServiceFactory = ({ if (!shouldUseSecretV2Bridge) throw new BadRequestError({ message: "Project version not supported" }); - const { permission } = await permissionService.getProjectPermission( - actor.type, - actor.id, - params.projectId, - actor.authMethod, - actor.orgId - ); + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId: params.projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.SecretManager + }); const secrets = secretV2BridgeService.getSecretsByFolderMappings({ ...params, userId: actor.id }, permission); diff --git a/backend/src/services/service-token/service-token-service.ts b/backend/src/services/service-token/service-token-service.ts index fe2c1c0d2..654917feb 100644 --- a/backend/src/services/service-token/service-token-service.ts +++ b/backend/src/services/service-token/service-token-service.ts @@ -3,6 +3,7 @@ import crypto from "node:crypto"; import { ForbiddenError, subject } from "@casl/ability"; import bcrypt from "bcrypt"; +import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { getConfig } from "@app/lib/config/env"; @@ -54,13 +55,14 @@ export const serviceTokenServiceFactory = ({ permissions, encryptedKey }: TCreateServiceTokenDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens); scopes.forEach(({ environment, secretPath }) => { @@ -109,13 +111,14 @@ export const serviceTokenServiceFactory = ({ const serviceToken = await serviceTokenDAL.findById(id); if (!serviceToken) throw new NotFoundError({ message: `Service token with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - serviceToken.projectId, + projectId: serviceToken.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.SecretManager + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens); const deletedServiceToken = await serviceTokenDAL.deleteById(id); @@ -143,13 +146,14 @@ export const serviceTokenServiceFactory = ({ actorAuthMethod, projectId }: TProjectServiceTokensDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); 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 a959d904c..26136aaf6 100644 --- a/backend/src/services/webhook/webhook-service.ts +++ b/backend/src/services/webhook/webhook-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { TWebhooksInsert } from "@app/db/schemas"; +import { ActionProjectType, TWebhooksInsert } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; @@ -45,13 +45,14 @@ export const webhookServiceFactory = ({ webhookSecretKey, type }: TCreateWebhookDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks); const env = await projectEnvDAL.findOne({ projectId, slug: environment }); if (!env) @@ -93,13 +94,14 @@ export const webhookServiceFactory = ({ const webhook = await webhookDAL.findById(id); if (!webhook) throw new NotFoundError({ message: `Webhook with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - webhook.projectId, + projectId: webhook.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks); const updatedWebhook = await webhookDAL.updateById(id, { isDisabled }); @@ -110,13 +112,14 @@ export const webhookServiceFactory = ({ const webhook = await webhookDAL.findById(id); if (!webhook) throw new NotFoundError({ message: `Webhook with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - webhook.projectId, + projectId: webhook.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks); const deletedWebhook = await webhookDAL.deleteById(id); @@ -127,13 +130,14 @@ export const webhookServiceFactory = ({ const webhook = await webhookDAL.findById(id); if (!webhook) throw new NotFoundError({ message: `Webhook with ID '${id}' not found` }); - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, - webhook.projectId, + projectId: webhook.projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); const project = await projectDAL.findById(webhook.projectId); @@ -170,13 +174,14 @@ export const webhookServiceFactory = ({ secretPath, environment }: TListWebhookDTO) => { - const { permission } = await permissionService.getProjectPermission( + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, actorAuthMethod, - actorOrgId - ); + actorOrgId, + actionProjectType: ActionProjectType.Any + }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); const webhooks = await webhookDAL.findAllWebhooks(projectId, environment, secretPath); diff --git a/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx b/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx index a41e13cdb..1f73202bd 100644 --- a/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx +++ b/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx @@ -46,8 +46,19 @@ export const ProjectLayout = () => { const workspaceId = currentWorkspace?.id || ""; const projectSlug = currentWorkspace?.slug || ""; - const { data: secretApprovalReqCount } = useGetSecretApprovalRequestCount({ workspaceId }); - const { data: accessApprovalRequestCount } = useGetAccessRequestsCount({ projectSlug }); + const isSecretManager = currentWorkspace?.type === ProjectType.SecretManager; + const isCertManager = currentWorkspace?.type === ProjectType.CertificateManager; + const isCmek = currentWorkspace?.type === ProjectType.KMS; + const isSSH = currentWorkspace?.type === ProjectType.SSH; + + const { data: secretApprovalReqCount } = useGetSecretApprovalRequestCount({ + workspaceId, + options: { enabled: isSecretManager } + }); + const { data: accessApprovalRequestCount } = useGetAccessRequestsCount({ + projectSlug, + options: { enabled: isSecretManager } + }); const pendingRequestsCount = (secretApprovalReqCount?.open || 0) + (accessApprovalRequestCount?.pendingCount || 0); @@ -86,11 +97,6 @@ export const ProjectLayout = () => { ); } - const isSecretManager = currentWorkspace?.type === ProjectType.SecretManager; - const isCertManager = currentWorkspace?.type === ProjectType.CertificateManager; - const isCmek = currentWorkspace?.type === ProjectType.KMS; - const isSSH = currentWorkspace?.type === ProjectType.SSH; - return ( <>