diff --git a/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts b/backend/src/ee/services/access-approval-policy/access-approval-policy-service.ts index 95d1a9877..929fdd575 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 @@ -3,7 +3,7 @@ import { ForbiddenError } from "@casl/ability"; import { ActionProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; -import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; +import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { groupBy } from "@app/lib/fn"; import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal"; import { TProjectDALFactory } from "@app/services/project/project-dal"; @@ -633,7 +633,7 @@ export const accessApprovalPolicyServiceFactory = ({ if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); - const { membership } = await permissionService.getProjectPermission({ + await permissionService.getProjectPermission({ actor, actorId, projectId: project.id, @@ -641,9 +641,6 @@ export const accessApprovalPolicyServiceFactory = ({ actorOrgId, actionProjectType: ActionProjectType.SecretManager }); - if (!membership) { - throw new ForbiddenRequestError({ message: "You are not a member of this project" }); - } const environment = await projectEnvDAL.findOne({ projectId: project.id, slug: envSlug }); if (!environment) throw new NotFoundError({ message: `Environment with slug '${envSlug}' not found` }); 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 d69c6da79..551321fd3 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 @@ -125,7 +125,7 @@ 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({ + await permissionService.getProjectPermission({ actor, actorId, projectId: project.id, @@ -133,9 +133,6 @@ export const accessApprovalRequestServiceFactory = ({ actorOrgId, actionProjectType: ActionProjectType.SecretManager }); - if (!membership) { - throw new ForbiddenRequestError({ message: "You are not a member of this project" }); - } const requestedByUser = await userDAL.findById(actorId); if (!requestedByUser) throw new ForbiddenRequestError({ message: "User not found" }); @@ -340,7 +337,7 @@ export const accessApprovalRequestServiceFactory = ({ }); } - const { membership, hasRole } = await permissionService.getProjectPermission({ + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId: accessApprovalRequest.projectId, @@ -349,10 +346,6 @@ export const accessApprovalRequestServiceFactory = ({ actionProjectType: ActionProjectType.SecretManager }); - if (!membership) { - throw new ForbiddenRequestError({ message: "You are not a member of this project" }); - } - const isApprover = policy.approvers.find((approver) => approver.userId === actorId); if (!hasRole(ProjectMembershipRole.Admin) && !isApprover) { @@ -496,7 +489,7 @@ 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({ + await permissionService.getProjectPermission({ actor, actorId, projectId: project.id, @@ -504,9 +497,6 @@ export const accessApprovalRequestServiceFactory = ({ actorOrgId, actionProjectType: ActionProjectType.SecretManager }); - if (!membership) { - throw new ForbiddenRequestError({ message: "You are not a member of this project" }); - } const policies = await accessApprovalPolicyDAL.find({ projectId: project.id }); let requests = await accessApprovalRequestDAL.findRequestsWithPrivilegeByPolicyIds(policies.map((p) => p.id)); @@ -566,7 +556,7 @@ export const accessApprovalRequestServiceFactory = ({ slug: permissionEnvironment }); - const { membership, hasRole } = await permissionService.getProjectPermission({ + const { hasRole } = await permissionService.getProjectPermission({ actor, actorId, projectId: accessApprovalRequest.projectId, @@ -575,10 +565,6 @@ export const accessApprovalRequestServiceFactory = ({ actionProjectType: ActionProjectType.SecretManager }); - if (!membership) { - throw new ForbiddenRequestError({ message: "You are not a member of this project" }); - } - const isSelfApproval = actorId === accessApprovalRequest.requestedByUserId; const isSoftEnforcement = policy.enforcementLevel === EnforcementLevel.Soft; const canBypass = !policy.bypassers.length || policy.bypassers.some((bypasser) => bypasser.userId === actorId); @@ -830,7 +816,7 @@ 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({ + await permissionService.getProjectPermission({ actor, actorId, projectId: project.id, @@ -838,9 +824,6 @@ export const accessApprovalRequestServiceFactory = ({ actorOrgId, actionProjectType: ActionProjectType.SecretManager }); - if (!membership) { - throw new ForbiddenRequestError({ message: "You are not a member of this project" }); - } const count = await accessApprovalRequestDAL.getCount({ projectId: project.id, policyId }); diff --git a/backend/src/ee/services/oidc/oidc-config-service.ts b/backend/src/ee/services/oidc/oidc-config-service.ts index 445ace2b5..3bfccf9aa 100644 --- a/backend/src/ee/services/oidc/oidc-config-service.ts +++ b/backend/src/ee/services/oidc/oidc-config-service.ts @@ -66,7 +66,7 @@ type TOidcConfigServiceFactoryDep = { licenseService: Pick; tokenService: Pick; smtpService: Pick; - permissionService: Pick; + permissionService: Pick; oidcConfigDAL: Pick; groupDAL: Pick; userGroupMembershipDAL: Pick< @@ -749,7 +749,7 @@ export const oidcConfigServiceFactory = ({ }; const isOidcManageGroupMembershipsEnabled = async (orgId: string, actor: OrgServiceActor) => { - await permissionService.getUserOrgPermission(actor.id, orgId, actor.authMethod, actor.orgId); + await permissionService.getOrgPermission(ActorType.USER, actor.id, orgId, actor.authMethod, actor.orgId); const oidcConfig = await oidcConfigDAL.findOne({ orgId, diff --git a/backend/src/ee/services/permission/permission-service-types.ts b/backend/src/ee/services/permission/permission-service-types.ts index 01da92a9b..3b65c09cb 100644 --- a/backend/src/ee/services/permission/permission-service-types.ts +++ b/backend/src/ee/services/permission/permission-service-types.ts @@ -67,6 +67,7 @@ export type TPermissionServiceFactory = { ) => Promise<{ permission: MongoAbility; memberships: TMemberships[]; + hasRole: (role: string) => boolean; }>; getProjectPermission: (arg: TGetProjectPermissionArg) => Promise<{ permission: MongoAbility; diff --git a/backend/src/ee/services/permission/permission-service.ts b/backend/src/ee/services/permission/permission-service.ts index 5071f3151..2564bf264 100644 --- a/backend/src/ee/services/permission/permission-service.ts +++ b/backend/src/ee/services/permission/permission-service.ts @@ -238,7 +238,9 @@ export const permissionServiceFactory = ({ return { permission, - memberships: permissionData + memberships: permissionData, + hasRole: (role: string) => + permissionData.some((memberships) => memberships.roles.some((el) => role === (el.customRoleSlug || el.role))) }; }; diff --git a/backend/src/ee/services/ssh-host-group/ssh-host-group-service.ts b/backend/src/ee/services/ssh-host-group/ssh-host-group-service.ts index aa6d4f66a..0846532f9 100644 --- a/backend/src/ee/services/ssh-host-group/ssh-host-group-service.ts +++ b/backend/src/ee/services/ssh-host-group/ssh-host-group-service.ts @@ -44,10 +44,7 @@ type TSshHostGroupServiceFactoryDep = { sshHostLoginUserDAL: Pick; sshHostLoginUserMappingDAL: Pick; userDAL: Pick; - permissionService: Pick< - TPermissionServiceFactory, - "getProjectPermission" | "getUserProjectPermission" | "checkGroupProjectPermission" - >; + permissionService: Pick; licenseService: Pick; groupDAL: Pick; }; diff --git a/backend/src/ee/services/ssh-host/ssh-host-fns.ts b/backend/src/ee/services/ssh-host/ssh-host-fns.ts index dec15e093..7e188a5fe 100644 --- a/backend/src/ee/services/ssh-host/ssh-host-fns.ts +++ b/backend/src/ee/services/ssh-host/ssh-host-fns.ts @@ -2,6 +2,7 @@ import { Knex } from "knex"; import { ActionProjectType } from "@app/db/schemas"; import { BadRequestError } from "@app/lib/errors"; +import { ActorType } from "@app/services/auth/auth-type"; import { ProjectPermissionSshHostActions, ProjectPermissionSub } from "../permission/project-permission"; import { TCreateSshLoginMappingsDTO } from "./ssh-host-types"; @@ -59,11 +60,12 @@ export const createSshLoginMappings = async ({ for await (const user of users) { // check that each user has access to the SSH project - await permissionService.getUserProjectPermission({ - userId: user.id, + await permissionService.getProjectPermission({ + actor: ActorType.USER, + actorId: user.id, projectId, - authMethod: actorAuthMethod, - userOrgId: actorOrgId, + actorAuthMethod, + actorOrgId, actionProjectType: ActionProjectType.SSH }); } diff --git a/backend/src/ee/services/ssh-host/ssh-host-service.ts b/backend/src/ee/services/ssh-host/ssh-host-service.ts index d1082b4df..37d843c47 100644 --- a/backend/src/ee/services/ssh-host/ssh-host-service.ts +++ b/backend/src/ee/services/ssh-host/ssh-host-service.ts @@ -64,10 +64,7 @@ type TSshHostServiceFactoryDep = { >; sshHostLoginUserDAL: TSshHostLoginUserDALFactory; sshHostLoginUserMappingDAL: TSshHostLoginUserMappingDALFactory; - permissionService: Pick< - TPermissionServiceFactory, - "getProjectPermission" | "getUserProjectPermission" | "checkGroupProjectPermission" - >; + permissionService: Pick; kmsService: Pick; }; diff --git a/backend/src/ee/services/ssh-host/ssh-host-types.ts b/backend/src/ee/services/ssh-host/ssh-host-types.ts index a8269ac37..698f067f2 100644 --- a/backend/src/ee/services/ssh-host/ssh-host-types.ts +++ b/backend/src/ee/services/ssh-host/ssh-host-types.ts @@ -66,7 +66,7 @@ type BaseCreateSshLoginMappingsDTO = { sshHostLoginUserDAL: Pick; sshHostLoginUserMappingDAL: Pick; userDAL: Pick; - permissionService: Pick; + permissionService: Pick; groupDAL: Pick; projectId: string; actorAuthMethod: ActorAuthMethod; diff --git a/backend/src/services/external-migration/external-migration-service.ts b/backend/src/services/external-migration/external-migration-service.ts index e801b607e..577712b9f 100644 --- a/backend/src/services/external-migration/external-migration-service.ts +++ b/backend/src/services/external-migration/external-migration-service.ts @@ -47,14 +47,14 @@ export const externalMigrationServiceFactory = ({ throw new BadRequestError({ message: "EnvKey migration is not supported when running in FIPS mode." }); } - const { membership } = await permissionService.getOrgPermission( + const { hasRole } = await permissionService.getOrgPermission( actor, actorId, actorOrgId, actorAuthMethod, actorOrgId ); - if (membership.role !== OrgMembershipRole.Admin) { + if (hasRole(OrgMembershipRole.Admin)) { throw new ForbiddenRequestError({ message: "Only admins can import data" }); } @@ -94,7 +94,7 @@ export const externalMigrationServiceFactory = ({ actorOrgId, actorAuthMethod }: TImportVaultDataDTO) => { - const { membership } = await permissionService.getOrgPermission( + const { hasRole } = await permissionService.getOrgPermission( actor, actorId, actorOrgId, @@ -102,7 +102,7 @@ export const externalMigrationServiceFactory = ({ actorOrgId ); - if (membership.role !== OrgMembershipRole.Admin) { + if (hasRole(OrgMembershipRole.Admin)) { throw new ForbiddenRequestError({ message: "Only admins can import data" }); } @@ -150,7 +150,7 @@ export const externalMigrationServiceFactory = ({ actorAuthMethod, provider }: THasCustomVaultMigrationDTO) => { - const { membership } = await permissionService.getOrgPermission( + const { hasRole } = await permissionService.getOrgPermission( actor, actorId, actorOrgId, @@ -158,7 +158,7 @@ export const externalMigrationServiceFactory = ({ actorOrgId ); - if (membership.role !== OrgMembershipRole.Admin) { + if (hasRole(OrgMembershipRole.Admin)) { throw new ForbiddenRequestError({ message: "Only admins can check custom migration status" }); } diff --git a/backend/src/services/identity-alicloud-auth/identity-alicloud-auth-service.ts b/backend/src/services/identity-alicloud-auth/identity-alicloud-auth-service.ts index af94c79c9..fb3f597c2 100644 --- a/backend/src/services/identity-alicloud-auth/identity-alicloud-auth-service.ts +++ b/backend/src/services/identity-alicloud-auth/identity-alicloud-auth-service.ts @@ -21,6 +21,7 @@ import { ActorType, AuthTokenType } from "../auth/auth-type"; import { TIdentityOrgDALFactory } from "../identity/identity-org-dal"; import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal"; import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types"; +import { TOrgDALFactory } from "../org/org-dal"; import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns"; import { TIdentityAliCloudAuthDALFactory } from "./identity-alicloud-auth-dal"; import { @@ -41,6 +42,7 @@ type TIdentityAliCloudAuthServiceFactoryDep = { identityOrgMembershipDAL: Pick; licenseService: Pick; permissionService: Pick; + orgDAL: Pick; }; export type TIdentityAliCloudAuthServiceFactory = ReturnType; @@ -50,7 +52,8 @@ export const identityAliCloudAuthServiceFactory = ({ identityAliCloudAuthDAL, identityOrgMembershipDAL, licenseService, - permissionService + permissionService, + orgDAL }: TIdentityAliCloudAuthServiceFactoryDep) => { const login = async ({ identityId, ...params }: TLoginAliCloudAuthDTO) => { const identityAliCloudAuth = await identityAliCloudAuthDAL.findOne({ identityId }); @@ -316,7 +319,7 @@ export const identityAliCloudAuthServiceFactory = ({ message: "The identity does not have Alibaba Cloud auth" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -333,8 +336,9 @@ export const identityAliCloudAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -345,7 +349,7 @@ export const identityAliCloudAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke Alibaba Cloud auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts b/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts index 3dff47403..53443adbe 100644 --- a/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts +++ b/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts @@ -5,6 +5,7 @@ import RE2 from "re2"; import { IdentityAuthMethod } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { constructPermissionErrorMessage, @@ -39,6 +40,7 @@ type TIdentityAwsAuthServiceFactoryDep = { identityOrgMembershipDAL: Pick; licenseService: Pick; permissionService: Pick; + orgDAL: Pick; }; export type TIdentityAwsAuthServiceFactory = ReturnType; @@ -82,7 +84,8 @@ export const identityAwsAuthServiceFactory = ({ identityAwsAuthDAL, identityOrgMembershipDAL, licenseService, - permissionService + permissionService, + orgDAL }: TIdentityAwsAuthServiceFactoryDep) => { const login = async ({ identityId, iamHttpRequestMethod, iamRequestBody, iamRequestHeaders }: TLoginAwsAuthDTO) => { const identityAwsAuth = await identityAwsAuthDAL.findOne({ identityId }); @@ -397,7 +400,7 @@ export const identityAwsAuthServiceFactory = ({ message: "The identity does not have aws auth" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -414,8 +417,9 @@ export const identityAwsAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -426,7 +430,7 @@ export const identityAwsAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke aws auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts b/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts index 9a2426a7c..0ca27c041 100644 --- a/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts +++ b/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts @@ -2,6 +2,7 @@ import { ForbiddenError } from "@casl/ability"; import { IdentityAuthMethod } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { constructPermissionErrorMessage, @@ -37,6 +38,7 @@ type TIdentityAzureAuthServiceFactoryDep = { identityAccessTokenDAL: Pick; permissionService: Pick; licenseService: Pick; + orgDAL: Pick; }; export type TIdentityAzureAuthServiceFactory = ReturnType; @@ -46,7 +48,8 @@ export const identityAzureAuthServiceFactory = ({ identityOrgMembershipDAL, identityAccessTokenDAL, permissionService, - licenseService + licenseService, + orgDAL }: TIdentityAzureAuthServiceFactoryDep) => { const login = async ({ identityId, jwt: azureJwt }: TLoginAzureAuthDTO) => { const identityAzureAuth = await identityAzureAuthDAL.findOne({ identityId }); @@ -311,7 +314,7 @@ export const identityAzureAuthServiceFactory = ({ message: "The identity does not have azure auth" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -327,8 +330,9 @@ export const identityAzureAuthServiceFactory = ({ actorAuthMethod, actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -338,7 +342,7 @@ export const identityAzureAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke azure auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts b/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts index 388c24d48..fccffdc89 100644 --- a/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts +++ b/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts @@ -2,6 +2,7 @@ import { ForbiddenError } from "@casl/ability"; import { IdentityAuthMethod } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { constructPermissionErrorMessage, @@ -35,6 +36,7 @@ type TIdentityGcpAuthServiceFactoryDep = { identityAccessTokenDAL: Pick; permissionService: Pick; licenseService: Pick; + orgDAL: Pick; }; export type TIdentityGcpAuthServiceFactory = ReturnType; @@ -44,7 +46,8 @@ export const identityGcpAuthServiceFactory = ({ identityOrgMembershipDAL, identityAccessTokenDAL, permissionService, - licenseService + licenseService, + orgDAL }: TIdentityGcpAuthServiceFactoryDep) => { const login = async ({ identityId, jwt: gcpJwt }: TLoginGcpAuthDTO) => { const identityGcpAuth = await identityGcpAuthDAL.findOne({ identityId }); @@ -357,7 +360,7 @@ export const identityGcpAuthServiceFactory = ({ message: "The identity does not have gcp auth" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -373,8 +376,9 @@ export const identityGcpAuthServiceFactory = ({ actorAuthMethod, actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -384,7 +388,7 @@ export const identityGcpAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke gcp auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts b/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts index 9cc851437..5d5af5841 100644 --- a/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts +++ b/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts @@ -5,6 +5,7 @@ import { JwksClient } from "jwks-rsa"; import { IdentityAuthMethod, TIdentityJwtAuthsUpdate } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { constructPermissionErrorMessage, @@ -48,6 +49,7 @@ type TIdentityJwtAuthServiceFactoryDep = { permissionService: Pick; licenseService: Pick; kmsService: Pick; + orgDAL: Pick; }; export type TIdentityJwtAuthServiceFactory = ReturnType; @@ -58,7 +60,8 @@ export const identityJwtAuthServiceFactory = ({ permissionService, licenseService, identityAccessTokenDAL, - kmsService + kmsService, + orgDAL }: TIdentityJwtAuthServiceFactoryDep) => { const login = async ({ identityId, jwt: jwtValue }: TLoginJwtAuthDTO) => { const identityJwtAuth = await identityJwtAuthDAL.findOne({ identityId }); @@ -520,7 +523,7 @@ export const identityJwtAuthServiceFactory = ({ }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -538,8 +541,9 @@ export const identityJwtAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -549,7 +553,7 @@ export const identityJwtAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke jwt auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts index bc231c6d6..021312fb1 100644 --- a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts +++ b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts @@ -9,6 +9,7 @@ import { TGatewayServiceFactory } from "@app/ee/services/gateway/gateway-service import { TGatewayV2DALFactory } from "@app/ee/services/gateway-v2/gateway-v2-dal"; import { TGatewayV2ServiceFactory } from "@app/ee/services/gateway-v2/gateway-v2-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionGatewayActions, OrgPermissionIdentityActions, @@ -60,6 +61,7 @@ type TIdentityKubernetesAuthServiceFactoryDep = { gatewayV2Service: TGatewayV2ServiceFactory; gatewayDAL: Pick; gatewayV2DAL: Pick; + orgDAL: Pick; }; export type TIdentityKubernetesAuthServiceFactory = ReturnType; @@ -76,7 +78,8 @@ export const identityKubernetesAuthServiceFactory = ({ gatewayV2Service, gatewayDAL, gatewayV2DAL, - kmsService + kmsService, + orgDAL }: TIdentityKubernetesAuthServiceFactoryDep) => { const $gatewayProxyWrapper = async ( inputs: { @@ -819,7 +822,7 @@ export const identityKubernetesAuthServiceFactory = ({ message: "The identity does not have kubernetes auth" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -835,8 +838,9 @@ export const identityKubernetesAuthServiceFactory = ({ actorAuthMethod, actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -846,7 +850,7 @@ export const identityKubernetesAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke kubernetes auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-ldap-auth/identity-ldap-auth-service.ts b/backend/src/services/identity-ldap-auth/identity-ldap-auth-service.ts index 46ec2f98a..6f672e167 100644 --- a/backend/src/services/identity-ldap-auth/identity-ldap-auth-service.ts +++ b/backend/src/services/identity-ldap-auth/identity-ldap-auth-service.ts @@ -6,6 +6,7 @@ import { IdentityAuthMethod } from "@app/db/schemas"; import { TIdentityAuthTemplateDALFactory } from "@app/ee/services/identity-auth-template"; import { testLDAPConfig } from "@app/ee/services/ldap-config/ldap-fns"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionIdentityActions, OrgPermissionMachineIdentityAuthTemplateActions, @@ -65,6 +66,7 @@ type TIdentityLdapAuthServiceFactoryDep = { TKeyStoreFactory, "setItemWithExpiry" | "getItem" | "deleteItem" | "getKeysByPattern" | "deleteItems" | "acquireLock" >; + orgDAL: Pick; }; export type TIdentityLdapAuthServiceFactory = ReturnType; @@ -83,7 +85,8 @@ export const identityLdapAuthServiceFactory = ({ permissionService, kmsService, identityAuthTemplateDAL, - keyStore + keyStore, + orgDAL }: TIdentityLdapAuthServiceFactoryDep) => { const getLdapConfig = async (identityId: string) => { const identity = await identityDAL.findOne({ id: identityId }); @@ -607,7 +610,7 @@ export const identityLdapAuthServiceFactory = ({ message: "The identity does not have LDAP Auth attached" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -624,8 +627,9 @@ export const identityLdapAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -636,7 +640,7 @@ export const identityLdapAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke LDAP auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-oci-auth/identity-oci-auth-service.ts b/backend/src/services/identity-oci-auth/identity-oci-auth-service.ts index a4294250c..260734b55 100644 --- a/backend/src/services/identity-oci-auth/identity-oci-auth-service.ts +++ b/backend/src/services/identity-oci-auth/identity-oci-auth-service.ts @@ -32,6 +32,7 @@ import { TRevokeOciAuthDTO, TUpdateOciAuthDTO } from "./identity-oci-auth-types"; +import { TOrgDALFactory } from "../org/org-dal"; type TIdentityOciAuthServiceFactoryDep = { identityAccessTokenDAL: Pick; @@ -39,6 +40,7 @@ type TIdentityOciAuthServiceFactoryDep = { identityOrgMembershipDAL: Pick; licenseService: Pick; permissionService: Pick; + orgDAL: Pick; }; export type TIdentityOciAuthServiceFactory = ReturnType; @@ -48,7 +50,8 @@ export const identityOciAuthServiceFactory = ({ identityOciAuthDAL, identityOrgMembershipDAL, licenseService, - permissionService + permissionService, + orgDAL }: TIdentityOciAuthServiceFactoryDep) => { const login = async ({ identityId, headers, userOcid }: TLoginOciAuthDTO) => { const identityOciAuth = await identityOciAuthDAL.findOne({ identityId }); @@ -322,7 +325,7 @@ export const identityOciAuthServiceFactory = ({ message: "The identity does not have OCI auth" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -339,8 +342,9 @@ export const identityOciAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(actorOrgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -351,7 +355,7 @@ export const identityOciAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke OCI auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts index 6585e61f3..d5ff33907 100644 --- a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts +++ b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts @@ -6,6 +6,7 @@ import { JwksClient } from "jwks-rsa"; import { IdentityAuthMethod, TIdentityOidcAuthsUpdate } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { constructPermissionErrorMessage, @@ -48,6 +49,7 @@ type TIdentityOidcAuthServiceFactoryDep = { permissionService: Pick; licenseService: Pick; kmsService: Pick; + orgDAL: Pick; }; export type TIdentityOidcAuthServiceFactory = ReturnType; @@ -58,7 +60,8 @@ export const identityOidcAuthServiceFactory = ({ permissionService, licenseService, identityAccessTokenDAL, - kmsService + kmsService, + orgDAL }: TIdentityOidcAuthServiceFactoryDep) => { const login = async ({ identityId, jwt: oidcJwt }: TLoginOidcAuthDTO) => { const identityOidcAuth = await identityOidcAuthDAL.findOne({ identityId }); @@ -460,7 +463,7 @@ export const identityOidcAuthServiceFactory = ({ }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -478,8 +481,9 @@ export const identityOidcAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -490,7 +494,7 @@ export const identityOidcAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke oidc auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-project/identity-project-service.ts b/backend/src/services/identity-project/identity-project-service.ts index 08fd2cf0b..99b5741e6 100644 --- a/backend/src/services/identity-project/identity-project-service.ts +++ b/backend/src/services/identity-project/identity-project-service.ts @@ -12,6 +12,7 @@ import { groupBy } from "@app/lib/fn"; import { ms } from "@app/lib/ms"; import { TIdentityOrgDALFactory } from "../identity/identity-org-dal"; +import { TOrgDALFactory } from "../org/org-dal"; import { TProjectDALFactory } from "../project/project-dal"; import { ProjectUserMembershipTemporaryMode } from "../project-membership/project-membership-types"; import { TProjectRoleDALFactory } from "../project-role/project-role-dal"; @@ -28,6 +29,7 @@ import { type TIdentityProjectServiceFactoryDep = { identityProjectDAL: TIdentityProjectDALFactory; + orgDAL: Pick; identityProjectMembershipRoleDAL: Pick< TIdentityProjectMembershipRoleDALFactory, "create" | "transaction" | "insertMany" | "delete" @@ -37,7 +39,7 @@ type TIdentityProjectServiceFactoryDep = { identityOrgMembershipDAL: Pick; permissionService: Pick< TPermissionServiceFactory, - "getProjectPermission" | "getProjectPermissionByRole" | "invalidateProjectPermissionCache" + "getProjectPermission" | "getProjectPermissionByRoles" | "invalidateProjectPermissionCache" >; }; @@ -49,7 +51,8 @@ export const identityProjectServiceFactory = ({ identityOrgMembershipDAL, identityProjectMembershipRoleDAL, projectDAL, - projectRoleDAL + projectRoleDAL, + orgDAL }: TIdentityProjectServiceFactoryDep) => { const createProjectIdentity = async ({ identityId, @@ -60,7 +63,7 @@ export const identityProjectServiceFactory = ({ projectId, roles }: TCreateProjectIdentityDTO) => { - const { permission, membership } = await permissionService.getProjectPermission({ + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, @@ -91,31 +94,29 @@ export const identityProjectServiceFactory = ({ message: `Failed to find identity with ID ${identityId}` }); - for await (const { role: requestedRoleChange } of roles) { - const { permission: rolePermission } = await permissionService.getProjectPermissionByRole( - requestedRoleChange, - projectId + const providedRolePermissionDetails = await permissionService.getProjectPermissionByRoles( + roles.map((el) => el.role).filter((el) => el !== ProjectMembershipRole.NoAccess), + projectId + ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(actorOrgId); + for await (const { permission: rolePermission } of providedRolePermissionDetails) { + const permissionBoundary = validatePrivilegeChangeOperation( + shouldUseNewPrivilegeSystem, + ProjectPermissionIdentityActions.GrantPrivileges, + ProjectPermissionSub.Identity, + permission, + rolePermission ); - - if (requestedRoleChange !== ProjectMembershipRole.NoAccess) { - const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, - ProjectPermissionIdentityActions.GrantPrivileges, - ProjectPermissionSub.Identity, - permission, - rolePermission - ); - if (!permissionBoundary.isValid) - throw new PermissionBoundaryError({ - message: constructPermissionErrorMessage( - "Failed to assign to role", - membership.shouldUseNewPrivilegeSystem, - ProjectPermissionIdentityActions.GrantPrivileges, - ProjectPermissionSub.Identity - ), - details: { missingPermissions: permissionBoundary.missingPermissions } - }); - } + if (!permissionBoundary.isValid) + throw new PermissionBoundaryError({ + message: constructPermissionErrorMessage( + "Failed to assign to role", + shouldUseNewPrivilegeSystem, + ProjectPermissionIdentityActions.GrantPrivileges, + ProjectPermissionSub.Identity + ), + details: { missingPermissions: permissionBoundary.missingPermissions } + }); } // validate custom roles input @@ -183,7 +184,7 @@ export const identityProjectServiceFactory = ({ actorAuthMethod, actorOrgId }: TUpdateProjectIdentityDTO) => { - const { permission, membership } = await permissionService.getProjectPermission({ + const { permission } = await permissionService.getProjectPermission({ actor, actorId, projectId, @@ -202,14 +203,14 @@ export const identityProjectServiceFactory = ({ message: `Identity with ID ${identityId} doesn't exists in project with ID ${projectId}` }); - for await (const { role: requestedRoleChange } of roles) { - const { permission: rolePermission } = await permissionService.getProjectPermissionByRole( - requestedRoleChange, - projectId - ); - + const providedRolePermissionDetails = await permissionService.getProjectPermissionByRoles( + roles.map((el) => el.role).filter((el) => el !== ProjectMembershipRole.NoAccess), + projectId + ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(actorOrgId); + for await (const { permission: rolePermission } of providedRolePermissionDetails) { const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, ProjectPermissionIdentityActions.GrantPrivileges, ProjectPermissionSub.Identity, permission, @@ -220,7 +221,7 @@ export const identityProjectServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to change role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, ProjectPermissionIdentityActions.GrantPrivileges, ProjectPermissionSub.Identity ), @@ -235,7 +236,7 @@ export const identityProjectServiceFactory = ({ // we don't want to include custom in this check; // this unintentionally enables setting slug to custom which is reserved .filter((r) => r !== ProjectMembershipRole.Custom) - .includes(role as ProjectMembershipRole) + .includes(role as ProjectMembershipRole.Admin) ); const hasCustomRole = Boolean(customInputRoles.length); const customRoles = hasCustomRole diff --git a/backend/src/services/identity-tls-cert-auth/identity-tls-cert-auth-service.ts b/backend/src/services/identity-tls-cert-auth/identity-tls-cert-auth-service.ts index ef2463eec..74ab525a0 100644 --- a/backend/src/services/identity-tls-cert-auth/identity-tls-cert-auth-service.ts +++ b/backend/src/services/identity-tls-cert-auth/identity-tls-cert-auth-service.ts @@ -2,6 +2,7 @@ import { ForbiddenError } from "@casl/ability"; import { IdentityAuthMethod } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { constructPermissionErrorMessage, @@ -34,6 +35,7 @@ type TIdentityTlsCertAuthServiceFactoryDep = { licenseService: Pick; permissionService: Pick; kmsService: Pick; + orgDAL: Pick; }; const parseSubjectDetails = (data: string) => { @@ -51,7 +53,8 @@ export const identityTlsCertAuthServiceFactory = ({ identityOrgMembershipDAL, licenseService, permissionService, - kmsService + kmsService, + orgDAL }: TIdentityTlsCertAuthServiceFactoryDep): TIdentityTlsCertAuthServiceFactory => { const login: TIdentityTlsCertAuthServiceFactory["login"] = async ({ identityId, clientCertificate }) => { const identityTlsCertAuth = await identityTlsCertAuthDAL.findOne({ identityId }); @@ -374,7 +377,7 @@ export const identityTlsCertAuthServiceFactory = ({ message: "The identity does not have TLS Certificate auth" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -391,8 +394,9 @@ export const identityTlsCertAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -403,7 +407,7 @@ export const identityTlsCertAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke TLS Certificate auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-token-auth/identity-token-auth-service.ts b/backend/src/services/identity-token-auth/identity-token-auth-service.ts index d3743bd96..9ef8d7216 100644 --- a/backend/src/services/identity-token-auth/identity-token-auth-service.ts +++ b/backend/src/services/identity-token-auth/identity-token-auth-service.ts @@ -2,6 +2,7 @@ import { ForbiddenError } from "@casl/ability"; import { IdentityAuthMethod, TableName } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TOrgDALFactory } from "../org/org-dal"; import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { constructPermissionErrorMessage, @@ -42,6 +43,7 @@ type TIdentityTokenAuthServiceFactoryDep = { >; permissionService: Pick; licenseService: Pick; + orgDAL: Pick; }; export type TIdentityTokenAuthServiceFactory = ReturnType; @@ -52,7 +54,8 @@ export const identityTokenAuthServiceFactory = ({ identityOrgMembershipDAL, identityAccessTokenDAL, permissionService, - licenseService + licenseService, + orgDAL }: TIdentityTokenAuthServiceFactoryDep) => { const attachTokenAuth = async ({ identityId, @@ -250,7 +253,7 @@ export const identityTokenAuthServiceFactory = ({ ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); - const { permission: rolePermission, membership } = await permissionService.getOrgPermission( + const { permission: rolePermission } = await permissionService.getOrgPermission( ActorType.IDENTITY, identityMembershipOrg.identityId, identityMembershipOrg.orgId, @@ -258,8 +261,9 @@ export const identityTokenAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -269,7 +273,7 @@ export const identityTokenAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke token auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), @@ -316,7 +320,7 @@ export const identityTokenAuthServiceFactory = ({ ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); - const { permission: rolePermission, membership } = await permissionService.getOrgPermission( + const { permission: rolePermission } = await permissionService.getOrgPermission( ActorType.IDENTITY, identityMembershipOrg.identityId, identityMembershipOrg.orgId, @@ -324,8 +328,9 @@ export const identityTokenAuthServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.CreateToken, OrgPermissionSubjects.Identity, permission, @@ -335,7 +340,7 @@ export const identityTokenAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to create token for identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.CreateToken, OrgPermissionSubjects.Identity ), @@ -463,15 +468,16 @@ export const identityTokenAuthServiceFactory = ({ ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); - const { permission: rolePermission, membership } = await permissionService.getOrgPermission( + const { permission: rolePermission } = await permissionService.getOrgPermission( ActorType.IDENTITY, identityMembershipOrg.identityId, identityMembershipOrg.orgId, actorAuthMethod, actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.CreateToken, OrgPermissionSubjects.Identity, permission, @@ -481,7 +487,7 @@ export const identityTokenAuthServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to update token for identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.CreateToken, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity-ua/identity-ua-service.ts b/backend/src/services/identity-ua/identity-ua-service.ts index 979e6f25f..f5cd5494d 100644 --- a/backend/src/services/identity-ua/identity-ua-service.ts +++ b/backend/src/services/identity-ua/identity-ua-service.ts @@ -25,6 +25,7 @@ import { ActorType, AuthTokenType } from "../auth/auth-type"; import { TIdentityOrgDALFactory } from "../identity/identity-org-dal"; import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal"; import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types"; +import { TOrgDALFactory } from "../org/org-dal"; import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns"; import { TIdentityUaClientSecretDALFactory } from "./identity-ua-client-secret-dal"; import { TIdentityUaDALFactory } from "./identity-ua-dal"; @@ -47,6 +48,7 @@ type TIdentityUaServiceFactoryDep = { identityOrgMembershipDAL: TIdentityOrgDALFactory; permissionService: Pick; licenseService: Pick; + orgDAL: Pick; keyStore: Pick< TKeyStoreFactory, "setItemWithExpiry" | "getItem" | "deleteItem" | "getKeysByPattern" | "deleteItems" | "acquireLock" @@ -67,6 +69,7 @@ export const identityUaServiceFactory = ({ identityOrgMembershipDAL, permissionService, licenseService, + orgDAL, keyStore }: TIdentityUaServiceFactoryDep) => { const login = async (clientId: string, clientSecret: string, ip: string) => { @@ -524,15 +527,16 @@ export const identityUaServiceFactory = ({ ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); - const { permission: rolePermission, membership } = await permissionService.getOrgPermission( + const { permission: rolePermission } = await permissionService.getOrgPermission( ActorType.IDENTITY, identityMembershipOrg.identityId, identityMembershipOrg.orgId, actorAuthMethod, actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity, permission, @@ -542,7 +546,7 @@ export const identityUaServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke universal auth of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity ), @@ -575,7 +579,7 @@ export const identityUaServiceFactory = ({ }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -591,8 +595,9 @@ export const identityUaServiceFactory = ({ actorAuthMethod, actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.CreateToken, OrgPermissionSubjects.Identity, permission, @@ -602,7 +607,7 @@ export const identityUaServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to create client secret for identity.", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.CreateToken, OrgPermissionSubjects.Identity ), @@ -648,7 +653,7 @@ export const identityUaServiceFactory = ({ message: "The identity does not have universal auth" }); } - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -665,8 +670,9 @@ export const identityUaServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.GetToken, OrgPermissionSubjects.Identity, permission, @@ -676,7 +682,7 @@ export const identityUaServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to get identity client secret with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.GetToken, OrgPermissionSubjects.Identity ), @@ -717,7 +723,7 @@ export const identityUaServiceFactory = ({ const clientSecret = await identityUaClientSecretDAL.findOne({ id: clientSecretId, identityUAId: identityUa.id }); if (!clientSecret) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -733,8 +739,9 @@ export const identityUaServiceFactory = ({ actorAuthMethod, actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.GetToken, OrgPermissionSubjects.Identity, permission, @@ -744,7 +751,7 @@ export const identityUaServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to read identity client secret of identity with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.GetToken, OrgPermissionSubjects.Identity ), @@ -777,7 +784,7 @@ export const identityUaServiceFactory = ({ const clientSecret = await identityUaClientSecretDAL.findOne({ id: clientSecretId, identityUAId: identityUa.id }); if (!clientSecret) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityMembershipOrg.orgId, @@ -794,8 +801,9 @@ export const identityUaServiceFactory = ({ actorOrgId ); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId); const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.DeleteToken, OrgPermissionSubjects.Identity, permission, @@ -805,7 +813,7 @@ export const identityUaServiceFactory = ({ throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to revoke identity client secret with more privileged role", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.DeleteToken, OrgPermissionSubjects.Identity ), diff --git a/backend/src/services/identity/identity-service.ts b/backend/src/services/identity/identity-service.ts index f216d6483..514f5fd9e 100644 --- a/backend/src/services/identity/identity-service.ts +++ b/backend/src/services/identity/identity-service.ts @@ -1,6 +1,6 @@ import { ForbiddenError } from "@casl/ability"; -import { OrgMembershipRole, TableName, TOrgRoles } from "@app/db/schemas"; +import { OrgMembershipRole, TableName, TRoles } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { @@ -12,6 +12,7 @@ import { TKeyStoreFactory } from "@app/keystore/keystore"; import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors"; import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal"; +import { TOrgDALFactory } from "../org/org-dal"; import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns"; import { TIdentityDALFactory } from "./identity-dal"; import { TIdentityMetadataDALFactory } from "./identity-metadata-dal"; @@ -31,9 +32,10 @@ type TIdentityServiceFactoryDep = { identityMetadataDAL: TIdentityMetadataDALFactory; identityOrgMembershipDAL: TIdentityOrgDALFactory; identityProjectDAL: Pick; - permissionService: Pick; + permissionService: Pick; licenseService: Pick; keyStore: Pick; + orgDAL: Pick; }; export type TIdentityServiceFactory = ReturnType; @@ -45,7 +47,8 @@ export const identityServiceFactory = ({ identityProjectDAL, permissionService, licenseService, - keyStore + keyStore, + orgDAL }: TIdentityServiceFactoryDep) => { const createIdentity = async ({ name, @@ -58,33 +61,26 @@ export const identityServiceFactory = ({ actorOrgId, metadata }: TCreateIdentityDTO) => { - const { permission, membership } = await permissionService.getOrgPermission( - actor, - actorId, - orgId, - actorAuthMethod, - actorOrgId - ); + const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity); - const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole( - role, - orgId - ); - const isCustomRole = Boolean(customRole); + const [rolePermissionDetails] = await permissionService.getOrgPermissionByRoles([role], orgId); + + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(actorOrgId); + const isCustomRole = Boolean(rolePermissionDetails?.role); if (role !== OrgMembershipRole.NoAccess) { const permissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.GrantPrivileges, OrgPermissionSubjects.Identity, permission, - rolePermission + rolePermissionDetails.permission ); if (!permissionBoundary.isValid) throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to create identity", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.GrantPrivileges, OrgPermissionSubjects.Identity ), @@ -108,7 +104,7 @@ export const identityServiceFactory = ({ identityId: newIdentity.id, orgId, role: isCustomRole ? OrgMembershipRole.Custom : role, - roleId: customRole?.id + roleId: rolePermissionDetails?.role?.id }, tx ); @@ -158,7 +154,7 @@ export const identityServiceFactory = ({ const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id }); if (!identityOrgMembership) throw new NotFoundError({ message: `Failed to find identity with id ${id}` }); - const { permission, membership } = await permissionService.getOrgPermission( + const { permission } = await permissionService.getOrgPermission( actor, actorId, identityOrgMembership.orgId, @@ -167,33 +163,31 @@ export const identityServiceFactory = ({ ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity); - let customRole: TOrgRoles | undefined; + let customRole: TRoles | undefined; if (role) { - const { permission: rolePermission, role: customOrgRole } = await permissionService.getOrgPermissionByRole( - role, - identityOrgMembership.orgId - ); + const [rolePermissionDetails] = await permissionService.getOrgPermissionByRoles([role], actorOrgId); + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(actorOrgId); - const isCustomRole = Boolean(customOrgRole); + const isCustomRole = Boolean(rolePermissionDetails?.role); const appliedRolePermissionBoundary = validatePrivilegeChangeOperation( - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.GrantPrivileges, OrgPermissionSubjects.Identity, permission, - rolePermission + rolePermissionDetails?.permission ); if (!appliedRolePermissionBoundary.isValid) throw new PermissionBoundaryError({ message: constructPermissionErrorMessage( "Failed to update identity", - membership.shouldUseNewPrivilegeSystem, + shouldUseNewPrivilegeSystem, OrgPermissionIdentityActions.GrantPrivileges, OrgPermissionSubjects.Identity ), details: { missingPermissions: appliedRolePermissionBoundary.missingPermissions } }); - if (isCustomRole) customRole = customOrgRole; + if (isCustomRole) customRole = rolePermissionDetails?.role; } const identity = await identityDAL.transaction(async (tx) => { diff --git a/backend/src/services/membership-user/membership-user-service.ts b/backend/src/services/membership-user/membership-user-service.ts index 73016b476..9ce1c8f4a 100644 --- a/backend/src/services/membership-user/membership-user-service.ts +++ b/backend/src/services/membership-user/membership-user-service.ts @@ -1,5 +1,6 @@ -import { ProjectMembershipRole, TemporaryPermissionMode, TMembershipRolesInsert } from "@app/db/schemas"; +import { AccessScope, ProjectMembershipRole, TemporaryPermissionMode, TMembershipRolesInsert } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { groupBy } from "@app/lib/fn"; import { ms } from "@app/lib/ms"; @@ -7,6 +8,7 @@ import { SearchResourceOperators } from "@app/lib/search-resource/search"; import { AuthMethod } from "../auth/auth-type"; import { TMembershipRoleDALFactory } from "../membership/membership-role-dal"; +import { TOrgDALFactory } from "../org/org-dal"; import { TRoleDALFactory } from "../role/role-dal"; import { TUserDALFactory } from "../user/user-dal"; import { TMembershipUserDALFactory } from "./membership-user-dal"; @@ -15,14 +17,17 @@ import { TDeleteMembershipUserDTO, TGetMembershipUserByUserIdDTO, TListMembershipUserDTO, - TMembershipUserScopeFactory, TUpdateMembershipUserDTO } from "./membership-user-types"; +import { newNamespaceMembershipUserFactory } from "./namespace/namespace-membership-user-factory"; +import { newOrgMembershipUserFactory } from "./org/org-membership-user-factory"; +import { newProjectMembershipUserFactory } from "./project/project-membership-user-factory"; type TMembershipUserServiceFactoryDep = { membershipUserDAL: TMembershipUserDALFactory; membershipRoleDAL: Pick; licenseService: Pick; + orgDAL: Pick; roleDAL: Pick; userDAL: Pick< TUserDALFactory, @@ -34,6 +39,10 @@ type TMembershipUserServiceFactoryDep = { | "findUserByEmail" | "findUserEncKeyByUserId" >; + permissionService: Pick< + TPermissionServiceFactory, + "getProjectPermission" | "getProjectPermissionByRoles" | "getOrgPermission" + >; }; export type TMembershipUserServiceFactory = ReturnType; @@ -43,9 +52,20 @@ export const membershipUserServiceFactory = ({ roleDAL, licenseService, membershipRoleDAL, - userDAL + userDAL, + permissionService, + orgDAL }: TMembershipUserServiceFactoryDep) => { - const scopeFactory: Record = {}; + const scopeFactory = { + [AccessScope.Organization]: newOrgMembershipUserFactory({ + permissionService + }), + [AccessScope.Namespace]: newNamespaceMembershipUserFactory({}), + [AccessScope.Project]: newProjectMembershipUserFactory({ + orgDAL, + permissionService + }) + }; const $getUsers = async (usernames: string[]) => { const existingUsers = await userDAL.find({ $in: { username: usernames } }); diff --git a/backend/src/services/membership-user/project/project-membership-user-factory.ts b/backend/src/services/membership-user/project/project-membership-user-factory.ts index 9b02e6561..703dd704b 100644 --- a/backend/src/services/membership-user/project/project-membership-user-factory.ts +++ b/backend/src/services/membership-user/project/project-membership-user-factory.ts @@ -1,22 +1,29 @@ import { ForbiddenError } from "@casl/ability"; -import { AccessScope, ActionProjectType } from "@app/db/schemas"; +import { AccessScope, ActionProjectType, ProjectMembershipRole } from "@app/db/schemas"; +import { + constructPermissionErrorMessage, + validatePrivilegeChangeOperation +} from "@app/ee/services/permission/permission-fns"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { isCustomProjectRole, ProjectPermissionMemberActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; -import { InternalServerError } from "@app/lib/errors"; +import { InternalServerError, PermissionBoundaryError } from "@app/lib/errors"; +import { TOrgDALFactory } from "@app/services/org/org-dal"; import { TMembershipUserScopeFactory } from "../membership-user-types"; type TProjectMembershipUserScopeFactoryDep = { - permissionService: Pick; + permissionService: Pick; + orgDAL: Pick; }; export const newProjectMembershipUserFactory = ({ - permissionService + permissionService, + orgDAL }: TProjectMembershipUserScopeFactoryDep): TMembershipUserScopeFactory => { const getScopeField: TMembershipUserScopeFactory["getScopeField"] = (dto) => { if (dto.scope === AccessScope.Project) { @@ -34,7 +41,6 @@ export const newProjectMembershipUserFactory = ({ const isCustomRole: TMembershipUserScopeFactory["isCustomRole"] = (role) => isCustomProjectRole(role); - // TODO(simp): do rest of the shouldUsePrivilegeV2 check const onCreateMembershipUserGuard: TMembershipUserScopeFactory["onCreateMembershipUserGuard"] = async (dto) => { const scope = getScopeField(dto.scopeData); const { permission } = await permissionService.getProjectPermission({ @@ -46,6 +52,32 @@ export const newProjectMembershipUserFactory = ({ actorOrgId: dto.permission.orgId }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Create, ProjectPermissionSub.Member); + + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(dto.permission.orgId); + const permissionRoles = await permissionService.getProjectPermissionByRoles( + dto.data.roles.filter((el) => el.role !== ProjectMembershipRole.NoAccess).map((el) => el.role), + scope.value + ); + + for (const permissionRole of permissionRoles) { + const permissionBoundary = validatePrivilegeChangeOperation( + shouldUseNewPrivilegeSystem, + ProjectPermissionMemberActions.GrantPrivileges, + ProjectPermissionSub.Member, + permission, + permissionRole.permission + ); + if (!permissionBoundary.isValid) + throw new PermissionBoundaryError({ + message: constructPermissionErrorMessage( + "Failed to create user project membership", + shouldUseNewPrivilegeSystem, + ProjectPermissionMemberActions.GrantPrivileges, + ProjectPermissionSub.Member + ), + details: { missingPermissions: permissionBoundary.missingPermissions } + }); + } }; const onCreateMembershipComplete: TMembershipUserScopeFactory["onCreateMembershipComplete"] = async () => { @@ -63,6 +95,32 @@ export const newProjectMembershipUserFactory = ({ actorOrgId: dto.permission.orgId }); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member); + + const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(dto.permission.orgId); + const permissionRoles = await permissionService.getProjectPermissionByRoles( + dto.data.roles.filter((el) => el.role !== ProjectMembershipRole.NoAccess).map((el) => el.role), + scope.value + ); + + for (const permissionRole of permissionRoles) { + const permissionBoundary = validatePrivilegeChangeOperation( + shouldUseNewPrivilegeSystem, + ProjectPermissionMemberActions.GrantPrivileges, + ProjectPermissionSub.Member, + permission, + permissionRole.permission + ); + if (!permissionBoundary.isValid) + throw new PermissionBoundaryError({ + message: constructPermissionErrorMessage( + "Failed to update user project membership", + shouldUseNewPrivilegeSystem, + ProjectPermissionMemberActions.GrantPrivileges, + ProjectPermissionSub.Member + ), + details: { missingPermissions: permissionBoundary.missingPermissions } + }); + } }; const onDeleteMembershipUserGuard: TMembershipUserScopeFactory["onDeleteMembershipUserGuard"] = async (dto) => { diff --git a/backend/src/services/project-role/project-role-service.ts b/backend/src/services/project-role/project-role-service.ts index f30da21f5..b4bfaac39 100644 --- a/backend/src/services/project-role/project-role-service.ts +++ b/backend/src/services/project-role/project-role-service.ts @@ -244,7 +244,7 @@ export const projectRoleServiceFactory = ({ actorAuthMethod: ActorAuthMethod, actorOrgId: string | undefined ) => { - const { permission, membership } = await permissionService.getProjectPermission({ + const { permission, memberships } = await permissionService.getProjectPermission({ actor: ActorType.USER, actorId: userId, projectId, @@ -253,7 +253,6 @@ export const projectRoleServiceFactory = ({ actionProjectType: ActionProjectType.Any }); // just to satisfy ts - if (!("roles" in membership)) throw new BadRequestError({ message: "Service token not allowed" }); const assumedPrivilegeDetailsCtx = requestContext.get("assumedPrivilegeDetails"); const isAssumingPrivilege = assumedPrivilegeDetailsCtx?.projectId === projectId; @@ -279,7 +278,7 @@ export const projectRoleServiceFactory = ({ assumedPrivilegeDetails.actorEmail = userDetails?.email || ""; } - return { permissions: packRules(permission.rules), membership, assumedPrivilegeDetails }; + return { permissions: packRules(permission.rules), memberships, assumedPrivilegeDetails }; }; return { createRole, updateRole, deleteRole, listRoles, getUserPermission, getRoleBySlug }; diff --git a/backend/src/services/project/project-service.ts b/backend/src/services/project/project-service.ts index 8dbba2b4f..d2d92d86a 100644 --- a/backend/src/services/project/project-service.ts +++ b/backend/src/services/project/project-service.ts @@ -511,7 +511,8 @@ export const projectServiceFactory = ({ : await projectDAL.findUserProjects(actorId, actorOrgId, type); if (includeRoles) { - const { permission } = await permissionService.getUserOrgPermission( + const { permission } = await permissionService.getOrgPermission( + actor, actorId, actorOrgId, actorAuthMethod, @@ -1346,7 +1347,7 @@ export const projectServiceFactory = ({ }; const getProjectKmsKeys = async ({ projectId, actor, actorId, actorAuthMethod, actorOrgId }: TGetProjectKmsKey) => { - const { membership } = await permissionService.getProjectPermission({ + await permissionService.getProjectPermission({ actor, actorId, projectId, @@ -1355,10 +1356,6 @@ export const projectServiceFactory = ({ actionProjectType: ActionProjectType.Any }); - if (!membership) { - throw new ForbiddenRequestError({ message: "You are not a member of this project" }); - } - const kmsKeyId = await kmsService.getProjectSecretManagerKmsKeyId(projectId); const kmsKey = await kmsService.getKmsById(kmsKeyId); diff --git a/backend/src/services/secret-import/secret-import-service.ts b/backend/src/services/secret-import/secret-import-service.ts index 30cd93291..36f3459cf 100644 --- a/backend/src/services/secret-import/secret-import-service.ts +++ b/backend/src/services/secret-import/secret-import-service.ts @@ -385,7 +385,7 @@ export const secretImportServiceFactory = ({ path: secretPath, id: secretImportDocId }: TResyncSecretImportReplicationDTO) => { - const { permission, membership } = await permissionService.getProjectPermission({ + const { permission, memberships } = await permissionService.getProjectPermission({ actor, actorId, projectId, @@ -437,7 +437,7 @@ export const secretImportServiceFactory = ({ secretImportDoc.importPath ); - if (membership && sourceFolder) { + if (memberships?.length && sourceFolder) { await secretQueueService.replicateSecrets({ orgId: actorOrgId, secretPath: secretImportDoc.importPath,