feat: fixing all ts error from membership and api changes

This commit is contained in:
=
2025-09-29 23:01:32 +05:30
parent 1571633d30
commit 81b7ea1a5a
29 changed files with 303 additions and 201 deletions

View File

@@ -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` });

View File

@@ -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 });

View File

@@ -66,7 +66,7 @@ type TOidcConfigServiceFactoryDep = {
licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">;
tokenService: Pick<TAuthTokenServiceFactory, "createTokenForUser">;
smtpService: Pick<TSmtpService, "sendMail" | "verify">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission" | "getUserOrgPermission">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
oidcConfigDAL: Pick<TOidcConfigDALFactory, "findOne" | "update" | "create">;
groupDAL: Pick<TGroupDALFactory, "findByOrgId">;
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,

View File

@@ -67,6 +67,7 @@ export type TPermissionServiceFactory = {
) => Promise<{
permission: MongoAbility<OrgPermissionSet, MongoQuery>;
memberships: TMemberships[];
hasRole: (role: string) => boolean;
}>;
getProjectPermission: (arg: TGetProjectPermissionArg) => Promise<{
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;

View File

@@ -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)))
};
};

View File

@@ -44,10 +44,7 @@ type TSshHostGroupServiceFactoryDep = {
sshHostLoginUserDAL: Pick<TSshHostLoginUserDALFactory, "create" | "transaction" | "delete">;
sshHostLoginUserMappingDAL: Pick<TSshHostLoginUserMappingDALFactory, "insertMany">;
userDAL: Pick<TUserDALFactory, "find">;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getUserProjectPermission" | "checkGroupProjectPermission"
>;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "checkGroupProjectPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
groupDAL: Pick<TGroupDALFactory, "findGroupsByProjectId">;
};

View File

@@ -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
});
}

View File

@@ -64,10 +64,7 @@ type TSshHostServiceFactoryDep = {
>;
sshHostLoginUserDAL: TSshHostLoginUserDALFactory;
sshHostLoginUserMappingDAL: TSshHostLoginUserMappingDALFactory;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getUserProjectPermission" | "checkGroupProjectPermission"
>;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "checkGroupProjectPermission">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
};

View File

@@ -66,7 +66,7 @@ type BaseCreateSshLoginMappingsDTO = {
sshHostLoginUserDAL: Pick<TSshHostLoginUserDALFactory, "create" | "transaction">;
sshHostLoginUserMappingDAL: Pick<TSshHostLoginUserMappingDALFactory, "insertMany">;
userDAL: Pick<TUserDALFactory, "find">;
permissionService: Pick<TPermissionServiceFactory, "getUserProjectPermission" | "checkGroupProjectPermission">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "checkGroupProjectPermission">;
groupDAL: Pick<TGroupDALFactory, "findGroupsByProjectId">;
projectId: string;
actorAuthMethod: ActorAuthMethod;

View File

@@ -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" });
}

View File

@@ -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<TIdentityOrgDALFactory, "findOne" | "updateById">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityAliCloudAuthServiceFactory = ReturnType<typeof identityAliCloudAuthServiceFactory>;
@@ -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
),

View File

@@ -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<TIdentityOrgDALFactory, "findOne" | "updateById">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityAwsAuthServiceFactory = ReturnType<typeof identityAwsAuthServiceFactory>;
@@ -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
),

View File

@@ -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<TIdentityAccessTokenDALFactory, "create" | "delete">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityAzureAuthServiceFactory = ReturnType<typeof identityAzureAuthServiceFactory>;
@@ -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
),

View File

@@ -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<TIdentityAccessTokenDALFactory, "create" | "delete">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityGcpAuthServiceFactory = ReturnType<typeof identityGcpAuthServiceFactory>;
@@ -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
),

View File

@@ -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<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityJwtAuthServiceFactory = ReturnType<typeof identityJwtAuthServiceFactory>;
@@ -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
),

View File

@@ -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<TGatewayDALFactory, "find">;
gatewayV2DAL: Pick<TGatewayV2DALFactory, "find">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityKubernetesAuthServiceFactory = ReturnType<typeof identityKubernetesAuthServiceFactory>;
@@ -76,7 +78,8 @@ export const identityKubernetesAuthServiceFactory = ({
gatewayV2Service,
gatewayDAL,
gatewayV2DAL,
kmsService
kmsService,
orgDAL
}: TIdentityKubernetesAuthServiceFactoryDep) => {
const $gatewayProxyWrapper = async <T>(
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
),

View File

@@ -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<TOrgDALFactory, "findById">;
};
export type TIdentityLdapAuthServiceFactory = ReturnType<typeof identityLdapAuthServiceFactory>;
@@ -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
),

View File

@@ -32,6 +32,7 @@ import {
TRevokeOciAuthDTO,
TUpdateOciAuthDTO
} from "./identity-oci-auth-types";
import { TOrgDALFactory } from "../org/org-dal";
type TIdentityOciAuthServiceFactoryDep = {
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
@@ -39,6 +40,7 @@ type TIdentityOciAuthServiceFactoryDep = {
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityOciAuthServiceFactory = ReturnType<typeof identityOciAuthServiceFactory>;
@@ -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
),

View File

@@ -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<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityOidcAuthServiceFactory = ReturnType<typeof identityOidcAuthServiceFactory>;
@@ -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
),

View File

@@ -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<TOrgDALFactory, "findById">;
identityProjectMembershipRoleDAL: Pick<
TIdentityProjectMembershipRoleDALFactory,
"create" | "transaction" | "insertMany" | "delete"
@@ -37,7 +39,7 @@ type TIdentityProjectServiceFactoryDep = {
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
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

View File

@@ -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<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
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
),

View File

@@ -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<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityTokenAuthServiceFactory = ReturnType<typeof identityTokenAuthServiceFactory>;
@@ -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
),

View File

@@ -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<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
orgDAL: Pick<TOrgDALFactory, "findById">;
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
),

View File

@@ -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<TIdentityProjectDALFactory, "findByIdentityId">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission" | "getOrgPermissionByRole">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission" | "getOrgPermissionByRoles">;
licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">;
keyStore: Pick<TKeyStoreFactory, "getKeysByPattern" | "getItem">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
export type TIdentityServiceFactory = ReturnType<typeof identityServiceFactory>;
@@ -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) => {

View File

@@ -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<TMembershipRoleDALFactory, "insertMany" | "delete">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
orgDAL: Pick<TOrgDALFactory, "findById">;
roleDAL: Pick<TRoleDALFactory, "find">;
userDAL: Pick<
TUserDALFactory,
@@ -34,6 +39,10 @@ type TMembershipUserServiceFactoryDep = {
| "findUserByEmail"
| "findUserEncKeyByUserId"
>;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getProjectPermissionByRoles" | "getOrgPermission"
>;
};
export type TMembershipUserServiceFactory = ReturnType<typeof membershipUserServiceFactory>;
@@ -43,9 +52,20 @@ export const membershipUserServiceFactory = ({
roleDAL,
licenseService,
membershipRoleDAL,
userDAL
userDAL,
permissionService,
orgDAL
}: TMembershipUserServiceFactoryDep) => {
const scopeFactory: Record<string, TMembershipUserScopeFactory> = {};
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 } });

View File

@@ -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<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissionByRole">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissionByRoles">;
orgDAL: Pick<TOrgDALFactory, "findById">;
};
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) => {

View File

@@ -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 };

View File

@@ -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);

View File

@@ -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,