@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
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterAll,
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
jest,
|
|
8
|
+
test,
|
|
9
|
+
} from "@jest/globals";
|
|
10
|
+
import EnterpriseEdition, {
|
|
11
|
+
EnterpriseFeatureStateChange,
|
|
12
|
+
RUNTIME_ENTERPRISE_FEATURES,
|
|
13
|
+
} from "../../../Server/Enterprise/EnterpriseEdition";
|
|
14
|
+
import EnterpriseFeature, {
|
|
15
|
+
ALL_ENTERPRISE_FEATURES,
|
|
16
|
+
} from "../../../Server/Enterprise/EnterpriseFeature";
|
|
17
|
+
import { EnterpriseLicenseSnapshot } from "../../../Server/Enterprise/EnterpriseLicenseSnapshot";
|
|
18
|
+
import logger from "../../../Server/Utils/Logger";
|
|
19
|
+
import FakeEnterpriseModule, {
|
|
20
|
+
createLicenseSnapshot,
|
|
21
|
+
createLicenseSnapshotWithStatus,
|
|
22
|
+
createEditionStateCases,
|
|
23
|
+
EditionStateCase,
|
|
24
|
+
installFakeEnterpriseModule,
|
|
25
|
+
LICENSE_STATE_CASES,
|
|
26
|
+
LicenseStateCase,
|
|
27
|
+
uninstallEnterpriseModule,
|
|
28
|
+
} from "./FakeEnterpriseModule";
|
|
29
|
+
import { setTestBillingEnabled } from "./TestBillingFlag";
|
|
30
|
+
import { getJestSpyOn } from "../../Spy";
|
|
31
|
+
|
|
32
|
+
type SpyInstance = ReturnType<typeof getJestSpyOn>;
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* EnterpriseEdition.isFeatureActive: whether a feature's RUNTIME behaviour
|
|
36
|
+
* (SSO sign-in and "Require SSO" enforcement, SCIM provisioning and its team
|
|
37
|
+
* locks, audit-log recording) runs right now.
|
|
38
|
+
*
|
|
39
|
+
* - Community Edition: never;
|
|
40
|
+
* - billing on (OneUptime Cloud): always, plan tiers gate instead;
|
|
41
|
+
* - self-hosted: while the license covers the feature (valid, grace, trial,
|
|
42
|
+
* accepted unverified legacy), and NOT once it lapsed (expired past grace,
|
|
43
|
+
* missing past the trial, invalid, feature not in the license);
|
|
44
|
+
* - unknown license state (not read yet, unreadable, or no license with no
|
|
45
|
+
* recorded trial start): active, with one warning per process - an
|
|
46
|
+
* unknown state must never lock anyone out or relax SSO.
|
|
47
|
+
*
|
|
48
|
+
* A change of answer is logged once per change and reported to listeners.
|
|
49
|
+
* Billing is pinned through the mocked EnvironmentConfig (CI's config.env sets
|
|
50
|
+
* BILLING_ENABLED=true). This suite must pass with ee/ deleted.
|
|
51
|
+
*/
|
|
52
|
+
jest.mock("../../../Server/EnvironmentConfig", () => {
|
|
53
|
+
const billingFlag: typeof import("./TestBillingFlag") = jest.requireActual(
|
|
54
|
+
"./TestBillingFlag",
|
|
55
|
+
) as typeof import("./TestBillingFlag");
|
|
56
|
+
|
|
57
|
+
return billingFlag.withLiveBillingFlag(
|
|
58
|
+
jest.requireActual("../../../Server/EnvironmentConfig") as Record<
|
|
59
|
+
string,
|
|
60
|
+
unknown
|
|
61
|
+
>,
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
let warn: SpyInstance;
|
|
66
|
+
let info: SpyInstance;
|
|
67
|
+
let error: SpyInstance;
|
|
68
|
+
|
|
69
|
+
const warnings: () => Array<string> = (): Array<string> => {
|
|
70
|
+
return warn.mock.calls
|
|
71
|
+
.map((call: Array<unknown>): unknown => {
|
|
72
|
+
return call[0];
|
|
73
|
+
})
|
|
74
|
+
.filter((value: unknown): value is string => {
|
|
75
|
+
return typeof value === "string";
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const infos: () => Array<string> = (): Array<string> => {
|
|
80
|
+
return info.mock.calls
|
|
81
|
+
.map((call: Array<unknown>): unknown => {
|
|
82
|
+
return call[0];
|
|
83
|
+
})
|
|
84
|
+
.filter((value: unknown): value is string => {
|
|
85
|
+
return typeof value === "string";
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const lapseWarnings: () => Array<string> = (): Array<string> => {
|
|
90
|
+
return warnings().filter((message: string): boolean => {
|
|
91
|
+
return message.startsWith("The OneUptime Enterprise license");
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
beforeEach(() => {
|
|
96
|
+
uninstallEnterpriseModule();
|
|
97
|
+
setTestBillingEnabled(false);
|
|
98
|
+
warn = getJestSpyOn(logger, "warn").mockImplementation((): void => {
|
|
99
|
+
return undefined;
|
|
100
|
+
});
|
|
101
|
+
info = getJestSpyOn(logger, "info").mockImplementation((): void => {
|
|
102
|
+
return undefined;
|
|
103
|
+
});
|
|
104
|
+
error = getJestSpyOn(logger, "error").mockImplementation((): void => {
|
|
105
|
+
return undefined;
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
afterEach(() => {
|
|
110
|
+
uninstallEnterpriseModule();
|
|
111
|
+
setTestBillingEnabled(false);
|
|
112
|
+
jest.restoreAllMocks();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
afterAll(() => {
|
|
116
|
+
uninstallEnterpriseModule();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe("isFeatureActive matrix", () => {
|
|
120
|
+
const cases: Array<EditionStateCase> = createEditionStateCases();
|
|
121
|
+
|
|
122
|
+
test("the matrix covers both editions, both billing values and every license state", () => {
|
|
123
|
+
expect(cases).toHaveLength(2 * (1 + LICENSE_STATE_CASES.length));
|
|
124
|
+
expect(
|
|
125
|
+
cases.filter((editionCase: EditionStateCase): boolean => {
|
|
126
|
+
return editionCase.isActive;
|
|
127
|
+
}).length,
|
|
128
|
+
).toBeGreaterThan(0);
|
|
129
|
+
expect(
|
|
130
|
+
cases.filter((editionCase: EditionStateCase): boolean => {
|
|
131
|
+
return !editionCase.isActive && editionCase.isLoaded;
|
|
132
|
+
}).length,
|
|
133
|
+
).toBeGreaterThan(0);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test.each(
|
|
137
|
+
cases.map((editionCase: EditionStateCase): [string, EditionStateCase] => {
|
|
138
|
+
return [editionCase.label, editionCase];
|
|
139
|
+
}),
|
|
140
|
+
)("%s", (_label: string, editionCase: EditionStateCase) => {
|
|
141
|
+
editionCase.apply();
|
|
142
|
+
|
|
143
|
+
for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
|
|
144
|
+
expect(`${feature}: ${EnterpriseEdition.isFeatureActive(feature)}`).toBe(
|
|
145
|
+
`${feature}: ${editionCase.isActive}`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
expect(EnterpriseEdition.isLoaded()).toBe(editionCase.isLoaded);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test.each(
|
|
153
|
+
LICENSE_STATE_CASES.map(
|
|
154
|
+
(licenseState: LicenseStateCase): [string, LicenseStateCase] => {
|
|
155
|
+
return [licenseState.label, licenseState];
|
|
156
|
+
},
|
|
157
|
+
),
|
|
158
|
+
)(
|
|
159
|
+
"billing off, %s: differs from isFeatureAvailableSync only in the unknown states",
|
|
160
|
+
(_label: string, licenseState: LicenseStateCase) => {
|
|
161
|
+
licenseState.install();
|
|
162
|
+
|
|
163
|
+
for (const feature of ALL_ENTERPRISE_FEATURES) {
|
|
164
|
+
const isActive: boolean = EnterpriseEdition.isFeatureActive(feature);
|
|
165
|
+
const isAvailable: boolean =
|
|
166
|
+
EnterpriseEdition.isFeatureAvailableSync(feature);
|
|
167
|
+
|
|
168
|
+
if (licenseState.isUnknown) {
|
|
169
|
+
expect({ feature, isActive, isAvailable }).toEqual({
|
|
170
|
+
feature,
|
|
171
|
+
isActive: true,
|
|
172
|
+
isAvailable: false,
|
|
173
|
+
});
|
|
174
|
+
} else {
|
|
175
|
+
expect({ feature, isActive }).toEqual({
|
|
176
|
+
feature,
|
|
177
|
+
isActive: isAvailable,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
test("the Community Edition never reads anything and is never active", () => {
|
|
185
|
+
for (const billing of [false, true]) {
|
|
186
|
+
setTestBillingEnabled(billing);
|
|
187
|
+
|
|
188
|
+
for (const feature of ALL_ENTERPRISE_FEATURES) {
|
|
189
|
+
expect(EnterpriseEdition.isFeatureActive(feature)).toBe(false);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
expect(warn).not.toHaveBeenCalled();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("billing on never reads the license (the Cloud gates by plan)", () => {
|
|
197
|
+
setTestBillingEnabled(true);
|
|
198
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
|
|
199
|
+
snapshot: createLicenseSnapshotWithStatus("expired"),
|
|
200
|
+
});
|
|
201
|
+
fake.licensing.getCachedSnapshotError = new Error("must not be read");
|
|
202
|
+
|
|
203
|
+
for (const feature of ALL_ENTERPRISE_FEATURES) {
|
|
204
|
+
expect(EnterpriseEdition.isFeatureActive(feature)).toBe(true);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
expect(warn).not.toHaveBeenCalled();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("a license that leaves out one feature stops only that feature", () => {
|
|
211
|
+
installFakeEnterpriseModule({
|
|
212
|
+
snapshot: createLicenseSnapshot({
|
|
213
|
+
features: ALL_ENTERPRISE_FEATURES.filter(
|
|
214
|
+
(feature: EnterpriseFeature): boolean => {
|
|
215
|
+
return feature !== EnterpriseFeature.SCIM;
|
|
216
|
+
},
|
|
217
|
+
),
|
|
218
|
+
}),
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(true);
|
|
222
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM)).toBe(
|
|
223
|
+
false,
|
|
224
|
+
);
|
|
225
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.AuditLogs)).toBe(
|
|
226
|
+
true,
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test("the answer follows the license at call time (renewal and lapse without a restart)", () => {
|
|
231
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
|
|
232
|
+
snapshot: createLicenseSnapshotWithStatus("expired"),
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
236
|
+
false,
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
|
|
240
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(true);
|
|
241
|
+
|
|
242
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("invalid"));
|
|
243
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
244
|
+
false,
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe("an unknown license state counts as active, and is warned about once", () => {
|
|
250
|
+
test("not read yet: active, one warning however many calls", () => {
|
|
251
|
+
installFakeEnterpriseModule({ snapshot: null });
|
|
252
|
+
|
|
253
|
+
for (let call: number = 0; call < 25; call++) {
|
|
254
|
+
for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
|
|
255
|
+
expect(EnterpriseEdition.isFeatureActive(feature)).toBe(true);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
expect(warnings()).toHaveLength(1);
|
|
260
|
+
expect(warnings()[0]).toContain("has not been read yet");
|
|
261
|
+
expect(warnings()[0]).toContain("once per process");
|
|
262
|
+
expect(lapseWarnings()).toEqual([]);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
test("unreadable: active, one warning (plus the error) however many calls", () => {
|
|
266
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
|
|
267
|
+
const readError: Error = new Error("snapshot exploded");
|
|
268
|
+
fake.licensing.getCachedSnapshotError = readError;
|
|
269
|
+
|
|
270
|
+
for (let call: number = 0; call < 25; call++) {
|
|
271
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
272
|
+
true,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
expect(warn).toHaveBeenCalledTimes(2);
|
|
277
|
+
expect(warnings()[0]).toContain("could not read the cached license");
|
|
278
|
+
expect(warn).toHaveBeenCalledWith(readError);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
test("an unknown state never counts as a lapse, and does not hide a later one", () => {
|
|
282
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
|
|
283
|
+
snapshot: createLicenseSnapshotWithStatus("valid"),
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(true);
|
|
287
|
+
|
|
288
|
+
fake.setSnapshot(null);
|
|
289
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(true);
|
|
290
|
+
expect(lapseWarnings()).toEqual([]);
|
|
291
|
+
|
|
292
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("expired"));
|
|
293
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
294
|
+
false,
|
|
295
|
+
);
|
|
296
|
+
expect(lapseWarnings()).toHaveLength(1);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
/*
|
|
300
|
+
* An upgraded install's first Enterprise boot whose first-run stamp could
|
|
301
|
+
* not be written (or whose GlobalConfig row does not exist yet): the
|
|
302
|
+
* classifier says "missing" with no graceEndsAt, because it cannot tell
|
|
303
|
+
* when the trial started - so it cannot tell whether the trial is over.
|
|
304
|
+
*/
|
|
305
|
+
describe("no license, and the trial start is not recorded yet", () => {
|
|
306
|
+
const unknownTrialStart: () => EnterpriseLicenseSnapshot =
|
|
307
|
+
(): EnterpriseLicenseSnapshot => {
|
|
308
|
+
return createLicenseSnapshotWithStatus("missing", {
|
|
309
|
+
graceEndsAt: undefined,
|
|
310
|
+
});
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
test("is active for every runtime feature, with one warning however many calls", () => {
|
|
314
|
+
installFakeEnterpriseModule({ snapshot: unknownTrialStart() });
|
|
315
|
+
|
|
316
|
+
for (let call: number = 0; call < 25; call++) {
|
|
317
|
+
for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
|
|
318
|
+
expect(EnterpriseEdition.isFeatureActive(feature)).toBe(true);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
expect(warnings()).toHaveLength(1);
|
|
323
|
+
expect(warnings()[0]).toContain(
|
|
324
|
+
"the start of the 14-day trial has not been recorded yet",
|
|
325
|
+
);
|
|
326
|
+
expect(warnings()[0]).toContain("once per process");
|
|
327
|
+
expect(lapseWarnings()).toEqual([]);
|
|
328
|
+
expect(info).not.toHaveBeenCalled();
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
test("configuration still fails closed", () => {
|
|
332
|
+
installFakeEnterpriseModule({ snapshot: unknownTrialStart() });
|
|
333
|
+
|
|
334
|
+
for (const feature of ALL_ENTERPRISE_FEATURES) {
|
|
335
|
+
expect(EnterpriseEdition.isFeatureAvailableSync(feature)).toBe(false);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
test("negative control: the same install once the trial is known to be over has lapsed", () => {
|
|
340
|
+
installFakeEnterpriseModule({
|
|
341
|
+
snapshot: createLicenseSnapshotWithStatus("missing", {
|
|
342
|
+
graceEndsAt: new Date(Date.now() - 1000),
|
|
343
|
+
}),
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
|
|
347
|
+
expect(EnterpriseEdition.isFeatureActive(feature)).toBe(false);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
expect(lapseWarnings()).toHaveLength(1);
|
|
351
|
+
expect(lapseWarnings()[0]).toContain("has lapsed (status: missing)");
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test("is not reported to listeners, and does not hide a later lapse", () => {
|
|
355
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
|
|
356
|
+
snapshot: createLicenseSnapshotWithStatus("valid"),
|
|
357
|
+
});
|
|
358
|
+
const changes: Array<EnterpriseFeatureStateChange> = [];
|
|
359
|
+
|
|
360
|
+
EnterpriseEdition.onFeatureStateChange(
|
|
361
|
+
(change: EnterpriseFeatureStateChange): void => {
|
|
362
|
+
changes.push(change);
|
|
363
|
+
},
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
367
|
+
true,
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
fake.setSnapshot(unknownTrialStart());
|
|
371
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
372
|
+
true,
|
|
373
|
+
);
|
|
374
|
+
expect(changes).toEqual([]);
|
|
375
|
+
|
|
376
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("missing"));
|
|
377
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
378
|
+
false,
|
|
379
|
+
);
|
|
380
|
+
expect(changes).toHaveLength(1);
|
|
381
|
+
expect(changes[0]!.stopped).toContain(EnterpriseFeature.SSO);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
test("billing on never reads it (the Cloud gates by plan)", () => {
|
|
385
|
+
setTestBillingEnabled(true);
|
|
386
|
+
installFakeEnterpriseModule({ snapshot: unknownTrialStart() });
|
|
387
|
+
|
|
388
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
389
|
+
true,
|
|
390
|
+
);
|
|
391
|
+
expect(warn).not.toHaveBeenCalled();
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
test("resetForTests forgets the one-time warning (a fresh process warns again)", () => {
|
|
396
|
+
installFakeEnterpriseModule({ snapshot: null });
|
|
397
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
398
|
+
|
|
399
|
+
installFakeEnterpriseModule({ snapshot: null });
|
|
400
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
401
|
+
|
|
402
|
+
expect(warnings()).toHaveLength(2);
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
describe("state changes are logged once per change", () => {
|
|
407
|
+
test("a license that has already lapsed at boot is reported once, naming everything that stopped", () => {
|
|
408
|
+
installFakeEnterpriseModule({
|
|
409
|
+
snapshot: createLicenseSnapshotWithStatus("expired", {
|
|
410
|
+
message: "The license expired on 2026-01-01.",
|
|
411
|
+
}),
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
for (let call: number = 0; call < 10; call++) {
|
|
415
|
+
for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
|
|
416
|
+
expect(EnterpriseEdition.isFeatureActive(feature)).toBe(false);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
expect(lapseWarnings()).toHaveLength(1);
|
|
421
|
+
|
|
422
|
+
const message: string = lapseWarnings()[0]!;
|
|
423
|
+
|
|
424
|
+
expect(message).toContain(
|
|
425
|
+
"The OneUptime Enterprise license has lapsed (status: expired)",
|
|
426
|
+
);
|
|
427
|
+
expect(message).toContain(
|
|
428
|
+
"single sign-on (SSO), SCIM provisioning and audit logging have stopped until a license is activated",
|
|
429
|
+
);
|
|
430
|
+
expect(message).toContain('"Require SSO for login" is not enforced');
|
|
431
|
+
expect(message).toContain("reset their password");
|
|
432
|
+
expect(message).toContain(
|
|
433
|
+
"License status: The license expired on 2026-01-01.",
|
|
434
|
+
);
|
|
435
|
+
expect(info).not.toHaveBeenCalled();
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
test("a valid license at boot logs nothing", () => {
|
|
439
|
+
installFakeEnterpriseModule();
|
|
440
|
+
|
|
441
|
+
for (const feature of ALL_ENTERPRISE_FEATURES) {
|
|
442
|
+
EnterpriseEdition.isFeatureActive(feature);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
expect(warn).not.toHaveBeenCalled();
|
|
446
|
+
expect(info).not.toHaveBeenCalled();
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test("lapse, renewal and lapse again: one warning, one info line, one warning", () => {
|
|
450
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
|
|
451
|
+
|
|
452
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
453
|
+
expect(lapseWarnings()).toHaveLength(0);
|
|
454
|
+
|
|
455
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("missing"));
|
|
456
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.AuditLogs);
|
|
457
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
458
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
|
|
459
|
+
expect(lapseWarnings()).toHaveLength(1);
|
|
460
|
+
expect(lapseWarnings()[0]).toContain("has lapsed (status: missing)");
|
|
461
|
+
|
|
462
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
|
|
463
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
|
|
464
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
465
|
+
expect(infos()).toEqual([
|
|
466
|
+
"The OneUptime Enterprise license covers single sign-on (SSO), SCIM provisioning and audit logging again: they have resumed.",
|
|
467
|
+
]);
|
|
468
|
+
|
|
469
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("invalid"));
|
|
470
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
471
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
472
|
+
expect(lapseWarnings()).toHaveLength(2);
|
|
473
|
+
expect(lapseWarnings()[1]).toContain("has lapsed (status: invalid)");
|
|
474
|
+
expect(infos()).toHaveLength(1);
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
test("a license without one feature names only that feature, as not included", () => {
|
|
478
|
+
installFakeEnterpriseModule({
|
|
479
|
+
snapshot: createLicenseSnapshot({
|
|
480
|
+
features: [
|
|
481
|
+
EnterpriseFeature.SSO,
|
|
482
|
+
EnterpriseFeature.AuditLogs,
|
|
483
|
+
EnterpriseFeature.TeamCompliance,
|
|
484
|
+
],
|
|
485
|
+
}),
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
489
|
+
expect(lapseWarnings()).toHaveLength(0);
|
|
490
|
+
|
|
491
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
|
|
492
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
|
|
493
|
+
|
|
494
|
+
expect(lapseWarnings()).toEqual([
|
|
495
|
+
"The OneUptime Enterprise license does not include SCIM provisioning: it has stopped until a license that includes it is activated. A master admin can activate or renew the license from the edition label in the Admin Dashboard header.",
|
|
496
|
+
]);
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
test("billing on never logs a change, whatever the license", () => {
|
|
500
|
+
setTestBillingEnabled(true);
|
|
501
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
|
|
502
|
+
snapshot: createLicenseSnapshotWithStatus("expired"),
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
506
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
|
|
507
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
508
|
+
|
|
509
|
+
expect(warn).not.toHaveBeenCalled();
|
|
510
|
+
expect(info).not.toHaveBeenCalled();
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
test("a logger that throws never changes the answer", () => {
|
|
514
|
+
warn.mockImplementation((): void => {
|
|
515
|
+
throw new Error("log sink down");
|
|
516
|
+
});
|
|
517
|
+
installFakeEnterpriseModule({
|
|
518
|
+
snapshot: createLicenseSnapshotWithStatus("expired"),
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
522
|
+
false,
|
|
523
|
+
);
|
|
524
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
525
|
+
false,
|
|
526
|
+
);
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
describe("onFeatureStateChange", () => {
|
|
531
|
+
test("listeners hear each change once, with what stopped and what resumed", () => {
|
|
532
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
|
|
533
|
+
const changes: Array<EnterpriseFeatureStateChange> = [];
|
|
534
|
+
|
|
535
|
+
EnterpriseEdition.onFeatureStateChange(
|
|
536
|
+
(change: EnterpriseFeatureStateChange): void => {
|
|
537
|
+
changes.push(change);
|
|
538
|
+
},
|
|
539
|
+
);
|
|
540
|
+
|
|
541
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
542
|
+
expect(changes).toHaveLength(0);
|
|
543
|
+
|
|
544
|
+
const lapsed: EnterpriseLicenseSnapshot =
|
|
545
|
+
createLicenseSnapshotWithStatus("expired");
|
|
546
|
+
fake.setSnapshot(lapsed);
|
|
547
|
+
|
|
548
|
+
for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
|
|
549
|
+
EnterpriseEdition.isFeatureActive(feature);
|
|
550
|
+
EnterpriseEdition.isFeatureActive(feature);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
expect(changes).toEqual([
|
|
554
|
+
{
|
|
555
|
+
stopped: [
|
|
556
|
+
EnterpriseFeature.SSO,
|
|
557
|
+
EnterpriseFeature.SCIM,
|
|
558
|
+
EnterpriseFeature.AuditLogs,
|
|
559
|
+
],
|
|
560
|
+
resumed: [],
|
|
561
|
+
snapshot: lapsed,
|
|
562
|
+
},
|
|
563
|
+
]);
|
|
564
|
+
|
|
565
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
|
|
566
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
|
|
567
|
+
|
|
568
|
+
expect(changes).toHaveLength(2);
|
|
569
|
+
expect(changes[1]!.stopped).toEqual([]);
|
|
570
|
+
expect(changes[1]!.resumed).toEqual([
|
|
571
|
+
EnterpriseFeature.SSO,
|
|
572
|
+
EnterpriseFeature.SCIM,
|
|
573
|
+
EnterpriseFeature.AuditLogs,
|
|
574
|
+
]);
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
test("a listener that throws is logged and never breaks the check or the other listeners", () => {
|
|
578
|
+
installFakeEnterpriseModule({
|
|
579
|
+
snapshot: createLicenseSnapshotWithStatus("expired"),
|
|
580
|
+
});
|
|
581
|
+
const heard: Array<string> = [];
|
|
582
|
+
|
|
583
|
+
EnterpriseEdition.onFeatureStateChange((): void => {
|
|
584
|
+
throw new Error("listener exploded");
|
|
585
|
+
});
|
|
586
|
+
EnterpriseEdition.onFeatureStateChange((): void => {
|
|
587
|
+
heard.push("second");
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
|
|
591
|
+
false,
|
|
592
|
+
);
|
|
593
|
+
expect(heard).toEqual(["second"]);
|
|
594
|
+
expect(error).toHaveBeenCalled();
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
test("the returned function removes the listener", () => {
|
|
598
|
+
const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
|
|
599
|
+
const heard: Array<EnterpriseFeatureStateChange> = [];
|
|
600
|
+
|
|
601
|
+
const stop: () => void = EnterpriseEdition.onFeatureStateChange(
|
|
602
|
+
(change: EnterpriseFeatureStateChange): void => {
|
|
603
|
+
heard.push(change);
|
|
604
|
+
},
|
|
605
|
+
);
|
|
606
|
+
stop();
|
|
607
|
+
|
|
608
|
+
fake.setSnapshot(createLicenseSnapshotWithStatus("expired"));
|
|
609
|
+
EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
|
|
610
|
+
|
|
611
|
+
expect(heard).toEqual([]);
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
describe("describeStoppedFeatures / describeResumedFeatures", () => {
|
|
616
|
+
test("nothing stopped or resumed is no line at all", () => {
|
|
617
|
+
expect(
|
|
618
|
+
EnterpriseEdition.describeStoppedFeatures(
|
|
619
|
+
[],
|
|
620
|
+
createLicenseSnapshotWithStatus("expired"),
|
|
621
|
+
),
|
|
622
|
+
).toBeNull();
|
|
623
|
+
expect(EnterpriseEdition.describeResumedFeatures([])).toBeNull();
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
test("audit logging alone does not mention SSO enforcement", () => {
|
|
627
|
+
const message: string | null = EnterpriseEdition.describeStoppedFeatures(
|
|
628
|
+
[EnterpriseFeature.AuditLogs],
|
|
629
|
+
createLicenseSnapshotWithStatus("expired"),
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
expect(message).toContain("audit logging has stopped");
|
|
633
|
+
expect(message).not.toContain("Require SSO");
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
test("one resumed feature reads in the singular", () => {
|
|
637
|
+
expect(
|
|
638
|
+
EnterpriseEdition.describeResumedFeatures([EnterpriseFeature.SSO]),
|
|
639
|
+
).toBe(
|
|
640
|
+
"The OneUptime Enterprise license covers single sign-on (SSO) again: it has resumed.",
|
|
641
|
+
);
|
|
642
|
+
});
|
|
643
|
+
});
|