@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,667 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import {
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
jest,
|
|
8
|
+
test,
|
|
9
|
+
} from "@jest/globals";
|
|
10
|
+
import { act, cleanup, render, screen } from "@testing-library/react";
|
|
11
|
+
import React, {
|
|
12
|
+
FunctionComponent,
|
|
13
|
+
ReactElement,
|
|
14
|
+
forwardRef,
|
|
15
|
+
useImperativeHandle,
|
|
16
|
+
} from "react";
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
* The Dashboard's Enterprise plugin door and the component every enterprise
|
|
20
|
+
* shell renders.
|
|
21
|
+
*
|
|
22
|
+
* A shell (Settings > SSO, the audit log table, ...) stays at its original
|
|
23
|
+
* path in core and renders <EnterprisePluginPage>: the ee plugin when the
|
|
24
|
+
* project may use the feature AND this bundle includes it, the upsell card
|
|
25
|
+
* otherwise. The plugins come from getDashboardPlugins(), which in every
|
|
26
|
+
* Community build - and in this jest config, through its moduleNameMapper -
|
|
27
|
+
* is the empty Community stub.
|
|
28
|
+
*
|
|
29
|
+
* Billing and the edition are pinned in every test: CI's config.env sets
|
|
30
|
+
* BILLING_ENABLED=true.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
let billingEnabledForTest: boolean = false;
|
|
34
|
+
let enterpriseEditionForTest: boolean = false;
|
|
35
|
+
let currentPlanForTest: string | null = null;
|
|
36
|
+
|
|
37
|
+
const CLOUD_PLAN_ENV: Record<string, string> = {
|
|
38
|
+
SUBSCRIPTION_PLAN_BASIC: "Free,priceMonthlyId1,priceYearlyId1,0,0,1,0",
|
|
39
|
+
SUBSCRIPTION_PLAN_GROWTH: "Growth,priceMonthlyId2,priceYearlyId2,0,0,2,14",
|
|
40
|
+
SUBSCRIPTION_PLAN_SCALE: "Scale,priceMonthlyId3,priceYearlyId3,0,0,3,0",
|
|
41
|
+
SUBSCRIPTION_PLAN_ENTERPRISE:
|
|
42
|
+
"Enterprise,priceMonthlyId4,priceYearlyId4,-1,-1,4,14",
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
jest.mock("../../../UI/Config", () => {
|
|
46
|
+
const actual: Record<string, unknown> = jest.requireActual(
|
|
47
|
+
"../../../UI/Config",
|
|
48
|
+
) as Record<string, unknown>;
|
|
49
|
+
|
|
50
|
+
const mocked: Record<string, unknown> = { ...actual };
|
|
51
|
+
|
|
52
|
+
Object.defineProperty(mocked, "BILLING_ENABLED", {
|
|
53
|
+
get: (): boolean => {
|
|
54
|
+
return billingEnabledForTest;
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
Object.defineProperty(mocked, "IS_ENTERPRISE_EDITION", {
|
|
59
|
+
get: (): boolean => {
|
|
60
|
+
return enterpriseEditionForTest;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
mocked["getAllEnvVars"] = (): Record<string, string> => {
|
|
65
|
+
return CLOUD_PLAN_ENV;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return mocked;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
jest.mock("../../../UI/Utils/Project", () => {
|
|
72
|
+
const actual: Record<string, any> = jest.requireActual(
|
|
73
|
+
"../../../UI/Utils/Project",
|
|
74
|
+
) as Record<string, any>;
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
__esModule: true,
|
|
78
|
+
...actual,
|
|
79
|
+
default: {
|
|
80
|
+
...actual["default"],
|
|
81
|
+
getCurrentPlan: (): string | null => {
|
|
82
|
+
return currentPlanForTest;
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
import EnterprisePluginPage, {
|
|
89
|
+
getUpgradeReason,
|
|
90
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Enterprise/EnterprisePluginPage";
|
|
91
|
+
import { getDashboardPlugins } from "../../../../App/FeatureSet/Dashboard/src/Enterprise/Plugins";
|
|
92
|
+
import {
|
|
93
|
+
DASHBOARD_ENTERPRISE_PLUGIN_KEYS,
|
|
94
|
+
DashboardEnterprisePlugins,
|
|
95
|
+
EnterprisePluginComponent,
|
|
96
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Enterprise/EnterprisePlugins";
|
|
97
|
+
import {
|
|
98
|
+
AUDIT_LOGS_REQUIRED_PLAN,
|
|
99
|
+
IDENTITY_REQUIRED_PLAN,
|
|
100
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Enterprise/EnterpriseEligibility";
|
|
101
|
+
import { EnterpriseUpgradeReason } from "../../../../App/FeatureSet/Dashboard/src/Components/EnterpriseEdition/EnterpriseFeatureUpgrade";
|
|
102
|
+
import AuditLogsEnterpriseUpgrade from "../../../../App/FeatureSet/Dashboard/src/Components/AuditLogs/AuditLogsEnterpriseUpgrade";
|
|
103
|
+
import PageComponentProps from "../../../../App/FeatureSet/Dashboard/src/Pages/PageComponentProps";
|
|
104
|
+
import Route from "../../../Types/API/Route";
|
|
105
|
+
import { PlanType } from "../../../Types/Billing/SubscriptionPlan";
|
|
106
|
+
import IconProp from "../../../Types/Icon/IconProp";
|
|
107
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
108
|
+
|
|
109
|
+
type Deployment = "cloud" | "self-hosted-enterprise" | "self-hosted-community";
|
|
110
|
+
|
|
111
|
+
const pinDeployment: (deployment: Deployment) => void = (
|
|
112
|
+
deployment: Deployment,
|
|
113
|
+
): void => {
|
|
114
|
+
billingEnabledForTest = deployment === "cloud";
|
|
115
|
+
// The Cloud runs the Enterprise image: its effective edition is true.
|
|
116
|
+
enterpriseEditionForTest = deployment !== "self-hosted-community";
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const PAGE_PROPS: PageComponentProps = {
|
|
120
|
+
pageRoute: new Route("/dashboard/project-id/settings/sso"),
|
|
121
|
+
currentProject: null,
|
|
122
|
+
hasPaymentMethod: true,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const UPSELL: {
|
|
126
|
+
title: string;
|
|
127
|
+
description: string;
|
|
128
|
+
featureName: string;
|
|
129
|
+
benefits: Array<{ icon: IconProp; title: string; subtitle: string }>;
|
|
130
|
+
} = {
|
|
131
|
+
title: "Single Sign On (SSO)",
|
|
132
|
+
description: "Configure SAML SSO for your project.",
|
|
133
|
+
featureName: "SAML Single Sign On",
|
|
134
|
+
benefits: [
|
|
135
|
+
{
|
|
136
|
+
icon: IconProp.Lock,
|
|
137
|
+
title: "Centralized auth",
|
|
138
|
+
subtitle: "Revoke access from one place.",
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const FakeSSOPage: FunctionComponent<PageComponentProps> = (
|
|
144
|
+
props: PageComponentProps,
|
|
145
|
+
): ReactElement => {
|
|
146
|
+
return (
|
|
147
|
+
<div data-testid="fake-sso-plugin">
|
|
148
|
+
{props.pageRoute.toString()}|{String(props.hasPaymentMethod)}
|
|
149
|
+
</div>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
let lazyLoads: number = 0;
|
|
154
|
+
let releaseLazyPlugin: (() => void) | null = null;
|
|
155
|
+
|
|
156
|
+
/*
|
|
157
|
+
* A React.lazy plugin, the shape ee areas hand over. It counts its loads (an
|
|
158
|
+
* ineligible project must never download the ee chunk) and can be held
|
|
159
|
+
* pending to observe the loading state.
|
|
160
|
+
*/
|
|
161
|
+
const makeLazyPlugin: (
|
|
162
|
+
holdUntilReleased: boolean,
|
|
163
|
+
) => EnterprisePluginComponent<PageComponentProps> = (
|
|
164
|
+
holdUntilReleased: boolean,
|
|
165
|
+
): EnterprisePluginComponent<PageComponentProps> => {
|
|
166
|
+
return React.lazy(
|
|
167
|
+
async (): Promise<{ default: FunctionComponent<PageComponentProps> }> => {
|
|
168
|
+
lazyLoads += 1;
|
|
169
|
+
|
|
170
|
+
if (holdUntilReleased) {
|
|
171
|
+
await new Promise<void>((resolve: () => void) => {
|
|
172
|
+
releaseLazyPlugin = resolve;
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return { default: FakeSSOPage };
|
|
177
|
+
},
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
beforeEach(() => {
|
|
182
|
+
billingEnabledForTest = false;
|
|
183
|
+
enterpriseEditionForTest = false;
|
|
184
|
+
currentPlanForTest = null;
|
|
185
|
+
lazyLoads = 0;
|
|
186
|
+
releaseLazyPlugin = null;
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
afterEach(() => {
|
|
190
|
+
cleanup();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe("getUpgradeReason", () => {
|
|
194
|
+
test("an eligible project that still sees the card lacks the Enterprise build, not a plan", () => {
|
|
195
|
+
pinDeployment("cloud");
|
|
196
|
+
expect(getUpgradeReason(true)).toBe(EnterpriseUpgradeReason.Edition);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("an ineligible Cloud project needs a plan", () => {
|
|
200
|
+
pinDeployment("cloud");
|
|
201
|
+
expect(getUpgradeReason(false)).toBe(EnterpriseUpgradeReason.Plan);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test("an ineligible self-hosted install needs the Enterprise Edition", () => {
|
|
205
|
+
pinDeployment("self-hosted-community");
|
|
206
|
+
expect(getUpgradeReason(false)).toBe(EnterpriseUpgradeReason.Edition);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe("EnterprisePluginPage", () => {
|
|
211
|
+
test("renders the plugin, with the shell's props, for an eligible Cloud project", () => {
|
|
212
|
+
pinDeployment("cloud");
|
|
213
|
+
currentPlanForTest = PlanType.Scale;
|
|
214
|
+
|
|
215
|
+
render(
|
|
216
|
+
<EnterprisePluginPage
|
|
217
|
+
plugin={FakeSSOPage}
|
|
218
|
+
pluginProps={PAGE_PROPS}
|
|
219
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
220
|
+
upsell={UPSELL}
|
|
221
|
+
/>,
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
expect(screen.getByTestId("fake-sso-plugin")).toHaveTextContent(
|
|
225
|
+
"/dashboard/project-id/settings/sso|true",
|
|
226
|
+
);
|
|
227
|
+
expect(screen.queryByText("SAML Single Sign On")).not.toBeInTheDocument();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test("shows the plan upsell, and never downloads the plugin, below the tier", () => {
|
|
231
|
+
pinDeployment("cloud");
|
|
232
|
+
currentPlanForTest = PlanType.Growth;
|
|
233
|
+
|
|
234
|
+
render(
|
|
235
|
+
<EnterprisePluginPage
|
|
236
|
+
plugin={makeLazyPlugin(false)}
|
|
237
|
+
pluginProps={PAGE_PROPS}
|
|
238
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
239
|
+
upsell={UPSELL}
|
|
240
|
+
/>,
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
expect(screen.getAllByText("Upgrade to Scale")).toHaveLength(2);
|
|
244
|
+
expect(screen.getByText("SAML Single Sign On")).toBeInTheDocument();
|
|
245
|
+
expect(screen.queryByTestId("fake-sso-plugin")).not.toBeInTheDocument();
|
|
246
|
+
expect(lazyLoads).toBe(0);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test("uses the page's own tier: Scale is not enough for an Enterprise-tier feature", () => {
|
|
250
|
+
pinDeployment("cloud");
|
|
251
|
+
currentPlanForTest = PlanType.Scale;
|
|
252
|
+
|
|
253
|
+
render(
|
|
254
|
+
<EnterprisePluginPage
|
|
255
|
+
plugin={FakeSSOPage}
|
|
256
|
+
pluginProps={PAGE_PROPS}
|
|
257
|
+
requiredPlan={AUDIT_LOGS_REQUIRED_PLAN}
|
|
258
|
+
upsell={UPSELL}
|
|
259
|
+
/>,
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
expect(screen.getAllByText("Upgrade to Enterprise")).toHaveLength(2);
|
|
263
|
+
expect(screen.queryByTestId("fake-sso-plugin")).not.toBeInTheDocument();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test("an eligible Cloud project on a Community bundle is pointed at the edition, never told to upgrade", () => {
|
|
267
|
+
pinDeployment("cloud");
|
|
268
|
+
currentPlanForTest = PlanType.Enterprise;
|
|
269
|
+
|
|
270
|
+
render(
|
|
271
|
+
<EnterprisePluginPage
|
|
272
|
+
plugin={undefined}
|
|
273
|
+
pluginProps={PAGE_PROPS}
|
|
274
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
275
|
+
upsell={UPSELL}
|
|
276
|
+
/>,
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
expect(screen.getAllByText("Learn about Enterprise Edition")).toHaveLength(
|
|
280
|
+
2,
|
|
281
|
+
);
|
|
282
|
+
expect(screen.queryByText("Upgrade to Scale")).not.toBeInTheDocument();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test("self-hosted Enterprise Edition renders the plugin", () => {
|
|
286
|
+
pinDeployment("self-hosted-enterprise");
|
|
287
|
+
|
|
288
|
+
render(
|
|
289
|
+
<EnterprisePluginPage
|
|
290
|
+
plugin={FakeSSOPage}
|
|
291
|
+
pluginProps={PAGE_PROPS}
|
|
292
|
+
requiredPlan={AUDIT_LOGS_REQUIRED_PLAN}
|
|
293
|
+
upsell={UPSELL}
|
|
294
|
+
/>,
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
expect(screen.getByTestId("fake-sso-plugin")).toBeInTheDocument();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test("self-hosted Community Edition shows the edition upsell, plugin or not", () => {
|
|
301
|
+
pinDeployment("self-hosted-community");
|
|
302
|
+
|
|
303
|
+
render(
|
|
304
|
+
<EnterprisePluginPage
|
|
305
|
+
plugin={FakeSSOPage}
|
|
306
|
+
pluginProps={PAGE_PROPS}
|
|
307
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
308
|
+
upsell={UPSELL}
|
|
309
|
+
/>,
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
expect(screen.getAllByText("Learn about Enterprise Edition")).toHaveLength(
|
|
313
|
+
2,
|
|
314
|
+
);
|
|
315
|
+
expect(screen.queryByTestId("fake-sso-plugin")).not.toBeInTheDocument();
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("self-hosted Enterprise Edition on a Community bundle shows the edition upsell", () => {
|
|
319
|
+
pinDeployment("self-hosted-enterprise");
|
|
320
|
+
|
|
321
|
+
render(
|
|
322
|
+
<EnterprisePluginPage
|
|
323
|
+
plugin={undefined}
|
|
324
|
+
pluginProps={PAGE_PROPS}
|
|
325
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
326
|
+
upsell={UPSELL}
|
|
327
|
+
/>,
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
expect(screen.getAllByText("Learn about Enterprise Edition")).toHaveLength(
|
|
331
|
+
2,
|
|
332
|
+
);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
test("a lazy plugin shows the in-card loader, then the plugin", async () => {
|
|
336
|
+
pinDeployment("self-hosted-enterprise");
|
|
337
|
+
|
|
338
|
+
render(
|
|
339
|
+
<EnterprisePluginPage
|
|
340
|
+
plugin={makeLazyPlugin(true)}
|
|
341
|
+
pluginProps={PAGE_PROPS}
|
|
342
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
343
|
+
upsell={UPSELL}
|
|
344
|
+
/>,
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
expect(await screen.findByTestId("component-loader")).toBeInTheDocument();
|
|
348
|
+
expect(screen.queryByTestId("fake-sso-plugin")).not.toBeInTheDocument();
|
|
349
|
+
|
|
350
|
+
await act(async () => {
|
|
351
|
+
releaseLazyPlugin?.();
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
expect(await screen.findByTestId("fake-sso-plugin")).toBeInTheDocument();
|
|
355
|
+
expect(screen.queryByTestId("component-loader")).not.toBeInTheDocument();
|
|
356
|
+
expect(lazyLoads).toBe(1);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
test("uses a caller's loading element while the plugin downloads", async () => {
|
|
360
|
+
pinDeployment("self-hosted-enterprise");
|
|
361
|
+
|
|
362
|
+
render(
|
|
363
|
+
<EnterprisePluginPage
|
|
364
|
+
plugin={makeLazyPlugin(true)}
|
|
365
|
+
pluginProps={PAGE_PROPS}
|
|
366
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
367
|
+
upsell={UPSELL}
|
|
368
|
+
loadingElement={<div data-testid="custom-loading" />}
|
|
369
|
+
/>,
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
expect(await screen.findByTestId("custom-loading")).toBeInTheDocument();
|
|
373
|
+
expect(screen.queryByTestId("component-loader")).not.toBeInTheDocument();
|
|
374
|
+
|
|
375
|
+
await act(async () => {
|
|
376
|
+
releaseLazyPlugin?.();
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
expect(await screen.findByTestId("fake-sso-plugin")).toBeInTheDocument();
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
test("isEligible overrides the plan and edition check, both ways", () => {
|
|
383
|
+
pinDeployment("cloud");
|
|
384
|
+
currentPlanForTest = PlanType.Free;
|
|
385
|
+
|
|
386
|
+
const { unmount } = render(
|
|
387
|
+
<EnterprisePluginPage
|
|
388
|
+
plugin={FakeSSOPage}
|
|
389
|
+
pluginProps={PAGE_PROPS}
|
|
390
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
391
|
+
upsell={UPSELL}
|
|
392
|
+
isEligible={true}
|
|
393
|
+
/>,
|
|
394
|
+
);
|
|
395
|
+
expect(screen.getByTestId("fake-sso-plugin")).toBeInTheDocument();
|
|
396
|
+
unmount();
|
|
397
|
+
|
|
398
|
+
pinDeployment("self-hosted-enterprise");
|
|
399
|
+
render(
|
|
400
|
+
<EnterprisePluginPage
|
|
401
|
+
plugin={FakeSSOPage}
|
|
402
|
+
pluginProps={PAGE_PROPS}
|
|
403
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
404
|
+
upsell={UPSELL}
|
|
405
|
+
isEligible={false}
|
|
406
|
+
/>,
|
|
407
|
+
);
|
|
408
|
+
expect(screen.queryByTestId("fake-sso-plugin")).not.toBeInTheDocument();
|
|
409
|
+
expect(screen.getByText("SAML Single Sign On")).toBeInTheDocument();
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test("renderUpsell replaces the card and is told why it is showing", () => {
|
|
413
|
+
pinDeployment("cloud");
|
|
414
|
+
const reasons: Array<EnterpriseUpgradeReason> = [];
|
|
415
|
+
|
|
416
|
+
const renderAuditUpsell: (
|
|
417
|
+
reason: EnterpriseUpgradeReason,
|
|
418
|
+
) => ReactElement = (reason: EnterpriseUpgradeReason): ReactElement => {
|
|
419
|
+
reasons.push(reason);
|
|
420
|
+
return (
|
|
421
|
+
<AuditLogsEnterpriseUpgrade
|
|
422
|
+
title="Audit Logs"
|
|
423
|
+
description="Every change made in this project."
|
|
424
|
+
reason={reason}
|
|
425
|
+
/>
|
|
426
|
+
);
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
// Below the tier: sell the plan.
|
|
430
|
+
currentPlanForTest = PlanType.Scale;
|
|
431
|
+
const { unmount } = render(
|
|
432
|
+
<EnterprisePluginPage
|
|
433
|
+
plugin={FakeSSOPage}
|
|
434
|
+
pluginProps={PAGE_PROPS}
|
|
435
|
+
requiredPlan={AUDIT_LOGS_REQUIRED_PLAN}
|
|
436
|
+
renderUpsell={renderAuditUpsell}
|
|
437
|
+
/>,
|
|
438
|
+
);
|
|
439
|
+
expect(
|
|
440
|
+
screen.getByText(
|
|
441
|
+
"Audit Logs are available on the Enterprise plan. Upgrade to turn on audit logging for this project.",
|
|
442
|
+
),
|
|
443
|
+
).toBeInTheDocument();
|
|
444
|
+
unmount();
|
|
445
|
+
|
|
446
|
+
// On the tier, but the bundle has no plugin: the edition, not a plan.
|
|
447
|
+
currentPlanForTest = PlanType.Enterprise;
|
|
448
|
+
render(
|
|
449
|
+
<EnterprisePluginPage
|
|
450
|
+
plugin={undefined}
|
|
451
|
+
pluginProps={PAGE_PROPS}
|
|
452
|
+
requiredPlan={AUDIT_LOGS_REQUIRED_PLAN}
|
|
453
|
+
renderUpsell={renderAuditUpsell}
|
|
454
|
+
/>,
|
|
455
|
+
);
|
|
456
|
+
expect(
|
|
457
|
+
screen.getByText(
|
|
458
|
+
"Audit Logs are a OneUptime Enterprise Edition feature. Switch to the Enterprise Edition build to enable audit logging.",
|
|
459
|
+
),
|
|
460
|
+
).toBeInTheDocument();
|
|
461
|
+
|
|
462
|
+
expect(reasons).toEqual([
|
|
463
|
+
EnterpriseUpgradeReason.Plan,
|
|
464
|
+
EnterpriseUpgradeReason.Edition,
|
|
465
|
+
]);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
test("forwards a ref through to the plugin, lazy or not", async () => {
|
|
469
|
+
pinDeployment("self-hosted-enterprise");
|
|
470
|
+
|
|
471
|
+
/*
|
|
472
|
+
* No contract key takes a ref today (the member compliance status table,
|
|
473
|
+
* the one that did, is imported by ee's Compliance page directly), so the
|
|
474
|
+
* props and handle are this test's own: a future ref-taking plugin must
|
|
475
|
+
* still get the caller's ref.
|
|
476
|
+
*/
|
|
477
|
+
interface FakeTableProps {
|
|
478
|
+
teamId: ObjectID;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
interface FakeTableRef {
|
|
482
|
+
refresh: () => void;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/*
|
|
486
|
+
* Spelled out rather than as RefAttributes: since @types/react 18.3
|
|
487
|
+
* RefAttributes also allows legacy string refs, which React.lazy strips -
|
|
488
|
+
* so a lazy forwardRef table would not fit a RefAttributes slot.
|
|
489
|
+
*/
|
|
490
|
+
type FakeTablePluginProps = FakeTableProps & {
|
|
491
|
+
ref?: React.Ref<FakeTableRef> | undefined;
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
const refreshes: Array<string> = [];
|
|
495
|
+
|
|
496
|
+
const FakeComplianceTable: React.ForwardRefExoticComponent<
|
|
497
|
+
FakeTableProps & React.RefAttributes<FakeTableRef>
|
|
498
|
+
> = forwardRef<FakeTableRef, FakeTableProps>(
|
|
499
|
+
(props: FakeTableProps, ref: React.Ref<FakeTableRef>): ReactElement => {
|
|
500
|
+
useImperativeHandle(ref, () => {
|
|
501
|
+
return {
|
|
502
|
+
refresh: (): void => {
|
|
503
|
+
refreshes.push(props.teamId.toString());
|
|
504
|
+
},
|
|
505
|
+
};
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
return <div data-testid="fake-compliance-table" />;
|
|
509
|
+
},
|
|
510
|
+
);
|
|
511
|
+
FakeComplianceTable.displayName = "FakeComplianceTable";
|
|
512
|
+
|
|
513
|
+
const teamId: ObjectID = new ObjectID(
|
|
514
|
+
"11111111-1111-4111-8111-111111111111",
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
/*
|
|
518
|
+
* Typed as a contract slot would be: a forwardRef table fits it both
|
|
519
|
+
* eagerly and behind React.lazy (a RefAttributes-typed slot would reject
|
|
520
|
+
* the lazy one under @types/react 18.3, which this package installs).
|
|
521
|
+
*/
|
|
522
|
+
const plugins: Array<EnterprisePluginComponent<FakeTablePluginProps>> = [
|
|
523
|
+
FakeComplianceTable,
|
|
524
|
+
React.lazy(async (): Promise<{ default: typeof FakeComplianceTable }> => {
|
|
525
|
+
return { default: FakeComplianceTable };
|
|
526
|
+
}),
|
|
527
|
+
];
|
|
528
|
+
|
|
529
|
+
for (const plugin of plugins) {
|
|
530
|
+
const tableRef: React.RefObject<FakeTableRef> =
|
|
531
|
+
React.createRef<FakeTableRef>();
|
|
532
|
+
|
|
533
|
+
const { unmount } = render(
|
|
534
|
+
<EnterprisePluginPage<FakeTablePluginProps>
|
|
535
|
+
plugin={plugin}
|
|
536
|
+
pluginProps={{ teamId, ref: tableRef }}
|
|
537
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
538
|
+
upsell={UPSELL}
|
|
539
|
+
/>,
|
|
540
|
+
);
|
|
541
|
+
|
|
542
|
+
expect(
|
|
543
|
+
await screen.findByTestId("fake-compliance-table"),
|
|
544
|
+
).toBeInTheDocument();
|
|
545
|
+
|
|
546
|
+
tableRef.current?.refresh();
|
|
547
|
+
unmount();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
expect(refreshes).toEqual([teamId.toString(), teamId.toString()]);
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
describe("the Community plugin door (what this jest config resolves)", () => {
|
|
555
|
+
test("getDashboardPlugins() is the empty Community stub", () => {
|
|
556
|
+
const plugins: DashboardEnterprisePlugins = getDashboardPlugins();
|
|
557
|
+
|
|
558
|
+
expect(plugins).toEqual({});
|
|
559
|
+
expect(plugins.buildMarker).toBeUndefined();
|
|
560
|
+
|
|
561
|
+
for (const key of DASHBOARD_ENTERPRISE_PLUGIN_KEYS) {
|
|
562
|
+
expect([key, plugins[key]]).toEqual([key, undefined]);
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
test("returns the same object on every call", () => {
|
|
567
|
+
expect(getDashboardPlugins()).toBe(getDashboardPlugins());
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
test("names every screen a plugin can provide, once", () => {
|
|
571
|
+
expect([...DASHBOARD_ENTERPRISE_PLUGIN_KEYS].sort()).toEqual(
|
|
572
|
+
[
|
|
573
|
+
"AuditLogsTable",
|
|
574
|
+
"SettingsAuditLogsSettings",
|
|
575
|
+
"SettingsOIDC",
|
|
576
|
+
"SettingsSCIM",
|
|
577
|
+
"SettingsSSO",
|
|
578
|
+
"StatusPageOIDC",
|
|
579
|
+
"StatusPageSCIM",
|
|
580
|
+
"StatusPageSSO",
|
|
581
|
+
"TeamCompliance",
|
|
582
|
+
"LicenseManager",
|
|
583
|
+
].sort(),
|
|
584
|
+
);
|
|
585
|
+
expect(new Set(DASHBOARD_ENTERPRISE_PLUGIN_KEYS).size).toBe(
|
|
586
|
+
DASHBOARD_ENTERPRISE_PLUGIN_KEYS.length,
|
|
587
|
+
);
|
|
588
|
+
// The member status table is only ever rendered by ee's Compliance page.
|
|
589
|
+
expect(DASHBOARD_ENTERPRISE_PLUGIN_KEYS).not.toContain(
|
|
590
|
+
"TeamComplianceStatusTable",
|
|
591
|
+
);
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
test("a shell reading the real door on a Community build shows the upsell even when eligible", () => {
|
|
595
|
+
pinDeployment("cloud");
|
|
596
|
+
currentPlanForTest = PlanType.Enterprise;
|
|
597
|
+
|
|
598
|
+
render(
|
|
599
|
+
<EnterprisePluginPage
|
|
600
|
+
plugin={getDashboardPlugins().SettingsSSO}
|
|
601
|
+
pluginProps={PAGE_PROPS}
|
|
602
|
+
requiredPlan={IDENTITY_REQUIRED_PLAN}
|
|
603
|
+
upsell={UPSELL}
|
|
604
|
+
/>,
|
|
605
|
+
);
|
|
606
|
+
|
|
607
|
+
expect(screen.getAllByText("Learn about Enterprise Edition")).toHaveLength(
|
|
608
|
+
2,
|
|
609
|
+
);
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
describe("the plugin door with other plugin modules", () => {
|
|
614
|
+
/*
|
|
615
|
+
* These swap what "@oneuptime/ee-dashboard" resolves to, so they run on a
|
|
616
|
+
* fresh module registry and render nothing afterwards.
|
|
617
|
+
*/
|
|
618
|
+
beforeEach(() => {
|
|
619
|
+
jest.resetModules();
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
afterEach(() => {
|
|
623
|
+
jest.dontMock("@oneuptime/ee-dashboard");
|
|
624
|
+
jest.resetModules();
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
test("hands back the Enterprise plugin object as is", async () => {
|
|
628
|
+
const enterprisePlugins: DashboardEnterprisePlugins = {
|
|
629
|
+
buildMarker: "ONEUPTIME_EE_DASHBOARD_PLUGIN_v1",
|
|
630
|
+
SettingsSSO: FakeSSOPage,
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
jest.doMock("@oneuptime/ee-dashboard", () => {
|
|
634
|
+
return { __esModule: true, default: enterprisePlugins };
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
const door: { getDashboardPlugins: () => DashboardEnterprisePlugins } =
|
|
638
|
+
await import(
|
|
639
|
+
"../../../../App/FeatureSet/Dashboard/src/Enterprise/Plugins"
|
|
640
|
+
);
|
|
641
|
+
|
|
642
|
+
expect(door.getDashboardPlugins()).toBe(enterprisePlugins);
|
|
643
|
+
expect(door.getDashboardPlugins().SettingsSSO).toBe(FakeSSOPage);
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
test("fails loudly, naming the rule, when read before the plugin module finished loading", async () => {
|
|
647
|
+
/*
|
|
648
|
+
* What a top-level read sees in the Enterprise bundle's import cycle: the
|
|
649
|
+
* plugin binding is still undefined. A silent {} would quietly turn an
|
|
650
|
+
* Enterprise install into the Community UI.
|
|
651
|
+
*/
|
|
652
|
+
jest.doMock("@oneuptime/ee-dashboard", () => {
|
|
653
|
+
return { __esModule: true, default: undefined };
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
const door: { getDashboardPlugins: () => DashboardEnterprisePlugins } =
|
|
657
|
+
await import(
|
|
658
|
+
"../../../../App/FeatureSet/Dashboard/src/Enterprise/Plugins"
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
expect(() => {
|
|
662
|
+
return door.getDashboardPlugins();
|
|
663
|
+
}).toThrow(
|
|
664
|
+
"getDashboardPlugins() ran before the Enterprise plugin module finished loading. Call it inside a render or function body, never at module top level.",
|
|
665
|
+
);
|
|
666
|
+
});
|
|
667
|
+
});
|