@oneuptime/common 13.0.8 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/AuditLog.ts +23 -15
- package/Models/DatabaseModels/GlobalConfig.ts +24 -0
- package/Models/DatabaseModels/Monitor.ts +3 -2
- package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
- package/Scripts/generate-service-worker.js +65 -4
- package/Server/API/BaseAPI.ts +26 -5
- package/Server/API/GlobalConfigAPI.ts +228 -462
- package/Server/API/ProjectOIDC.ts +25 -16
- package/Server/API/ProjectSSO.ts +24 -16
- package/Server/API/StatusPageAPI.ts +100 -42
- package/Server/API/TeamMemberAPI.ts +10 -1
- package/Server/Enterprise/EnterpriseEdition.ts +649 -0
- package/Server/Enterprise/EnterpriseFeature.ts +48 -0
- package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
- package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
- package/Server/EnvironmentConfig.ts +147 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Middleware/UserAuthorization.ts +38 -16
- package/Server/Services/AuditLogService.ts +84 -1079
- package/Server/Services/EnterpriseLicenseService.ts +38 -0
- package/Server/Services/GlobalConfigService.ts +80 -1
- package/Server/Services/MonitorProbeService.ts +116 -20
- package/Server/Services/MonitorService.ts +56 -4
- package/Server/Services/MonitorStatusTimelineService.ts +284 -0
- package/Server/Services/MonitorTemplateService.ts +26 -0
- package/Server/Services/ProjectService.ts +284 -0
- package/Server/Services/RumSessionPinService.ts +25 -6
- package/Server/Services/StatusPagePrivateUserService.ts +7 -3
- package/Server/Services/StatusPageService.ts +78 -1
- package/Server/Services/TeamMemberService.ts +11 -0
- package/Server/Services/TeamService.ts +10 -0
- package/Server/Services/UserService.ts +10 -17
- package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
- package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
- package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
- package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
- package/Server/Types/Markdown.ts +41 -0
- package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
- package/Server/Utils/EditionEnforcement.ts +233 -0
- package/Server/Utils/FrontendEnvironment.ts +41 -2
- package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
- package/Server/Utils/Monitor/AffectedResourceList.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +543 -333
- package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
- package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
- package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
- package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
- package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
- package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
- package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
- package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
- package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
- package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
- package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
- package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
- package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
- package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
- package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
- package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
- package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
- package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
- package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
- package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
- package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
- package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
- package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
- package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
- package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
- package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
- package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
- package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
- package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
- package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
- package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
- package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
- package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
- package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
- package/Tests/Server/Services/AuditLogService.test.ts +460 -990
- package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
- package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
- package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
- package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
- package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
- package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
- package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
- package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
- package/Tests/Server/Types/Markdown.test.ts +181 -0
- package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
- package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
- package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
- package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
- package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +934 -96
- package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
- package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
- package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
- package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
- package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
- package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
- package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
- package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
- package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
- package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
- package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
- package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
- package/Tests/Utils/HostAddressUtil.test.ts +138 -0
- package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
- package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
- package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
- package/Types/API/Hostname.ts +63 -16
- package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
- package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
- package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
- package/Types/Database/CanonicalModelInstance.ts +102 -0
- package/Types/Database/TableColumn.ts +20 -6
- package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
- package/Types/IP/IPv6.ts +6 -1
- package/Types/Monitor/MonitorStep.ts +6 -1
- package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
- package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
- package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
- package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/ModelList/ModelList.tsx +11 -1
- package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
- package/UI/esbuild-enterprise.js +263 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
- package/Utils/HostAddressUtil.ts +94 -0
- package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
- package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
- package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
- package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +26 -5
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectOIDC.js +24 -16
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
- package/build/dist/Server/API/ProjectSSO.js +24 -16
- package/build/dist/Server/API/ProjectSSO.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +93 -43
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TeamMemberAPI.js +8 -1
- package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
- package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
- package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
- package/build/dist/Server/EnvironmentConfig.js +84 -2
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AuditLogService.js +71 -740
- package/build/dist/Server/Services/AuditLogService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/GlobalConfigService.js +63 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +90 -17
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +45 -4
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +214 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RumSessionPinService.js +24 -6
- package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +71 -0
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +10 -0
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TeamService.js +9 -0
- package/build/dist/Server/Services/TeamService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +10 -16
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +31 -0
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
- package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
- package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
- package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
- package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
- package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
- package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +96 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +449 -261
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
- package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Types/API/Hostname.js +59 -11
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
- package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
- package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
- package/build/dist/Types/Database/TableColumn.js +19 -6
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
- package/build/dist/Types/IP/IPv6.js +6 -1
- package/build/dist/Types/IP/IPv6.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +5 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
- package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
- package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
- package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
- package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/HostAddressUtil.js +80 -0
- package/build/dist/Utils/HostAddressUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
- package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
- package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
- package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
- package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
- package/jest.config.json +3 -1
- package/package.json +1 -1
- package/test-setup.sh +103 -34
- package/tsconfig.json +13 -0
- package/Server/API/EnterpriseLicenseAPI.ts +0 -925
- package/Server/API/TeamComplianceAPI.ts +0 -158
- package/Server/Middleware/SCIMAuthorization.ts +0 -141
- package/Server/Services/TeamComplianceService.ts +0 -733
- package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
- package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
- package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
- package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
- package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
- package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
- package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
- package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
- package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
- package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
- package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
- package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
- package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
- package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
- package/build/dist/Server/Services/TeamComplianceService.js +0 -537
- package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
- package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
- package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
|
@@ -2,8 +2,9 @@ import { afterEach, beforeEach, describe, expect, test } from "@jest/globals";
|
|
|
2
2
|
import ObjectID from "../../../Types/ObjectID";
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* The audit-log recorder (Enterprise Edition, behind core's AuditLogService)
|
|
6
|
+
* caches each project's audit settings (enabled, retention, system events,
|
|
7
|
+
* plan) for a minute. Nothing ever invalidated that cache, so
|
|
7
8
|
* for up to a minute after an admin turned audit logging on, the process that
|
|
8
9
|
* saved the setting went on recording nothing - exactly when someone is
|
|
9
10
|
* watching the empty audit page to check that it works. ProjectService now
|
|
@@ -34,10 +35,14 @@ jest.mock(
|
|
|
34
35
|
|
|
35
36
|
import AuditLogService from "../../../Server/Services/AuditLogService";
|
|
36
37
|
import ProjectService from "../../../Server/Services/ProjectService";
|
|
37
|
-
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
38
38
|
import Project from "../../../Models/DatabaseModels/Project";
|
|
39
39
|
import { PlanType } from "../../../Types/Billing/SubscriptionPlan";
|
|
40
|
-
import
|
|
40
|
+
import {
|
|
41
|
+
createAuditLogRecorderSpy,
|
|
42
|
+
installFakeEnterpriseModule,
|
|
43
|
+
MockedAuditLogRecorder,
|
|
44
|
+
uninstallEnterpriseModule,
|
|
45
|
+
} from "../Enterprise/FakeEnterpriseModule";
|
|
41
46
|
|
|
42
47
|
type HookCallable = {
|
|
43
48
|
onUpdateSuccess: (
|
|
@@ -65,9 +70,11 @@ const updateProject: UpdateProjectFunction = async (
|
|
|
65
70
|
|
|
66
71
|
beforeEach(() => {
|
|
67
72
|
jest.clearAllMocks();
|
|
73
|
+
uninstallEnterpriseModule();
|
|
68
74
|
});
|
|
69
75
|
|
|
70
76
|
afterEach(() => {
|
|
77
|
+
uninstallEnterpriseModule();
|
|
71
78
|
jest.restoreAllMocks();
|
|
72
79
|
});
|
|
73
80
|
|
|
@@ -135,42 +142,31 @@ describe("ProjectService invalidates the audit log settings cache", () => {
|
|
|
135
142
|
expect(invalidate).toHaveBeenCalledTimes(1);
|
|
136
143
|
});
|
|
137
144
|
|
|
138
|
-
|
|
145
|
+
/*
|
|
146
|
+
* The cache itself lives in the Enterprise audit-log recorder (ee/), so
|
|
147
|
+
* "the next write reads the new setting" is pinned there, end to end
|
|
148
|
+
* (ee/Tests/Server/AuditLog/AuditLogSettingsInvalidation.test.ts). What
|
|
149
|
+
* core owns is that the invalidation reaches whichever recorder is
|
|
150
|
+
* registered, and is harmless when none is.
|
|
151
|
+
*/
|
|
152
|
+
test("the invalidation reaches the Enterprise audit-log recorder", async () => {
|
|
153
|
+
const recorder: MockedAuditLogRecorder = createAuditLogRecorderSpy();
|
|
154
|
+
installFakeEnterpriseModule({ auditLogRecorder: recorder });
|
|
155
|
+
|
|
139
156
|
const projectId: ObjectID = ObjectID.generate();
|
|
140
|
-
const project: Project = new Project();
|
|
141
|
-
project._id = projectId.toString();
|
|
142
|
-
project.enableAuditLogs = true;
|
|
143
|
-
|
|
144
|
-
const findProject: jest.SpyInstance = jest
|
|
145
|
-
.spyOn(ProjectService, "findOneById")
|
|
146
|
-
.mockResolvedValue(project as never);
|
|
147
|
-
jest.spyOn(AuditLogService, "create").mockResolvedValue(undefined as never);
|
|
148
|
-
|
|
149
|
-
const monitor: Monitor = new Monitor();
|
|
150
|
-
monitor._id = ObjectID.generate().toString();
|
|
151
|
-
monitor.name = "Checkout API";
|
|
152
|
-
|
|
153
|
-
type RecordFunction = () => Promise<void>;
|
|
154
|
-
|
|
155
|
-
const recordMonitorCreate: RecordFunction = async (): Promise<void> => {
|
|
156
|
-
await AuditLogService.recordCreate({
|
|
157
|
-
model: new Monitor(),
|
|
158
|
-
createdItem: monitor,
|
|
159
|
-
// An API-key actor needs no user lookup.
|
|
160
|
-
props: { tenantId: projectId, userType: UserType.API },
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
157
|
|
|
164
|
-
await
|
|
165
|
-
await recordMonitorCreate();
|
|
158
|
+
await updateProject({ enableAuditLogs: false }, [projectId]);
|
|
166
159
|
|
|
167
|
-
|
|
168
|
-
expect(
|
|
160
|
+
expect(recorder.invalidateProjectSettings).toHaveBeenCalledTimes(1);
|
|
161
|
+
expect(recorder.invalidateProjectSettings).toHaveBeenCalledWith(projectId);
|
|
162
|
+
});
|
|
169
163
|
|
|
170
|
-
|
|
171
|
-
|
|
164
|
+
test("on the Community Edition there is no cache to drop, and the update still succeeds", async () => {
|
|
165
|
+
uninstallEnterpriseModule();
|
|
172
166
|
|
|
173
|
-
expect(
|
|
167
|
+
await expect(
|
|
168
|
+
updateProject({ enableAuditLogs: true }, [ObjectID.generate()]),
|
|
169
|
+
).resolves.toBeUndefined();
|
|
174
170
|
});
|
|
175
171
|
|
|
176
172
|
test("a failure to invalidate never fails the project update", async () => {
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
import TeamService from "../../../Server/Services/TeamService";
|
|
2
|
+
import TeamMemberService from "../../../Server/Services/TeamMemberService";
|
|
3
|
+
import ProjectSCIMService from "../../../Server/Services/ProjectSCIMService";
|
|
4
|
+
import TeamPermissionService from "../../../Server/Services/TeamPermissionService";
|
|
5
|
+
import OnCallDutyPolicyTimeLogService from "../../../Server/Services/OnCallDutyPolicyTimeLogService";
|
|
6
|
+
import ProjectService from "../../../Server/Services/ProjectService";
|
|
7
|
+
import ModelPermission from "../../../Server/Types/Database/Permissions/Index";
|
|
8
|
+
import Errors from "../../../Server/Utils/Errors";
|
|
9
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
10
|
+
import PositiveNumber from "../../../Types/PositiveNumber";
|
|
11
|
+
import Team from "../../../Models/DatabaseModels/Team";
|
|
12
|
+
import TeamMember from "../../../Models/DatabaseModels/TeamMember";
|
|
13
|
+
import FakeEnterpriseModule, {
|
|
14
|
+
createEditionStateCases,
|
|
15
|
+
createLicenseSnapshotWithStatus,
|
|
16
|
+
EditionStateCase,
|
|
17
|
+
installFakeEnterpriseModule,
|
|
18
|
+
uninstallEnterpriseModule,
|
|
19
|
+
} from "../Enterprise/FakeEnterpriseModule";
|
|
20
|
+
import logger from "../../../Server/Utils/Logger";
|
|
21
|
+
import { setTestBillingEnabled } from "../Enterprise/TestBillingFlag";
|
|
22
|
+
import { getJestSpyOn } from "../../Spy";
|
|
23
|
+
import {
|
|
24
|
+
afterEach,
|
|
25
|
+
beforeEach,
|
|
26
|
+
describe,
|
|
27
|
+
expect,
|
|
28
|
+
jest,
|
|
29
|
+
test,
|
|
30
|
+
} from "@jest/globals";
|
|
31
|
+
|
|
32
|
+
type SpyInstance = ReturnType<typeof getJestSpyOn>;
|
|
33
|
+
|
|
34
|
+
jest.mock("../../../Server/EnvironmentConfig", () => {
|
|
35
|
+
const billingFlag: typeof import("../Enterprise/TestBillingFlag") =
|
|
36
|
+
jest.requireActual(
|
|
37
|
+
"../Enterprise/TestBillingFlag",
|
|
38
|
+
) as typeof import("../Enterprise/TestBillingFlag");
|
|
39
|
+
|
|
40
|
+
return billingFlag.withLiveBillingFlag(
|
|
41
|
+
jest.requireActual("../../../Server/EnvironmentConfig") as Record<
|
|
42
|
+
string,
|
|
43
|
+
unknown
|
|
44
|
+
>,
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* SCIM Push Groups team locks. While a project's SCIM configuration has Push
|
|
50
|
+
* Groups on, its identity provider owns team membership, so OneUptime refuses
|
|
51
|
+
* to create or delete teams, invite or remove members, and lifts the
|
|
52
|
+
* "at least one member" guard (the IdP may empty a team).
|
|
53
|
+
*
|
|
54
|
+
* The locks follow the RUNTIME state of SCIM
|
|
55
|
+
* (EnterpriseEdition.isFeatureActive(SCIM), through EditionEnforcement):
|
|
56
|
+
* - SCIM active (the Enterprise Edition with billing on, or with a license
|
|
57
|
+
* that covers SCIM - valid, grace, trial - or an unknown license state):
|
|
58
|
+
* locks ON, the identity provider owns the teams.
|
|
59
|
+
* - SCIM not active (the Community Edition, or an Enterprise install whose
|
|
60
|
+
* license lapsed): locks OFF. No SCIM endpoint answers the identity
|
|
61
|
+
* provider there, so a Push Groups setting left on would leave teams
|
|
62
|
+
* nobody can manage.
|
|
63
|
+
* A license change applies to the next write, without a restart.
|
|
64
|
+
*
|
|
65
|
+
* Billing and the edition are pinned in every test.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
69
|
+
"11111111-1111-4111-8111-111111111111",
|
|
70
|
+
);
|
|
71
|
+
const TEAM_ID: ObjectID = new ObjectID("44444444-4444-4444-8444-444444444444");
|
|
72
|
+
const USER_ID: ObjectID = new ObjectID("22222222-2222-4222-8222-222222222222");
|
|
73
|
+
const INVITEE_ID: ObjectID = new ObjectID(
|
|
74
|
+
"55555555-5555-4555-8555-555555555555",
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const EDITION_CASES: Array<EditionStateCase> = createEditionStateCases();
|
|
78
|
+
|
|
79
|
+
const toMatrix: (
|
|
80
|
+
cases: Array<EditionStateCase>,
|
|
81
|
+
) => Array<[string, EditionStateCase]> = (
|
|
82
|
+
cases: Array<EditionStateCase>,
|
|
83
|
+
): Array<[string, EditionStateCase]> => {
|
|
84
|
+
return cases.map(
|
|
85
|
+
(editionCase: EditionStateCase): [string, EditionStateCase] => {
|
|
86
|
+
return [editionCase.label, editionCase];
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Every state in which SCIM is active, so Push Groups locks the teams.
|
|
92
|
+
const LOCKED_MATRIX: Array<[string, EditionStateCase]> = toMatrix(
|
|
93
|
+
EDITION_CASES.filter((editionCase: EditionStateCase): boolean => {
|
|
94
|
+
return editionCase.isActive;
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// The Community Edition and every lapsed Enterprise license: not locked.
|
|
99
|
+
const UNLOCKED_MATRIX: Array<[string, EditionStateCase]> = toMatrix(
|
|
100
|
+
EDITION_CASES.filter((editionCase: EditionStateCase): boolean => {
|
|
101
|
+
return !editionCase.isActive;
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const userProps: () => Record<string, unknown> = (): Record<
|
|
106
|
+
string,
|
|
107
|
+
unknown
|
|
108
|
+
> => {
|
|
109
|
+
return { userId: USER_ID, tenantId: PROJECT_ID };
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const buildTeam: () => Team = (): Team => {
|
|
113
|
+
const team: Team = new Team();
|
|
114
|
+
team._id = TEAM_ID.toString();
|
|
115
|
+
team.name = "Backend";
|
|
116
|
+
team.projectId = PROJECT_ID;
|
|
117
|
+
team.isTeamDeleteable = true;
|
|
118
|
+
return team;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const buildMember: (data: {
|
|
122
|
+
shouldHaveAtLeastOneMember: boolean;
|
|
123
|
+
}) => TeamMember = (data: {
|
|
124
|
+
shouldHaveAtLeastOneMember: boolean;
|
|
125
|
+
}): TeamMember => {
|
|
126
|
+
const member: TeamMember = new TeamMember();
|
|
127
|
+
member.userId = INVITEE_ID;
|
|
128
|
+
member.projectId = PROJECT_ID;
|
|
129
|
+
member.teamId = TEAM_ID;
|
|
130
|
+
member.hasAcceptedInvitation = true;
|
|
131
|
+
|
|
132
|
+
const team: Team = new Team();
|
|
133
|
+
team._id = TEAM_ID.toString();
|
|
134
|
+
team.shouldHaveAtLeastOneMember = data.shouldHaveAtLeastOneMember;
|
|
135
|
+
member.team = team;
|
|
136
|
+
|
|
137
|
+
return member;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
let scimCount: SpyInstance;
|
|
141
|
+
|
|
142
|
+
describe("SCIM Push Groups team locks by edition", () => {
|
|
143
|
+
beforeEach(() => {
|
|
144
|
+
setTestBillingEnabled(false);
|
|
145
|
+
uninstallEnterpriseModule();
|
|
146
|
+
|
|
147
|
+
getJestSpyOn(logger, "warn").mockImplementation((): void => {
|
|
148
|
+
return undefined;
|
|
149
|
+
});
|
|
150
|
+
getJestSpyOn(logger, "info").mockImplementation((): void => {
|
|
151
|
+
return undefined;
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Push Groups is ON for the project in every test below.
|
|
155
|
+
scimCount = getJestSpyOn(ProjectSCIMService, "countBy").mockResolvedValue(
|
|
156
|
+
new PositiveNumber(1),
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
afterEach(() => {
|
|
161
|
+
uninstallEnterpriseModule();
|
|
162
|
+
setTestBillingEnabled(false);
|
|
163
|
+
jest.restoreAllMocks();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe("TeamService: creating and deleting teams", () => {
|
|
167
|
+
const createTeam: (props: Record<string, unknown>) => Promise<unknown> = (
|
|
168
|
+
props: Record<string, unknown>,
|
|
169
|
+
): Promise<unknown> => {
|
|
170
|
+
const team: Team = new Team();
|
|
171
|
+
team.projectId = PROJECT_ID;
|
|
172
|
+
team.name = "Backend";
|
|
173
|
+
|
|
174
|
+
return (TeamService as any).onBeforeCreate({
|
|
175
|
+
data: team,
|
|
176
|
+
props: props,
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const deleteTeam: (props: Record<string, unknown>) => Promise<unknown> = (
|
|
181
|
+
props: Record<string, unknown>,
|
|
182
|
+
): Promise<unknown> => {
|
|
183
|
+
return (TeamService as any).onBeforeDelete({
|
|
184
|
+
query: { _id: TEAM_ID },
|
|
185
|
+
props: props,
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
let memberDelete: SpyInstance;
|
|
190
|
+
|
|
191
|
+
beforeEach(() => {
|
|
192
|
+
getJestSpyOn(TeamService, "findBy").mockResolvedValue([buildTeam()]);
|
|
193
|
+
getJestSpyOn(
|
|
194
|
+
ModelPermission,
|
|
195
|
+
"checkDeleteQueryPermission",
|
|
196
|
+
).mockImplementation(
|
|
197
|
+
async (_modelType: unknown, query: unknown): Promise<unknown> => {
|
|
198
|
+
return query;
|
|
199
|
+
},
|
|
200
|
+
);
|
|
201
|
+
memberDelete = getJestSpyOn(
|
|
202
|
+
TeamMemberService,
|
|
203
|
+
"deleteBy",
|
|
204
|
+
).mockResolvedValue(0);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test.each(LOCKED_MATRIX)(
|
|
208
|
+
"SCIM active (%s): creating a team is locked",
|
|
209
|
+
async (_label: string, editionCase: EditionStateCase) => {
|
|
210
|
+
editionCase.apply();
|
|
211
|
+
|
|
212
|
+
await expect(createTeam(userProps())).rejects.toThrow(
|
|
213
|
+
"Cannot create teams while SCIM Push Groups is enabled for this project",
|
|
214
|
+
);
|
|
215
|
+
},
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
test.each(LOCKED_MATRIX)(
|
|
219
|
+
"SCIM active (%s): deleting a team is locked before any member is removed",
|
|
220
|
+
async (_label: string, editionCase: EditionStateCase) => {
|
|
221
|
+
editionCase.apply();
|
|
222
|
+
|
|
223
|
+
await expect(deleteTeam(userProps())).rejects.toThrow(
|
|
224
|
+
"Cannot delete teams while SCIM Push Groups is enabled for this project",
|
|
225
|
+
);
|
|
226
|
+
expect(memberDelete).not.toHaveBeenCalled();
|
|
227
|
+
},
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
test.each(UNLOCKED_MATRIX)(
|
|
231
|
+
"SCIM not active (%s): creating a team is not locked and SCIM is not consulted",
|
|
232
|
+
async (_label: string, editionCase: EditionStateCase) => {
|
|
233
|
+
editionCase.apply();
|
|
234
|
+
|
|
235
|
+
await expect(createTeam(userProps())).resolves.toEqual(
|
|
236
|
+
expect.objectContaining({ carryForward: null }),
|
|
237
|
+
);
|
|
238
|
+
expect(scimCount).not.toHaveBeenCalled();
|
|
239
|
+
},
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
test.each(UNLOCKED_MATRIX)(
|
|
243
|
+
"SCIM not active (%s): deleting a team is not locked",
|
|
244
|
+
async (_label: string, editionCase: EditionStateCase) => {
|
|
245
|
+
editionCase.apply();
|
|
246
|
+
|
|
247
|
+
await expect(deleteTeam(userProps())).resolves.toEqual(
|
|
248
|
+
expect.objectContaining({ carryForward: null }),
|
|
249
|
+
);
|
|
250
|
+
expect(scimCount).not.toHaveBeenCalled();
|
|
251
|
+
expect(memberDelete).toHaveBeenCalledTimes(1);
|
|
252
|
+
},
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
test("internal root writes are never locked, on either edition", async () => {
|
|
256
|
+
installFakeEnterpriseModule();
|
|
257
|
+
|
|
258
|
+
await expect(createTeam({ isRoot: true })).resolves.toBeDefined();
|
|
259
|
+
await expect(deleteTeam({ isRoot: true })).resolves.toBeDefined();
|
|
260
|
+
expect(scimCount).not.toHaveBeenCalled();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("with Push Groups off the Enterprise Edition does not lock either", async () => {
|
|
264
|
+
installFakeEnterpriseModule();
|
|
265
|
+
scimCount.mockResolvedValue(new PositiveNumber(0));
|
|
266
|
+
|
|
267
|
+
await expect(createTeam(userProps())).resolves.toBeDefined();
|
|
268
|
+
await expect(deleteTeam(userProps())).resolves.toBeDefined();
|
|
269
|
+
expect(scimCount).toHaveBeenCalled();
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
describe("TeamMemberService: inviting and removing members", () => {
|
|
274
|
+
const inviteMember: (props: Record<string, unknown>) => Promise<unknown> = (
|
|
275
|
+
props: Record<string, unknown>,
|
|
276
|
+
): Promise<unknown> => {
|
|
277
|
+
const member: TeamMember = new TeamMember();
|
|
278
|
+
member.projectId = PROJECT_ID;
|
|
279
|
+
member.teamId = TEAM_ID;
|
|
280
|
+
member.userId = INVITEE_ID;
|
|
281
|
+
|
|
282
|
+
return (TeamMemberService as any).onBeforeCreate({
|
|
283
|
+
data: member,
|
|
284
|
+
props: props,
|
|
285
|
+
});
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const removeMember: (props: Record<string, unknown>) => Promise<unknown> = (
|
|
289
|
+
props: Record<string, unknown>,
|
|
290
|
+
): Promise<unknown> => {
|
|
291
|
+
return (TeamMemberService as any).onBeforeDelete({
|
|
292
|
+
query: { teamId: TEAM_ID, userId: INVITEE_ID },
|
|
293
|
+
props: props,
|
|
294
|
+
});
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
let memberLookup: SpyInstance;
|
|
298
|
+
|
|
299
|
+
beforeEach(() => {
|
|
300
|
+
getJestSpyOn(TeamService, "findOneBy").mockResolvedValue(buildTeam());
|
|
301
|
+
getJestSpyOn(
|
|
302
|
+
TeamPermissionService,
|
|
303
|
+
"assertCanGrantTeamPermissions",
|
|
304
|
+
).mockResolvedValue(undefined);
|
|
305
|
+
// "Is this user already invited?" - no.
|
|
306
|
+
getJestSpyOn(TeamMemberService, "findOneBy").mockResolvedValue(null);
|
|
307
|
+
memberLookup = getJestSpyOn(
|
|
308
|
+
TeamMemberService,
|
|
309
|
+
"findBy",
|
|
310
|
+
).mockResolvedValue([buildMember({ shouldHaveAtLeastOneMember: false })]);
|
|
311
|
+
getJestSpyOn(
|
|
312
|
+
OnCallDutyPolicyTimeLogService,
|
|
313
|
+
"endTimeForUser",
|
|
314
|
+
).mockResolvedValue(undefined);
|
|
315
|
+
// The billing seat check (billing on) finds no seat limit.
|
|
316
|
+
getJestSpyOn(ProjectService, "findOneById").mockResolvedValue(null);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test.each(LOCKED_MATRIX)(
|
|
320
|
+
"SCIM active (%s): inviting a member is locked",
|
|
321
|
+
async (_label: string, editionCase: EditionStateCase) => {
|
|
322
|
+
editionCase.apply();
|
|
323
|
+
|
|
324
|
+
await expect(inviteMember(userProps())).rejects.toThrow(
|
|
325
|
+
"Cannot invite team members while SCIM Push Groups is enabled for this project",
|
|
326
|
+
);
|
|
327
|
+
},
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
test.each(LOCKED_MATRIX)(
|
|
331
|
+
"SCIM active (%s): removing a member is locked",
|
|
332
|
+
async (_label: string, editionCase: EditionStateCase) => {
|
|
333
|
+
editionCase.apply();
|
|
334
|
+
|
|
335
|
+
await expect(removeMember(userProps())).rejects.toThrow(
|
|
336
|
+
"Cannot delete team members while SCIM Push Groups is enabled for this project",
|
|
337
|
+
);
|
|
338
|
+
},
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
test.each(UNLOCKED_MATRIX)(
|
|
342
|
+
"SCIM not active (%s): inviting a member is not locked",
|
|
343
|
+
async (_label: string, editionCase: EditionStateCase) => {
|
|
344
|
+
editionCase.apply();
|
|
345
|
+
|
|
346
|
+
await expect(inviteMember(userProps())).resolves.toEqual(
|
|
347
|
+
expect.objectContaining({ carryForward: null }),
|
|
348
|
+
);
|
|
349
|
+
expect(scimCount).not.toHaveBeenCalled();
|
|
350
|
+
},
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
test.each(UNLOCKED_MATRIX)(
|
|
354
|
+
"SCIM not active (%s): removing a member is not locked",
|
|
355
|
+
async (_label: string, editionCase: EditionStateCase) => {
|
|
356
|
+
editionCase.apply();
|
|
357
|
+
|
|
358
|
+
await expect(removeMember(userProps())).resolves.toEqual(
|
|
359
|
+
expect.objectContaining({ deleteBy: expect.anything() }),
|
|
360
|
+
);
|
|
361
|
+
expect(scimCount).not.toHaveBeenCalled();
|
|
362
|
+
},
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
describe("the one-member guard", () => {
|
|
366
|
+
beforeEach(() => {
|
|
367
|
+
memberLookup.mockResolvedValue([
|
|
368
|
+
buildMember({ shouldHaveAtLeastOneMember: true }),
|
|
369
|
+
]);
|
|
370
|
+
// The member being removed is the team's last accepted member.
|
|
371
|
+
getJestSpyOn(TeamMemberService, "countBy").mockResolvedValue(
|
|
372
|
+
new PositiveNumber(1),
|
|
373
|
+
);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
test("is lifted while SCIM is active and Push Groups owns the team (the IdP may empty it)", async () => {
|
|
377
|
+
installFakeEnterpriseModule({
|
|
378
|
+
snapshot: createLicenseSnapshotWithStatus("grace"),
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
await expect(removeMember({ isRoot: true })).resolves.toBeDefined();
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
test("applies again once the license lapsed, because no IdP manages the team any more", async () => {
|
|
385
|
+
installFakeEnterpriseModule({
|
|
386
|
+
snapshot: createLicenseSnapshotWithStatus("expired"),
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
await expect(removeMember({ isRoot: true })).rejects.toThrow(
|
|
390
|
+
Errors.TeamMemberService.ONE_MEMBER_REQUIRED,
|
|
391
|
+
);
|
|
392
|
+
expect(scimCount).not.toHaveBeenCalled();
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
test("applies on the Community Edition, where no IdP manages the team", async () => {
|
|
396
|
+
await expect(removeMember({ isRoot: true })).rejects.toThrow(
|
|
397
|
+
Errors.TeamMemberService.ONE_MEMBER_REQUIRED,
|
|
398
|
+
);
|
|
399
|
+
expect(scimCount).not.toHaveBeenCalled();
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
test("internal root invites are never locked", async () => {
|
|
404
|
+
installFakeEnterpriseModule();
|
|
405
|
+
|
|
406
|
+
await expect(inviteMember({ isRoot: true })).resolves.toBeDefined();
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
test("the lock follows the license at write time: relaxed while lapsed, back after renewal", async () => {
|
|
410
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
|
|
411
|
+
snapshot: createLicenseSnapshotWithStatus("valid"),
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
await expect(inviteMember(userProps())).rejects.toThrow(
|
|
415
|
+
"Cannot invite team members while SCIM Push Groups is enabled for this project",
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("missing"));
|
|
419
|
+
|
|
420
|
+
await expect(inviteMember(userProps())).resolves.toEqual(
|
|
421
|
+
expect.objectContaining({ carryForward: null }),
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
|
|
425
|
+
|
|
426
|
+
await expect(inviteMember(userProps())).rejects.toThrow(
|
|
427
|
+
"Cannot invite team members while SCIM Push Groups is enabled for this project",
|
|
428
|
+
);
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
});
|