feat: fixing all ts error from membership and api changes

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