feat: fixing more and more ts

This commit is contained in:
=
2025-10-10 00:09:46 +05:30
parent 5a8bad3556
commit fd98465dec
47 changed files with 1369 additions and 1161 deletions
+2 -9
View File
@@ -20,8 +20,6 @@ import { TGatewayV2ServiceFactory } from "@app/ee/services/gateway-v2/gateway-v2
import { TGithubOrgSyncServiceFactory } from "@app/ee/services/github-org-sync/github-org-sync-service";
import { TGroupServiceFactory } from "@app/ee/services/group/group-service";
import { TIdentityAuthTemplateServiceFactory } from "@app/ee/services/identity-auth-template";
import { TIdentityProjectAdditionalPrivilegeServiceFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service";
import { TIdentityProjectAdditionalPrivilegeV2ServiceFactory } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service";
import { TKmipClientDALFactory } from "@app/ee/services/kmip/kmip-client-dal";
import { TKmipOperationServiceFactory } from "@app/ee/services/kmip/kmip-operation-service";
import { TKmipServiceFactory } from "@app/ee/services/kmip/kmip-service";
@@ -35,7 +33,6 @@ import { TPamSessionServiceFactory } from "@app/ee/services/pam-session/pam-sess
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { TPitServiceFactory } from "@app/ee/services/pit/pit-service";
import { TProjectTemplateServiceFactory } from "@app/ee/services/project-template/project-template-types";
import { TProjectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-types";
import { RateLimitConfiguration, TRateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-types";
import { TRelayServiceFactory } from "@app/ee/services/relay/relay-service";
import { TSamlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-types";
@@ -53,7 +50,6 @@ import { TSshHostServiceFactory } from "@app/ee/services/ssh-host/ssh-host-servi
import { TSshHostGroupServiceFactory } from "@app/ee/services/ssh-host-group/ssh-host-group-service";
import { TTrustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-types";
import { TAuthMode } from "@app/server/plugins/auth/inject-identity";
import { TAdditionalPrivilegeServiceFactory } from "@app/services/additional-privilege/additional-privilege-service";
import { TApiKeyServiceFactory } from "@app/services/api-key/api-key-service";
import { TAppConnectionServiceFactory } from "@app/services/app-connection/app-connection-service";
import { TAuthLoginFactory } from "@app/services/auth/auth-login-service";
@@ -95,7 +91,6 @@ import { TMembershipUserServiceFactory } from "@app/services/membership-user/mem
import { TMicrosoftTeamsServiceFactory } from "@app/services/microsoft-teams/microsoft-teams-service";
import { TNotificationServiceFactory } from "@app/services/notification/notification-service";
import { TOfflineUsageReportServiceFactory } from "@app/services/offline-usage-report/offline-usage-report-service";
import { TOrgRoleServiceFactory } from "@app/services/org/org-role-service";
import { TOrgServiceFactory } from "@app/services/org/org-service";
import { TOrgAdminServiceFactory } from "@app/services/org-admin/org-admin-service";
import { TPkiAlertServiceFactory } from "@app/services/pki-alert/pki-alert-service";
@@ -108,7 +103,6 @@ import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot
import { TProjectEnvServiceFactory } from "@app/services/project-env/project-env-service";
import { TProjectKeyServiceFactory } from "@app/services/project-key/project-key-service";
import { TProjectMembershipServiceFactory } from "@app/services/project-membership/project-membership-service";
import { TProjectRoleServiceFactory } from "@app/services/project-role/project-role-service";
import { TReminderServiceFactory } from "@app/services/reminder/reminder-types";
import { TRoleServiceFactory } from "@app/services/role/role-service";
import { TSecretServiceFactory } from "@app/services/secret/secret-service";
@@ -131,6 +125,7 @@ import { TUserEngagementServiceFactory } from "@app/services/user-engagement/use
import { TWebhookServiceFactory } from "@app/services/webhook/webhook-service";
import { TWorkflowIntegrationServiceFactory } from "@app/services/workflow-integration/workflow-integration-service";
import { TConvertorServiceFactory } from "@app/services/convertor/convertor-service";
import { TAdditionalPrivilegeServiceFactory } from "@app/services/additional-privilege/additional-privilege-service";
declare module "@fastify/request-context" {
interface RequestContextData {
@@ -219,7 +214,6 @@ declare module "fastify" {
authToken: TAuthTokenServiceFactory;
permission: TPermissionServiceFactory;
org: TOrgServiceFactory;
orgRole: TOrgRoleServiceFactory;
oidc: TOidcConfigServiceFactory;
superAdmin: TSuperAdminServiceFactory;
user: TUserServiceFactory;
@@ -231,7 +225,6 @@ declare module "fastify" {
projectMembership: TProjectMembershipServiceFactory;
projectEnv: TProjectEnvServiceFactory;
projectKey: TProjectKeyServiceFactory;
projectRole: TProjectRoleServiceFactory;
secret: TSecretServiceFactory;
secretReplication: TSecretReplicationServiceFactory;
secretTag: TSecretTagServiceFactory;
@@ -331,8 +324,8 @@ declare module "fastify" {
membershipUser: TMembershipUserServiceFactory;
membershipIdentity: TMembershipIdentityServiceFactory;
membershipGroup: TMembershipGroupServiceFactory;
role: TRoleServiceFactory;
additionalPrivilege: TAdditionalPrivilegeServiceFactory;
role: TRoleServiceFactory;
convertor: TConvertorServiceFactory;
};
// this is exclusive use for middlewares in which we need to inject data
+8 -13
View File
@@ -277,21 +277,16 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { permissions, memberships } = await server.services.orgRole.getUserPermission(
req.permission.id,
req.params.organizationId,
req.permission.authMethod,
req.permission.orgId
);
const { permissions, memberships } = await server.services.role.getUserPermission({
permission: req.permission,
scopeData: {
scope: AccessScope.Organization,
orgId: req.permission.orgId
}
});
return {
permissions,
memberships: memberships.map((el) => ({
...el,
role: el.roles[0].customRoleSlug || el.roles[0].role,
orgId: el.scopeOrgId,
status: el.status || "",
isActive: el.isActive || true
}))
memberships
};
}
});
@@ -337,12 +337,14 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { permissions, memberships, assumedPrivilegeDetails } = await server.services.projectRole.getUserPermission(
req.permission.id,
req.params.projectId,
req.permission.authMethod,
req.permission.orgId
);
const { permissions, memberships, assumedPrivilegeDetails } = await server.services.role.getUserPermission({
permission: req.permission,
scopeData: {
scope: AccessScope.Project,
projectId: req.params.projectId,
orgId: req.permission.orgId
}
});
return {
data: {
+96 -164
View File
@@ -50,9 +50,6 @@ import { hsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
import { HsmModule } from "@app/ee/services/hsm/hsm-types";
import { identityAuthTemplateDALFactory } from "@app/ee/services/identity-auth-template/identity-auth-template-dal";
import { identityAuthTemplateServiceFactory } from "@app/ee/services/identity-auth-template/identity-auth-template-service";
import { identityProjectAdditionalPrivilegeDALFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-dal";
import { identityProjectAdditionalPrivilegeServiceFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service";
import { identityProjectAdditionalPrivilegeV2ServiceFactory } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service";
import { kmipClientCertificateDALFactory } from "@app/ee/services/kmip/kmip-client-certificate-dal";
import { kmipClientDALFactory } from "@app/ee/services/kmip/kmip-client-dal";
import { kmipOperationServiceFactory } from "@app/ee/services/kmip/kmip-operation-service";
@@ -79,8 +76,6 @@ import { permissionServiceFactory } from "@app/ee/services/permission/permission
import { pitServiceFactory } from "@app/ee/services/pit/pit-service";
import { projectTemplateDALFactory } from "@app/ee/services/project-template/project-template-dal";
import { projectTemplateServiceFactory } from "@app/ee/services/project-template/project-template-service";
import { projectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
import { projectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
import { rateLimitDALFactory } from "@app/ee/services/rate-limit/rate-limit-dal";
import { rateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-service";
import { instanceRelayConfigDalFactory } from "@app/ee/services/relay/instance-relay-config-dal";
@@ -189,8 +184,6 @@ import { folderCommitChangesDALFactory } from "@app/services/folder-commit-chang
import { folderTreeCheckpointDALFactory } from "@app/services/folder-tree-checkpoint/folder-tree-checkpoint-dal";
import { folderTreeCheckpointResourcesDALFactory } from "@app/services/folder-tree-checkpoint-resources/folder-tree-checkpoint-resources-dal";
import { groupProjectDALFactory } from "@app/services/group-project/group-project-dal";
import { groupProjectMembershipRoleDALFactory } from "@app/services/group-project/group-project-membership-role-dal";
import { groupProjectServiceFactory } from "@app/services/group-project/group-project-service";
import { identityDALFactory } from "@app/services/identity/identity-dal";
import { identityMetadataDALFactory } from "@app/services/identity/identity-metadata-dal";
import { identityOrgDALFactory } from "@app/services/identity/identity-org-dal";
@@ -216,8 +209,6 @@ import { identityOciAuthServiceFactory } from "@app/services/identity-oci-auth/i
import { identityOidcAuthDALFactory } from "@app/services/identity-oidc-auth/identity-oidc-auth-dal";
import { identityOidcAuthServiceFactory } from "@app/services/identity-oidc-auth/identity-oidc-auth-service";
import { identityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
import { identityProjectMembershipRoleDALFactory } from "@app/services/identity-project/identity-project-membership-role-dal";
import { identityProjectServiceFactory } from "@app/services/identity-project/identity-project-service";
import { identityTlsCertAuthDALFactory } from "@app/services/identity-tls-cert-auth/identity-tls-cert-auth-dal";
import { identityTlsCertAuthServiceFactory } from "@app/services/identity-tls-cert-auth/identity-tls-cert-auth-service";
import { identityTokenAuthDALFactory } from "@app/services/identity-token-auth/identity-token-auth-dal";
@@ -252,7 +243,6 @@ import { offlineUsageReportServiceFactory } from "@app/services/offline-usage-re
import { incidentContactDALFactory } from "@app/services/org/incident-contacts-dal";
import { orgBotDALFactory } from "@app/services/org/org-bot-dal";
import { orgDALFactory } from "@app/services/org/org-dal";
import { orgRoleServiceFactory } from "@app/services/org/org-role-service";
import { orgServiceFactory } from "@app/services/org/org-service";
import { orgAdminServiceFactory } from "@app/services/org-admin/org-admin-service";
import { orgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
@@ -283,9 +273,6 @@ import { projectKeyDALFactory } from "@app/services/project-key/project-key-dal"
import { projectKeyServiceFactory } from "@app/services/project-key/project-key-service";
import { projectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
import { projectMembershipServiceFactory } from "@app/services/project-membership/project-membership-service";
import { projectUserMembershipRoleDALFactory } from "@app/services/project-membership/project-user-membership-role-dal";
import { projectRoleDALFactory } from "@app/services/project-role/project-role-dal";
import { projectRoleServiceFactory } from "@app/services/project-role/project-role-service";
import { reminderDALFactory } from "@app/services/reminder/reminder-dal";
import { dailyReminderQueueServiceFactory } from "@app/services/reminder/reminder-queue";
import { reminderServiceFactory } from "@app/services/reminder/reminder-service";
@@ -353,6 +340,9 @@ import { initializeOauthConfigSync } from "./v1/sso-router";
import { registerV2Routes } from "./v2";
import { registerV3Routes } from "./v3";
import { registerV4Routes } from "./v4";
import { groupProjectServiceFactory } from "@app/services/group-project/group-project-service";
import { identityProjectServiceFactory } from "@app/services/identity-project/identity-project-service";
import { convertorServiceFactory } from "@app/services/convertor/convertor-service";
const histogram = monitorEventLoopDelay({ resolution: 20 });
histogram.enable();
@@ -399,9 +389,6 @@ export const registerRoutes = async (
const projectDAL = projectDALFactory(db);
const projectSshConfigDAL = projectSshConfigDALFactory(db);
const projectMembershipDAL = projectMembershipDALFactory(db);
const projectUserAdditionalPrivilegeDAL = projectUserAdditionalPrivilegeDALFactory(db);
const projectUserMembershipRoleDAL = projectUserMembershipRoleDALFactory(db);
const projectRoleDAL = projectRoleDALFactory(db);
const projectEnvDAL = projectEnvDALFactory(db);
const projectKeyDAL = projectKeyDALFactory(db);
const projectBotDAL = projectBotDALFactory(db);
@@ -433,8 +420,6 @@ export const registerRoutes = async (
const identityAccessTokenDAL = identityAccessTokenDALFactory(db);
const identityOrgMembershipDAL = identityOrgDALFactory(db);
const identityProjectDAL = identityProjectDALFactory(db);
const identityProjectMembershipRoleDAL = identityProjectMembershipRoleDALFactory(db);
const identityProjectAdditionalPrivilegeDAL = identityProjectAdditionalPrivilegeDALFactory(db);
const identityAuthTemplateDAL = identityAuthTemplateDALFactory(db);
const identityTokenAuthDAL = identityTokenAuthDALFactory(db);
@@ -492,7 +477,6 @@ export const registerRoutes = async (
const gitAppOrgDAL = gitAppDALFactory(db);
const groupDAL = groupDALFactory(db);
const groupProjectDAL = groupProjectDALFactory(db);
const groupProjectMembershipRoleDAL = groupProjectMembershipRoleDALFactory(db);
const userGroupMembershipDAL = userGroupMembershipDALFactory(db);
const secretScanningDAL = secretScanningDALFactory(db);
const secretSharingDAL = secretSharingDALFactory(db);
@@ -602,7 +586,10 @@ export const registerRoutes = async (
const roleService = roleServiceFactory({
permissionService,
roleDAL
roleDAL,
projectDAL,
identityDAL,
userDAL
});
const additionalPrivilegeService = additionalPrivilegeServiceFactory({
additionalPrivilegeDAL,
@@ -676,13 +663,12 @@ export const registerRoutes = async (
userDAL,
secretApprovalRequestDAL
});
const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL, orgMembershipDAL });
const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL, membershipUserDAL });
const samlService = samlConfigServiceFactory({
identityMetadataDAL,
permissionService,
orgDAL,
orgMembershipDAL,
userDAL,
userAliasDAL,
samlConfigDAL,
@@ -695,12 +681,12 @@ export const registerRoutes = async (
licenseService,
tokenService,
smtpService,
kmsService
kmsService,
membershipRoleDAL
});
const groupService = groupServiceFactory({
userDAL,
groupDAL,
groupProjectDAL,
orgDAL,
userGroupMembershipDAL,
projectDAL,
@@ -708,17 +694,13 @@ export const registerRoutes = async (
projectKeyDAL,
permissionService,
licenseService,
oidcConfigDAL
oidcConfigDAL,
membershipGroupDAL,
membershipRoleDAL
});
const groupProjectService = groupProjectServiceFactory({
groupDAL,
groupProjectDAL,
groupProjectMembershipRoleDAL,
userGroupMembershipDAL,
projectDAL,
projectKeyDAL,
projectBotDAL,
projectRoleDAL,
permissionService
});
@@ -763,18 +745,18 @@ export const registerRoutes = async (
userDAL,
userAliasDAL,
orgDAL,
orgMembershipDAL,
projectDAL,
projectUserAdditionalPrivilegeDAL,
projectMembershipDAL,
groupDAL,
groupProjectDAL,
userGroupMembershipDAL,
projectKeyDAL,
projectBotDAL,
permissionService,
smtpService,
externalGroupOrgRoleMappingDAL
externalGroupOrgRoleMappingDAL,
groupDAL,
membershipGroupDAL,
membershipRoleDAL,
membershipUserDAL
});
const githubOrgSyncConfigService = githubOrgSyncServiceFactory({
@@ -791,9 +773,7 @@ export const registerRoutes = async (
ldapConfigDAL,
ldapGroupMapDAL,
orgDAL,
orgMembershipDAL,
groupDAL,
groupProjectDAL,
projectKeyDAL,
projectDAL,
projectBotDAL,
@@ -804,7 +784,9 @@ export const registerRoutes = async (
licenseService,
tokenService,
smtpService,
kmsService
kmsService,
membershipGroupDAL,
membershipRoleDAL
});
const telemetryService = telemetryServiceFactory({
@@ -826,13 +808,12 @@ export const registerRoutes = async (
const userService = userServiceFactory({
userDAL,
orgDAL,
orgMembershipDAL,
tokenService,
permissionService,
groupProjectDAL,
smtpService,
projectMembershipDAL,
userAliasDAL
userAliasDAL,
membershipUserDAL
});
const upgradePathService = upgradePathServiceFactory({ keyStore });
@@ -849,9 +830,10 @@ export const registerRoutes = async (
tokenService,
orgDAL,
totpService,
orgMembershipDAL,
auditLogService,
notificationService
notificationService,
membershipRoleDAL,
membershipUserDAL
});
const passwordService = authPaswordServiceFactory({
tokenService,
@@ -881,14 +863,10 @@ export const registerRoutes = async (
folderDAL,
licenseService,
samlConfigDAL,
orgRoleDAL,
permissionService,
orgDAL,
incidentContactDAL,
tokenService,
projectUserAdditionalPrivilegeDAL,
projectUserMembershipRoleDAL,
projectRoleDAL,
projectDAL,
projectMembershipDAL,
orgMembershipDAL,
@@ -901,7 +879,10 @@ export const registerRoutes = async (
ldapConfigDAL,
loginService,
projectBotService,
reminderService
reminderService,
membershipRoleDAL,
membershipUserDAL,
roleDAL
});
const signupService = authSignupServiceFactory({
tokenService,
@@ -912,18 +893,10 @@ export const registerRoutes = async (
projectKeyDAL,
projectDAL,
projectBotDAL,
groupProjectDAL,
projectMembershipDAL,
projectUserMembershipRoleDAL,
orgDAL,
orgService,
licenseService
});
const orgRoleService = orgRoleServiceFactory({
permissionService,
orgRoleDAL,
orgDAL,
externalGroupOrgRoleMappingDAL
licenseService,
membershipGroupDAL
});
const microsoftTeamsService = microsoftTeamsServiceFactory({
@@ -940,8 +913,6 @@ export const registerRoutes = async (
userAliasDAL,
identityTokenAuthDAL,
identityAccessTokenDAL,
orgMembershipDAL,
identityOrgMembershipDAL,
authService: loginService,
serverCfgDAL: superAdminDAL,
kmsRootConfigDAL,
@@ -953,7 +924,10 @@ export const registerRoutes = async (
microsoftTeamsService,
invalidateCacheQueue,
smtpService,
tokenService
tokenService,
membershipIdentityDAL,
membershipRoleDAL,
membershipUserDAL
});
const offlineUsageReportService = offlineUsageReportServiceFactory({
@@ -965,9 +939,10 @@ export const registerRoutes = async (
smtpService,
projectDAL,
permissionService,
projectUserMembershipRoleDAL,
projectMembershipDAL,
notificationService
notificationService,
membershipRoleDAL,
membershipUserDAL,
projectMembershipDAL
});
const rateLimitService = rateLimitServiceFactory({
@@ -993,32 +968,24 @@ export const registerRoutes = async (
const projectMembershipService = projectMembershipServiceFactory({
projectMembershipDAL,
projectUserMembershipRoleDAL,
projectDAL,
permissionService,
projectBotDAL,
orgDAL,
userDAL,
projectUserAdditionalPrivilegeDAL,
userGroupMembershipDAL,
smtpService,
projectKeyDAL,
projectRoleDAL,
groupProjectDAL,
secretReminderRecipientsDAL,
licenseService,
notificationService
});
const projectUserAdditionalPrivilegeService = projectUserAdditionalPrivilegeServiceFactory({
permissionService,
projectMembershipDAL,
projectUserAdditionalPrivilegeDAL,
accessApprovalRequestDAL
notificationService,
membershipDAL
});
const projectKeyService = projectKeyServiceFactory({
permissionService,
projectKeyDAL,
projectMembershipDAL
membershipUserDAL
});
const projectQueueService = projectQueueFactory({
@@ -1034,10 +1001,10 @@ export const registerRoutes = async (
secretVersionDAL,
projectKeyDAL,
projectBotDAL,
projectMembershipDAL,
secretApprovalRequestDAL,
secretApprovalSecretDAL: secretApprovalRequestSecretDAL,
projectUserMembershipRoleDAL
membershipRoleDAL,
membershipUserDAL
});
const certificateAuthorityDAL = certificateAuthorityDALFactory(db);
@@ -1249,14 +1216,15 @@ export const registerRoutes = async (
snapshotSecretV2BridgeDAL,
secretApprovalRequestDAL,
projectKeyDAL,
projectUserMembershipRoleDAL,
orgService,
resourceMetadataDAL,
folderCommitService,
secretSyncQueue,
reminderService,
eventBusService,
licenseService
licenseService,
membershipRoleDAL,
membershipUserDAL
});
const projectService = projectServiceFactory({
@@ -1267,13 +1235,10 @@ export const registerRoutes = async (
secretV2BridgeDAL,
projectQueue: projectQueueService,
projectBotService,
identityProjectDAL,
identityOrgMembershipDAL,
userDAL,
projectEnvDAL,
orgDAL,
projectMembershipDAL,
projectRoleDAL,
folderDAL,
licenseService,
pkiSubscriberDAL,
@@ -1287,8 +1252,6 @@ export const registerRoutes = async (
sshCertificateTemplateDAL,
sshHostDAL,
sshHostGroupDAL,
projectUserMembershipRoleDAL,
identityProjectMembershipRoleDAL,
keyStore,
kmsService,
certificateTemplateDAL,
@@ -1297,7 +1260,6 @@ export const registerRoutes = async (
projectMicrosoftTeamsConfigDAL,
microsoftTeamsIntegrationDAL,
projectTemplateService,
groupProjectDAL,
smtpService,
reminderService,
notificationService
@@ -1314,16 +1276,6 @@ export const registerRoutes = async (
secretApprovalPolicyEnvironmentDAL: sapEnvironmentDAL
});
const projectRoleService = projectRoleServiceFactory({
permissionService,
projectRoleDAL,
projectUserMembershipRoleDAL,
identityProjectMembershipRoleDAL,
projectDAL,
identityDAL,
userDAL
});
const snapshotService = secretSnapshotServiceFactory({
permissionService,
licenseService,
@@ -1478,21 +1430,16 @@ export const registerRoutes = async (
groupDAL,
permissionService,
projectEnvDAL,
projectMembershipDAL,
projectDAL,
userDAL,
accessApprovalRequestDAL,
additionalPrivilegeDAL: projectUserAdditionalPrivilegeDAL,
accessApprovalRequestReviewerDAL,
orgMembershipDAL
accessApprovalRequestReviewerDAL
});
const accessApprovalRequestService = accessApprovalRequestServiceFactory({
projectDAL,
permissionService,
accessApprovalRequestReviewerDAL,
additionalPrivilegeDAL: projectUserAdditionalPrivilegeDAL,
projectMembershipDAL,
accessApprovalPolicyDAL,
accessApprovalRequestDAL,
projectEnvDAL,
@@ -1594,7 +1541,14 @@ export const registerRoutes = async (
licenseService,
identityMetadataDAL,
keyStore,
orgDAL
orgDAL,
membershipIdentityDAL,
membershipRoleDAL
});
const identityProjectService = identityProjectServiceFactory({
identityProjectDAL,
membershipIdentityDAL,
permissionService
});
const identityAuthTemplateService = identityAuthTemplateServiceFactory({
@@ -1613,53 +1567,28 @@ export const registerRoutes = async (
identityDAL
});
const identityProjectService = identityProjectServiceFactory({
permissionService,
projectDAL,
identityProjectDAL,
identityOrgMembershipDAL,
identityProjectMembershipRoleDAL,
projectRoleDAL,
orgDAL
});
const identityProjectAdditionalPrivilegeService = identityProjectAdditionalPrivilegeServiceFactory({
projectDAL,
identityProjectAdditionalPrivilegeDAL,
permissionService,
identityProjectDAL
});
const identityProjectAdditionalPrivilegeV2Service = identityProjectAdditionalPrivilegeV2ServiceFactory({
projectDAL,
identityProjectAdditionalPrivilegeDAL,
permissionService,
identityProjectDAL
});
const identityTokenAuthService = identityTokenAuthServiceFactory({
identityTokenAuthDAL,
identityOrgMembershipDAL,
identityAccessTokenDAL,
permissionService,
licenseService,
orgDAL
orgDAL,
membershipIdentityDAL
});
const identityUaService = identityUaServiceFactory({
identityOrgMembershipDAL,
permissionService,
identityAccessTokenDAL,
identityUaClientSecretDAL,
identityUaDAL,
licenseService,
keyStore,
orgDAL
orgDAL,
membershipIdentityDAL
});
const identityKubernetesAuthService = identityKubernetesAuthServiceFactory({
identityKubernetesAuthDAL,
identityOrgMembershipDAL,
identityAccessTokenDAL,
permissionService,
licenseService,
@@ -1668,61 +1597,62 @@ export const registerRoutes = async (
gatewayV2Service,
gatewayV2DAL,
gatewayDAL,
kmsService
kmsService,
membershipIdentityDAL
});
const identityGcpAuthService = identityGcpAuthServiceFactory({
identityGcpAuthDAL,
orgDAL,
identityOrgMembershipDAL,
identityAccessTokenDAL,
permissionService,
licenseService
licenseService,
membershipIdentityDAL
});
const identityAliCloudAuthService = identityAliCloudAuthServiceFactory({
identityAccessTokenDAL,
orgDAL,
identityAliCloudAuthDAL,
identityOrgMembershipDAL,
licenseService,
permissionService
permissionService,
membershipIdentityDAL
});
const identityTlsCertAuthService = identityTlsCertAuthServiceFactory({
identityAccessTokenDAL,
orgDAL,
identityTlsCertAuthDAL,
identityOrgMembershipDAL,
licenseService,
permissionService,
kmsService
kmsService,
membershipIdentityDAL
});
const identityAwsAuthService = identityAwsAuthServiceFactory({
identityAccessTokenDAL,
orgDAL,
identityAwsAuthDAL,
identityOrgMembershipDAL,
licenseService,
permissionService
permissionService,
membershipIdentityDAL
});
const identityAzureAuthService = identityAzureAuthServiceFactory({
identityAzureAuthDAL,
orgDAL,
identityOrgMembershipDAL,
identityAccessTokenDAL,
permissionService,
licenseService
licenseService,
membershipIdentityDAL
});
const identityOciAuthService = identityOciAuthServiceFactory({
identityAccessTokenDAL,
orgDAL,
identityOciAuthDAL,
identityOrgMembershipDAL,
licenseService,
permissionService
permissionService,
membershipIdentityDAL
});
const pitService = pitServiceFactory({
@@ -1742,11 +1672,11 @@ export const registerRoutes = async (
const identityOidcAuthService = identityOidcAuthServiceFactory({
identityOidcAuthDAL,
orgDAL,
identityOrgMembershipDAL,
identityAccessTokenDAL,
permissionService,
licenseService,
kmsService
kmsService,
membershipIdentityDAL
});
const identityJwtAuthService = identityJwtAuthServiceFactory({
@@ -1754,9 +1684,9 @@ export const registerRoutes = async (
orgDAL,
permissionService,
identityAccessTokenDAL,
identityOrgMembershipDAL,
licenseService,
kmsService
kmsService,
membershipIdentityDAL
});
const identityLdapAuthService = identityLdapAuthServiceFactory({
@@ -1765,11 +1695,17 @@ export const registerRoutes = async (
permissionService,
kmsService,
identityAccessTokenDAL,
identityOrgMembershipDAL,
licenseService,
identityDAL,
identityAuthTemplateDAL,
keyStore
keyStore,
membershipIdentityDAL
});
const convertorService = convertorServiceFactory({
additionalPrivilegeDAL,
membershipDAL,
projectDAL
});
const dynamicSecretProviders = buildDynamicSecretProviders({
@@ -1844,7 +1780,6 @@ export const registerRoutes = async (
const oidcService = oidcConfigServiceFactory({
orgDAL,
orgMembershipDAL,
userDAL,
userAliasDAL,
licenseService,
@@ -1857,9 +1792,10 @@ export const registerRoutes = async (
projectKeyDAL,
projectDAL,
userGroupMembershipDAL,
groupProjectDAL,
groupDAL,
auditLogService
auditLogService,
membershipGroupDAL,
membershipRoleDAL
});
const userEngagementService = userEngagementServiceFactory({
@@ -1915,8 +1851,8 @@ export const registerRoutes = async (
const externalGroupOrgRoleMappingService = externalGroupOrgRoleMappingServiceFactory({
permissionService,
licenseService,
orgRoleDAL,
externalGroupOrgRoleMappingDAL
externalGroupOrgRoleMappingDAL,
roleDAL
});
const appConnectionService = appConnectionServiceFactory({
@@ -2262,7 +2198,6 @@ export const registerRoutes = async (
groupProject: groupProjectService,
permission: permissionService,
org: orgService,
orgRole: orgRoleService,
oidc: oidcService,
apiKey: apiKeyService,
authToken: tokenService,
@@ -2272,7 +2207,6 @@ export const registerRoutes = async (
projectMembership: projectMembershipService,
projectKey: projectKeyService,
projectEnv: projectEnvService,
projectRole: projectRoleService,
secret: secretService,
secretReplication: secretReplicationService,
secretTag: secretTagService,
@@ -2287,7 +2221,6 @@ export const registerRoutes = async (
identity: identityService,
identityAuthTemplate: identityAuthTemplateService,
identityAccessToken: identityAccessTokenService,
identityProject: identityProjectService,
identityTokenAuth: identityTokenAuthService,
identityUa: identityUaService,
identityKubernetesAuth: identityKubernetesAuthService,
@@ -2334,9 +2267,6 @@ export const registerRoutes = async (
scim: scimService,
secretBlindIndex: secretBlindIndexService,
telemetry: telemetryService,
projectUserAdditionalPrivilege: projectUserAdditionalPrivilegeService,
identityProjectAdditionalPrivilege: identityProjectAdditionalPrivilegeService,
identityProjectAdditionalPrivilegeV2: identityProjectAdditionalPrivilegeV2Service,
secretSharing: secretSharingService,
userEngagement: userEngagementService,
externalKms: externalKmsService,
@@ -2376,7 +2306,9 @@ export const registerRoutes = async (
membershipIdentity: membershipIdentityService,
membershipGroup: membershipGroupService,
role: roleService,
additionalPrivilege: additionalPrivilegeService
additionalPrivilege: additionalPrivilegeService,
identityProject: identityProjectService,
convertor: convertorService
});
const cronJobs: CronJob[] = [];
@@ -78,7 +78,7 @@ export const registerIdentityAliCloudAuthRouter = async (server: FastifyZodProvi
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_ALICLOUD_AUTH,
metadata: {
@@ -45,7 +45,7 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_AWS_AUTH,
metadata: {
@@ -40,7 +40,7 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_AZURE_AUTH,
metadata: {
@@ -40,7 +40,7 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_GCP_AUTH,
metadata: {
@@ -119,7 +119,7 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_JWT_AUTH,
metadata: {
@@ -64,7 +64,7 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_KUBERNETES_AUTH,
metadata: {
@@ -168,7 +168,7 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_LDAP_AUTH,
metadata: {
@@ -57,7 +57,7 @@ export const registerIdentityOciAuthRouter = async (server: FastifyZodProvider)
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_OCI_AUTH,
metadata: {
@@ -67,7 +67,7 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_OIDC_AUTH,
metadata: {
@@ -72,7 +72,7 @@ export const registerIdentityTlsCertAuthRouter = async (server: FastifyZodProvid
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_TLS_CERT_AUTH,
metadata: {
@@ -332,7 +332,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.CREATE_TOKEN_IDENTITY_TOKEN_AUTH,
metadata: {
@@ -393,7 +393,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.GET_TOKENS_IDENTITY_TOKEN_AUTH,
metadata: {
@@ -447,7 +447,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.UPDATE_TOKEN_IDENTITY_TOKEN_AUTH,
metadata: {
@@ -59,7 +59,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
orgId: identityMembershipOrg.scopeOrgId,
event: {
type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH,
metadata: {
@@ -204,7 +204,7 @@ export const identityAccessTokenServiceFactory = ({
}
const identityOrgMembership = await identityOrgMembershipDAL.findOne({
identityId: identityAccessToken.identityId
actorIdentityId: identityAccessToken.identityId
});
if (!identityOrgMembership) {
@@ -219,7 +219,7 @@ export const identityAccessTokenServiceFactory = ({
await validateAccessTokenExp({ ...identityAccessToken, accessTokenNumUses });
await accessTokenQueue.updateIdentityAccessTokenStatus(identityAccessToken.id, Number(accessTokenNumUses) + 1);
return { ...identityAccessToken, orgId: identityOrgMembership.orgId };
return { ...identityAccessToken, orgId: identityOrgMembership.scopeOrgId };
};
return { renewAccessToken, revokeAccessToken, fnValidateIdentityAccessToken };
@@ -2,7 +2,7 @@
import { ForbiddenError } from "@casl/ability";
import { AxiosError } from "axios";
import { IdentityAuthMethod } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import {
@@ -18,7 +18,7 @@ import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { logger } from "@app/lib/logger";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TOrgDALFactory } from "../org/org-dal";
@@ -39,7 +39,7 @@ type TIdentityAliCloudAuthServiceFactoryDep = {
TIdentityAliCloudAuthDALFactory,
"findOne" | "transaction" | "create" | "updateById" | "delete"
>;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
orgDAL: Pick<TOrgDALFactory, "findById">;
@@ -50,7 +50,7 @@ export type TIdentityAliCloudAuthServiceFactory = ReturnType<typeof identityAliC
export const identityAliCloudAuthServiceFactory = ({
identityAccessTokenDAL,
identityAliCloudAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
licenseService,
permissionService,
orgDAL
@@ -63,8 +63,9 @@ export const identityAliCloudAuthServiceFactory = ({
});
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
identityId: identityAliCloudAuth.identityId
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityAliCloudAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) throw new UnauthorizedError({ message: "Identity not attached to a organization" });
@@ -92,7 +93,7 @@ export const identityAliCloudAuthServiceFactory = ({
// Generate the token
const identityAccessToken = await identityAliCloudAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.ALICLOUD_AUTH,
@@ -153,7 +154,13 @@ export const identityAliCloudAuthServiceFactory = ({
}: TAttachAliCloudAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
@@ -169,13 +176,13 @@ export const identityAliCloudAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -196,7 +203,7 @@ export const identityAliCloudAuthServiceFactory = ({
const identityAliCloudAuth = await identityAliCloudAuthDAL.transaction(async (tx) => {
const doc = await identityAliCloudAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
type: "iam",
allowedArns,
accessTokenMaxTTL,
@@ -208,7 +215,7 @@ export const identityAliCloudAuthServiceFactory = ({
);
return doc;
});
return { ...identityAliCloudAuth, orgId: identityMembershipOrg.orgId };
return { ...identityAliCloudAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const updateAliCloudAuth = async ({
@@ -223,7 +230,13 @@ export const identityAliCloudAuthServiceFactory = ({
actor,
actorOrgId
}: TUpdateAliCloudAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
@@ -245,13 +258,13 @@ export const identityAliCloudAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -279,11 +292,17 @@ export const identityAliCloudAuthServiceFactory = ({
: undefined
});
return { ...updatedAliCloudAuth, orgId: identityMembershipOrg.orgId };
return { ...updatedAliCloudAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const getAliCloudAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAliCloudAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
@@ -297,12 +316,12 @@ export const identityAliCloudAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...alicloudIdentityAuth, orgId: identityMembershipOrg.orgId };
return { ...alicloudIdentityAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeIdentityAliCloudAuth = async ({
@@ -312,7 +331,13 @@ export const identityAliCloudAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TRevokeAliCloudAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new BadRequestError({
@@ -322,7 +347,7 @@ export const identityAliCloudAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -330,13 +355,13 @@ export const identityAliCloudAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -360,7 +385,7 @@ export const identityAliCloudAuthServiceFactory = ({
const deletedAliCloudAuth = await identityAliCloudAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.ALICLOUD_AUTH }, tx);
return { ...deletedAliCloudAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedAliCloudAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityAliCloudAuth;
};
@@ -3,7 +3,7 @@ import { ForbiddenError } from "@casl/ability";
import axios from "axios";
import RE2 from "re2";
import { IdentityAuthMethod } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TOrgDALFactory } from "../org/org-dal";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
@@ -18,7 +18,7 @@ import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedEr
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
@@ -37,7 +37,7 @@ import {
type TIdentityAwsAuthServiceFactoryDep = {
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
identityAwsAuthDAL: Pick<TIdentityAwsAuthDALFactory, "findOne" | "transaction" | "create" | "updateById" | "delete">;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
orgDAL: Pick<TOrgDALFactory, "findById">;
@@ -82,7 +82,7 @@ function isValidAwsRegion(region: string | null): boolean {
export const identityAwsAuthServiceFactory = ({
identityAccessTokenDAL,
identityAwsAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
licenseService,
permissionService,
orgDAL
@@ -93,7 +93,10 @@ export const identityAwsAuthServiceFactory = ({
throw new NotFoundError({ message: "AWS auth method not found for identity, did you configure AWS auth?" });
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityAwsAuth.identityId });
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityAwsAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) throw new UnauthorizedError({ message: "Identity not attached to a organization" });
const headers: TAwsGetCallerIdentityHeaders = JSON.parse(Buffer.from(iamRequestHeaders, "base64").toString());
@@ -156,7 +159,7 @@ export const identityAwsAuthServiceFactory = ({
}
const identityAccessToken = await identityAwsAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.AWS_AUTH,
@@ -229,7 +232,13 @@ export const identityAwsAuthServiceFactory = ({
}: TAttachAwsAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
@@ -245,13 +254,13 @@ export const identityAwsAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -272,7 +281,7 @@ export const identityAwsAuthServiceFactory = ({
const identityAwsAuth = await identityAwsAuthDAL.transaction(async (tx) => {
const doc = await identityAwsAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
type: "iam",
stsEndpoint,
allowedPrincipalArns,
@@ -286,7 +295,7 @@ export const identityAwsAuthServiceFactory = ({
);
return doc;
});
return { ...identityAwsAuth, orgId: identityMembershipOrg.orgId };
return { ...identityAwsAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const updateAwsAuth = async ({
@@ -303,7 +312,13 @@ export const identityAwsAuthServiceFactory = ({
actor,
actorOrgId
}: TUpdateAwsAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
@@ -324,13 +339,13 @@ export const identityAwsAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -360,11 +375,17 @@ export const identityAwsAuthServiceFactory = ({
: undefined
});
return { ...updatedAwsAuth, orgId: identityMembershipOrg.orgId };
return { ...updatedAwsAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const getAwsAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAwsAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
@@ -378,12 +399,12 @@ export const identityAwsAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...awsIdentityAuth, orgId: identityMembershipOrg.orgId };
return { ...awsIdentityAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeIdentityAwsAuth = async ({
@@ -393,7 +414,13 @@ export const identityAwsAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TRevokeAwsAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
throw new BadRequestError({
@@ -403,7 +430,7 @@ export const identityAwsAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -411,13 +438,13 @@ export const identityAwsAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -441,7 +468,7 @@ export const identityAwsAuthServiceFactory = ({
const deletedAwsAuth = await identityAwsAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.AWS_AUTH }, tx);
return { ...deletedAwsAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedAwsAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityAwsAuth;
};
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability";
import { IdentityAuthMethod } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TOrgDALFactory } from "../org/org-dal";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
@@ -15,7 +15,7 @@ import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedEr
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
@@ -34,7 +34,7 @@ type TIdentityAzureAuthServiceFactoryDep = {
TIdentityAzureAuthDALFactory,
"findOne" | "transaction" | "create" | "updateById" | "delete"
>;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
@@ -45,7 +45,7 @@ export type TIdentityAzureAuthServiceFactory = ReturnType<typeof identityAzureAu
export const identityAzureAuthServiceFactory = ({
identityAzureAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
identityAccessTokenDAL,
permissionService,
licenseService,
@@ -57,7 +57,10 @@ export const identityAzureAuthServiceFactory = ({
throw new NotFoundError({ message: "Azure auth method not found for identity, did you configure Azure Auth?" });
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityAzureAuth.identityId });
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityAzureAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) throw new UnauthorizedError({ message: "Identity not attached to a organization" });
const azureIdentity = await validateAzureIdentity({
@@ -83,7 +86,7 @@ export const identityAzureAuthServiceFactory = ({
}
const identityAccessToken = await identityAzureAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.AZURE_AUTH,
@@ -142,7 +145,13 @@ export const identityAzureAuthServiceFactory = ({
}: TAttachAzureAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
@@ -157,13 +166,13 @@ export const identityAzureAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -184,7 +193,7 @@ export const identityAzureAuthServiceFactory = ({
const identityAzureAuth = await identityAzureAuthDAL.transaction(async (tx) => {
const doc = await identityAzureAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
tenantId,
resource,
allowedServicePrincipalIds,
@@ -198,7 +207,7 @@ export const identityAzureAuthServiceFactory = ({
return doc;
});
return { ...identityAzureAuth, orgId: identityMembershipOrg.orgId };
return { ...identityAzureAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const updateAzureAuth = async ({
@@ -215,7 +224,13 @@ export const identityAzureAuthServiceFactory = ({
actor,
actorOrgId
}: TUpdateAzureAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
throw new BadRequestError({
@@ -235,13 +250,13 @@ export const identityAzureAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -273,12 +288,18 @@ export const identityAzureAuthServiceFactory = ({
return {
...updatedAzureAuth,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
};
};
const getAzureAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAzureAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
throw new BadRequestError({
@@ -291,13 +312,13 @@ export const identityAzureAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...identityAzureAuth, orgId: identityMembershipOrg.orgId };
return { ...identityAzureAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeIdentityAzureAuth = async ({
@@ -307,7 +328,13 @@ export const identityAzureAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TRevokeAzureAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
throw new BadRequestError({
@@ -317,7 +344,7 @@ export const identityAzureAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -325,12 +352,12 @@ export const identityAzureAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -353,7 +380,7 @@ export const identityAzureAuthServiceFactory = ({
const deletedAzureAuth = await identityAzureAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.AZURE_AUTH }, tx);
return { ...deletedAzureAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedAzureAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityAzureAuth;
};
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability";
import { IdentityAuthMethod } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TOrgDALFactory } from "../org/org-dal";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
@@ -15,7 +15,7 @@ import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedEr
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
@@ -32,7 +32,7 @@ import {
type TIdentityGcpAuthServiceFactoryDep = {
identityGcpAuthDAL: Pick<TIdentityGcpAuthDALFactory, "findOne" | "transaction" | "create" | "updateById" | "delete">;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
@@ -43,7 +43,7 @@ export type TIdentityGcpAuthServiceFactory = ReturnType<typeof identityGcpAuthSe
export const identityGcpAuthServiceFactory = ({
identityGcpAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
identityAccessTokenDAL,
permissionService,
licenseService,
@@ -55,7 +55,10 @@ export const identityGcpAuthServiceFactory = ({
throw new NotFoundError({ message: "GCP auth method not found for identity, did you configure GCP auth?" });
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityGcpAuth.identityId });
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityGcpAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) {
throw new UnauthorizedError({ message: "Identity does not belong to any organization" });
}
@@ -122,7 +125,7 @@ export const identityGcpAuthServiceFactory = ({
}
const identityAccessToken = await identityGcpAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.GCP_AUTH,
@@ -182,7 +185,13 @@ export const identityGcpAuthServiceFactory = ({
}: TAttachGcpAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
@@ -198,13 +207,13 @@ export const identityGcpAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -225,7 +234,7 @@ export const identityGcpAuthServiceFactory = ({
const identityGcpAuth = await identityGcpAuthDAL.transaction(async (tx) => {
const doc = await identityGcpAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
type,
allowedServiceAccounts,
allowedProjects,
@@ -239,7 +248,7 @@ export const identityGcpAuthServiceFactory = ({
);
return doc;
});
return { ...identityGcpAuth, orgId: identityMembershipOrg.orgId };
return { ...identityGcpAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const updateGcpAuth = async ({
@@ -257,7 +266,13 @@ export const identityGcpAuthServiceFactory = ({
actor,
actorOrgId
}: TUpdateGcpAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
@@ -278,13 +293,13 @@ export const identityGcpAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -317,12 +332,18 @@ export const identityGcpAuthServiceFactory = ({
return {
...updatedGcpAuth,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
};
};
const getGcpAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetGcpAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
@@ -336,13 +357,13 @@ export const identityGcpAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...identityGcpAuth, orgId: identityMembershipOrg.orgId };
return { ...identityGcpAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeIdentityGcpAuth = async ({
@@ -352,7 +373,13 @@ export const identityGcpAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TRevokeGcpAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
@@ -363,7 +390,7 @@ export const identityGcpAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -371,12 +398,12 @@ export const identityGcpAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -399,7 +426,7 @@ export const identityGcpAuthServiceFactory = ({
const deletedGcpAuth = await identityGcpAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.GCP_AUTH }, tx);
return { ...deletedGcpAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedGcpAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityGcpAuth;
};
@@ -3,7 +3,7 @@ import https from "https";
import jwt from "jsonwebtoken";
import { JwksClient } from "jwks-rsa";
import { IdentityAuthMethod, TIdentityJwtAuthsUpdate } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod, TIdentityJwtAuthsUpdate } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TOrgDALFactory } from "../org/org-dal";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
@@ -25,7 +25,7 @@ import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { getValueByDot } from "@app/lib/template/dot-access";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TKmsServiceFactory } from "../kms/kms-service";
@@ -44,7 +44,7 @@ import {
type TIdentityJwtAuthServiceFactoryDep = {
identityJwtAuthDAL: TIdentityJwtAuthDALFactory;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
@@ -56,7 +56,7 @@ export type TIdentityJwtAuthServiceFactory = ReturnType<typeof identityJwtAuthSe
export const identityJwtAuthServiceFactory = ({
identityJwtAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
permissionService,
licenseService,
identityAccessTokenDAL,
@@ -69,8 +69,9 @@ export const identityJwtAuthServiceFactory = ({
throw new NotFoundError({ message: "JWT auth method not found for identity, did you configure JWT auth?" });
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
identityId: identityJwtAuth.identityId
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityJwtAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) {
throw new NotFoundError({
@@ -80,7 +81,7 @@ export const identityJwtAuthServiceFactory = ({
const { decryptor: orgDataKeyDecryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const decodedToken = crypto.jwt().decode(jwtValue, { complete: true });
@@ -210,7 +211,7 @@ export const identityJwtAuthServiceFactory = ({
}
const identityAccessToken = await identityJwtAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.JWT_AUTH,
@@ -275,10 +276,14 @@ export const identityJwtAuthServiceFactory = ({
}: TAttachJwtAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) {
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
}
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) {
throw new BadRequestError({
message: "Failed to add JWT Auth to already configured identity"
@@ -292,14 +297,14 @@ export const identityJwtAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -333,7 +338,7 @@ export const identityJwtAuthServiceFactory = ({
const identityJwtAuth = await identityJwtAuthDAL.transaction(async (tx) => {
const doc = await identityJwtAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
configurationType,
jwksUrl,
encryptedJwksCaCert,
@@ -352,7 +357,7 @@ export const identityJwtAuthServiceFactory = ({
return doc;
});
return { ...identityJwtAuth, orgId: identityMembershipOrg.orgId, jwksCaCert, publicKeys };
return { ...identityJwtAuth, orgId: identityMembershipOrg.scopeOrgId, jwksCaCert, publicKeys };
};
const updateJwtAuth = async ({
@@ -374,7 +379,13 @@ export const identityJwtAuthServiceFactory = ({
actor,
actorOrgId
}: TUpdateJwtAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) {
@@ -395,14 +406,14 @@ export const identityJwtAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -465,14 +476,20 @@ export const identityJwtAuthServiceFactory = ({
return {
...updatedJwtAuth,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
jwksCaCert: decryptedJwksCaCert,
publicKeys: decryptedPublicKeys
};
};
const getJwtAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetJwtAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) {
@@ -484,7 +501,7 @@ export const identityJwtAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -505,14 +522,20 @@ export const identityJwtAuthServiceFactory = ({
return {
...identityJwtAuth,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
jwksCaCert: decryptedJwksCaCert,
publicKeys: decryptedPublicKeys
};
};
const revokeJwtAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TRevokeJwtAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) {
throw new NotFoundError({ message: "Failed to find identity" });
}
@@ -526,7 +549,7 @@ export const identityJwtAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -535,13 +558,13 @@ export const identityJwtAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -564,7 +587,7 @@ export const identityJwtAuthServiceFactory = ({
const deletedJwtAuth = await identityJwtAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.JWT_AUTH }, tx);
return { ...deletedJwtAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedJwtAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityJwtAuth;
@@ -3,7 +3,7 @@ import axios, { AxiosError } from "axios";
import https from "https";
import RE2 from "re2";
import { IdentityAuthMethod, TIdentityKubernetesAuthsUpdate } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod, TIdentityKubernetesAuthsUpdate } from "@app/db/schemas";
import { TGatewayDALFactory } from "@app/ee/services/gateway/gateway-dal";
import { TGatewayServiceFactory } from "@app/ee/services/gateway/gateway-service";
import { TGatewayV2DALFactory } from "@app/ee/services/gateway-v2/gateway-v2-dal";
@@ -29,7 +29,7 @@ import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { logger } from "@app/lib/logger";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TKmsServiceFactory } from "../kms/kms-service";
@@ -53,7 +53,7 @@ type TIdentityKubernetesAuthServiceFactoryDep = {
"create" | "findOne" | "transaction" | "updateById" | "delete"
>;
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "findById" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
@@ -70,7 +70,7 @@ const GATEWAY_AUTH_DEFAULT_HOST = "https://kubernetes.default.svc.cluster.local"
export const identityKubernetesAuthServiceFactory = ({
identityKubernetesAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
identityAccessTokenDAL,
permissionService,
licenseService,
@@ -175,8 +175,9 @@ export const identityKubernetesAuthServiceFactory = ({
});
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
identityId: identityKubernetesAuth.identityId
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityKubernetesAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) {
throw new NotFoundError({
@@ -186,7 +187,7 @@ export const identityKubernetesAuthServiceFactory = ({
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
let caCert = "";
@@ -429,7 +430,7 @@ export const identityKubernetesAuthServiceFactory = ({
}
const identityAccessToken = await identityKubernetesAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.KUBERNETES_AUTH,
@@ -499,7 +500,13 @@ export const identityKubernetesAuthServiceFactory = ({
}: TAttachKubernetesAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
@@ -515,13 +522,13 @@ export const identityKubernetesAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -541,8 +548,8 @@ export const identityKubernetesAuthServiceFactory = ({
let isGatewayV1 = true;
if (gatewayId) {
const [gateway] = await gatewayDAL.find({ id: gatewayId, orgId: identityMembershipOrg.orgId });
const [gatewayV2] = await gatewayV2DAL.find({ id: gatewayId, orgId: identityMembershipOrg.orgId });
const [gateway] = await gatewayDAL.find({ id: gatewayId, orgId: identityMembershipOrg.scopeOrgId });
const [gatewayV2] = await gatewayV2DAL.find({ id: gatewayId, orgId: identityMembershipOrg.scopeOrgId });
if (!gateway && !gatewayV2) {
throw new NotFoundError({
message: `Gateway with ID ${gatewayId} not found`
@@ -556,7 +563,7 @@ export const identityKubernetesAuthServiceFactory = ({
const { permission: orgPermission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -568,13 +575,13 @@ export const identityKubernetesAuthServiceFactory = ({
const { encryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const identityKubernetesAuth = await identityKubernetesAuthDAL.transaction(async (tx) => {
const doc = await identityKubernetesAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
kubernetesHost,
tokenReviewMode,
allowedNamespaces,
@@ -596,7 +603,7 @@ export const identityKubernetesAuthServiceFactory = ({
return doc;
});
return { ...identityKubernetesAuth, caCert, tokenReviewerJwt, orgId: identityMembershipOrg.orgId };
return { ...identityKubernetesAuth, caCert, tokenReviewerJwt, orgId: identityMembershipOrg.scopeOrgId };
};
const updateKubernetesAuth = async ({
@@ -618,7 +625,13 @@ export const identityKubernetesAuthServiceFactory = ({
actor,
actorOrgId
}: TUpdateKubernetesAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
@@ -640,13 +653,13 @@ export const identityKubernetesAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -666,8 +679,8 @@ export const identityKubernetesAuthServiceFactory = ({
let isGatewayV1 = true;
if (gatewayId) {
const [gateway] = await gatewayDAL.find({ id: gatewayId, orgId: identityMembershipOrg.orgId });
const [gatewayV2] = await gatewayV2DAL.find({ id: gatewayId, orgId: identityMembershipOrg.orgId });
const [gateway] = await gatewayDAL.find({ id: gatewayId, orgId: identityMembershipOrg.scopeOrgId });
const [gatewayV2] = await gatewayV2DAL.find({ id: gatewayId, orgId: identityMembershipOrg.scopeOrgId });
if (!gateway && !gatewayV2) {
throw new NotFoundError({
@@ -682,7 +695,7 @@ export const identityKubernetesAuthServiceFactory = ({
const { permission: orgPermission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -714,7 +727,7 @@ export const identityKubernetesAuthServiceFactory = ({
const { encryptor, decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
if (caCert !== undefined) {
@@ -745,7 +758,7 @@ export const identityKubernetesAuthServiceFactory = ({
return {
...updatedKubernetesAuth,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
caCert: updatedCACert,
tokenReviewerJwt: updatedTokenReviewerJwt
};
@@ -758,7 +771,13 @@ export const identityKubernetesAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TGetKubernetesAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
@@ -775,7 +794,7 @@ export const identityKubernetesAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -783,7 +802,7 @@ export const identityKubernetesAuthServiceFactory = ({
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
let caCert = "";
@@ -802,7 +821,7 @@ export const identityKubernetesAuthServiceFactory = ({
...identityKubernetesAuth,
caCert,
tokenReviewerJwt,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
gatewayId: identityKubernetesAuth.gatewayId ?? identityKubernetesAuth.gatewayV2Id
};
};
@@ -814,7 +833,13 @@ export const identityKubernetesAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TRevokeKubernetesAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
@@ -825,7 +850,7 @@ export const identityKubernetesAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -833,12 +858,12 @@ export const identityKubernetesAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -860,7 +885,7 @@ export const identityKubernetesAuthServiceFactory = ({
const revokedIdentityKubernetesAuth = await identityKubernetesAuthDAL.transaction(async (tx) => {
const deletedKubernetesAuth = await identityKubernetesAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.KUBERNETES_AUTH }, tx);
return { ...deletedKubernetesAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedKubernetesAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityKubernetesAuth;
};
@@ -2,7 +2,7 @@
import { ForbiddenError } from "@casl/ability";
import slugify from "@sindresorhus/slugify";
import { IdentityAuthMethod } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod } from "@app/db/schemas";
import { TIdentityAuthTemplateDALFactory } from "@app/ee/services/identity-auth-template";
import { testLDAPConfig } from "@app/ee/services/ldap-config/ldap-fns";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
@@ -32,7 +32,7 @@ import { logger } from "@app/lib/logger";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityDALFactory } from "../identity/identity-dal";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TKmsServiceFactory } from "../kms/kms-service";
@@ -56,7 +56,7 @@ type TIdentityLdapAuthServiceFactoryDep = {
TIdentityLdapAuthDALFactory,
"findOne" | "transaction" | "create" | "updateById" | "delete"
>;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
kmsService: TKmsServiceFactory;
@@ -80,7 +80,7 @@ export const identityLdapAuthServiceFactory = ({
identityAccessTokenDAL,
identityDAL,
identityLdapAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
licenseService,
permissionService,
kmsService,
@@ -92,7 +92,10 @@ export const identityLdapAuthServiceFactory = ({
const identity = await identityDAL.findOne({ id: identityId });
if (!identity) throw new NotFoundError({ message: `Identity with ID '${identityId}' not found` });
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: identity.id });
const identityOrgMembership = await membershipIdentityDAL.findOne({
actorIdentityId: identity.id,
scope: AccessScope.Organization
});
if (!identityOrgMembership) throw new NotFoundError({ message: `Identity with ID '${identityId}' not found` });
const ldapAuth = await identityLdapAuthDAL.findOne({ identityId: identity.id });
@@ -104,7 +107,7 @@ export const identityLdapAuthServiceFactory = ({
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityOrgMembership.orgId
orgId: identityOrgMembership.scopeOrgId
});
const bindDN = decryptor({ cipherTextBlob: ldapAuth.encryptedBindDN }).toString();
@@ -115,7 +118,7 @@ export const identityLdapAuthServiceFactory = ({
const ldapConfig = {
id: ldapAuth.id,
organization: identityOrgMembership.orgId,
organization: identityOrgMembership.scopeOrgId,
url: ldapAuth.url,
bindDN,
bindPass,
@@ -147,7 +150,10 @@ export const identityLdapAuthServiceFactory = ({
};
const login = async ({ identityId }: TLoginLdapAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) {
throw new UnauthorizedError({
@@ -163,7 +169,7 @@ export const identityLdapAuthServiceFactory = ({
});
}
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
if (!plan.ldap) {
throw new BadRequestError({
message:
@@ -172,7 +178,7 @@ export const identityLdapAuthServiceFactory = ({
}
const identityAccessToken = await identityLdapAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.LDAP_AUTH,
@@ -240,7 +246,13 @@ export const identityLdapAuthServiceFactory = ({
}: TAttachLdapAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
@@ -256,7 +268,7 @@ export const identityLdapAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -269,7 +281,7 @@ export const identityLdapAuthServiceFactory = ({
);
}
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
if (!plan.ldap) {
throw new BadRequestError({
@@ -299,11 +311,11 @@ export const identityLdapAuthServiceFactory = ({
const identityLdapAuth = await identityLdapAuthDAL.transaction(async (tx) => {
const { encryptor, decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const template = templateId
? await identityAuthTemplateDAL.findByIdAndOrgId(templateId, identityMembershipOrg.orgId)
? await identityAuthTemplateDAL.findByIdAndOrgId(templateId, identityMembershipOrg.scopeOrgId)
: undefined;
let ldapConfig: { bindDN: string; bindPass: string; searchBase: string; url: string; ldapCaCertificate?: string };
@@ -357,7 +369,7 @@ export const identityLdapAuthServiceFactory = ({
const doc = await identityLdapAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
encryptedBindDN,
encryptedBindPass,
searchBase: ldapConfig.searchBase,
@@ -379,7 +391,7 @@ export const identityLdapAuthServiceFactory = ({
);
return doc;
});
return { ...identityLdapAuth, orgId: identityMembershipOrg.orgId };
return { ...identityLdapAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const updateLdapAuth = async ({
@@ -405,7 +417,13 @@ export const identityLdapAuthServiceFactory = ({
lockoutDurationSeconds,
lockoutCounterResetSeconds
}: TUpdateLdapAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
@@ -426,7 +444,7 @@ export const identityLdapAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -439,7 +457,7 @@ export const identityLdapAuthServiceFactory = ({
);
}
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
if (!plan.ldap) {
throw new BadRequestError({
@@ -468,11 +486,11 @@ export const identityLdapAuthServiceFactory = ({
const { encryptor, decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const template = templateId
? await identityAuthTemplateDAL.findByIdAndOrgId(templateId, identityMembershipOrg.orgId)
? await identityAuthTemplateDAL.findByIdAndOrgId(templateId, identityMembershipOrg.scopeOrgId)
: undefined;
let config: {
bindDN?: string;
@@ -558,11 +576,17 @@ export const identityLdapAuthServiceFactory = ({
lockoutCounterResetSeconds
});
return { ...updatedLdapAuth, orgId: identityMembershipOrg.orgId };
return { ...updatedLdapAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const getLdapAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetLdapAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
@@ -576,14 +600,14 @@ export const identityLdapAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const bindDN = decryptor({ cipherTextBlob: ldapIdentityAuth.encryptedBindDN }).toString();
@@ -593,7 +617,7 @@ export const identityLdapAuthServiceFactory = ({
: undefined;
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...ldapIdentityAuth, orgId: identityMembershipOrg.orgId, bindDN, bindPass, ldapCaCertificate };
return { ...ldapIdentityAuth, orgId: identityMembershipOrg.scopeOrgId, bindDN, bindPass, ldapCaCertificate };
};
const revokeIdentityLdapAuth = async ({
@@ -603,7 +627,13 @@ export const identityLdapAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TRevokeLdapAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
throw new BadRequestError({
@@ -613,7 +643,7 @@ export const identityLdapAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -621,13 +651,13 @@ export const identityLdapAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -651,7 +681,7 @@ export const identityLdapAuthServiceFactory = ({
const [deletedLdapAuth] = await identityLdapAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.LDAP_AUTH }, tx);
return { ...deletedLdapAuth, orgId: identityMembershipOrg.orgId };
return { ...deletedLdapAuth, orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityLdapAuth;
};
@@ -740,7 +770,13 @@ export const identityLdapAuthServiceFactory = ({
actorOrgId,
actorAuthMethod
}: TClearLdapAuthLockoutsDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
@@ -752,7 +788,7 @@ export const identityLdapAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -762,7 +798,7 @@ export const identityLdapAuthServiceFactory = ({
pattern: `lockout:identity:${identityId}:${IdentityAuthMethod.LDAP_AUTH}:*`
});
return { deleted, identityId, orgId: identityMembershipOrg.orgId };
return { deleted, identityId, orgId: identityMembershipOrg.scopeOrgId };
};
return {
@@ -3,7 +3,7 @@ import { ForbiddenError } from "@casl/ability";
import { AxiosError } from "axios";
import RE2 from "re2";
import { IdentityAuthMethod } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import {
@@ -19,7 +19,7 @@ import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { logger } from "@app/lib/logger";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
@@ -37,7 +37,7 @@ import { TOrgDALFactory } from "../org/org-dal";
type TIdentityOciAuthServiceFactoryDep = {
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
identityOciAuthDAL: Pick<TIdentityOciAuthDALFactory, "findOne" | "transaction" | "create" | "updateById" | "delete">;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
orgDAL: Pick<TOrgDALFactory, "findById">;
@@ -48,7 +48,7 @@ export type TIdentityOciAuthServiceFactory = ReturnType<typeof identityOciAuthSe
export const identityOciAuthServiceFactory = ({
identityAccessTokenDAL,
identityOciAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
licenseService,
permissionService,
orgDAL
@@ -59,7 +59,10 @@ export const identityOciAuthServiceFactory = ({
throw new NotFoundError({ message: "OCI auth method not found for identity, did you configure OCI auth?" });
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityOciAuth.identityId });
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityOciAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) throw new UnauthorizedError({ message: "Identity not attached to a organization" });
// Validate OCI host format. Ensures that the host is in "identity.<region>.oraclecloud.com" format.
@@ -95,7 +98,7 @@ export const identityOciAuthServiceFactory = ({
// Generate the token
const identityAccessToken = await identityOciAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.OCI_AUTH,
@@ -157,7 +160,13 @@ export const identityOciAuthServiceFactory = ({
}: TAttachOciAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) {
@@ -173,13 +182,13 @@ export const identityOciAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -200,7 +209,7 @@ export const identityOciAuthServiceFactory = ({
const identityOciAuth = await identityOciAuthDAL.transaction(async (tx) => {
const doc = await identityOciAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
type: "iam",
tenancyOcid,
allowedUsernames,
@@ -213,7 +222,7 @@ export const identityOciAuthServiceFactory = ({
);
return doc;
});
return { ...identityOciAuth, orgId: identityMembershipOrg.orgId };
return { ...identityOciAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const updateOciAuth = async ({
@@ -229,7 +238,13 @@ export const identityOciAuthServiceFactory = ({
actor,
actorOrgId
}: TUpdateOciAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) {
@@ -250,13 +265,13 @@ export const identityOciAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -285,11 +300,17 @@ export const identityOciAuthServiceFactory = ({
: undefined
});
return { ...updatedOciAuth, orgId: identityMembershipOrg.orgId };
return { ...updatedOciAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const getOciAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetOciAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) {
@@ -303,12 +324,12 @@ export const identityOciAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...ociIdentityAuth, orgId: identityMembershipOrg.orgId };
return { ...ociIdentityAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeIdentityOciAuth = async ({
@@ -318,7 +339,13 @@ export const identityOciAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TRevokeOciAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) {
throw new BadRequestError({
@@ -328,7 +355,7 @@ export const identityOciAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -336,8 +363,8 @@ export const identityOciAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -366,7 +393,7 @@ export const identityOciAuthServiceFactory = ({
const deletedOciAuth = await identityOciAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.OCI_AUTH }, tx);
return { ...deletedOciAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedOciAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityOciAuth;
};
@@ -4,7 +4,7 @@ import https from "https";
import jwt from "jsonwebtoken";
import { JwksClient } from "jwks-rsa";
import { IdentityAuthMethod, TIdentityOidcAuthsUpdate } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod, TIdentityOidcAuthsUpdate } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TOrgDALFactory } from "../org/org-dal";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
@@ -26,7 +26,7 @@ import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { getValueByDot } from "@app/lib/template/dot-access";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TKmsServiceFactory } from "../kms/kms-service";
@@ -44,7 +44,7 @@ import {
type TIdentityOidcAuthServiceFactoryDep = {
identityOidcAuthDAL: TIdentityOidcAuthDALFactory;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
@@ -56,7 +56,7 @@ export type TIdentityOidcAuthServiceFactory = ReturnType<typeof identityOidcAuth
export const identityOidcAuthServiceFactory = ({
identityOidcAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
permissionService,
licenseService,
identityAccessTokenDAL,
@@ -69,8 +69,9 @@ export const identityOidcAuthServiceFactory = ({
throw new NotFoundError({ message: "OIDC auth method not found for identity, did you configure OIDC auth?" });
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
identityId: identityOidcAuth.identityId
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityOidcAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) {
throw new NotFoundError({
@@ -80,7 +81,7 @@ export const identityOidcAuthServiceFactory = ({
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
let caCert = "";
@@ -181,7 +182,7 @@ export const identityOidcAuthServiceFactory = ({
}
const identityAccessToken = await identityOidcAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.OIDC_AUTH,
@@ -248,7 +249,13 @@ export const identityOidcAuthServiceFactory = ({
isActorSuperAdmin
}: TAttachOidcAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) {
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
}
@@ -265,14 +272,14 @@ export const identityOidcAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -292,13 +299,13 @@ export const identityOidcAuthServiceFactory = ({
const { encryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const identityOidcAuth = await identityOidcAuthDAL.transaction(async (tx) => {
const doc = await identityOidcAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
oidcDiscoveryUrl,
encryptedCaCertificate: encryptor({ plainText: Buffer.from(caCert) }).cipherTextBlob,
boundIssuer,
@@ -315,7 +322,7 @@ export const identityOidcAuthServiceFactory = ({
);
return doc;
});
return { ...identityOidcAuth, orgId: identityMembershipOrg.orgId, caCert };
return { ...identityOidcAuth, orgId: identityMembershipOrg.scopeOrgId, caCert };
};
const updateOidcAuth = async ({
@@ -336,7 +343,13 @@ export const identityOidcAuthServiceFactory = ({
actor,
actorOrgId
}: TUpdateOidcAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
@@ -357,14 +370,14 @@ export const identityOidcAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -399,7 +412,7 @@ export const identityOidcAuthServiceFactory = ({
const { encryptor, decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
if (caCert !== undefined) {
@@ -413,13 +426,19 @@ export const identityOidcAuthServiceFactory = ({
return {
...updatedOidcAuth,
orgId: identityMembershipOrg.orgId,
orgId: identityMembershipOrg.scopeOrgId,
caCert: updatedCACert
};
};
const getOidcAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetOidcAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
@@ -431,7 +450,7 @@ export const identityOidcAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -441,18 +460,24 @@ export const identityOidcAuthServiceFactory = ({
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const caCert = identityOidcAuth.encryptedCaCertificate
? decryptor({ cipherTextBlob: identityOidcAuth.encryptedCaCertificate }).toString()
: "";
return { ...identityOidcAuth, orgId: identityMembershipOrg.orgId, caCert };
return { ...identityOidcAuth, orgId: identityMembershipOrg.scopeOrgId, caCert };
};
const revokeOidcAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TRevokeOidcAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) {
throw new NotFoundError({ message: "Failed to find identity" });
}
@@ -466,7 +491,7 @@ export const identityOidcAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -475,13 +500,13 @@ export const identityOidcAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -505,7 +530,7 @@ export const identityOidcAuthServiceFactory = ({
const deletedOidcAuth = await identityOidcAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.OIDC_AUTH }, tx);
return { ...deletedOidcAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedOidcAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityOidcAuth;
@@ -1,46 +1,22 @@
import { ForbiddenError, subject } from "@casl/ability";
import { ActionProjectType, ProjectMembershipRole } from "@app/db/schemas";
import {
constructPermissionErrorMessage,
validatePrivilegeChangeOperation
} from "@app/ee/services/permission/permission-fns";
import { AccessScope, ActionProjectType } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionIdentityActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { ms } from "@app/lib/ms";
import { NotFoundError } from "@app/lib/errors";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TOrgDALFactory } from "../org/org-dal";
import { TProjectDALFactory } from "../project/project-dal";
import { ProjectUserMembershipTemporaryMode } from "../project-membership/project-membership-types";
import { TProjectRoleDALFactory } from "../project-role/project-role-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityProjectDALFactory } from "./identity-project-dal";
import { TIdentityProjectMembershipRoleDALFactory } from "./identity-project-membership-role-dal";
import {
TCreateProjectIdentityDTO,
TDeleteProjectIdentityDTO,
TGetProjectIdentityByIdentityIdDTO,
TGetProjectIdentityByMembershipIdDTO,
TListProjectIdentityDTO,
TUpdateProjectIdentityDTO
TListProjectIdentityDTO
} from "./identity-project-types";
type TIdentityProjectServiceFactoryDep = {
identityProjectDAL: TIdentityProjectDALFactory;
orgDAL: Pick<TOrgDALFactory, "findById">;
identityProjectMembershipRoleDAL: Pick<
TIdentityProjectMembershipRoleDALFactory,
"create" | "transaction" | "insertMany" | "delete"
>;
projectDAL: Pick<TProjectDALFactory, "findById">;
projectRoleDAL: Pick<TProjectRoleDALFactory, "find">;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getProjectPermissionByRoles" | "invalidateProjectPermissionCache"
>;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissionByRoles">;
membershipIdentityDAL: TMembershipIdentityDALFactory;
};
export type TIdentityProjectServiceFactory = ReturnType<typeof identityProjectServiceFactory>;
@@ -48,275 +24,8 @@ export type TIdentityProjectServiceFactory = ReturnType<typeof identityProjectSe
export const identityProjectServiceFactory = ({
identityProjectDAL,
permissionService,
identityOrgMembershipDAL,
identityProjectMembershipRoleDAL,
projectDAL,
projectRoleDAL,
orgDAL
membershipIdentityDAL
}: TIdentityProjectServiceFactoryDep) => {
const createProjectIdentity = async ({
identityId,
actor,
actorId,
actorOrgId,
actorAuthMethod,
projectId,
roles
}: TCreateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId,
actionProjectType: ActionProjectType.Any
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Create,
subject(ProjectPermissionSub.Identity, {
identityId
})
);
const existingIdentity = await identityProjectDAL.findOne({ identityId, projectId });
if (existingIdentity)
throw new BadRequestError({
message: `Identity with ID ${identityId} already exists in project with ID ${projectId}`
});
const project = await projectDAL.findById(projectId);
const identityOrgMembership = await identityOrgMembershipDAL.findOne({
identityId,
orgId: project.orgId
});
if (!identityOrgMembership)
throw new NotFoundError({
message: `Failed to find identity with ID ${identityId}`
});
const providedRolePermissionDetails = await permissionService.getProjectPermissionByRoles(
roles.map((el) => el.role).filter((el) => el !== ProjectMembershipRole.NoAccess),
projectId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(actorOrgId);
for await (const { permission: rolePermission } of providedRolePermissionDetails) {
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to assign to role",
shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
// validate custom roles input
const customInputRoles = roles.filter(
({ role }) => !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole)
);
const hasCustomRole = Boolean(customInputRoles.length);
const customRoles = hasCustomRole
? await projectRoleDAL.find({
projectId,
$in: { slug: customInputRoles.map(({ role }) => role) }
})
: [];
if (customRoles.length !== customInputRoles.length)
throw new NotFoundError({ message: "One or more custom project roles not found" });
const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug);
const projectIdentity = await identityProjectDAL.transaction(async (tx) => {
const identityProjectMembership = await identityProjectDAL.create(
{
identityId,
projectId: project.id
},
tx
);
const sanitizedProjectMembershipRoles = roles.map((inputRole) => {
const isCustomRole = Boolean(customRolesGroupBySlug?.[inputRole.role]?.[0]);
if (!inputRole.isTemporary) {
return {
projectMembershipId: identityProjectMembership.id,
role: isCustomRole ? ProjectMembershipRole.Custom : inputRole.role,
customRoleId: customRolesGroupBySlug[inputRole.role] ? customRolesGroupBySlug[inputRole.role][0].id : null
};
}
// check cron or relative here later for now its just relative
const relativeTimeInMs = ms(inputRole.temporaryRange);
return {
projectMembershipId: identityProjectMembership.id,
role: isCustomRole ? ProjectMembershipRole.Custom : inputRole.role,
customRoleId: customRolesGroupBySlug[inputRole.role] ? customRolesGroupBySlug[inputRole.role][0].id : null,
isTemporary: true,
temporaryMode: ProjectUserMembershipTemporaryMode.Relative,
temporaryRange: inputRole.temporaryRange,
temporaryAccessStartTime: new Date(inputRole.temporaryAccessStartTime),
temporaryAccessEndTime: new Date(new Date(inputRole.temporaryAccessStartTime).getTime() + relativeTimeInMs)
};
});
const identityRoles = await identityProjectMembershipRoleDAL.insertMany(sanitizedProjectMembershipRoles, tx);
return { ...identityProjectMembership, roles: identityRoles };
});
await permissionService.invalidateProjectPermissionCache(projectId);
return projectIdentity;
};
const updateProjectIdentity = async ({
projectId,
identityId,
roles,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TUpdateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId,
actionProjectType: ActionProjectType.Any
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Edit,
subject(ProjectPermissionSub.Identity, { identityId })
);
const projectIdentity = await identityProjectDAL.findOne({ identityId, projectId });
if (!projectIdentity)
throw new NotFoundError({
message: `Identity with ID ${identityId} doesn't exists in project with ID ${projectId}`
});
const providedRolePermissionDetails = await permissionService.getProjectPermissionByRoles(
roles.map((el) => el.role).filter((el) => el !== ProjectMembershipRole.NoAccess),
projectId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(actorOrgId);
for await (const { permission: rolePermission } of providedRolePermissionDetails) {
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to change role",
shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
// validate custom roles input
const customInputRoles = roles.filter(
({ role }) =>
!Object.values(ProjectMembershipRole)
// we don't want to include custom in this check;
// this unintentionally enables setting slug to custom which is reserved
.filter((r) => r !== ProjectMembershipRole.Custom)
.includes(role as ProjectMembershipRole.Admin)
);
const hasCustomRole = Boolean(customInputRoles.length);
const customRoles = hasCustomRole
? await projectRoleDAL.find({
projectId,
$in: { slug: customInputRoles.map(({ role }) => role) }
})
: [];
if (customRoles.length !== customInputRoles.length)
throw new NotFoundError({ message: "One or more custom project roles not found" });
const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug);
const sanitizedProjectMembershipRoles = roles.map((inputRole) => {
const isCustomRole = Boolean(customRolesGroupBySlug?.[inputRole.role]?.[0]);
if (!inputRole.isTemporary) {
return {
projectMembershipId: projectIdentity.id,
role: isCustomRole ? ProjectMembershipRole.Custom : inputRole.role,
customRoleId: customRolesGroupBySlug[inputRole.role] ? customRolesGroupBySlug[inputRole.role][0].id : null
};
}
// check cron or relative here later for now its just relative
const relativeTimeInMs = ms(inputRole.temporaryRange);
return {
projectMembershipId: projectIdentity.id,
role: isCustomRole ? ProjectMembershipRole.Custom : inputRole.role,
customRoleId: customRolesGroupBySlug[inputRole.role] ? customRolesGroupBySlug[inputRole.role][0].id : null,
isTemporary: true,
temporaryMode: ProjectUserMembershipTemporaryMode.Relative,
temporaryRange: inputRole.temporaryRange,
temporaryAccessStartTime: new Date(inputRole.temporaryAccessStartTime),
temporaryAccessEndTime: new Date(new Date(inputRole.temporaryAccessStartTime).getTime() + relativeTimeInMs)
};
});
const updatedRoles = await identityProjectMembershipRoleDAL.transaction(async (tx) => {
await identityProjectMembershipRoleDAL.delete({ projectMembershipId: projectIdentity.id }, tx);
return identityProjectMembershipRoleDAL.insertMany(sanitizedProjectMembershipRoles, tx);
});
await permissionService.invalidateProjectPermissionCache(projectId);
return updatedRoles;
};
const deleteProjectIdentity = async ({
identityId,
actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId
}: TDeleteProjectIdentityDTO) => {
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
if (!identityProjectMembership) {
throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
}
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId,
actionProjectType: ActionProjectType.Any
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Delete,
subject(ProjectPermissionSub.Identity, { identityId })
);
const [deletedIdentity] = await identityProjectDAL.delete({ identityId, projectId });
await permissionService.invalidateProjectPermissionCache(projectId);
return deletedIdentity;
};
const listProjectIdentities = async ({
projectId,
actor,
@@ -392,9 +101,13 @@ export const identityProjectServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TGetProjectIdentityByMembershipIdDTO) => {
const membership = await identityProjectDAL.findOne({ id: identityMembershipId });
const membership = await membershipIdentityDAL.findOne({
id: identityMembershipId,
scope: AccessScope.Project,
scopeOrgId: actorOrgId
});
if (!membership) {
if (!membership || !membership.scopeProjectId || !membership.actorIdentityId) {
throw new NotFoundError({
message: `Project membership with ID '${identityMembershipId}' not found`
});
@@ -403,7 +116,7 @@ export const identityProjectServiceFactory = ({
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId: membership.projectId,
projectId: membership.scopeProjectId,
actorAuthMethod,
actorOrgId,
actionProjectType: ActionProjectType.Any
@@ -411,20 +124,17 @@ export const identityProjectServiceFactory = ({
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Read,
subject(ProjectPermissionSub.Identity, { identityId: membership.identityId })
subject(ProjectPermissionSub.Identity, { identityId: membership.actorIdentityId })
);
const [identityMembership] = await identityProjectDAL.findByProjectId(membership.projectId, {
identityId: membership.identityId
const [identityMembership] = await identityProjectDAL.findByProjectId(membership.scopeProjectId, {
identityId: membership.actorIdentityId
});
return identityMembership;
};
return {
createProjectIdentity,
updateProjectIdentity,
deleteProjectIdentity,
listProjectIdentities,
getProjectIdentityByIdentityId,
getProjectIdentityByMembershipId
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability";
import { IdentityAuthMethod } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TOrgDALFactory } from "../org/org-dal";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
@@ -16,7 +16,7 @@ import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedEr
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TKmsServiceFactory } from "../kms/kms-service";
@@ -31,7 +31,7 @@ type TIdentityTlsCertAuthServiceFactoryDep = {
TIdentityTlsCertAuthDALFactory,
"findOne" | "transaction" | "create" | "updateById" | "delete"
>;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
@@ -50,7 +50,7 @@ const parseSubjectDetails = (data: string) => {
export const identityTlsCertAuthServiceFactory = ({
identityAccessTokenDAL,
identityTlsCertAuthDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
licenseService,
permissionService,
kmsService,
@@ -64,8 +64,9 @@ export const identityTlsCertAuthServiceFactory = ({
});
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
identityId: identityTlsCertAuth.identityId
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityTlsCertAuth.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) {
@@ -76,7 +77,7 @@ export const identityTlsCertAuthServiceFactory = ({
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const caCertificate = decryptor({
@@ -121,7 +122,7 @@ export const identityTlsCertAuthServiceFactory = ({
// Generate the token
const identityAccessToken = await identityTlsCertAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.TLS_CERT_AUTH,
@@ -183,7 +184,13 @@ export const identityTlsCertAuthServiceFactory = ({
}) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
@@ -199,13 +206,13 @@ export const identityTlsCertAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -225,13 +232,13 @@ export const identityTlsCertAuthServiceFactory = ({
const { encryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const identityTlsCertAuth = await identityTlsCertAuthDAL.transaction(async (tx) => {
const doc = await identityTlsCertAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
accessTokenMaxTTL,
allowedCommonNames,
accessTokenTTL,
@@ -243,7 +250,7 @@ export const identityTlsCertAuthServiceFactory = ({
);
return doc;
});
return { ...identityTlsCertAuth, orgId: identityMembershipOrg.orgId };
return { ...identityTlsCertAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const updateTlsCertAuth: TIdentityTlsCertAuthServiceFactory["updateTlsCertAuth"] = async ({
@@ -259,7 +266,13 @@ export const identityTlsCertAuthServiceFactory = ({
actor,
actorOrgId
}) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
@@ -281,13 +294,13 @@ export const identityTlsCertAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -306,7 +319,7 @@ export const identityTlsCertAuthServiceFactory = ({
});
const { encryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
const updatedTlsCertAuth = await identityTlsCertAuthDAL.updateById(identityTlsCertAuth.id, {
@@ -322,7 +335,7 @@ export const identityTlsCertAuthServiceFactory = ({
: undefined
});
return { ...updatedTlsCertAuth, orgId: identityMembershipOrg.orgId };
return { ...updatedTlsCertAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const getTlsCertAuth: TIdentityTlsCertAuthServiceFactory["getTlsCertAuth"] = async ({
@@ -332,7 +345,13 @@ export const identityTlsCertAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
@@ -346,21 +365,21 @@ export const identityTlsCertAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
});
let caCertificate = "";
if (identityAuth.encryptedCaCertificate) {
caCertificate = decryptor({ cipherTextBlob: identityAuth.encryptedCaCertificate }).toString();
}
return { ...identityAuth, caCertificate, orgId: identityMembershipOrg.orgId };
return { ...identityAuth, caCertificate, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeTlsCertAuth: TIdentityTlsCertAuthServiceFactory["revokeTlsCertAuth"] = async ({
@@ -370,7 +389,13 @@ export const identityTlsCertAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
}) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new BadRequestError({
@@ -380,7 +405,7 @@ export const identityTlsCertAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -388,13 +413,13 @@ export const identityTlsCertAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -418,7 +443,7 @@ export const identityTlsCertAuthServiceFactory = ({
const deletedTlsCertAuth = await identityTlsCertAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.TLS_CERT_AUTH }, tx);
return { ...deletedTlsCertAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedTlsCertAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityTlsCertAuth;
};
@@ -1,4 +1,4 @@
import { TIdentityAccessTokens, TIdentityOrgMemberships, TIdentityTlsCertAuths } from "@app/db/schemas";
import { TIdentityAccessTokens, TMemberships, TIdentityTlsCertAuths } from "@app/db/schemas";
import { TProjectPermission } from "@app/lib/types";
export type TLoginTlsCertAuthDTO = {
@@ -40,7 +40,7 @@ export type TIdentityTlsCertAuthServiceFactory = {
identityTlsCertAuth: TIdentityTlsCertAuths;
accessToken: string;
identityAccessToken: TIdentityAccessTokens;
identityMembershipOrg: TIdentityOrgMemberships;
identityMembershipOrg: TMemberships;
}>;
attachTlsCertAuth: (dto: TAttachTlsCertAuthDTO) => Promise<TIdentityTlsCertAuths>;
updateTlsCertAuth: (dto: TUpdateTlsCertAuthDTO) => Promise<TIdentityTlsCertAuths>;
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability";
import { IdentityAuthMethod, TableName } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod, TableName } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TOrgDALFactory } from "../org/org-dal";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
@@ -15,7 +15,7 @@ import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/li
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
@@ -36,7 +36,7 @@ type TIdentityTokenAuthServiceFactoryDep = {
TIdentityTokenAuthDALFactory,
"transaction" | "create" | "findOne" | "updateById" | "delete"
>;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "updateById">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "findOne" | "updateById" | "getIdentityById">;
identityAccessTokenDAL: Pick<
TIdentityAccessTokenDALFactory,
"create" | "find" | "update" | "findById" | "findOne" | "updateById" | "delete"
@@ -51,7 +51,7 @@ export type TIdentityTokenAuthServiceFactory = ReturnType<typeof identityTokenAu
export const identityTokenAuthServiceFactory = ({
identityTokenAuthDAL,
// identityDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
identityAccessTokenDAL,
permissionService,
licenseService,
@@ -71,7 +71,13 @@ export const identityTokenAuthServiceFactory = ({
}: TAttachTokenAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
@@ -87,13 +93,13 @@ export const identityTokenAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -114,7 +120,7 @@ export const identityTokenAuthServiceFactory = ({
const identityTokenAuth = await identityTokenAuthDAL.transaction(async (tx) => {
const doc = await identityTokenAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
accessTokenMaxTTL,
accessTokenTTL,
accessTokenNumUsesLimit,
@@ -124,7 +130,7 @@ export const identityTokenAuthServiceFactory = ({
);
return doc;
});
return { ...identityTokenAuth, orgId: identityMembershipOrg.orgId };
return { ...identityTokenAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const updateTokenAuth = async ({
@@ -141,7 +147,13 @@ export const identityTokenAuthServiceFactory = ({
}: TUpdateTokenAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
@@ -163,13 +175,13 @@ export const identityTokenAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -198,12 +210,18 @@ export const identityTokenAuthServiceFactory = ({
return {
...updatedTokenAuth,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
};
};
const getTokenAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetTokenAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
@@ -217,13 +235,13 @@ export const identityTokenAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...identityTokenAuth, orgId: identityMembershipOrg.orgId };
return { ...identityTokenAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeIdentityTokenAuth = async ({
@@ -236,7 +254,13 @@ export const identityTokenAuthServiceFactory = ({
}: TRevokeTokenAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
@@ -247,7 +271,7 @@ export const identityTokenAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -255,13 +279,13 @@ export const identityTokenAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -287,7 +311,7 @@ export const identityTokenAuthServiceFactory = ({
authMethod: IdentityAuthMethod.TOKEN_AUTH
});
return { ...deletedTokenAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedTokenAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityTokenAuth;
};
@@ -303,7 +327,13 @@ export const identityTokenAuthServiceFactory = ({
}: TCreateTokenAuthTokenDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
@@ -314,7 +344,7 @@ export const identityTokenAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -322,13 +352,13 @@ export const identityTokenAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.CreateToken,
@@ -350,7 +380,7 @@ export const identityTokenAuthServiceFactory = ({
const identityTokenAuth = await identityTokenAuthDAL.findOne({ identityId });
const identityAccessToken = await identityTokenAuthDAL.transaction(async (tx) => {
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.TOKEN_AUTH,
@@ -405,7 +435,13 @@ export const identityTokenAuthServiceFactory = ({
}: TGetTokenAuthTokensDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
@@ -416,7 +452,7 @@ export const identityTokenAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -448,7 +484,13 @@ export const identityTokenAuthServiceFactory = ({
});
if (!foundToken) throw new NotFoundError({ message: `Token with ID ${tokenId} not found` });
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: foundToken.identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId: foundToken.identityId
});
if (!identityMembershipOrg) {
throw new NotFoundError({ message: `Failed to find identity with ID ${foundToken.identityId}` });
}
@@ -462,7 +504,7 @@ export const identityTokenAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -470,12 +512,12 @@ export const identityTokenAuthServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.CreateToken,
@@ -529,8 +571,9 @@ export const identityTokenAuthServiceFactory = ({
await validateIdentityUpdateForSuperAdminPrivileges(identityAccessToken.identityId, isActorSuperAdmin);
const identityOrgMembership = await identityOrgMembershipDAL.findOne({
identityId: identityAccessToken.identityId
const identityOrgMembership = await membershipIdentityDAL.findOne({
actorIdentityId: identityAccessToken.identityId,
scope: AccessScope.Organization
});
if (!identityOrgMembership) {
@@ -540,7 +583,7 @@ export const identityTokenAuthServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityOrgMembership.orgId,
identityOrgMembership.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability";
import { IdentityAuthMethod } from "@app/db/schemas";
import { AccessScope, IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import {
@@ -22,9 +22,9 @@ import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr, TIp } from
import { logger } from "@app/lib/logger";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TOrgDALFactory } from "../org/org-dal";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
import { TIdentityUaClientSecretDALFactory } from "./identity-ua-client-secret-dal";
@@ -45,7 +45,7 @@ type TIdentityUaServiceFactoryDep = {
identityUaDAL: TIdentityUaDALFactory;
identityUaClientSecretDAL: TIdentityUaClientSecretDALFactory;
identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
identityOrgMembershipDAL: TIdentityOrgDALFactory;
membershipIdentityDAL: TMembershipIdentityDALFactory;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
orgDAL: Pick<TOrgDALFactory, "findById">;
@@ -66,7 +66,7 @@ export const identityUaServiceFactory = ({
identityUaDAL,
identityUaClientSecretDAL,
identityAccessTokenDAL,
identityOrgMembershipDAL,
membershipIdentityDAL,
permissionService,
licenseService,
orgDAL,
@@ -100,7 +100,10 @@ export const identityUaServiceFactory = ({
});
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: identityUa.identityId });
const identityMembershipOrg = await membershipIdentityDAL.findOne({
actorIdentityId: identityUa.identityId,
scope: AccessScope.Organization
});
if (!identityMembershipOrg) {
throw new UnauthorizedError({
message: "Invalid credentials"
@@ -226,7 +229,7 @@ export const identityUaServiceFactory = ({
const identityAccessToken = await identityUaDAL.transaction(async (tx) => {
const uaClientSecretDoc = await identityUaClientSecretDAL.incrementUsage(validClientSecretInfo!.id, tx);
await identityOrgMembershipDAL.updateById(
await membershipIdentityDAL.updateById(
identityMembershipOrg.id,
{
lastLoginAuthMethod: IdentityAuthMethod.UNIVERSAL_AUTH,
@@ -298,7 +301,13 @@ export const identityUaServiceFactory = ({
}: TAttachUaDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
@@ -314,13 +323,13 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -357,7 +366,7 @@ export const identityUaServiceFactory = ({
const identityUa = await identityUaDAL.transaction(async (tx) => {
const doc = await identityUaDAL.create(
{
identityId: identityMembershipOrg.identityId,
identityId: identityMembershipOrg.identity.id,
clientId: crypto.nativeCrypto.randomUUID(),
clientSecretTrustedIps: JSON.stringify(reformattedClientSecretTrustedIps),
accessTokenMaxTTL,
@@ -374,7 +383,7 @@ export const identityUaServiceFactory = ({
);
return doc;
});
return { ...identityUa, orgId: identityMembershipOrg.orgId };
return { ...identityUa, orgId: identityMembershipOrg.scopeOrgId };
};
const updateUniversalAuth = async ({
@@ -394,7 +403,13 @@ export const identityUaServiceFactory = ({
lockoutDurationSeconds,
lockoutCounterResetSeconds
}: TUpdateUaDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
const uaIdentityAuth = await identityUaDAL.findOne({ identityId });
@@ -418,13 +433,13 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const plan = await licenseService.getPlan(identityMembershipOrg.scopeOrgId);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps?.map((clientSecretTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -474,11 +489,17 @@ export const identityUaServiceFactory = ({
lockoutDurationSeconds,
lockoutCounterResetSeconds
});
return { ...updatedUaAuth, orgId: identityMembershipOrg.orgId };
return { ...updatedUaAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const getIdentityUniversalAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetUaDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
const uaIdentityAuth = await identityUaDAL.findOne({ identityId });
@@ -495,12 +516,12 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...uaIdentityAuth, orgId: identityMembershipOrg.orgId };
return { ...uaIdentityAuth, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeIdentityUniversalAuth = async ({
@@ -510,7 +531,13 @@ export const identityUaServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TRevokeUaDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
@@ -521,7 +548,7 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -529,12 +556,12 @@ export const identityUaServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
@@ -555,7 +582,7 @@ export const identityUaServiceFactory = ({
const revokedIdentityUniversalAuth = await identityUaDAL.transaction(async (tx) => {
const deletedUniversalAuth = await identityUaDAL.delete({ identityId }, tx);
return { ...deletedUniversalAuth?.[0], orgId: identityMembershipOrg.orgId };
return { ...deletedUniversalAuth?.[0], orgId: identityMembershipOrg.scopeOrgId };
});
return revokedIdentityUniversalAuth;
};
@@ -570,7 +597,13 @@ export const identityUaServiceFactory = ({
description,
numUsesLimit
}: TCreateUaClientSecretDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
@@ -582,7 +615,7 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -590,12 +623,12 @@ export const identityUaServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.CreateToken,
@@ -618,7 +651,7 @@ export const identityUaServiceFactory = ({
const clientSecret = crypto.randomBytes(32).toString("hex");
const clientSecretHash = await crypto.hashing().createHash(clientSecret, appCfg.SALT_ROUNDS);
const identityUaAuth = await identityUaDAL.findOne({ identityId: identityMembershipOrg.identityId });
const identityUaAuth = await identityUaDAL.findOne({ identityId: identityMembershipOrg.identity.id });
if (!identityUaAuth) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
const identityUaClientSecret = await identityUaClientSecretDAL.create({
@@ -634,7 +667,7 @@ export const identityUaServiceFactory = ({
return {
clientSecret,
clientSecretData: identityUaClientSecret,
orgId: identityMembershipOrg.orgId
orgId: identityMembershipOrg.scopeOrgId
};
};
@@ -645,7 +678,13 @@ export const identityUaServiceFactory = ({
actorAuthMethod,
identityId
}: TGetUaClientSecretsDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
@@ -656,7 +695,7 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -664,13 +703,13 @@ export const identityUaServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.GetToken,
@@ -697,7 +736,7 @@ export const identityUaServiceFactory = ({
identityUAId: identityUniversalAuth.id,
isClientSecretRevoked: false
});
return { clientSecrets, orgId: identityMembershipOrg.orgId };
return { clientSecrets, orgId: identityMembershipOrg.scopeOrgId };
};
const getUniversalAuthClientSecretById = async ({
@@ -708,7 +747,13 @@ export const identityUaServiceFactory = ({
actorAuthMethod,
clientSecretId
}: TGetUniversalAuthClientSecretByIdDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
@@ -726,7 +771,7 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -734,12 +779,12 @@ export const identityUaServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.GetToken,
@@ -758,7 +803,7 @@ export const identityUaServiceFactory = ({
details: { missingPermissions: permissionBoundary.missingPermissions }
});
return { ...clientSecret, identityId, orgId: identityMembershipOrg.orgId };
return { ...clientSecret, identityId, orgId: identityMembershipOrg.scopeOrgId };
};
const revokeUniversalAuthClientSecret = async ({
@@ -769,7 +814,13 @@ export const identityUaServiceFactory = ({
actorAuthMethod,
clientSecretId
}: TRevokeUaClientSecretDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
@@ -787,7 +838,7 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -795,13 +846,13 @@ export const identityUaServiceFactory = ({
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
identityMembershipOrg.identity.id,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.orgId);
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(identityMembershipOrg.scopeOrgId);
const permissionBoundary = validatePrivilegeChangeOperation(
shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.DeleteToken,
@@ -825,7 +876,7 @@ export const identityUaServiceFactory = ({
isClientSecretRevoked: true
});
return { ...updatedClientSecret, identityId, orgId: identityMembershipOrg.orgId };
return { ...updatedClientSecret, identityId, orgId: identityMembershipOrg.scopeOrgId };
};
const clearUniversalAuthLockouts = async ({
@@ -835,7 +886,13 @@ export const identityUaServiceFactory = ({
actorOrgId,
actorAuthMethod
}: TClearUaLockoutsDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
const identityMembershipOrg = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId
});
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
@@ -847,7 +904,7 @@ export const identityUaServiceFactory = ({
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
identityMembershipOrg.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -857,7 +914,7 @@ export const identityUaServiceFactory = ({
pattern: `lockout:identity:${identityId}:${IdentityAuthMethod.UNIVERSAL_AUTH}:*`
});
return { deleted, identityId, orgId: identityMembershipOrg.orgId };
return { deleted, identityId, orgId: identityMembershipOrg.scopeOrgId };
};
return {
@@ -608,7 +608,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
}
: undefined,
identity: {
id: identityId,
id: identityId as string,
name: identityName,
hasDeleteProtection,
authMethods: buildAuthMethods({
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability";
import { OrgMembershipRole, TableName, TRoles } from "@app/db/schemas";
import { AccessScope, OrgMembershipRole, TableName, TRoles } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import {
@@ -26,11 +26,15 @@ import {
TSearchOrgIdentitiesByOrgIdDTO,
TUpdateIdentityDTO
} from "./identity-types";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
type TIdentityServiceFactoryDep = {
identityDAL: TIdentityDALFactory;
identityMetadataDAL: TIdentityMetadataDALFactory;
identityOrgMembershipDAL: TIdentityOrgDALFactory;
membershipIdentityDAL: TMembershipIdentityDALFactory;
membershipRoleDAL: TMembershipRoleDALFactory;
identityProjectDAL: Pick<TIdentityProjectDALFactory, "findByIdentityId">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission" | "getOrgPermissionByRoles">;
licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">;
@@ -48,7 +52,9 @@ export const identityServiceFactory = ({
permissionService,
licenseService,
keyStore,
orgDAL
orgDAL,
membershipIdentityDAL,
membershipRoleDAL
}: TIdentityServiceFactoryDep) => {
const createIdentity = async ({
name,
@@ -99,12 +105,20 @@ export const identityServiceFactory = ({
const identity = await identityDAL.transaction(async (tx) => {
const newIdentity = await identityDAL.create({ name, hasDeleteProtection }, tx);
await identityOrgMembershipDAL.create(
const membership = await membershipIdentityDAL.create(
{
identityId: newIdentity.id,
orgId,
scope: AccessScope.Organization,
actorIdentityId: newIdentity.id,
scopeOrgId: orgId
},
tx
);
await membershipRoleDAL.create(
{
membershipId: membership.id,
role: isCustomRole ? OrgMembershipRole.Custom : role,
roleId: rolePermissionDetails?.role?.id
customRoleId: rolePermissionDetails?.role?.id
},
tx
);
@@ -151,13 +165,17 @@ export const identityServiceFactory = ({
}: TUpdateIdentityDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(id, isActorSuperAdmin);
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
const identityOrgMembership = await membershipIdentityDAL.findOne({
actorIdentityId: id,
scope: AccessScope.Organization,
scopeOrgId: actorOrgId
});
if (!identityOrgMembership) throw new NotFoundError({ message: `Failed to find identity with id ${id}` });
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityOrgMembership.orgId,
identityOrgMembership.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -197,11 +215,14 @@ export const identityServiceFactory = ({
: await identityDAL.findById(id, tx);
if (role) {
await identityOrgMembershipDAL.updateById(
identityOrgMembership.id,
await membershipRoleDAL.delete({ membershipId: identityOrgMembership.id }, tx);
await membershipRoleDAL.update(
{
membershipId: identityOrgMembership.id
},
{
role: customRole ? OrgMembershipRole.Custom : role,
roleId: customRole?.id || null
customRoleId: customRole?.id || null
},
tx
);
@@ -213,12 +234,12 @@ export const identityServiceFactory = ({
}> = [];
if (metadata) {
await identityMetadataDAL.delete({ orgId: identityOrgMembership.orgId, identityId: id }, tx);
await identityMetadataDAL.delete({ orgId: identityOrgMembership.scopeOrgId, identityId: id }, tx);
if (metadata.length) {
const rowsToInsert = metadata.map(({ key, value }) => ({
identityId: newIdentity.id,
orgId: identityOrgMembership.orgId,
orgId: identityOrgMembership.scopeOrgId,
key,
value
}));
@@ -233,12 +254,14 @@ export const identityServiceFactory = ({
};
});
return { ...identity, orgId: identityOrgMembership.orgId };
return { ...identity, orgId: identityOrgMembership.scopeOrgId };
};
const getIdentityById = async ({ id, actor, actorId, actorOrgId, actorAuthMethod }: TGetIdentityByIdDTO) => {
const doc = await identityOrgMembershipDAL.find({
[`${TableName.IdentityOrgMembership}.identityId` as "identityId"]: id
[`${TableName.Membership}.actorIdentityId` as "actorIdentityId"]: id,
scope: AccessScope.Organization,
scopeOrgId: actorOrgId
});
const identity = doc[0];
if (!identity) throw new NotFoundError({ message: `Failed to find identity with id ${id}` });
@@ -252,6 +275,7 @@ export const identityServiceFactory = ({
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
// TODO(simp): check this in identity service
const activeLockouts = await keyStore.getKeysByPattern(`lockout:identity:${id}:*`);
const activeLockoutAuthMethods = new Set<string>();
@@ -283,14 +307,19 @@ export const identityServiceFactory = ({
isActorSuperAdmin
}: TDeleteIdentityDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(id, isActorSuperAdmin);
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
const identityOrgMembership = await membershipIdentityDAL.getIdentityById({
scopeData: {
scope: AccessScope.Organization,
orgId: actorOrgId
},
identityId: id
});
if (!identityOrgMembership) throw new NotFoundError({ message: `Failed to find identity with id ${id}` });
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityOrgMembership.orgId,
identityOrgMembership.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -302,9 +331,9 @@ export const identityServiceFactory = ({
const deletedIdentity = await identityDAL.deleteById(id);
await licenseService.updateSubscriptionOrgMemberCount(identityOrgMembership.orgId);
await licenseService.updateSubscriptionOrgMemberCount(identityOrgMembership.scopeOrgId);
return { ...deletedIdentity, orgId: identityOrgMembership.orgId };
return { ...deletedIdentity, orgId: identityOrgMembership.scopeOrgId };
};
const listOrgIdentities = async ({
@@ -323,7 +352,8 @@ export const identityServiceFactory = ({
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
const identityMemberships = await identityOrgMembershipDAL.find({
[`${TableName.IdentityOrgMembership}.orgId` as "orgId"]: orgId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
scope: AccessScope.Organization,
limit,
offset,
orderBy,
@@ -332,7 +362,7 @@ export const identityServiceFactory = ({
});
const totalCount = await identityOrgMembershipDAL.countAllOrgIdentities({
[`${TableName.IdentityOrgMembership}.orgId` as "orgId"]: orgId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
search
});
@@ -373,13 +403,17 @@ export const identityServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TListProjectIdentitiesByIdentityIdDTO) => {
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId });
const identityOrgMembership = await membershipIdentityDAL.findOne({
actorIdentityId: identityId,
scope: AccessScope.Organization,
scopeOrgId: actorOrgId
});
if (!identityOrgMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` });
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityOrgMembership.orgId,
identityOrgMembership.scopeOrgId,
actorAuthMethod,
actorOrgId
);
@@ -269,7 +269,7 @@ export const membershipGroupServiceFactory = ({
[SearchResourceOperators.$contains]: dto.data.groupName
}
: undefined,
role: dto.data.roles.length
role: dto.data.roles?.length
? {
[SearchResourceOperators.$in]: dto.data.roles
}
@@ -1,26 +1,25 @@
import { ForbiddenError } from "@casl/ability";
import { ProjectMembershipRole, ProjectVersion } from "@app/db/schemas";
import { AccessScope, ProjectMembershipRole, ProjectVersion } from "@app/db/schemas";
import { OrgPermissionAdminConsoleAction, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal";
import { TNotificationServiceFactory } from "../notification/notification-service";
import { NotificationType } from "../notification/notification-types";
import { TProjectDALFactory } from "../project/project-dal";
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
import { TProjectUserMembershipRoleDALFactory } from "../project-membership/project-user-membership-role-dal";
import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service";
import { TAccessProjectDTO, TListOrgProjectsDTO } from "./org-admin-types";
type TOrgAdminServiceFactoryDep = {
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
projectDAL: Pick<TProjectDALFactory, "find" | "findById" | "findProjectGhostUser" | "findOne">;
projectMembershipDAL: Pick<
TProjectMembershipDALFactory,
"findOne" | "create" | "transaction" | "delete" | "findAllProjectMembers"
>;
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create" | "delete">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findAllProjectMembers">;
membershipUserDAL: TMembershipUserDALFactory;
membershipRoleDAL: TMembershipRoleDALFactory;
smtpService: Pick<TSmtpService, "sendMail">;
notificationService: Pick<TNotificationServiceFactory, "createUserNotifications">;
};
@@ -31,9 +30,10 @@ export const orgAdminServiceFactory = ({
permissionService,
projectDAL,
projectMembershipDAL,
projectUserMembershipRoleDAL,
smtpService,
notificationService
notificationService,
membershipUserDAL,
membershipRoleDAL
}: TOrgAdminServiceFactoryDep) => {
const listOrgProjects = async ({
actor,
@@ -98,17 +98,18 @@ export const orgAdminServiceFactory = ({
}
// check already there exist a membership if there return it
const projectMembership = await projectMembershipDAL.findOne({
projectId,
userId: actorId
const projectMembership = await membershipUserDAL.findOne({
scopeProjectId: projectId,
scope: AccessScope.Project,
actorUserId: actorId
});
if (projectMembership) {
// reset and make the user admin
await projectMembershipDAL.transaction(async (tx) => {
await projectUserMembershipRoleDAL.delete({ projectMembershipId: projectMembership.id }, tx);
await projectUserMembershipRoleDAL.create(
await membershipUserDAL.transaction(async (tx) => {
await membershipRoleDAL.delete({ membershipId: projectMembership.id }, tx);
await membershipRoleDAL.create(
{
projectMembershipId: projectMembership.id,
membershipId: projectMembership.id,
role: ProjectMembershipRole.Admin
},
tx
@@ -117,18 +118,16 @@ export const orgAdminServiceFactory = ({
return { isExistingMember: true, membership: projectMembership };
}
const updatedMembership = await projectMembershipDAL.transaction(async (tx) => {
const newProjectMembership = await projectMembershipDAL.create(
const updatedMembership = await membershipUserDAL.transaction(async (tx) => {
const newProjectMembership = await membershipUserDAL.create(
{
projectId,
userId: actorId
scopeProjectId: projectId,
actorUserId: actorId,
scope: AccessScope.Project
},
tx
);
await projectUserMembershipRoleDAL.create(
{ projectMembershipId: newProjectMembership.id, role: ProjectMembershipRole.Admin },
tx
);
await membershipRoleDAL.create({ membershipId: newProjectMembership.id, role: ProjectMembershipRole.Admin }, tx);
return newProjectMembership;
});
@@ -15,7 +15,6 @@ import { TExternalGroupOrgRoleMappingDALFactory } from "@app/services/external-g
import { TOrgDALFactory } from "@app/services/org/org-dal";
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
import { TOrgRoleDALFactory } from "./org-role-dal";
type TOrgRoleServiceFactoryDep = {
orgRoleDAL: TOrgRoleDALFactory;
+131 -71
View File
@@ -3,6 +3,7 @@ import slugify from "@sindresorhus/slugify";
import { Knex } from "knex";
import {
AccessScope,
ActionProjectType,
OrgMembershipRole,
OrgMembershipStatus,
@@ -31,7 +32,6 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionMemberActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { TProjectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
import { TSamlConfigDALFactory } from "@app/ee/services/saml-config/saml-config-dal";
import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto/cryptography";
@@ -59,13 +59,14 @@ import { ActorAuthMethod, ActorType, AuthMethod, AuthModeJwtTokenPayload, AuthTo
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
import { TokenType } from "../auth-token/auth-token-types";
import { TIdentityMetadataDALFactory } from "../identity/identity-metadata-dal";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal";
import { TProjectDALFactory } from "../project/project-dal";
import { TProjectBotServiceFactory } from "../project-bot/project-bot-service";
import { TProjectKeyDALFactory } from "../project-key/project-key-dal";
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
import { TProjectUserMembershipRoleDALFactory } from "../project-membership/project-user-membership-role-dal";
import { TProjectRoleDALFactory } from "../project-role/project-role-dal";
import { TReminderServiceFactory } from "../reminder/reminder-types";
import { TRoleDALFactory } from "../role/role-dal";
import { TSecretDALFactory } from "../secret/secret-dal";
import { fnDeleteProjectSecretReminders } from "../secret/secret-fns";
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
@@ -91,7 +92,6 @@ import {
TUpgradePrivilegeSystemDTO,
TVerifyUserToOrgDTO
} from "./org-types";
import { TRoleDALFactory } from "../role/role-dal";
type TOrgServiceFactoryDep = {
userAliasDAL: Pick<TUserAliasDALFactory, "delete">;
@@ -105,26 +105,17 @@ type TOrgServiceFactoryDep = {
groupDAL: TGroupDALFactory;
projectDAL: TProjectDALFactory;
identityMetadataDAL: Pick<TIdentityMetadataDALFactory, "delete" | "insertMany" | "transaction">;
membershipUserDAL: TMembershipUserDALFactory;
projectMembershipDAL: Pick<
TProjectMembershipDALFactory,
| "findProjectMembershipsByUserId"
| "delete"
| "create"
| "find"
| "insertMany"
| "transaction"
| "findProjectMembershipsByUserIds"
"findProjectMembershipsByUserId" | "findProjectMembershipsByUserIds"
>;
projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "delete" | "insertMany" | "findLatestProjectKey" | "create">;
orgMembershipDAL: Pick<
TOrgMembershipDALFactory,
| "findOrgMembershipById"
| "findOne"
| "findById"
| "findRecentInvitedMemberships"
| "updateById"
| "updateLastInvitedAtByIds"
"findOrgMembershipById" | "findRecentInvitedMemberships" | "updateLastInvitedAtByIds"
>;
membershipRoleDAL: TMembershipRoleDALFactory;
incidentContactDAL: TIncidentContactsDALFactory;
samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne">;
oidcConfigDAL: Pick<TOidcConfigDALFactory, "findOne">;
@@ -136,9 +127,6 @@ type TOrgServiceFactoryDep = {
TLicenseServiceFactory,
"getPlan" | "updateSubscriptionOrgMemberCount" | "generateOrgCustomerId" | "removeOrgCustomer"
>;
projectUserAdditionalPrivilegeDAL: Pick<TProjectUserAdditionalPrivilegeDALFactory, "delete">;
projectRoleDAL: Pick<TProjectRoleDALFactory, "find">;
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "insertMany" | "create">;
projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
loginService: Pick<TAuthLoginFactory, "generateUserTokens">;
reminderService: Pick<TReminderServiceFactory, "deleteReminderBySecretId">;
@@ -162,19 +150,18 @@ export const orgServiceFactory = ({
projectMembershipDAL,
projectKeyDAL,
orgMembershipDAL,
projectUserAdditionalPrivilegeDAL,
tokenService,
orgBotDAL,
licenseService,
projectRoleDAL,
samlConfigDAL,
oidcConfigDAL,
ldapConfigDAL,
projectUserMembershipRoleDAL,
identityMetadataDAL,
projectBotService,
loginService,
reminderService
reminderService,
membershipRoleDAL,
membershipUserDAL
}: TOrgServiceFactoryDep) => {
/*
* Get organization details by the organization id
@@ -273,7 +260,7 @@ export const orgServiceFactory = ({
}
if (actor === ActorType.IDENTITY) {
const workspaces = await projectDAL.findAllProjectsByIdentity(actorId);
const workspaces = await projectDAL.findIdentityProjects(actorId, orgId);
return workspaces;
}
@@ -308,14 +295,21 @@ export const orgServiceFactory = ({
);
const createMembershipData = {
orgId,
userId: user.id,
role: OrgMembershipRole.Admin,
scopeOrgId: orgId,
scope: AccessScope.Organization,
actorUserId: user.id,
status: OrgMembershipStatus.Accepted,
isActive: true
};
await orgDAL.createMembership(createMembershipData, tx);
const membership = await orgDAL.createMembership(createMembershipData, tx);
await membershipRoleDAL.create(
{
membershipId: membership.id,
role: OrgMembershipRole.Admin
},
tx
);
return {
user,
@@ -613,16 +607,23 @@ export const orgServiceFactory = ({
tx
);
if (userId) {
await orgDAL.createMembership(
const membership = await orgDAL.createMembership(
{
userId,
orgId: org.id,
role: OrgMembershipRole.Admin,
scope: AccessScope.Organization,
actorUserId: userId,
scopeOrgId: org.id,
status: OrgMembershipStatus.Accepted,
isActive: true
},
tx
);
await membershipRoleDAL.create(
{
membershipId: membership.id,
role: OrgMembershipRole.Admin
},
tx
);
}
await orgBotDAL.create(
{
@@ -766,12 +767,16 @@ export const orgServiceFactory = ({
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Member);
const foundMembership = await orgMembershipDAL.findById(membershipId);
const foundMembership = await membershipUserDAL.findOne({
id: membershipId,
scope: AccessScope.Organization,
scopeOrgId: actorOrgId
});
if (!foundMembership)
throw new NotFoundError({ message: `Organization membership with ID ${membershipId} not found` });
if (foundMembership.orgId !== orgId)
if (foundMembership.scopeOrgId !== orgId)
throw new UnauthorizedError({ message: "Updated org member doesn't belong to the organization" });
if (foundMembership.userId === userId)
if (foundMembership.scopeOrgId === userId)
throw new UnauthorizedError({ message: "Cannot update own organization membership" });
const isCustomRole = !Object.values(OrgMembershipRole).includes(role as OrgMembershipRole);
@@ -793,8 +798,20 @@ export const orgServiceFactory = ({
const membership = await orgDAL.transaction(async (tx) => {
const [updatedOrgMembership] = await orgDAL.updateMembership(
{ id: membershipId, scopeOrgId: orgId },
{ role: userRole, roleId: userRoleId, isActive }
{ isActive },
tx
);
if (userRole) {
await membershipRoleDAL.delete({ membershipId: updatedOrgMembership.id }, tx);
await membershipRoleDAL.create(
{
membershipId: updatedOrgMembership.id,
role: userRole,
customRoleId: userRoleId
},
tx
);
}
if (metadata) {
await identityMetadataDAL.delete({ userId: updatedOrgMembership.actorUserId, orgId }, tx);
@@ -833,8 +850,9 @@ export const orgServiceFactory = ({
const org = await orgDAL.findOrgById(orgId);
const [inviteeOrgMembership] = await orgDAL.findMembership({
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId,
[`${TableName.OrgMembership}.id` as "id"]: membershipId
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization,
[`${TableName.Membership}.id` as "id"]: membershipId
});
if (inviteeOrgMembership.status !== OrgMembershipStatus.Invited) {
@@ -845,7 +863,7 @@ export const orgServiceFactory = ({
const token = await tokenService.createTokenForUser({
type: TokenType.TOKEN_EMAIL_ORG_INVITATION,
userId: inviteeOrgMembership.userId,
userId: inviteeOrgMembership.actorUserId as string,
orgId
});
@@ -873,7 +891,7 @@ export const orgServiceFactory = ({
}
});
await orgMembershipDAL.updateById(inviteeOrgMembership.id, {
await membershipUserDAL.updateById(inviteeOrgMembership.id, {
lastInvitedAt: new Date()
});
@@ -991,8 +1009,9 @@ export const orgServiceFactory = ({
const [inviteeOrgMembership] = await orgDAL.findMembership(
{
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId,
[`${TableName.OrgMembership}.userId` as "userId"]: inviteeUserId
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization,
[`${TableName.Membership}.id` as "id"]: inviteeUserId
},
{ tx }
);
@@ -1019,7 +1038,7 @@ export const orgServiceFactory = ({
let roleId;
const orgRole = isCustomOrgRole ? OrgMembershipRole.Custom : organizationRoleSlug;
if (isCustomOrgRole) {
const customRole = await orgRoleDAL.findOne({ slug: organizationRoleSlug, orgId });
const customRole = await roleDAL.findOne({ slug: organizationRoleSlug, orgId });
if (!customRole) {
throw new NotFoundError({
name: "InviteUser",
@@ -1029,15 +1048,22 @@ export const orgServiceFactory = ({
roleId = customRole.id;
}
await orgDAL.createMembership(
const membership = await orgDAL.createMembership(
{
userId: inviteeUser.id,
actorUserId: inviteeUser.id,
inviteEmail: inviteeEmail,
orgId,
role: orgRole,
scopeOrgId: orgId,
status: OrgMembershipStatus.Invited,
isActive: true,
roleId
scope: AccessScope.Organization
},
tx
);
await membershipRoleDAL.create(
{
membershipId: membership.id,
role: orgRole,
customRoleId: roleId
},
tx
);
@@ -1072,14 +1098,16 @@ export const orgServiceFactory = ({
ProjectPermissionMemberActions.Create,
ProjectPermissionSub.Member
);
const existingMembers = await projectMembershipDAL.find(
const existingMembers = await membershipUserDAL.find(
{
projectId: project.id,
scopeOrgId: project.orgId,
scope: AccessScope.Project,
scopeProjectId: project.id,
$in: { userId: userIds }
},
{ tx }
);
const existingMembersGroupByUserId = groupBy(existingMembers, (i) => i.userId);
const existingMembersGroupByUserId = groupBy(existingMembers, (i) => i.actorUserId as string);
const userWithEncryptionKeyInvitedToProject = userEncryptionKeys.filter(
(user) => !existingMembersGroupByUserId?.[user.userId]
);
@@ -1246,9 +1274,10 @@ export const orgServiceFactory = ({
}
const [orgMembership] = await orgDAL.findMembership({
[`${TableName.OrgMembership}.userId` as "userId"]: user.id,
[`${TableName.Membership}.actorUserId` as "actorUserId"]: user.id,
scope: AccessScope.Organization,
status: OrgMembershipStatus.Invited,
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId
});
if (!orgMembership)
@@ -1261,7 +1290,7 @@ export const orgServiceFactory = ({
await tokenService.validateTokenForUser({
type: TokenType.TOKEN_EMAIL_ORG_INVITATION,
userId: user.id,
orgId: orgMembership.orgId,
orgId: orgMembership.scopeOrgId,
code
});
@@ -1273,16 +1302,17 @@ export const orgServiceFactory = ({
// this means user has already completed signup process
// isAccepted is set true when keys are exchanged
await orgDAL.updateMembershipById(orgMembership.id, {
orgId,
scopeOrgId: orgId,
status: OrgMembershipStatus.Accepted
});
await licenseService.updateSubscriptionOrgMemberCount(orgId);
return { user };
}
const membershipRole = await membershipRoleDAL.findOne({ membershipId: orgMembership.id });
if (
organization.authEnforced &&
!(organization.bypassOrgAuthEnabled && orgMembership.role === OrgMembershipRole.Admin)
!(organization.bypassOrgAuthEnabled && membershipRole.role === OrgMembershipRole.Admin)
) {
return { user };
}
@@ -1331,7 +1361,13 @@ export const orgServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TDeleteOrgMembershipDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
const { permission } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member);
const deletedMembership = await deleteOrgMembershipFn({
@@ -1339,11 +1375,11 @@ export const orgServiceFactory = ({
orgId,
orgDAL,
projectMembershipDAL,
projectUserAdditionalPrivilegeDAL,
projectKeyDAL,
userAliasDAL,
licenseService,
userId
userId,
membershipUserDAL
});
return deletedMembership;
@@ -1356,7 +1392,13 @@ export const orgServiceFactory = ({
actorAuthMethod,
actorOrgId
}: TDeleteOrgMembershipsDTO) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
const { permission } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member);
if (membershipIds.includes(userId)) {
@@ -1368,11 +1410,11 @@ export const orgServiceFactory = ({
orgId,
orgDAL,
projectMembershipDAL,
projectUserAdditionalPrivilegeDAL,
projectKeyDAL,
userAliasDAL,
licenseService,
userId
userId,
membershipUserDAL
});
return deletedMemberships;
@@ -1409,7 +1451,13 @@ export const orgServiceFactory = ({
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
const { permission } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount);
const incidentContacts = await incidentContactDAL.findByOrgId(orgId);
return incidentContacts;
@@ -1422,7 +1470,13 @@ export const orgServiceFactory = ({
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
const { permission } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.IncidentAccount);
const doesIncidentContactExist = await incidentContactDAL.findOne(orgId, { email });
if (doesIncidentContactExist) {
@@ -1443,7 +1497,13 @@ export const orgServiceFactory = ({
actorAuthMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => {
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
const { permission } = await permissionService.getOrgPermission(
ActorType.USER,
userId,
orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.IncidentAccount);
const incidentContact = await incidentContactDAL.deleteById(id, orgId);
@@ -1464,17 +1524,17 @@ export const orgServiceFactory = ({
await Promise.all(
invitedUsers.map(async (invitedUser) => {
let org = orgCache[invitedUser.orgId];
let org = orgCache[invitedUser.scopeOrgId];
if (!org) {
org = await orgDAL.findById(invitedUser.orgId);
orgCache[invitedUser.orgId] = org;
org = await orgDAL.findById(invitedUser.scopeOrgId);
orgCache[invitedUser.scopeOrgId] = org;
}
if (!org || !invitedUser.userId) return;
if (!org || !invitedUser.actorUserId) return;
const token = await tokenService.createTokenForUser({
type: TokenType.TOKEN_EMAIL_ORG_INVITATION,
userId: invitedUser.userId,
userId: invitedUser.actorUserId,
orgId: org.id
});
@@ -1,25 +1,25 @@
import { ForbiddenError } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { AccessScope, ActionProjectType } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionMemberActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError } from "@app/lib/errors";
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal";
import { TProjectKeyDALFactory } from "./project-key-dal";
import { TGetLatestProjectKeyDTO, TUploadProjectKeyDTO } from "./project-key-types";
type TProjectKeyServiceFactoryDep = {
permissionService: TPermissionServiceFactory;
projectKeyDAL: TProjectKeyDALFactory;
projectMembershipDAL: TProjectMembershipDALFactory;
membershipUserDAL: TMembershipUserDALFactory;
};
export type TProjectKeyServiceFactory = ReturnType<typeof projectKeyServiceFactory>;
export const projectKeyServiceFactory = ({
projectKeyDAL,
projectMembershipDAL,
membershipUserDAL,
permissionService
}: TProjectKeyServiceFactoryDep) => {
const uploadProjectKeys = async ({
@@ -42,9 +42,10 @@ export const projectKeyServiceFactory = ({
});
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
const receiverMembership = await projectMembershipDAL.findOne({
userId: receiverId,
projectId
const receiverMembership = await membershipUserDAL.findOne({
actorUserId: receiverId,
scopeProjectId: projectId,
scope: AccessScope.Project
});
if (!receiverMembership)
throw new BadRequestError({
+12 -25
View File
@@ -348,10 +348,11 @@ export const projectDALFactory = (db: TDbClient) => {
.where(`${TableName.Groups}.orgId`, dto.orgId)
.where(`${TableName.UserGroupMembership}.userId`, dto.actorId)
.select(db.ref("id").withSchema(TableName.Groups));
const userMembershipSubquery = db(TableName.Membership)
const membershipSubQuery = db(TableName.Membership)
.where(`${TableName.Membership}.scope`, AccessScope.Project)
.where((qb) => {
if (dto.actor === ActorType.IDENTITY) {
void qb.where(`${TableName.Membership}.actorIdentityId`, dto.actorId);
} else {
void qb
.where(`${TableName.Membership}.actorUserId`, dto.actorId)
@@ -360,11 +361,8 @@ export const projectDALFactory = (db: TDbClient) => {
})
.select("scopeProjectId");
const identityMembershipSubQuery = db(TableName.Membership).where({ identityId: dto.actorId }).select("projectId");
// Get the SQL strings for the subqueries
const userMembershipSql = userMembershipSubquery.toQuery();
const identityMembershipSql = identityMembershipSubQuery.toQuery();
const membershipSQL = membershipSubQuery.toQuery();
const query = db
.replicaNode()(TableName.Project)
@@ -372,26 +370,15 @@ export const projectDALFactory = (db: TDbClient) => {
.select(selectAllTableCols(TableName.Project))
.select(db.raw("COUNT(*) OVER() AS count"))
.select<(TProjects & { isMember: boolean; count: number })[]>(
dto.actor === ActorType.USER
? db.raw(
`
CASE
WHEN ${TableName.Project}.id IN (?) THEN TRUE
WHEN ${TableName.Project}.id IN (?) THEN TRUE
ELSE FALSE
END as "isMember"
`,
[db.raw(userMembershipSql)]
)
: db.raw(
`
CASE
WHEN ${TableName.Project}.id IN (?) THEN TRUE
ELSE FALSE
END as "isMember"
`,
[db.raw(identityMembershipSql)]
)
db.raw(
`
CASE
WHEN ${TableName.Project}.id IN (?) THEN TRUE
ELSE FALSE
END as "isMember"
`,
[db.raw(membershipSQL)]
)
)
.limit(limit)
.offset(offset);
+16 -15
View File
@@ -1,5 +1,6 @@
/* eslint-disable no-await-in-loop */
import {
AccessScope,
IntegrationAuthsSchema,
ProjectMembershipRole,
ProjectUpgradeStatus,
@@ -34,14 +35,14 @@ import { TOrgServiceFactory } from "../org/org-service";
import { TProjectBotDALFactory } from "../project-bot/project-bot-dal";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
import { TProjectKeyDALFactory } from "../project-key/project-key-dal";
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
import { TProjectUserMembershipRoleDALFactory } from "../project-membership/project-user-membership-role-dal";
import { TSecretDALFactory } from "../secret/secret-dal";
import { TSecretVersionDALFactory } from "../secret/secret-version-dal";
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TUserDALFactory } from "../user/user-dal";
import { TProjectDALFactory } from "./project-dal";
import { assignWorkspaceKeysToMembers, createProjectKey } from "./project-fns";
import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
export type TProjectQueueFactory = ReturnType<typeof projectQueueFactory>;
@@ -55,13 +56,13 @@ type TProjectQueueFactoryDep = {
secretApprovalSecretDAL: Pick<TSecretApprovalRequestSecretDALFactory, "find" | "bulkUpdateNoVersionIncrement">;
projectBotDAL: Pick<TProjectBotDALFactory, "findOne" | "delete" | "create">;
orgService: Pick<TOrgServiceFactory, "addGhostUser">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "create">;
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">;
integrationAuthDAL: TIntegrationAuthDALFactory;
userDAL: Pick<TUserDALFactory, "findUserEncKeyByUserId">;
projectEnvDAL: Pick<TProjectEnvDALFactory, "find">;
projectDAL: Pick<TProjectDALFactory, "findOne" | "transaction" | "updateById" | "setProjectUpgradeStatus" | "find">;
orgDAL: Pick<TOrgDALFactory, "findMembership">;
membershipUserDAL: TMembershipUserDALFactory;
membershipRoleDAL: TMembershipRoleDALFactory;
};
export const projectQueueFactory = ({
@@ -79,8 +80,8 @@ export const projectQueueFactory = ({
orgDAL,
projectDAL,
orgService,
projectMembershipDAL,
projectUserMembershipRoleDAL
membershipUserDAL,
membershipRoleDAL
}: TProjectQueueFactoryDep) => {
const upgradeProject = async (dto: TQueueJobTypes["upgrade-project-to-ghost"]["payload"]) => {
await queueService.queue(QueueName.UpgradeProjectToGhost, QueueJobs.UpgradeProjectToGhost, dto, {
@@ -227,17 +228,16 @@ export const projectQueueFactory = ({
);
// Create a membership for the ghost user
const projectMembership = await projectMembershipDAL.create(
const projectMembership = await membershipUserDAL.create(
{
projectId: project.id,
userId: ghostUser.user.id
scopeProjectId: project.id,
scope: AccessScope.Project,
actorUserId: ghostUser.user.id,
scopeOrgId: project.orgId
},
tx
);
await projectUserMembershipRoleDAL.create(
{ projectMembershipId: projectMembership.id, role: ProjectMembershipRole.Admin },
tx
);
await membershipRoleDAL.create({ membershipId: projectMembership.id, role: ProjectMembershipRole.Admin }, tx);
// If a bot already exists, delete it
if (existingBot) {
@@ -272,8 +272,9 @@ export const projectQueueFactory = ({
for (const key of existingProjectKeys) {
const user = await userDAL.findUserEncKeyByUserId(key.receiverId);
const [orgMembership] = await orgDAL.findMembership({
[`${TableName.OrgMembership}.userId` as "userId"]: key.receiverId,
[`${TableName.OrgMembership}.orgId` as "orgId"]: project.orgId
[`${TableName.Membership}.actorUserId` as "actorUserId"]: key.receiverId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: project.orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization
});
if (!user) {
+44 -42
View File
@@ -3,6 +3,7 @@ import { PackRule, unpackRules } from "@casl/ability/extra";
import slugify from "@sindresorhus/slugify";
import {
AccessScope,
ActionProjectType,
ProjectMembershipRole,
ProjectType,
@@ -49,11 +50,11 @@ import { TCertificateDALFactory } from "../certificate/certificate-dal";
import { TCertificateAuthorityDALFactory } from "../certificate-authority/certificate-authority-dal";
import { expandInternalCa } from "../certificate-authority/certificate-authority-fns";
import { TCertificateTemplateDALFactory } from "../certificate-template/certificate-template-dal";
import { TGroupProjectDALFactory } from "../group-project/group-project-dal";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityProjectDALFactory } from "../identity-project/identity-project-dal";
import { TIdentityProjectMembershipRoleDALFactory } from "../identity-project/identity-project-membership-role-dal";
import { TKmsServiceFactory } from "../kms/kms-service";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
import { TMembershipGroupDALFactory } from "../membership-group/membership-group-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal";
import { validateMicrosoftTeamsChannelsSchema } from "../microsoft-teams/microsoft-teams-fns";
import { TMicrosoftTeamsIntegrationDALFactory } from "../microsoft-teams/microsoft-teams-integration-dal";
import { TProjectMicrosoftTeamsConfigDALFactory } from "../microsoft-teams/project-microsoft-teams-config-dal";
@@ -65,10 +66,9 @@ import { TPkiCollectionDALFactory } from "../pki-collection/pki-collection-dal";
import { TProjectBotServiceFactory } from "../project-bot/project-bot-service";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
import { TProjectUserMembershipRoleDALFactory } from "../project-membership/project-user-membership-role-dal";
import { TProjectRoleDALFactory } from "../project-role/project-role-dal";
import { getPredefinedRoles } from "../project-role/project-role-fns";
import { TReminderServiceFactory } from "../reminder/reminder-types";
import { TRoleDALFactory } from "../role/role-dal";
import { TSecretDALFactory } from "../secret/secret-dal";
import { fnDeleteProjectSecretReminders } from "../secret/secret-fns";
import { ROOT_FOLDER_NAME, TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
@@ -125,7 +125,6 @@ export const DEFAULT_PROJECT_ENVS = [
type TProjectServiceFactoryDep = {
projectDAL: TProjectDALFactory;
identityProjectDAL: Pick<TIdentityProjectDALFactory, "create">;
projectSshConfigDAL: Pick<TProjectSshConfigDALFactory, "transaction" | "create" | "findOne" | "updateById">;
projectQueue: TProjectQueueFactory;
userDAL: TUserDALFactory;
@@ -134,13 +133,11 @@ type TProjectServiceFactoryDep = {
secretDAL: Pick<TSecretDALFactory, "find">;
secretV2BridgeDAL: Pick<TSecretV2BridgeDALFactory, "find">;
projectEnvDAL: Pick<TProjectEnvDALFactory, "insertMany" | "find">;
identityOrgMembershipDAL: TIdentityOrgDALFactory;
identityProjectMembershipRoleDAL: Pick<TIdentityProjectMembershipRoleDALFactory, "create">;
projectMembershipDAL: Pick<
TProjectMembershipDALFactory,
"create" | "findProjectGhostUser" | "findOne" | "delete" | "findAllProjectMembers"
>;
groupProjectDAL: Pick<TGroupProjectDALFactory, "delete">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findProjectGhostUser" | "findAllProjectMembers">;
membershipUserDAL: Pick<TMembershipUserDALFactory, "create" | "findOne" | "delete">;
membershipGroupDAL: Pick<TMembershipGroupDALFactory, "delete">;
membershipIdentityDAL: Pick<TMembershipIdentityDALFactory, "create" | "findOne">;
membershipRoleDAL: Pick<TMembershipRoleDALFactory, "create">;
projectSlackConfigDAL: Pick<
TProjectSlackConfigDALFactory,
"findOne" | "transaction" | "updateById" | "create" | "delete"
@@ -154,7 +151,6 @@ type TProjectServiceFactoryDep = {
TMicrosoftTeamsIntegrationDALFactory,
"findById" | "findByIdWithWorkflowIntegrationDetails"
>;
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">;
pkiSubscriberDAL: Pick<TPkiSubscriberDALFactory, "find">;
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "find" | "findWithAssociatedCa">;
certificateDAL: Pick<TCertificateDALFactory, "find" | "countCertificatesInProject">;
@@ -172,7 +168,7 @@ type TProjectServiceFactoryDep = {
smtpService: Pick<TSmtpService, "sendMail">;
orgDAL: Pick<TOrgDALFactory, "findOne">;
keyStore: Pick<TKeyStoreFactory, "deleteItem">;
projectRoleDAL: Pick<TProjectRoleDALFactory, "find" | "insertMany" | "delete">;
roleDAL: Pick<TRoleDALFactory, "find" | "insertMany" | "delete">;
kmsService: Pick<
TKmsServiceFactory,
| "updateProjectSecretManagerKmsKey"
@@ -201,20 +197,15 @@ export const projectServiceFactory = ({
orgDAL,
userDAL,
folderDAL,
identityOrgMembershipDAL,
projectMembershipDAL,
projectEnvDAL,
licenseService,
projectUserMembershipRoleDAL,
projectRoleDAL,
certificateAuthorityDAL,
certificateDAL,
certificateTemplateDAL,
pkiCollectionDAL,
pkiAlertDAL,
pkiSubscriberDAL,
identityProjectDAL,
identityProjectMembershipRoleDAL,
sshCertificateAuthorityDAL,
sshCertificateAuthoritySecretDAL,
sshCertificateDAL,
@@ -228,10 +219,13 @@ export const projectServiceFactory = ({
slackIntegrationDAL,
microsoftTeamsIntegrationDAL,
projectTemplateService,
groupProjectDAL,
smtpService,
reminderService,
notificationService
notificationService,
membershipIdentityDAL,
membershipUserDAL,
membershipRoleDAL,
roleDAL
}: TProjectServiceFactoryDep) => {
/*
* Create workspace. Make user the admin
@@ -345,7 +339,7 @@ export const projectServiceFactory = ({
tx
);
}
await projectRoleDAL.insertMany(
await roleDAL.insertMany(
projectTemplate.packedRoles.map((role) => ({
...role,
permissions: JSON.stringify(role.permissions),
@@ -374,15 +368,17 @@ export const projectServiceFactory = ({
}
// Create a membership for the user
const userProjectMembership = await projectMembershipDAL.create(
const userProjectMembership = await membershipUserDAL.create(
{
projectId: project.id,
userId: user.id
scopeProjectId: project.id,
actorUserId: user.id,
scope: AccessScope.Project,
scopeOrgId: project.orgId
},
tx
);
await projectUserMembershipRoleDAL.create(
{ projectMembershipId: userProjectMembership.id, role: ProjectMembershipRole.Admin },
await membershipRoleDAL.create(
{ membershipId: userProjectMembership.id, role: ProjectMembershipRole.Admin },
tx
);
}
@@ -390,10 +386,11 @@ export const projectServiceFactory = ({
// If the project is being created by an identity, add the identity to the project as an admin
else if (actor === ActorType.IDENTITY) {
// Find identity org membership
const identityOrgMembership = await identityOrgMembershipDAL.findOne(
const identityOrgMembership = await membershipIdentityDAL.findOne(
{
identityId: actorId,
orgId: project.orgId
actorIdentityId: actorId,
scopeOrgId: project.orgId,
scope: AccessScope.Organization
},
tx
);
@@ -405,17 +402,19 @@ export const projectServiceFactory = ({
});
}
const identityProjectMembership = await identityProjectDAL.create(
const identityProjectMembership = await membershipIdentityDAL.create(
{
identityId: actorId,
projectId: project.id
actorIdentityId: actorId,
scopeProjectId: project.id,
scope: AccessScope.Project,
scopeOrgId: project.orgId
},
tx
);
await identityProjectMembershipRoleDAL.create(
await membershipRoleDAL.create(
{
projectMembershipId: identityProjectMembership.id,
membershipId: identityProjectMembership.id,
role: ProjectMembershipRole.Admin
},
tx
@@ -459,8 +458,11 @@ export const projectServiceFactory = ({
const deletedProject = await projectDAL.transaction(async (tx) => {
// delete these so that project custom roles can be deleted in cascade effect
// direct deletion of project without these will cause fk error
await projectMembershipDAL.delete({ projectId: project.id }, tx);
await groupProjectDAL.delete({ projectId: project.id }, tx);
// this will clean up all memberships
await membershipUserDAL.delete(
{ scopeOrgId: project.orgId, scopeProjectId: project.id, scope: AccessScope.Project },
tx
);
const delProject = await projectDAL.deleteById(project.id, tx);
const projectGhostUser = await projectMembershipDAL.findProjectGhostUser(project.id, tx).catch(() => null);
// akhilmhdh: before removing those kms checking any other project uses it
@@ -521,13 +523,13 @@ export const projectServiceFactory = ({
// `includeRoles` is specifically used by organization admins when inviting new users to the organizations to avoid looping redundant api calls.
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Member);
const customRoles = await projectRoleDAL.find({
const customRoles = await roleDAL.find({
$in: {
projectId: workspaces.map((workspace) => workspace.id)
}
});
const workspaceMappedToRoles = groupBy(customRoles, (role) => role.projectId);
const workspaceMappedToRoles = groupBy(customRoles, (role) => role.projectId as string);
const workspacesWithRoles = await Promise.all(
workspaces.map(async (workspace) => {
@@ -1872,7 +1874,7 @@ export const projectServiceFactory = ({
.filter((member) => member.roles.some((role) => role.role === ProjectMembershipRole.Admin))
.map((el) => el.user.email!);
if (filteredProjectMembers.length === 0) {
const customRolesWithMemberCreate = await projectRoleDAL.find({ projectId });
const customRolesWithMemberCreate = await roleDAL.find({ projectId });
const customRoleSlugsCanCreate = customRolesWithMemberCreate
.filter((role) => {
try {
@@ -14,6 +14,7 @@ import { BadRequestError } from "@app/lib/errors";
import { TRoleScopeFactory } from "../role-types";
import { isCustomOrgRole } from "@app/services/org/org-role-fns";
// TODO(simp): missing external group checking
type TOrgRoleScopeFactoryDep = {
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
};
+70 -3
View File
@@ -1,4 +1,4 @@
import { AccessScope, TableName } from "@app/db/schemas";
import { AccessScope, ActionProjectType, TableName } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
@@ -13,20 +13,34 @@ import {
TDeleteRoleDTO,
TGetRoleByIdDTO,
TGetRoleBySlugDTO,
TGetUserPermissionDTO,
TListRoleDTO,
TUpdateRoleDTO
} from "./role-types";
import { TProjectDALFactory } from "../project/project-dal";
import { packRules } from "@casl/ability/extra";
import { requestContext } from "@fastify/request-context";
import { TIdentityDALFactory } from "../identity/identity-dal";
import { TUserDALFactory } from "../user/user-dal";
import { ActorType } from "../auth/auth-type";
type TRoleServiceFactoryDep = {
roleDAL: TRoleDALFactory;
identityDAL: Pick<TIdentityDALFactory, "findById">;
userDAL: Pick<TUserDALFactory, "findById">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getOrgPermission">;
projectDAL: Pick<TProjectDALFactory, "findById">;
};
export type TRoleServiceFactory = ReturnType<typeof roleServiceFactory>;
export const roleServiceFactory = ({ roleDAL, permissionService, projectDAL }: TRoleServiceFactoryDep) => {
export const roleServiceFactory = ({
roleDAL,
permissionService,
projectDAL,
identityDAL,
userDAL
}: TRoleServiceFactoryDep) => {
const orgRoleFactory = newOrgRoleFactory({
permissionService
});
@@ -186,12 +200,65 @@ export const roleServiceFactory = ({ roleDAL, permissionService, projectDAL }: T
return { ...role, [scope.key]: scope.value, permissions: unpackPermissions(role.permissions) };
};
const getUserPermission = async (dto: TGetUserPermissionDTO) => {
if (dto.scopeData.scope === AccessScope.Organization) {
const { permission, memberships } = await permissionService.getOrgPermission(
dto.permission.type,
dto.permission.id,
dto.permission.orgId,
dto.permission.authMethod,
dto.permission.orgId
);
return { permissions: packRules(permission.rules), memberships, assumedPrivilegeDetails: undefined };
}
if (dto.scopeData.scope === AccessScope.Project) {
const { permission, memberships } = await permissionService.getProjectPermission({
actor: dto.permission.type,
actorId: dto.permission.id,
actionProjectType: ActionProjectType.Any,
actorAuthMethod: dto.permission.authMethod,
projectId: dto.scopeData.projectId,
actorOrgId: dto.permission.orgId
});
const assumedPrivilegeDetailsCtx = requestContext.get("assumedPrivilegeDetails");
const isAssumingPrivilege = assumedPrivilegeDetailsCtx?.projectId === dto.scopeData.projectId;
const assumedPrivilegeDetails = isAssumingPrivilege
? {
actorId: assumedPrivilegeDetailsCtx?.actorId,
actorType: assumedPrivilegeDetailsCtx?.actorType,
actorName: "",
actorEmail: ""
}
: undefined;
if (assumedPrivilegeDetails?.actorType === ActorType.IDENTITY) {
const identityDetails = await identityDAL.findById(assumedPrivilegeDetails.actorId);
if (!identityDetails)
throw new NotFoundError({ message: `Identity with ID ${assumedPrivilegeDetails.actorId} not found` });
assumedPrivilegeDetails.actorName = identityDetails.name;
} else if (assumedPrivilegeDetails?.actorType === ActorType.USER) {
const userDetails = await userDAL.findById(assumedPrivilegeDetails?.actorId);
if (!userDetails)
throw new NotFoundError({ message: `User with ID ${assumedPrivilegeDetails.actorId} not found` });
assumedPrivilegeDetails.actorName = `${userDetails?.firstName} ${userDetails?.lastName || ""}`;
assumedPrivilegeDetails.actorEmail = userDetails?.email || "";
}
return { permissions: packRules(permission.rules), memberships, assumedPrivilegeDetails };
}
throw new BadRequestError({ message: "Invalid scope defined" });
};
return {
createRole,
updateRole,
deleteRole,
listRoles,
getRoleById,
getRoleBySlug
getRoleBySlug,
getUserPermission
};
};
+5
View File
@@ -71,3 +71,8 @@ export type TGetRoleBySlugDTO = {
slug: string;
};
};
export type TGetUserPermissionDTO = {
permission: OrgServiceActor;
scopeData: AccessScopeData;
};
+15 -12
View File
@@ -4,6 +4,7 @@ import { AxiosError } from "axios";
import { Knex } from "knex";
import {
AccessScope,
ProjectMembershipRole,
ProjectType,
ProjectUpgradeStatus,
@@ -50,7 +51,6 @@ import { TProjectBotServiceFactory } from "../project-bot/project-bot-service";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
import { TProjectKeyDALFactory } from "../project-key/project-key-dal";
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
import { TProjectUserMembershipRoleDALFactory } from "../project-membership/project-user-membership-role-dal";
import { TReminderServiceFactory } from "../reminder/reminder-types";
import { TResourceMetadataDALFactory } from "../resource-metadata/resource-metadata-dal";
import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema";
@@ -76,6 +76,8 @@ import {
TRemoveSecretReminderDTO,
TSyncSecretsDTO
} from "./secret-types";
import { TMembershipDALFactory } from "../membership/membership-dal";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
export type TSecretQueueFactory = ReturnType<typeof secretQueueFactory>;
type TSecretQueueFactoryDep = {
@@ -92,7 +94,9 @@ type TSecretQueueFactoryDep = {
projectDAL: TProjectDALFactory;
projectBotDAL: TProjectBotDALFactory;
projectKeyDAL: Pick<TProjectKeyDALFactory, "create">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findAllProjectMembers" | "create">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findAllProjectMembers">;
membershipUserDAL: Pick<TMembershipDALFactory, "create">;
membershipRoleDAL: Pick<TMembershipRoleDALFactory, "create">;
smtpService: TSmtpService;
secretVersionDAL: TSecretVersionDALFactory;
secretBlindIndexDAL: TSecretBlindIndexDALFactory;
@@ -110,7 +114,6 @@ type TSecretQueueFactoryDep = {
keyStore: Pick<TKeyStoreFactory, "acquireLock" | "setItemWithExpiry" | "getItem">;
auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
orgService: Pick<TOrgServiceFactory, "addGhostUser">;
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
folderCommitService: Pick<TFolderCommitServiceFactory, "createCommit">;
secretSyncQueue: Pick<TSecretSyncQueueFactory, "queueSecretSyncsSyncSecretsByPath">;
@@ -173,14 +176,15 @@ export const secretQueueFactory = ({
keyStore,
auditLogService,
orgService,
projectUserMembershipRoleDAL,
projectKeyDAL,
resourceMetadataDAL,
secretSyncQueue,
folderCommitService,
reminderService,
eventBusService,
licenseService
licenseService,
membershipUserDAL,
membershipRoleDAL
}: TSecretQueueFactoryDep) => {
const integrationMeter = opentelemetry.metrics.getMeter("Integrations");
const errorHistogram = integrationMeter.createHistogram("integration_secret_sync_errors", {
@@ -1165,17 +1169,16 @@ export const secretQueueFactory = ({
// if project v1 create the project ghost user
if (project.version === ProjectVersion.V1) {
const ghostUser = await orgService.addGhostUser(project.orgId, tx);
const projectMembership = await projectMembershipDAL.create(
const projectMembership = await membershipUserDAL.create(
{
userId: ghostUser.user.id,
projectId: project.id
actorUserId: ghostUser.user.id,
scopeOrgId: project.orgId,
scope: AccessScope.Project,
scopeProjectId: project.id
},
tx
);
await projectUserMembershipRoleDAL.create(
{ projectMembershipId: projectMembership.id, role: ProjectMembershipRole.Admin },
tx
);
await membershipRoleDAL.create({ membershipId: projectMembership.id, role: ProjectMembershipRole.Admin }, tx);
const { key: encryptedProjectKey, iv: encryptedProjectKeyIv } = createProjectKey({
publicKey: ghostUser.keys.publicKey,
@@ -1,6 +1,7 @@
import { CronJob } from "cron";
import {
AccessScope,
IdentityAuthMethod,
OrgMembershipRole,
OrgMembershipStatus,
@@ -29,7 +30,6 @@ import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
import { TAuthLoginFactory } from "../auth/auth-login-service";
import { ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TIdentityTokenAuthDALFactory } from "../identity-token-auth/identity-token-auth-dal";
@@ -37,10 +37,12 @@ import { KMS_ROOT_CONFIG_UUID } from "../kms/kms-fns";
import { TKmsRootConfigDALFactory } from "../kms/kms-root-config-dal";
import { TKmsServiceFactory } from "../kms/kms-service";
import { RootKeyEncryptionStrategy } from "../kms/kms-types";
import { TMembershipRoleDALFactory } from "../membership/membership-role-dal";
import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal";
import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal";
import { TMicrosoftTeamsServiceFactory } from "../microsoft-teams/microsoft-teams-service";
import { TOrgDALFactory } from "../org/org-dal";
import { TOrgServiceFactory } from "../org/org-service";
import { TOrgMembershipDALFactory } from "../org-membership/org-membership-dal";
import { TUserDALFactory } from "../user/user-dal";
import { TUserAliasDALFactory } from "../user-alias/user-alias-dal";
import { UserAliasType } from "../user-alias/user-alias-types";
@@ -64,11 +66,12 @@ type TSuperAdminServiceFactoryDep = {
identityDAL: TIdentityDALFactory;
identityTokenAuthDAL: TIdentityTokenAuthDALFactory;
identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
identityOrgMembershipDAL: TIdentityOrgDALFactory;
orgDAL: TOrgDALFactory;
orgMembershipDAL: TOrgMembershipDALFactory;
serverCfgDAL: TSuperAdminDALFactory;
userDAL: TUserDALFactory;
membershipUserDAL: TMembershipUserDALFactory;
membershipIdentityDAL: TMembershipIdentityDALFactory;
membershipRoleDAL: TMembershipRoleDALFactory;
userAliasDAL: Pick<TUserAliasDALFactory, "findOne">;
authService: Pick<TAuthLoginFactory, "generateUserTokens">;
kmsService: Pick<TKmsServiceFactory, "encryptWithRootKey" | "decryptWithRootKey" | "updateEncryptionStrategy">;
@@ -127,7 +130,6 @@ export const superAdminServiceFactory = ({
userDAL,
identityDAL,
orgDAL,
orgMembershipDAL,
userAliasDAL,
authService,
orgService,
@@ -137,11 +139,13 @@ export const superAdminServiceFactory = ({
licenseService,
identityAccessTokenDAL,
identityTokenAuthDAL,
identityOrgMembershipDAL,
microsoftTeamsService,
invalidateCacheQueue,
smtpService,
tokenService
tokenService,
membershipIdentityDAL,
membershipUserDAL,
membershipRoleDAL
}: TSuperAdminServiceFactoryDep) => {
const initServerCfg = async () => {
// TODO(akhilmhdh): bad pattern time less change this later to me itself
@@ -589,10 +593,17 @@ export const superAdminServiceFactory = ({
const { identity, credentials } = await identityDAL.transaction(async (tx) => {
const newIdentity = await identityDAL.create({ name: "Instance Admin Identity" }, tx);
await identityOrgMembershipDAL.create(
const membership = await membershipIdentityDAL.create(
{
identityId: newIdentity.id,
orgId: organization.id,
actorIdentityId: newIdentity.id,
scopeOrgId: organization.id,
scope: AccessScope.Project
},
tx
);
await membershipRoleDAL.create(
{
membershipId: membership.id,
role: OrgMembershipRole.Admin
},
tx
@@ -834,18 +845,23 @@ export const superAdminServiceFactory = ({
});
}
await orgDAL.createMembership(
const membership = await orgDAL.createMembership(
{
userId: inviteeUser.id,
actorUserId: inviteeUser.id,
scope: AccessScope.Organization,
inviteEmail: inviteeEmail,
orgId: org.id,
role: OrgMembershipRole.Admin,
scopeOrgId: org.id,
status: inviteeUser.isAccepted ? OrgMembershipStatus.Accepted : OrgMembershipStatus.Invited,
isActive: true
},
tx
);
await membershipRoleDAL.create({
membershipId: membership.id,
role: OrgMembershipRole.Admin
});
users.push(inviteeUser);
}
@@ -914,20 +930,25 @@ export const superAdminServiceFactory = ({
actorType: ActorType
) => {
if (actorType === ActorType.USER) {
const orgMembership = await orgMembershipDAL.findById(membershipId);
const orgMembership = await membershipUserDAL.findOne({
scope: AccessScope.Organization,
id: membershipId,
scopeOrgId: organizationId
});
if (!orgMembership) {
throw new NotFoundError({ name: "Organization Membership", message: "Organization membership not found" });
}
if (orgMembership.userId === actorId) {
if (orgMembership.actorUserId === actorId) {
throw new BadRequestError({
message: "You cannot remove yourself from the organization from the instance management panel."
});
}
}
const [organizationMembership] = await orgMembershipDAL.delete({
orgId: organizationId,
const [organizationMembership] = await membershipUserDAL.delete({
scopeOrgId: organizationId,
scope: AccessScope.Organization,
id: membershipId
});
return organizationMembership;
@@ -946,25 +967,46 @@ export const superAdminServiceFactory = ({
throw new NotFoundError({ message: `Could not organization with ID "${orgId}"` });
}
const existingOrgMembership = await orgMembershipDAL.findOne({ userId: serverAdmin.id, orgId });
const existingOrgMembership = await membershipUserDAL.findOne({
actorUserId: serverAdmin.id,
scopeOrgId: org.id,
scope: AccessScope.Organization
});
if (existingOrgMembership) {
throw new BadRequestError({ message: `You are already a part of the organization with ID ${orgId}` });
}
const orgMembership = await orgDAL.createMembership({
userId: serverAdmin.id,
orgId: org.id,
role: OrgMembershipRole.Admin,
status: OrgMembershipStatus.Accepted,
isActive: true
const orgMembership = await orgDAL.transaction(async (tx) => {
const membership = await orgDAL.createMembership(
{
actorUserId: serverAdmin.id,
scopeOrgId: org.id,
status: OrgMembershipStatus.Accepted,
isActive: true,
scope: AccessScope.Organization
},
tx
);
await membershipRoleDAL.create(
{
membershipId: membership.id,
role: OrgMembershipRole.Admin
},
tx
);
return membership;
});
return orgMembership;
};
const resendOrgInvite = async ({ organizationId, membershipId }: TResendOrgInviteDTO, actor: OrgServiceActor) => {
const orgMembership = await orgMembershipDAL.findOne({ id: membershipId, orgId: organizationId });
const orgMembership = await membershipUserDAL.findOne({
id: membershipId,
scopeOrgId: organizationId,
scope: AccessScope.Organization
});
if (!orgMembership) {
throw new NotFoundError({ name: "Organization Membership", message: "Organization membership not found" });
@@ -976,7 +1018,7 @@ export const superAdminServiceFactory = ({
});
}
if (!orgMembership.userId) {
if (!orgMembership.actorUserId) {
throw new NotFoundError({ message: "Cannot find user associated with Org Membership." });
}
@@ -984,15 +1026,15 @@ export const superAdminServiceFactory = ({
throw new BadRequestError({ message: "No invite email associated with user." });
}
const org = await orgDAL.findOrgById(orgMembership.orgId);
const org = await orgDAL.findOrgById(orgMembership.scopeOrgId);
const appCfg = getConfig();
const serverAdmin = await userDAL.findById(actor.id);
const token = await tokenService.createTokenForUser({
type: TokenType.TOKEN_EMAIL_ORG_INVITATION,
userId: orgMembership.userId,
orgId: orgMembership.orgId
userId: orgMembership.actorUserId,
orgId: orgMembership.scopeOrgId
});
await smtpService.sendMail({
@@ -1004,7 +1046,7 @@ export const superAdminServiceFactory = ({
inviterUsername: serverAdmin?.email,
organizationName: org?.name,
email: orgMembership.inviteEmail,
organizationId: orgMembership.orgId,
organizationId: orgMembership.scopeOrgId,
token,
callback_url: `${appCfg.SITE_URL}/signupinvite`
}
+27 -19
View File
@@ -1,6 +1,7 @@
import { ForbiddenError } from "@casl/ability";
import { Knex } from "knex";
import { AccessScope } from "@app/db/schemas";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { crypto } from "@app/lib/crypto";
@@ -9,12 +10,11 @@ import { logger } from "@app/lib/logger";
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
import { TokenType } from "@app/services/auth-token/auth-token-types";
import { TOrgDALFactory } from "@app/services/org/org-dal";
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
import { AuthMethod, AuthTokenType } from "../auth/auth-type";
import { TGroupProjectDALFactory } from "../group-project/group-project-dal";
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
import { TMembershipUserDALFactory } from "../membership-user/membership-user-dal";
import { TUserAliasDALFactory } from "../user-alias/user-alias-dal";
import { TUserDALFactory } from "./user-dal";
import { TListUserGroupsDTO, TUpdateUserEmailDTO, TUpdateUserMfaDTO } from "./user-types";
@@ -37,9 +37,8 @@ type TUserServiceFactoryDep = {
>;
groupProjectDAL: Pick<TGroupProjectDALFactory, "findByUserId">;
orgDAL: Pick<TOrgDALFactory, "findById" | "find">;
orgMembershipDAL: Pick<TOrgMembershipDALFactory, "find" | "insertMany" | "findOne" | "updateById">;
membershipUserDAL: Pick<TMembershipUserDALFactory, "find" | "insertMany" | "findOne" | "updateById">;
tokenService: Pick<TAuthTokenServiceFactory, "createTokenForUser" | "validateTokenForUser" | "revokeAllMySessions">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find">;
smtpService: Pick<TSmtpService, "sendMail">;
permissionService: TPermissionServiceFactory;
userAliasDAL: Pick<TUserAliasDALFactory, "findOne" | "find" | "updateById" | "delete">;
@@ -50,8 +49,7 @@ export type TUserServiceFactory = ReturnType<typeof userServiceFactory>;
export const userServiceFactory = ({
userDAL,
orgDAL,
orgMembershipDAL,
projectMembershipDAL,
membershipUserDAL,
groupProjectDAL,
tokenService,
smtpService,
@@ -183,13 +181,19 @@ export const userServiceFactory = ({
};
const checkUserScimRestriction = async (userId: string, tx?: Knex) => {
const userOrgs = await orgMembershipDAL.find({ userId }, { tx });
const userOrgs = await membershipUserDAL.find(
{
actorUserId: userId,
scope: AccessScope.Organization
},
{ tx }
);
if (userOrgs.length === 0) {
return false;
}
const orgIds = userOrgs.map((membership) => membership.orgId);
const orgIds = userOrgs.map((membership) => membership.scopeOrgId);
const organizations = await orgDAL.find({ $in: { id: orgIds } }, { tx });
return organizations.some((org) => org.scimEnabled);
@@ -397,9 +401,10 @@ export const userServiceFactory = ({
};
const getUserProjectFavorites = async (userId: string, orgId: string) => {
const orgMembership = await orgMembershipDAL.findOne({
userId,
orgId
const orgMembership = await membershipUserDAL.findOne({
scope: AccessScope.Organization,
actorUserId: userId,
scopeOrgId: orgId
});
if (!orgMembership) {
@@ -412,9 +417,10 @@ export const userServiceFactory = ({
};
const updateUserProjectFavorites = async (userId: string, orgId: string, projectIds: string[]) => {
const orgMembership = await orgMembershipDAL.findOne({
userId,
orgId
const orgMembership = await membershipUserDAL.findOne({
scope: AccessScope.Organization,
actorUserId: userId,
scopeOrgId: orgId
});
if (!orgMembership) {
@@ -423,18 +429,20 @@ export const userServiceFactory = ({
});
}
const matchingUserProjectMemberships = await projectMembershipDAL.find({
userId,
const matchingUserProjectMemberships = await membershipUserDAL.find({
scope: AccessScope.Project,
scopeOrgId: orgId,
actorUserId: userId,
$in: {
projectId: projectIds
scopeProjectId: projectIds
}
});
const memberProjectFavorites = matchingUserProjectMemberships.map(
(projectMembership) => projectMembership.projectId
(projectMembership) => projectMembership.scopeProjectId as string
);
const updatedOrgMembership = await orgMembershipDAL.updateById(orgMembership.id, {
const updatedOrgMembership = await membershipUserDAL.updateById(orgMembership.id, {
projectFavorites: memberProjectFavorites
});