diff --git a/backend/src/services/identity-project/identity-project-service.ts b/backend/src/services/identity-project/identity-project-service.ts index b6f6e4343..d554c81ac 100644 --- a/backend/src/services/identity-project/identity-project-service.ts +++ b/backend/src/services/identity-project/identity-project-service.ts @@ -49,10 +49,17 @@ export const identityProjectServiceFactory = ({ actor, actorId, actorOrgId, + actorAuthMethod, projectId, role }: TCreateProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Identity); const existingIdentity = await identityProjectDAL.findOne({ identityId, projectId }); @@ -112,9 +119,16 @@ export const identityProjectServiceFactory = ({ roles, actor, actorId, + actorAuthMethod, actorOrgId }: TUpdateProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity); const projectIdentity = await identityProjectDAL.findOne({ identityId, projectId }); @@ -127,6 +141,7 @@ export const identityProjectServiceFactory = ({ ActorType.IDENTITY, projectIdentity.identityId, projectIdentity.projectId, + actorAuthMethod, actorOrgId ); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); @@ -185,6 +200,7 @@ export const identityProjectServiceFactory = ({ actorId, actor, actorOrgId, + actorAuthMethod, projectId }: TDeleteProjectIdentityDTO) => { const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId }); @@ -195,6 +211,7 @@ export const identityProjectServiceFactory = ({ actor, actorId, identityProjectMembership.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity); @@ -202,6 +219,7 @@ export const identityProjectServiceFactory = ({ ActorType.IDENTITY, identityId, identityProjectMembership.projectId, + actorAuthMethod, actorOrgId ); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); @@ -212,8 +230,20 @@ export const identityProjectServiceFactory = ({ return deletedIdentity; }; - const listProjectIdentities = async ({ projectId, actor, actorId, actorOrgId }: TListProjectIdentityDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); + const listProjectIdentities = async ({ + projectId, + actor, + actorId, + actorAuthMethod, + actorOrgId + }: TListProjectIdentityDTO) => { + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity); const identityMemberhips = await identityProjectDAL.findByProjectId(projectId); diff --git a/backend/src/services/identity-ua/identity-ua-service.ts b/backend/src/services/identity-ua/identity-ua-service.ts index d375a8fa5..54a074073 100644 --- a/backend/src/services/identity-ua/identity-ua-service.ts +++ b/backend/src/services/identity-ua/identity-ua-service.ts @@ -144,6 +144,7 @@ export const identityUaServiceFactory = ({ accessTokenTrustedIps, clientSecretTrustedIps, actorId, + actorAuthMethod, actor, actorOrgId }: TAttachUaDTO) => { @@ -162,6 +163,7 @@ export const identityUaServiceFactory = ({ actor, actorId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); @@ -233,6 +235,7 @@ export const identityUaServiceFactory = ({ accessTokenTrustedIps, clientSecretTrustedIps, actorId, + actorAuthMethod, actor, actorOrgId }: TUpdateUaDTO) => { @@ -256,6 +259,7 @@ export const identityUaServiceFactory = ({ actor, actorId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); @@ -308,7 +312,7 @@ export const identityUaServiceFactory = ({ return { ...updatedUaAuth, orgId: identityMembershipOrg.orgId }; }; - const getIdentityUa = async ({ identityId, actorId, actor, actorOrgId }: TGetUaDTO) => { + const getIdentityUa = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetUaDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) @@ -322,6 +326,7 @@ export const identityUaServiceFactory = ({ actor, actorId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); @@ -334,6 +339,7 @@ export const identityUaServiceFactory = ({ actorOrgId, identityId, ttl, + actorAuthMethod, description, numUsesLimit }: TCreateUaClientSecretDTO) => { @@ -347,6 +353,7 @@ export const identityUaServiceFactory = ({ actor, actorId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); @@ -355,6 +362,7 @@ export const identityUaServiceFactory = ({ ActorType.IDENTITY, identityMembershipOrg.identityId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); @@ -388,7 +396,13 @@ export const identityUaServiceFactory = ({ }; }; - const getUaClientSecrets = async ({ actor, actorId, actorOrgId, identityId }: TGetUaClientSecretsDTO) => { + const getUaClientSecrets = async ({ + actor, + actorId, + actorOrgId, + actorAuthMethod, + identityId + }: TGetUaClientSecretsDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral) @@ -399,6 +413,7 @@ export const identityUaServiceFactory = ({ actor, actorId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); @@ -407,6 +422,7 @@ export const identityUaServiceFactory = ({ ActorType.IDENTITY, identityMembershipOrg.identityId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); @@ -431,6 +447,7 @@ export const identityUaServiceFactory = ({ actorId, actor, actorOrgId, + actorAuthMethod, clientSecretId }: TRevokeUaClientSecretDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); @@ -443,6 +460,7 @@ export const identityUaServiceFactory = ({ actor, actorId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity); @@ -451,6 +469,7 @@ export const identityUaServiceFactory = ({ ActorType.IDENTITY, identityMembershipOrg.identityId, identityMembershipOrg.orgId, + actorAuthMethod, actorOrgId ); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); diff --git a/backend/src/services/identity/identity-service.ts b/backend/src/services/identity/identity-service.ts index e37a3a6dd..be79a0ba2 100644 --- a/backend/src/services/identity/identity-service.ts +++ b/backend/src/services/identity/identity-service.ts @@ -25,8 +25,16 @@ export const identityServiceFactory = ({ identityOrgMembershipDAL, permissionService }: TIdentityServiceFactoryDep) => { - const createIdentity = async ({ name, role, actor, orgId, actorId, actorOrgId }: TCreateIdentityDTO) => { - const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); + const createIdentity = async ({ + name, + role, + actor, + orgId, + actorId, + actorAuthMethod, + actorOrgId + }: TCreateIdentityDTO) => { + const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity); const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole( @@ -54,7 +62,15 @@ export const identityServiceFactory = ({ return identity; }; - const updateIdentity = async ({ id, role, name, actor, actorId, actorOrgId }: TUpdateIdentityDTO) => { + const updateIdentity = async ({ + id, + role, + name, + actor, + actorId, + actorAuthMethod, + actorOrgId + }: TUpdateIdentityDTO) => { const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id }); if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${id}` }); @@ -62,6 +78,7 @@ export const identityServiceFactory = ({ actor, actorId, identityOrgMembership.orgId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); @@ -70,6 +87,7 @@ export const identityServiceFactory = ({ ActorType.IDENTITY, id, identityOrgMembership.orgId, + actorAuthMethod, actorOrgId ); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); @@ -108,7 +126,7 @@ export const identityServiceFactory = ({ return { ...identity, orgId: identityOrgMembership.orgId }; }; - const deleteIdentity = async ({ actorId, actor, actorOrgId, id }: TDeleteIdentityDTO) => { + const deleteIdentity = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteIdentityDTO) => { const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id }); if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${id}` }); @@ -116,13 +134,15 @@ export const identityServiceFactory = ({ actor, actorId, identityOrgMembership.orgId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity); const { permission: identityRolePermission } = await permissionService.getOrgPermission( ActorType.IDENTITY, id, - identityOrgMembership.orgId + identityOrgMembership.orgId, + actorAuthMethod ); const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission); if (!hasRequiredPriviledges) @@ -132,8 +152,8 @@ export const identityServiceFactory = ({ return { ...deletedIdentity, orgId: identityOrgMembership.orgId }; }; - const listOrgIdentities = async ({ orgId, actor, actorId, actorOrgId }: TOrgPermission) => { - const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); + const listOrgIdentities = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TOrgPermission) => { + const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); const identityMemberhips = await identityOrgMembershipDAL.findByOrgId(orgId); diff --git a/backend/src/services/integration-auth/integration-auth-service.ts b/backend/src/services/integration-auth/integration-auth-service.ts index 35ff27a9a..c8551df7d 100644 --- a/backend/src/services/integration-auth/integration-auth-service.ts +++ b/backend/src/services/integration-auth/integration-auth-service.ts @@ -64,14 +64,26 @@ export const integrationAuthServiceFactory = ({ projectBotDAL, projectBotService }: TIntegrationAuthServiceFactoryDep) => { - const listIntegrationAuthByProjectId = async ({ actorId, actor, actorOrgId, projectId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); + const listIntegrationAuthByProjectId = async ({ + actorId, + actor, + actorOrgId, + actorAuthMethod, + projectId + }: TProjectPermission) => { + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const authorizations = await integrationAuthDAL.find({ projectId }); return authorizations; }; - const getIntegrationAuth = async ({ actor, id, actorId, actorOrgId }: TGetIntegrationAuthDTO) => { + const getIntegrationAuth = async ({ actor, id, actorId, actorAuthMethod, actorOrgId }: TGetIntegrationAuthDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -79,6 +91,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -90,6 +103,7 @@ export const integrationAuthServiceFactory = ({ actorId, actor, actorOrgId, + actorAuthMethod, integration, url, code @@ -97,7 +111,13 @@ export const integrationAuthServiceFactory = ({ if (!Object.values(Integrations).includes(integration as Integrations)) throw new BadRequestError({ message: "Invalid integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); const bot = await projectBotDAL.findOne({ isActive: true, projectId }); @@ -153,6 +173,7 @@ export const integrationAuthServiceFactory = ({ url, actor, actorOrgId, + actorAuthMethod, accessId, namespace, accessToken @@ -160,7 +181,13 @@ export const integrationAuthServiceFactory = ({ if (!Object.values(Integrations).includes(integration as Integrations)) throw new BadRequestError({ message: "Invalid integration" }); - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); const bot = await projectBotDAL.findOne({ isActive: true, projectId }); @@ -277,6 +304,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, actorOrgId, + actorAuthMethod, teamId, id, workspaceSlug @@ -288,6 +316,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -305,7 +334,13 @@ export const integrationAuthServiceFactory = ({ return apps; }; - const getIntegrationAuthTeams = async ({ actor, actorId, actorOrgId, id }: TIntegrationAuthTeamsDTO) => { + const getIntegrationAuthTeams = async ({ + actor, + actorId, + actorAuthMethod, + actorOrgId, + id + }: TIntegrationAuthTeamsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -313,6 +348,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -327,7 +363,14 @@ export const integrationAuthServiceFactory = ({ return teams; }; - const getVercelBranches = async ({ appId, id, actor, actorId, actorOrgId }: TIntegrationAuthVercelBranchesDTO) => { + const getVercelBranches = async ({ + appId, + id, + actor, + actorId, + actorAuthMethod, + actorOrgId + }: TIntegrationAuthVercelBranchesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -335,6 +378,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -360,7 +404,14 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getChecklyGroups = async ({ actorId, actor, actorOrgId, id, accountId }: TIntegrationAuthChecklyGroupsDTO) => { + const getChecklyGroups = async ({ + actorId, + actor, + actorOrgId, + actorAuthMethod, + id, + accountId + }: TIntegrationAuthChecklyGroupsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -368,6 +419,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -386,7 +438,7 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getGithubOrgs = async ({ actorId, actor, actorOrgId, id }: TIntegrationAuthGithubOrgsDTO) => { + const getGithubOrgs = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TIntegrationAuthGithubOrgsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -394,6 +446,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -418,6 +471,7 @@ export const integrationAuthServiceFactory = ({ actorId, actor, actorOrgId, + actorAuthMethod, id, repoOwner, repoName @@ -429,6 +483,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -452,7 +507,7 @@ export const integrationAuthServiceFactory = ({ return environments.map(({ id: envId, name }) => ({ name, envId: String(envId) })); }; - const getQoveryOrgs = async ({ actorId, actor, actorOrgId, id }: TIntegrationAuthQoveryOrgsDTO) => { + const getQoveryOrgs = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TIntegrationAuthQoveryOrgsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -460,6 +515,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -478,7 +534,14 @@ export const integrationAuthServiceFactory = ({ return data.results.map(({ name, id: orgId }) => ({ name, orgId })); }; - const getQoveryProjects = async ({ actorId, actor, actorOrgId, id, orgId }: TIntegrationAuthQoveryProjectDTO) => { + const getQoveryProjects = async ({ + actorId, + actor, + actorOrgId, + actorAuthMethod, + id, + orgId + }: TIntegrationAuthQoveryProjectDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -486,6 +549,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -511,6 +575,7 @@ export const integrationAuthServiceFactory = ({ id, actor, actorId, + actorAuthMethod, actorOrgId }: TIntegrationAuthQoveryEnvironmentsDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); @@ -520,6 +585,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -545,7 +611,14 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getQoveryApps = async ({ id, actor, actorId, actorOrgId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { + const getQoveryApps = async ({ + id, + actor, + actorId, + actorOrgId, + actorAuthMethod, + environmentId + }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -553,6 +626,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -582,6 +656,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, actorOrgId, + actorAuthMethod, environmentId }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); @@ -591,6 +666,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -615,7 +691,14 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getQoveryJobs = async ({ id, actor, actorId, actorOrgId, environmentId }: TIntegrationAuthQoveryScopesDTO) => { + const getQoveryJobs = async ({ + id, + actor, + actorId, + actorOrgId, + actorAuthMethod, + environmentId + }: TIntegrationAuthQoveryScopesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -623,6 +706,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -647,7 +731,13 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getHerokuPipelines = async ({ id, actor, actorId, actorOrgId }: TIntegrationAuthHerokuPipelinesDTO) => { + const getHerokuPipelines = async ({ + id, + actor, + actorId, + actorAuthMethod, + actorOrgId + }: TIntegrationAuthHerokuPipelinesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -655,6 +745,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -679,7 +770,14 @@ export const integrationAuthServiceFactory = ({ })); }; - const getRailwayEnvironments = async ({ id, actor, actorId, actorOrgId, appId }: TIntegrationAuthRailwayEnvDTO) => { + const getRailwayEnvironments = async ({ + id, + actor, + actorId, + actorOrgId, + actorAuthMethod, + appId + }: TIntegrationAuthRailwayEnvDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -687,6 +785,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -739,7 +838,14 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getRailwayServices = async ({ id, actor, actorId, actorOrgId, appId }: TIntegrationAuthRailwayServicesDTO) => { + const getRailwayServices = async ({ + id, + actor, + actorId, + actorOrgId, + actorAuthMethod, + appId + }: TIntegrationAuthRailwayServicesDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -747,6 +853,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -806,7 +913,13 @@ export const integrationAuthServiceFactory = ({ return []; }; - const getBitbucketWorkspaces = async ({ actorId, actor, actorOrgId, id }: TIntegrationAuthBitbucketWorkspaceDTO) => { + const getBitbucketWorkspaces = async ({ + actorId, + actor, + actorOrgId, + actorAuthMethod, + id + }: TIntegrationAuthBitbucketWorkspaceDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -814,6 +927,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -852,6 +966,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, actorOrgId, + actorAuthMethod, appId }: TIntegrationAuthNorthflankSecretGroupDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); @@ -861,6 +976,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -918,6 +1034,7 @@ export const integrationAuthServiceFactory = ({ id, actorId, actorOrgId, + actorAuthMethod, actor }: TGetIntegrationAuthTeamCityBuildConfigDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); @@ -927,6 +1044,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); @@ -958,16 +1076,29 @@ export const integrationAuthServiceFactory = ({ integration, actor, actorId, + actorAuthMethod, actorOrgId }: TDeleteIntegrationAuthsDTO) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); const integrations = await integrationAuthDAL.delete({ integration, projectId }); return integrations; }; - const deleteIntegrationAuthById = async ({ id, actorId, actor, actorOrgId }: TDeleteIntegrationAuthByIdDTO) => { + const deleteIntegrationAuthById = async ({ + id, + actorId, + actor, + actorAuthMethod, + actorOrgId + }: TDeleteIntegrationAuthByIdDTO) => { const integrationAuth = await integrationAuthDAL.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -975,6 +1106,7 @@ export const integrationAuthServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); diff --git a/backend/src/services/integration/integration-service.ts b/backend/src/services/integration/integration-service.ts index 4a6bed75f..5bf412c9b 100644 --- a/backend/src/services/integration/integration-service.ts +++ b/backend/src/services/integration/integration-service.ts @@ -42,6 +42,7 @@ export const integrationServiceFactory = ({ metadata, secretPath, targetService, + actorAuthMethod, targetServiceId, integrationAuthId, sourceEnvironment, @@ -55,6 +56,7 @@ export const integrationServiceFactory = ({ actor, actorId, integrationAuth.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); @@ -93,6 +95,7 @@ export const integrationServiceFactory = ({ actorId, actor, actorOrgId, + actorAuthMethod, targetEnvironment, app, id, @@ -109,6 +112,7 @@ export const integrationServiceFactory = ({ actor, actorId, integration.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); @@ -129,7 +133,7 @@ export const integrationServiceFactory = ({ return updatedIntegration; }; - const deleteIntegration = async ({ actorId, id, actor, actorOrgId }: TDeleteIntegrationDTO) => { + const deleteIntegration = async ({ actorId, id, actor, actorAuthMethod, actorOrgId }: TDeleteIntegrationDTO) => { const integration = await integrationDAL.findById(id); if (!integration) throw new BadRequestError({ message: "Integration auth not found" }); @@ -137,6 +141,7 @@ export const integrationServiceFactory = ({ actor, actorId, integration.projectId, + actorAuthMethod, actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); @@ -145,8 +150,20 @@ export const integrationServiceFactory = ({ return { ...integration, ...deletedIntegration }; }; - const listIntegrationByProject = async ({ actor, actorId, actorOrgId, projectId }: TProjectPermission) => { - const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); + const listIntegrationByProject = async ({ + actor, + actorId, + actorOrgId, + actorAuthMethod, + projectId + }: TProjectPermission) => { + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + projectId, + actorAuthMethod, + actorOrgId + ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); const integrations = await integrationDAL.findByProjectId(projectId); diff --git a/backend/src/services/org/org-role-service.ts b/backend/src/services/org/org-role-service.ts index fb8a57440..74c4887fb 100644 --- a/backend/src/services/org/org-role-service.ts +++ b/backend/src/services/org/org-role-service.ts @@ -12,6 +12,7 @@ import { import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { BadRequestError } from "@app/lib/errors"; +import { ActorAuthMethod } from "../auth/auth-type"; import { TOrgRoleDALFactory } from "./org-role-dal"; type TOrgRoleServiceFactoryDep = { @@ -26,9 +27,10 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol userId: string, orgId: string, data: Omit, + actorAuthMethod: ActorAuthMethod, actorOrgId?: string ) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Role); const existingRole = await orgRoleDAL.findOne({ slug: data.slug, orgId }); if (existingRole) throw new BadRequestError({ name: "Create Role", message: "Duplicate role" }); @@ -45,9 +47,10 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol orgId: string, roleId: string, data: Omit, + actorAuthMethod: ActorAuthMethod, actorOrgId?: string ) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Role); if (data?.slug) { const existingRole = await orgRoleDAL.findOne({ slug: data.slug, orgId }); @@ -62,8 +65,14 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol return updatedRole; }; - const deleteRole = async (userId: string, orgId: string, roleId: string, actorOrgId?: string) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const deleteRole = async ( + userId: string, + orgId: string, + roleId: string, + actorAuthMethod: ActorAuthMethod, + actorOrgId?: string + ) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role); const [deletedRole] = await orgRoleDAL.delete({ id: roleId, orgId }); if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" }); @@ -71,8 +80,8 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol return deletedRole; }; - const listRoles = async (userId: string, orgId: string, actorOrgId?: string) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const listRoles = async (userId: string, orgId: string, actorAuthMethod: ActorAuthMethod, actorOrgId?: string) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Role); const customRoles = await orgRoleDAL.find({ orgId }); const roles = [ @@ -115,8 +124,18 @@ export const orgRoleServiceFactory = ({ orgRoleDAL, permissionService }: TOrgRol return roles; }; - const getUserPermission = async (userId: string, orgId: string, actorOrgId?: string) => { - const { permission, membership } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const getUserPermission = async ( + userId: string, + orgId: string, + actorAuthMethod: ActorAuthMethod, + actorOrgId?: string + ) => { + const { permission, membership } = await permissionService.getUserOrgPermission( + userId, + orgId, + actorAuthMethod, + actorOrgId + ); return { permissions: packRules(permission.rules), membership }; }; diff --git a/backend/src/services/org/org-service.ts b/backend/src/services/org/org-service.ts index db6d9654d..a545739be 100644 --- a/backend/src/services/org/org-service.ts +++ b/backend/src/services/org/org-service.ts @@ -18,7 +18,7 @@ import { BadRequestError, UnauthorizedError } from "@app/lib/errors"; import { alphaNumericNanoId } from "@app/lib/nanoid"; import { isDisposableEmail } from "@app/lib/validator"; -import { ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type"; +import { ActorAuthMethod, ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type"; import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; import { TokenType } from "../auth-token/auth-token-types"; import { TProjectDALFactory } from "../project/project-dal"; @@ -79,8 +79,13 @@ export const orgServiceFactory = ({ /* * Get organization details by the organization id * */ - const findOrganizationById = async (userId: string, orgId: string, actorOrgId?: string) => { - await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const findOrganizationById = async ( + userId: string, + orgId: string, + actorAuthMethod: ActorAuthMethod, + actorOrgId?: string + ) => { + await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); const org = await orgDAL.findOrgById(orgId); if (!org) throw new BadRequestError({ name: "Org not found", message: "Organization not found" }); return org; @@ -95,16 +100,28 @@ export const orgServiceFactory = ({ /* * Get all workspace members * */ - const findAllOrgMembers = async (userId: string, orgId: string, actorOrgId?: string) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const findAllOrgMembers = async ( + userId: string, + orgId: string, + actorAuthMethod: ActorAuthMethod, + actorOrgId?: string + ) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member); const members = await orgDAL.findAllOrgMembers(orgId); return members; }; - const findOrgMembersByUsername = async ({ actor, actorId, orgId, emails }: TFindOrgMembersByEmailDTO) => { - const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); + const findOrgMembersByUsername = async ({ + actor, + actorId, + actorOrgId, + actorAuthMethod, + orgId, + emails + }: TFindOrgMembersByEmailDTO) => { + const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Member); const members = await orgDAL.findOrgMembersByUsername(orgId, emails); @@ -112,8 +129,8 @@ export const orgServiceFactory = ({ return members; }; - const findAllWorkspaces = async ({ actor, actorId, actorOrgId, orgId }: TFindAllWorkspacesDTO) => { - const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); + const findAllWorkspaces = async ({ actor, actorId, actorOrgId, actorAuthMethod, orgId }: TFindAllWorkspacesDTO) => { + const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Workspace); const organizationWorkspaceIds = new Set((await projectDAL.find({ orgId })).map((workspace) => workspace.id)); @@ -193,10 +210,11 @@ export const orgServiceFactory = ({ actor, actorId, actorOrgId, + actorAuthMethod, orgId, data: { name, slug, authEnforced, scimEnabled } }: TUpdateOrgDTO) => { - const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId); + const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); const plan = await licenseService.getPlan(orgId); @@ -309,8 +327,13 @@ export const orgServiceFactory = ({ /* * Delete organization by id * */ - const deleteOrganizationById = async (userId: string, orgId: string, actorOrgId?: string) => { - const { membership } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const deleteOrganizationById = async ( + userId: string, + orgId: string, + actorAuthMethod: ActorAuthMethod, + actorOrgId?: string + ) => { + const { membership } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); if ((membership.role as OrgMembershipRole) !== OrgMembershipRole.Admin) throw new UnauthorizedError({ name: "Delete org by id", message: "Not an admin" }); @@ -324,8 +347,15 @@ export const orgServiceFactory = ({ * Org membership management * Not another service because it has close ties with how an org works doesn't make sense to seperate them * */ - const updateOrgMembership = async ({ role, orgId, userId, membershipId, actorOrgId }: TUpdateOrgMembershipDTO) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const updateOrgMembership = async ({ + role, + orgId, + userId, + membershipId, + actorAuthMethod, + actorOrgId + }: TUpdateOrgMembershipDTO) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Member); const isCustomRole = !Object.values(OrgMembershipRole).includes(role as OrgMembershipRole); @@ -355,8 +385,14 @@ export const orgServiceFactory = ({ /* * Invite user to organization */ - const inviteUserToOrganization = async ({ orgId, userId, inviteeEmail, actorOrgId }: TInviteUserToOrgDTO) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const inviteUserToOrganization = async ({ + orgId, + userId, + inviteeEmail, + actorAuthMethod, + actorOrgId + }: TInviteUserToOrgDTO) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Member); const org = await orgDAL.findOrgById(orgId); @@ -515,8 +551,14 @@ export const orgServiceFactory = ({ return { token, user }; }; - const deleteOrgMembership = async ({ orgId, userId, membershipId, actorOrgId }: TDeleteOrgMembershipDTO) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const deleteOrgMembership = async ({ + orgId, + userId, + membershipId, + actorAuthMethod, + actorOrgId + }: TDeleteOrgMembershipDTO) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member); const deletedMembership = await orgDAL.transaction(async (tx) => { @@ -568,15 +610,26 @@ export const orgServiceFactory = ({ /* * CRUD operations of incident contacts * */ - const findIncidentContacts = async (userId: string, orgId: string, actorOrgId?: string) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const findIncidentContacts = async ( + userId: string, + orgId: string, + actorAuthMethod: ActorAuthMethod, + actorOrgId?: string + ) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount); const incidentContacts = await incidentContactDAL.findByOrgId(orgId); return incidentContacts; }; - const createIncidentContact = async (userId: string, orgId: string, email: string, actorOrgId?: string) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const createIncidentContact = async ( + userId: string, + orgId: string, + email: string, + actorAuthMethod: ActorAuthMethod, + actorOrgId?: string + ) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.IncidentAccount); const doesIncidentContactExist = await incidentContactDAL.findOne(orgId, { email }); if (doesIncidentContactExist) { @@ -590,8 +643,14 @@ export const orgServiceFactory = ({ return incidentContact; }; - const deleteIncidentContact = async (userId: string, orgId: string, id: string, actorOrgId?: string) => { - const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorOrgId); + const deleteIncidentContact = async ( + userId: string, + orgId: string, + id: string, + actorAuthMethod: ActorAuthMethod, + actorOrgId?: string + ) => { + const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.IncidentAccount); const incidentContact = await incidentContactDAL.deleteById(id, orgId); diff --git a/backend/src/services/org/org-types.ts b/backend/src/services/org/org-types.ts index bd8fe2e95..a0c0b25c9 100644 --- a/backend/src/services/org/org-types.ts +++ b/backend/src/services/org/org-types.ts @@ -1,6 +1,6 @@ import { TOrgPermission } from "@app/lib/types"; -import { ActorType } from "../auth/auth-type"; +import { ActorAuthMethod, ActorType } from "../auth/auth-type"; export type TUpdateOrgMembershipDTO = { userId: string; @@ -32,6 +32,8 @@ export type TVerifyUserToOrgDTO = { export type TFindOrgMembersByEmailDTO = { actor: ActorType; + actorAuthMethod: ActorAuthMethod; + actorOrgId: string | undefined; actorId: string; orgId: string; emails: string[];