@oneuptime/common 12.0.5 → 12.0.6
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/DatabaseModels/AIRun.ts +33 -0
- package/Models/DatabaseModels/DataSource.ts +744 -0
- package/Models/DatabaseModels/Index.ts +3 -0
- package/Models/DatabaseModels/ProjectCallSMSConfig.ts +10 -2
- package/Models/DatabaseModels/User.ts +2 -0
- package/Models/DatabaseModels/UserOnCallLog.ts +2 -0
- package/Models/DatabaseModels/UserOnCallLogTimeline.ts +2 -0
- package/Models/DatabaseModels/UserSession.ts +2 -0
- package/Models/DatabaseModels/UserTotpAuth.ts +6 -4
- package/Models/DatabaseModels/UserWebAuthn.ts +5 -3
- package/Server/API/AIInsightAPI.ts +47 -4
- package/Server/API/AIInvestigationAPI.ts +25 -0
- package/Server/API/DashboardAPI.ts +176 -492
- package/Server/API/DataSourceAPI.ts +268 -0
- package/Server/API/StatusPageAPI.ts +11 -1
- package/Server/API/UserAPI.ts +119 -0
- package/Server/Infrastructure/ClickhouseConfig.ts +59 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.ts +24 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.ts +76 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Infrastructure/Queue.ts +26 -0
- package/Server/Infrastructure/QueueWorker.ts +17 -0
- package/Server/Middleware/TelemetryIngest.ts +8 -3
- package/Server/Services/AIInsightService.ts +132 -12
- package/Server/Services/AIRunService.ts +34 -0
- package/Server/Services/AIService.ts +17 -2
- package/Server/Services/AlertService.ts +38 -32
- package/Server/Services/AnalyticsDatabaseService.ts +8 -4
- package/Server/Services/DataSourceService.ts +200 -0
- package/Server/Services/HostService.ts +92 -0
- package/Server/Services/IncidentService.ts +45 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/MonitorService.ts +49 -0
- package/Server/Services/MonitorStatusService.ts +166 -0
- package/Server/Services/OpenTelemetryIngestService.ts +255 -184
- package/Server/Services/RumSessionPinService.ts +7 -21
- package/Server/Services/StatusPageSubscriberService.ts +13 -0
- package/Server/Services/UserService.ts +280 -9
- package/Server/Static/Vendor/README.md +62 -0
- package/Server/Static/Vendor/fonts/InterVariable.woff2 +0 -0
- package/Server/Static/Vendor/highlight/highlight.min.js +1244 -0
- package/Server/Static/Vendor/highlight/languages/apache.min.js +15 -0
- package/Server/Static/Vendor/highlight/languages/bash.min.js +21 -0
- package/Server/Static/Vendor/highlight/languages/c.min.js +41 -0
- package/Server/Static/Vendor/highlight/languages/cpp.min.js +47 -0
- package/Server/Static/Vendor/highlight/languages/csharp.min.js +49 -0
- package/Server/Static/Vendor/highlight/languages/css.min.js +31 -0
- package/Server/Static/Vendor/highlight/languages/diff.min.js +9 -0
- package/Server/Static/Vendor/highlight/languages/dns.min.js +11 -0
- package/Server/Static/Vendor/highlight/languages/dockerfile.min.js +8 -0
- package/Server/Static/Vendor/highlight/languages/go.min.js +20 -0
- package/Server/Static/Vendor/highlight/languages/graphql.min.js +12 -0
- package/Server/Static/Vendor/highlight/languages/http.min.js +14 -0
- package/Server/Static/Vendor/highlight/languages/ini.min.js +15 -0
- package/Server/Static/Vendor/highlight/languages/java.min.js +38 -0
- package/Server/Static/Vendor/highlight/languages/javascript.min.js +81 -0
- package/Server/Static/Vendor/highlight/languages/json.min.js +8 -0
- package/Server/Static/Vendor/highlight/languages/kotlin.min.js +46 -0
- package/Server/Static/Vendor/highlight/languages/lua.min.js +15 -0
- package/Server/Static/Vendor/highlight/languages/makefile.min.js +14 -0
- package/Server/Static/Vendor/highlight/languages/nginx.min.js +21 -0
- package/Server/Static/Vendor/highlight/languages/perl.min.js +41 -0
- package/Server/Static/Vendor/highlight/languages/php.min.js +59 -0
- package/Server/Static/Vendor/highlight/languages/powershell.min.js +39 -0
- package/Server/Static/Vendor/highlight/languages/python.min.js +42 -0
- package/Server/Static/Vendor/highlight/languages/r.min.js +26 -0
- package/Server/Static/Vendor/highlight/languages/ruby.min.js +54 -0
- package/Server/Static/Vendor/highlight/languages/rust.min.js +27 -0
- package/Server/Static/Vendor/highlight/languages/scala.min.js +28 -0
- package/Server/Static/Vendor/highlight/languages/sql.min.js +21 -0
- package/Server/Static/Vendor/highlight/languages/swift.min.js +68 -0
- package/Server/Static/Vendor/highlight/languages/typescript.min.js +99 -0
- package/Server/Static/Vendor/highlight/languages/xml.min.js +29 -0
- package/Server/Static/Vendor/highlight/languages/yaml.min.js +28 -0
- package/Server/Static/Vendor/highlight/styles/github-dark.min.css +10 -0
- package/Server/Static/Vendor/highlight/styles/vs2015.min.css +1 -0
- package/Server/Static/Vendor/tailwind/tailwind-3.4.5.js +21028 -0
- package/Server/Types/Database/Permissions/BasePermission.ts +7 -0
- package/Server/Types/Database/Permissions/DeletePermission.ts +2 -0
- package/Server/Types/Database/Permissions/ReadPermission.ts +3 -0
- package/Server/Types/Database/Permissions/TenantPermission.ts +101 -16
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +2 -2
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +90 -11
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +1 -0
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +1 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.ts +125 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +25 -15
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +256 -57
- package/Server/Utils/AI/SRE/Insights/InsightStore.ts +76 -18
- package/Server/Utils/AI/SRE/InvestigationTldr.ts +352 -0
- package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +7 -2
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +1793 -0
- package/Server/Utils/Dashboard/PublicDashboardViewConfig.ts +65 -0
- package/Server/Utils/DataSource/ConnectorRegistry.ts +53 -0
- package/Server/Utils/DataSource/Connectors/ClickHouseConnector.ts +338 -0
- package/Server/Utils/DataSource/Connectors/ElasticsearchConnector.ts +717 -0
- package/Server/Utils/DataSource/Connectors/LokiConnector.ts +606 -0
- package/Server/Utils/DataSource/Connectors/MySqlConnector.ts +307 -0
- package/Server/Utils/DataSource/Connectors/PostgresConnector.ts +260 -0
- package/Server/Utils/DataSource/Connectors/PrometheusConnector.ts +555 -0
- package/Server/Utils/DataSource/Connectors/RestApiConnector.ts +597 -0
- package/Server/Utils/DataSource/Connectors/SqlServerConnector.ts +318 -0
- package/Server/Utils/DataSource/EgressGuard.ts +446 -0
- package/Server/Utils/DataSource/HttpFetch.ts +221 -0
- package/Server/Utils/DataSource/SqlQueryGuard.ts +383 -0
- package/Server/Utils/DataSource/SqlResultShaper.ts +372 -0
- package/Server/Utils/DataSource/Types.ts +93 -0
- package/Server/Utils/Database/PostgresErrorTranslator.ts +172 -17
- package/Server/Utils/InProcessMemo.ts +141 -0
- package/Server/Utils/InstanceHealth/TelemetryIngestion.ts +628 -0
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +58 -0
- package/Server/Utils/Monitor/MonitorResource.ts +14 -0
- package/Server/Utils/Response.ts +12 -1
- package/Server/Utils/SSRFProtection.ts +237 -0
- package/Server/Utils/StartServer.ts +8 -0
- package/Server/Utils/StatusPageSubscriberWebhook.ts +30 -0
- package/Server/Utils/Telemetry/CaptureSpan.ts +30 -18
- package/Server/Utils/Telemetry/IngestionTimestamp.ts +75 -0
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +99 -7
- package/Server/Utils/Telemetry/Telemetry.ts +112 -1
- package/Server/Utils/Telemetry.ts +104 -3
- package/Server/Utils/VendorAssets.ts +165 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +28 -5
- package/Server/Utils/Workspace/Slack/Slack.ts +5 -0
- package/Server/Views/Partials/Head.ejs +21 -7
- package/Tests/App/AdminDashboard/AdminProjectsIdFilter.test.tsx +207 -0
- package/Tests/App/AdminDashboard/AdminUsersIdFilter.test.tsx +216 -0
- package/Tests/App/Dashboard/AIInsightViewActions.test.tsx +422 -0
- package/Tests/App/Dashboard/AddWidgetModal.test.tsx +10 -3
- package/Tests/App/Dashboard/AlertsSideMenu.test.tsx +387 -0
- package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +199 -0
- package/Tests/App/Dashboard/DataSourceChartSyntheticConfig.test.tsx +736 -0
- package/Tests/App/Dashboard/DataSourceQueryEditor.test.tsx +868 -0
- package/Tests/App/Dashboard/DataSourceWidgetCatalog.test.ts +440 -0
- package/Tests/App/Dashboard/DataSourceWidgetFetching.test.tsx +2109 -0
- package/Tests/App/Dashboard/DataSourceWidgetViews.test.tsx +726 -0
- package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +447 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +514 -3
- package/Tests/App/Dashboard/ProductMenuBreadcrumbs.test.tsx +391 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceSideMenu.test.tsx +326 -0
- package/Tests/App/Dashboard/SideMenuHarness.tsx +187 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +6 -1
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +1858 -0
- package/Tests/Models/DatabaseModels/DataSourceModelSecrets.test.ts +70 -0
- package/Tests/Server/API/AIInvestigationAPI.test.ts +187 -0
- package/Tests/Server/API/DashboardPublicDataSourceStrip.test.ts +686 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +585 -823
- package/Tests/Server/API/DataSourceAPIRoutes.test.ts +486 -0
- package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +291 -0
- package/Tests/Server/API/UserAuthenticationAPI.test.ts +641 -0
- package/Tests/Server/Infrastructure/ClickhouseKeepAliveOptions.test.ts +441 -0
- package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +140 -0
- package/Tests/Server/Services/AIInsightService.test.ts +266 -11
- package/Tests/Server/Services/AIRunAnalysisTldrPersistence.test.ts +160 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +4 -0
- package/Tests/Server/Services/AlertMetricResourceAttributes.test.ts +352 -0
- package/Tests/Server/Services/DataSourceServiceSettings.test.ts +244 -0
- package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +397 -0
- package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +41 -2
- package/Tests/Server/Services/IncidentMetricResourceAttributes.test.ts +408 -0
- package/Tests/Server/Services/MonitorStatusServiceDeleteReferenceCleanup.test.ts +351 -0
- package/Tests/Server/Services/MonitorStatusServiceValidation.test.ts +171 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +398 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +19 -0
- package/Tests/Server/Services/ProjectCallSMSConfigCredentialUniqueness.test.ts +305 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +36 -1
- package/Tests/Server/Services/RumSessionPinUniqueViolationRecovery.test.ts +163 -0
- package/Tests/Server/Services/UserAuthenticationService.test.ts +973 -0
- package/Tests/Server/Types/Database/ObjectIdColumnQuery.test.ts +262 -0
- package/Tests/Server/Types/Database/Permissions/TenantPermission.test.ts +358 -0
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +2 -2
- package/Tests/Server/Utils/AI/Insights/ExceptionSpikeDetector.test.ts +6 -1
- package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +121 -4
- package/Tests/Server/Utils/AI/Insights/NewExceptionDetector.test.ts +361 -10
- package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +292 -0
- package/Tests/Server/Utils/AI/InvestigationTldr.test.ts +623 -0
- package/Tests/Server/Utils/AI/InvestigationTldrWiring.test.ts +98 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +857 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardViewConfig.test.ts +480 -0
- package/Tests/Server/Utils/DataSource/ClickHouseConnector.test.ts +759 -0
- package/Tests/Server/Utils/DataSource/ConnectorRegistry.test.ts +37 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +645 -0
- package/Tests/Server/Utils/DataSource/ElasticsearchConnector.test.ts +1206 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +616 -0
- package/Tests/Server/Utils/DataSource/LokiConnector.test.ts +970 -0
- package/Tests/Server/Utils/DataSource/MySqlConnector.test.ts +935 -0
- package/Tests/Server/Utils/DataSource/PostgresConnector.test.ts +854 -0
- package/Tests/Server/Utils/DataSource/PrometheusConnector.test.ts +881 -0
- package/Tests/Server/Utils/DataSource/RestApiConnector.test.ts +1020 -0
- package/Tests/Server/Utils/DataSource/SqlQueryGuard.test.ts +425 -0
- package/Tests/Server/Utils/DataSource/SqlResultShaper.test.ts +555 -0
- package/Tests/Server/Utils/DataSource/SqlServerConnector.test.ts +934 -0
- package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +228 -7
- package/Tests/Server/Utils/InProcessMemo.test.ts +292 -0
- package/Tests/Server/Utils/InstanceHealth/TelemetryIngestion.test.ts +960 -0
- package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +103 -0
- package/Tests/Server/Utils/Monitor/MonitorMetricResourceAttributes.test.ts +336 -0
- package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +521 -0
- package/Tests/Server/Utils/ResponseRenderAnalytics.test.ts +143 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +193 -0
- package/Tests/Server/Utils/StatusPageSubscriberWebhook.test.ts +101 -0
- package/Tests/Server/Utils/TailwindBuildCopy.test.ts +225 -0
- package/Tests/Server/Utils/Telemetry/ResourceHeartbeatL1Memo.test.ts +355 -0
- package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +128 -0
- package/Tests/Server/Utils/Telemetry/TelemetryUtilAttributeKeys.test.ts +381 -0
- package/Tests/Server/Utils/Telemetry.test.ts +87 -0
- package/Tests/Server/Utils/VendorAssetIntegrity.test.ts +343 -0
- package/Tests/Server/Utils/VendorAssets.test.ts +671 -0
- package/Tests/Server/Views/OfflineRender.test.ts +297 -0
- package/Tests/Types/Dashboard/DataSourceComponentTypes.test.ts +618 -0
- package/Tests/Types/DateClickhouseFormat.test.ts +192 -0
- package/Tests/Types/Password.test.ts +363 -0
- package/Tests/UI/Components/ConfirmModal.test.tsx +7 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +53 -0
- package/Tests/UI/Components/Modal.test.tsx +281 -1
- package/Tests/UI/Components/ObjectIdFilterPipeline.test.tsx +396 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupNavigator.test.tsx +1147 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +116 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
- package/Tests/Utils/Analytics.test.ts +23 -0
- package/Tests/Utils/Dashboard/Components/DashboardDataSourceComponents.test.ts +640 -0
- package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +138 -0
- package/Tests/Utils/DataSource/DataSourceValueReducer.test.ts +526 -0
- package/Tests/Utils/Metrics/MetricResourceAttributeUtil.test.ts +691 -0
- package/Tests/Utils/StatusPage/GroupHierarchyView.test.ts +1452 -0
- package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +931 -0
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +288 -0
- package/Tests/Utils/Telemetry/IngestionTimestamp.test.ts +170 -0
- package/Types/AI/AIInsightEvidence.ts +6 -0
- package/Types/Analytics/RevenueEvent.ts +31 -0
- package/Types/Dashboard/DashboardComponentType.ts +31 -0
- package/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.ts +27 -0
- package/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.ts +32 -0
- package/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.ts +30 -0
- package/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.ts +55 -0
- package/Types/DataSource/DataSourceLimits.ts +62 -0
- package/Types/DataSource/DataSourceQueryConfig.ts +41 -0
- package/Types/DataSource/DataSourceTableResult.ts +38 -0
- package/Types/DataSource/DataSourceType.ts +213 -0
- package/Types/Date.ts +43 -3
- package/Types/Password.ts +64 -0
- package/Types/Permission.ts +46 -0
- package/Types/UserAuthenticationStatus.ts +34 -0
- package/UI/Components/Button/Button.tsx +1 -1
- package/UI/Components/ErrorBoundary.tsx +459 -108
- package/UI/Components/Icon/Icon.tsx +10 -9
- package/UI/Components/Modal/ConfirmModal.tsx +6 -1
- package/UI/Components/Modal/Modal.tsx +267 -35
- package/UI/Components/Modal/ModalFooter.tsx +6 -1
- package/UI/Components/MoreMenu/MoreMenu.tsx +19 -4
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +6 -1
- package/UI/Components/StatusPage/ResourceGrid.tsx +314 -0
- package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +808 -0
- package/UI/Components/StatusPage/ResourceList.tsx +570 -0
- package/UI/Styles/Theme.css +18 -0
- package/UI/Utils/API/RequestOptions.ts +7 -0
- package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +1 -0
- package/UI/Utils/TestDataSource.ts +61 -0
- package/UI/esbuild-config.js +45 -0
- package/Utils/Analytics.ts +15 -0
- package/Utils/Dashboard/Components/DashboardDataSourceChartComponent.ts +88 -0
- package/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.ts +123 -0
- package/Utils/Dashboard/Components/DashboardDataSourceShared.ts +16 -0
- package/Utils/Dashboard/Components/DashboardDataSourceTableComponent.ts +72 -0
- package/Utils/Dashboard/Components/DashboardDataSourceValueComponent.ts +126 -0
- package/Utils/Dashboard/Components/Index.ts +28 -0
- package/Utils/DataSource/DataSourceQueryText.ts +94 -0
- package/Utils/DataSource/DataSourceValueReducer.ts +156 -0
- package/Utils/Metrics/MetricResourceAttributeUtil.ts +380 -0
- package/Utils/NetworkDiscovery/ScanTargetUtil.ts +8 -6
- package/Utils/StatusPage/GroupHierarchyView.ts +931 -0
- package/Utils/StatusPage/ResourceExplorer.ts +853 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +34 -0
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DataSource.js +774 -0
- package/build/dist/Models/DatabaseModels/DataSource.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js +14 -4
- package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +2 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +2 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +2 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSession.js +2 -0
- package/build/dist/Models/DatabaseModels/UserSession.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserTotpAuth.js +6 -4
- package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js +5 -3
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
- package/build/dist/Server/API/AIInsightAPI.js +34 -4
- package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +23 -0
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +119 -433
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/DataSourceAPI.js +173 -0
- package/build/dist/Server/API/DataSourceAPI.js.map +1 -0
- package/build/dist/Server/API/StatusPageAPI.js +11 -1
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/UserAPI.js +94 -2
- package/build/dist/Server/API/UserAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js +49 -0
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js +64 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Queue.js +27 -0
- package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +13 -0
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +8 -3
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIInsightService.js +110 -10
- package/build/dist/Server/Services/AIInsightService.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +34 -0
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +16 -2
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +28 -35
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +8 -4
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DataSourceService.js +159 -0
- package/build/dist/Server/Services/DataSourceService.js.map +1 -0
- package/build/dist/Server/Services/HostService.js +74 -0
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +35 -24
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +45 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusService.js +129 -0
- package/build/dist/Server/Services/MonitorStatusService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +222 -159
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/RumSessionPinService.js +7 -15
- package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +10 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +241 -10
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js +6 -0
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/DeletePermission.js +1 -0
- package/build/dist/Server/Types/Database/Permissions/DeletePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/ReadPermission.js +2 -0
- package/build/dist/Server/Types/Database/Permissions/ReadPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +68 -12
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +2 -2
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +68 -8
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +1 -0
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +1 -0
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js +97 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +17 -15
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +178 -54
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js +65 -16
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js +303 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js.map +1 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +1261 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js +47 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js +42 -0
- package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js +187 -0
- package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js +493 -0
- package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js +399 -0
- package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js +195 -0
- package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js +149 -0
- package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js +362 -0
- package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js +342 -0
- package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js +186 -0
- package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +305 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +134 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js +331 -0
- package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/SqlResultShaper.js +280 -0
- package/build/dist/Server/Utils/DataSource/SqlResultShaper.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/Types.js +2 -0
- package/build/dist/Server/Utils/DataSource/Types.js.map +1 -0
- package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +103 -9
- package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -1
- package/build/dist/Server/Utils/InProcessMemo.js +113 -0
- package/build/dist/Server/Utils/InProcessMemo.js.map +1 -0
- package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js +406 -0
- package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +34 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +14 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +9 -1
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +192 -0
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +7 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +24 -0
- package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +25 -11
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js +32 -0
- package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +92 -5
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +92 -6
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +93 -6
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +121 -0
- package/build/dist/Server/Utils/VendorAssets.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -4
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +5 -0
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Types/Analytics/RevenueEvent.js +26 -0
- package/build/dist/Types/Analytics/RevenueEvent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js +27 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js +16 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js.map +1 -0
- package/build/dist/Types/DataSource/DataSourceLimits.js +47 -0
- package/build/dist/Types/DataSource/DataSourceLimits.js.map +1 -0
- package/build/dist/Types/DataSource/DataSourceQueryConfig.js +10 -0
- package/build/dist/Types/DataSource/DataSourceQueryConfig.js.map +1 -0
- package/build/dist/Types/DataSource/DataSourceTableResult.js +14 -0
- package/build/dist/Types/DataSource/DataSourceTableResult.js.map +1 -0
- package/build/dist/Types/DataSource/DataSourceType.js +183 -0
- package/build/dist/Types/DataSource/DataSourceType.js.map +1 -0
- package/build/dist/Types/Date.js +38 -3
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Password.js +56 -0
- package/build/dist/Types/Password.js.map +1 -0
- package/build/dist/Types/Permission.js +42 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/UserAuthenticationStatus.js +2 -0
- package/build/dist/Types/UserAuthenticationStatus.js.map +1 -0
- package/build/dist/UI/Components/ErrorBoundary.js +388 -72
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +10 -4
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +178 -19
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +3 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +9 -6
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +7 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +119 -0
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -0
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +354 -0
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -0
- package/build/dist/UI/Components/StatusPage/ResourceList.js +203 -0
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -0
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -6
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +3 -8
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/TestDataSource.js +39 -0
- package/build/dist/UI/Utils/TestDataSource.js.map +1 -0
- package/build/dist/Utils/Analytics.js +4 -0
- package/build/dist/Utils/Analytics.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js +79 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js +111 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js +15 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js +62 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js +112 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/DataSource/DataSourceQueryText.js +64 -0
- package/build/dist/Utils/DataSource/DataSourceQueryText.js.map +1 -0
- package/build/dist/Utils/DataSource/DataSourceValueReducer.js +124 -0
- package/build/dist/Utils/DataSource/DataSourceValueReducer.js.map +1 -0
- package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js +281 -0
- package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +8 -6
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupHierarchyView.js +560 -0
- package/build/dist/Utils/StatusPage/GroupHierarchyView.js.map +1 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js +519 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -0
- package/jest.config.json +1 -0
- package/package.json +5 -1
- package/tsconfig.json +12 -10
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import {
|
|
5
|
+
VendorAssetsPath,
|
|
6
|
+
VendorAssetsRoute,
|
|
7
|
+
getMermaidDistPath,
|
|
8
|
+
} from "../../../Server/Utils/VendorAssets";
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* Every server-rendered page must be able to render with no route off the box.
|
|
12
|
+
*
|
|
13
|
+
* A CDN <script> in a view does not degrade on an air-gapped install; it
|
|
14
|
+
* blocks the parser until the connect times out, which is what
|
|
15
|
+
* https://github.com/OneUptime/oneuptime/issues/2570 reported as pages stuck
|
|
16
|
+
* on "Loading..." forever. One file added to a views directory with a
|
|
17
|
+
* copy-pasted CDN tag puts it back, and nothing else in the build would
|
|
18
|
+
* notice - so this scans the directories rather than the handful of files the
|
|
19
|
+
* fix happened to touch.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const REPOSITORY_ROOT: string = path.resolve(__dirname, "..", "..", "..", "..");
|
|
23
|
+
|
|
24
|
+
interface ViewFile {
|
|
25
|
+
/** Repo-relative, so a failure message names something greppable. */
|
|
26
|
+
name: string;
|
|
27
|
+
absolutePath: string;
|
|
28
|
+
contents: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface ViewRoot {
|
|
32
|
+
label: string;
|
|
33
|
+
directories: Array<string>;
|
|
34
|
+
/*
|
|
35
|
+
* Hosts a view under this root may still reference. Anything not listed is
|
|
36
|
+
* a failure.
|
|
37
|
+
*/
|
|
38
|
+
allowedHosts: Array<string>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
* Prose explains these rules at length - including, in a couple of places, by
|
|
43
|
+
* naming the exact CDN host that is no longer allowed. Scanning the raw text
|
|
44
|
+
* would fail on the comment that documents the rule.
|
|
45
|
+
*
|
|
46
|
+
* Line comments are only stripped when they START a line: `//cdnjs.cloudflare.com`
|
|
47
|
+
* in an href is a protocol-relative URL, not a comment, and it is precisely
|
|
48
|
+
* the form this test has to keep catching.
|
|
49
|
+
*/
|
|
50
|
+
const COMMENT_SYNTAXES: Array<RegExp> = [
|
|
51
|
+
/<!--[\s\S]*?-->/g,
|
|
52
|
+
/<%#[\s\S]*?%>/g,
|
|
53
|
+
/\/\*[\s\S]*?\*\//g,
|
|
54
|
+
/^[ \t]*\/\/.*$/gm,
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
function stripComments(source: string): string {
|
|
58
|
+
/*
|
|
59
|
+
* Repeated until the text stops changing, rather than one pass per syntax.
|
|
60
|
+
* A single pass leaves the opener behind on overlapping comments
|
|
61
|
+
* ("<!--<!-- x -->" keeps a "<!--"), and removing a block comment can
|
|
62
|
+
* uncover a line comment that was inside it. Cheap here - these files are a
|
|
63
|
+
* few KB and it converges in two passes.
|
|
64
|
+
*/
|
|
65
|
+
let previous: string = "";
|
|
66
|
+
let current: string = source;
|
|
67
|
+
|
|
68
|
+
while (current !== previous) {
|
|
69
|
+
previous = current;
|
|
70
|
+
|
|
71
|
+
for (const syntax of COMMENT_SYNTAXES) {
|
|
72
|
+
current = current.replace(syntax, "");
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return current;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function collectViewFiles(directory: string): Array<ViewFile> {
|
|
80
|
+
if (!fs.existsSync(directory)) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const files: Array<ViewFile> = [];
|
|
85
|
+
|
|
86
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
87
|
+
const absolutePath: string = path.join(directory, entry.name);
|
|
88
|
+
|
|
89
|
+
if (entry.isDirectory()) {
|
|
90
|
+
files.push(...collectViewFiles(absolutePath));
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!entry.name.endsWith(".ejs")) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
files.push({
|
|
99
|
+
name: path.relative(REPOSITORY_ROOT, absolutePath),
|
|
100
|
+
absolutePath,
|
|
101
|
+
contents: stripComments(fs.readFileSync(absolutePath, "utf8")),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return files;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function featureSetViewDirectories(): Array<string> {
|
|
109
|
+
const featureSetRoot: string = path.join(
|
|
110
|
+
REPOSITORY_ROOT,
|
|
111
|
+
"App",
|
|
112
|
+
"FeatureSet",
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (!fs.existsSync(featureSetRoot)) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const directories: Array<string> = [];
|
|
120
|
+
|
|
121
|
+
for (const featureSet of fs.readdirSync(featureSetRoot)) {
|
|
122
|
+
/* Docs and Identity capitalise it, the API reference does not. */
|
|
123
|
+
for (const viewsDirectory of ["Views", "views"]) {
|
|
124
|
+
const candidate: string = path.join(
|
|
125
|
+
featureSetRoot,
|
|
126
|
+
featureSet,
|
|
127
|
+
viewsDirectory,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
if (fs.existsSync(candidate)) {
|
|
131
|
+
directories.push(candidate);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return directories;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/*
|
|
140
|
+
* Analytics is the one third-party host a view may still name. It is loaded
|
|
141
|
+
* async, it never blocks a render, and every occurrence is required to sit
|
|
142
|
+
* behind the enableGoogleTagManager flag - which Response.render and the
|
|
143
|
+
* frontend index pages both default to "only when this is the hosted
|
|
144
|
+
* product". The dedicated test below enforces the guard.
|
|
145
|
+
*/
|
|
146
|
+
const ANALYTICS_HOST: string = "www.googletagmanager.com";
|
|
147
|
+
|
|
148
|
+
/*
|
|
149
|
+
* Matched as a pattern rather than with includes(), so that reading a view's
|
|
150
|
+
* source is not mistaken for validating a URL - it is neither given a URL nor
|
|
151
|
+
* deciding whether to fetch one.
|
|
152
|
+
*/
|
|
153
|
+
const ANALYTICS_HOST_PATTERN: RegExp = /www\.googletagmanager\.com/;
|
|
154
|
+
|
|
155
|
+
const RENDER_BLOCKING_CDN_HOSTS: Array<string> = [
|
|
156
|
+
"cdn.tailwindcss.com",
|
|
157
|
+
"cdnjs.cloudflare.com",
|
|
158
|
+
"cdn.jsdelivr.net",
|
|
159
|
+
"unpkg.com",
|
|
160
|
+
"ajax.googleapis.com",
|
|
161
|
+
"code.jquery.com",
|
|
162
|
+
"js.stripe.com",
|
|
163
|
+
"fonts.googleapis.com",
|
|
164
|
+
"fonts.gstatic.com",
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
const VIEW_ROOTS: Array<ViewRoot> = [
|
|
168
|
+
{
|
|
169
|
+
/*
|
|
170
|
+
* On-call acknowledge / message pages. Rendered by the API service, which
|
|
171
|
+
* every install has, and reached from a notification at the worst possible
|
|
172
|
+
* moment - these are the pages that must not need the internet.
|
|
173
|
+
*/
|
|
174
|
+
label: "Common server views",
|
|
175
|
+
directories: [path.join(REPOSITORY_ROOT, "Common", "Server", "Views")],
|
|
176
|
+
allowedHosts: [ANALYTICS_HOST],
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
/*
|
|
180
|
+
* Docs, the API reference, and the SSO/OIDC message pages. All served out
|
|
181
|
+
* of the App container, which is what nginx routes "/" to whenever billing
|
|
182
|
+
* is off - i.e. on every self-hosted install.
|
|
183
|
+
*/
|
|
184
|
+
label: "App feature set views",
|
|
185
|
+
directories: featureSetViewDirectories(),
|
|
186
|
+
allowedHosts: [ANALYTICS_HOST],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
/*
|
|
190
|
+
* The marketing site and blog. nginx only routes to Home when billing is
|
|
191
|
+
* on, so this is never part of a self-hosted deployment and Google Fonts
|
|
192
|
+
* stays. The libraries a page cannot render without do not: those are
|
|
193
|
+
* shared with Docs and the reference, and one CDN copy drifting from the
|
|
194
|
+
* vendored one is its own bug.
|
|
195
|
+
*/
|
|
196
|
+
label: "Home views",
|
|
197
|
+
directories: [path.join(REPOSITORY_ROOT, "Home", "Views")],
|
|
198
|
+
allowedHosts: [ANALYTICS_HOST, "fonts.googleapis.com", "fonts.gstatic.com"],
|
|
199
|
+
},
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
describe("server-rendered views load no third-party assets", () => {
|
|
203
|
+
for (const root of VIEW_ROOTS) {
|
|
204
|
+
describe(root.label, () => {
|
|
205
|
+
const views: Array<ViewFile> = root.directories.flatMap(collectViewFiles);
|
|
206
|
+
|
|
207
|
+
test("has views to scan", () => {
|
|
208
|
+
/*
|
|
209
|
+
* A rename that empties a root would otherwise turn every check below
|
|
210
|
+
* into a vacuous pass.
|
|
211
|
+
*/
|
|
212
|
+
expect(views.length).toBeGreaterThan(0);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const bannedHosts: Array<string> = RENDER_BLOCKING_CDN_HOSTS.filter(
|
|
216
|
+
(host: string): boolean => {
|
|
217
|
+
return !root.allowedHosts.includes(host);
|
|
218
|
+
},
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
test.each(
|
|
222
|
+
bannedHosts.map((host: string) => {
|
|
223
|
+
return [host];
|
|
224
|
+
}),
|
|
225
|
+
)("never references %s", (host: string) => {
|
|
226
|
+
const offenders: Array<string> = views
|
|
227
|
+
.filter((view: ViewFile): boolean => {
|
|
228
|
+
return view.contents.includes(host);
|
|
229
|
+
})
|
|
230
|
+
.map((view: ViewFile): string => {
|
|
231
|
+
return view.name;
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
expect(offenders).toEqual([]);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
test("keeps analytics behind the enableGoogleTagManager flag", () => {
|
|
240
|
+
/*
|
|
241
|
+
* Not because googletagmanager.com hangs a render - it is injected async -
|
|
242
|
+
* but because a self-hosted install has no business phoning Google, and an
|
|
243
|
+
* air-gapped one just accumulates failed requests.
|
|
244
|
+
*/
|
|
245
|
+
const offenders: Array<string> = VIEW_ROOTS.flatMap((root: ViewRoot) => {
|
|
246
|
+
return root.directories.flatMap(collectViewFiles);
|
|
247
|
+
})
|
|
248
|
+
.filter((view: ViewFile): boolean => {
|
|
249
|
+
return (
|
|
250
|
+
ANALYTICS_HOST_PATTERN.test(view.contents) &&
|
|
251
|
+
!view.contents.includes("enableGoogleTagManager")
|
|
252
|
+
);
|
|
253
|
+
})
|
|
254
|
+
.map((view: ViewFile): string => {
|
|
255
|
+
return view.name;
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
expect(offenders).toEqual([]);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe("every /oneuptime-assets URL a view uses resolves to a real file", () => {
|
|
263
|
+
const allViews: Array<ViewFile> = VIEW_ROOTS.flatMap((root: ViewRoot) => {
|
|
264
|
+
return root.directories.flatMap(collectViewFiles);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
/*
|
|
268
|
+
* Static references only. The two dynamic ones - the lazy highlight.js
|
|
269
|
+
* language loaders - are built by string concatenation and are covered by
|
|
270
|
+
* the langMap test below.
|
|
271
|
+
*/
|
|
272
|
+
function referencedAssetPaths(): Array<{ view: string; urlPath: string }> {
|
|
273
|
+
const references: Array<{ view: string; urlPath: string }> = [];
|
|
274
|
+
|
|
275
|
+
for (const view of allViews) {
|
|
276
|
+
const matches: Array<string> =
|
|
277
|
+
view.contents.match(
|
|
278
|
+
new RegExp(`${VendorAssetsRoute}/[A-Za-z0-9._/-]+`, "g"),
|
|
279
|
+
) || [];
|
|
280
|
+
|
|
281
|
+
for (const match of matches) {
|
|
282
|
+
references.push({ view: view.name, urlPath: match });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return references;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function resolveOnDisk(urlPath: string): string | null {
|
|
290
|
+
const relative: string = urlPath.slice(VendorAssetsRoute.length + 1);
|
|
291
|
+
|
|
292
|
+
if (relative.startsWith("mermaid/")) {
|
|
293
|
+
const mermaidDistPath: string | null = getMermaidDistPath();
|
|
294
|
+
|
|
295
|
+
if (!mermaidDistPath) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return path.join(mermaidDistPath, relative.slice("mermaid/".length));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return path.join(VendorAssetsPath, relative);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
test("finds the references at all", () => {
|
|
306
|
+
expect(referencedAssetPaths().length).toBeGreaterThan(0);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test("resolves every one of them", () => {
|
|
310
|
+
const missing: Array<string> = referencedAssetPaths()
|
|
311
|
+
.filter((reference: { urlPath: string }): boolean => {
|
|
312
|
+
const onDisk: string | null = resolveOnDisk(reference.urlPath);
|
|
313
|
+
|
|
314
|
+
return !onDisk || !fs.existsSync(onDisk);
|
|
315
|
+
})
|
|
316
|
+
.map((reference: { view: string; urlPath: string }): string => {
|
|
317
|
+
return `${reference.view}: ${reference.urlPath}`;
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
expect(missing).toEqual([]);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test("covers the assets the fix was actually about", () => {
|
|
324
|
+
/*
|
|
325
|
+
* The scan above proves whatever is referenced exists; it would also pass
|
|
326
|
+
* on a view that had quietly dropped the reference. These are the three
|
|
327
|
+
* things the issue named.
|
|
328
|
+
*/
|
|
329
|
+
const expectations: Array<[string, Array<string>]> = [
|
|
330
|
+
[
|
|
331
|
+
path.join("App", "FeatureSet", "Docs", "Views", "Partials", "Head.ejs"),
|
|
332
|
+
[
|
|
333
|
+
"/oneuptime-assets/tailwind/tailwind-3.4.5.js",
|
|
334
|
+
"/oneuptime-assets/highlight/highlight.min.js",
|
|
335
|
+
"/oneuptime-assets/highlight/styles/vs2015.min.css",
|
|
336
|
+
"/oneuptime-assets/mermaid/mermaid.esm.min.mjs",
|
|
337
|
+
],
|
|
338
|
+
],
|
|
339
|
+
[
|
|
340
|
+
path.join(
|
|
341
|
+
"App",
|
|
342
|
+
"FeatureSet",
|
|
343
|
+
"APIReference",
|
|
344
|
+
"views",
|
|
345
|
+
"partials",
|
|
346
|
+
"head.ejs",
|
|
347
|
+
),
|
|
348
|
+
[
|
|
349
|
+
"/oneuptime-assets/tailwind/tailwind-3.4.5.js",
|
|
350
|
+
"/oneuptime-assets/highlight/highlight.min.js",
|
|
351
|
+
"/oneuptime-assets/highlight/styles/github-dark.min.css",
|
|
352
|
+
],
|
|
353
|
+
],
|
|
354
|
+
[
|
|
355
|
+
path.join(
|
|
356
|
+
"App",
|
|
357
|
+
"FeatureSet",
|
|
358
|
+
"Identity",
|
|
359
|
+
"Views",
|
|
360
|
+
"Partials",
|
|
361
|
+
"Head.ejs",
|
|
362
|
+
),
|
|
363
|
+
["/oneuptime-assets/tailwind/tailwind-3.4.5.js"],
|
|
364
|
+
],
|
|
365
|
+
[
|
|
366
|
+
path.join("Common", "Server", "Views", "Partials", "Head.ejs"),
|
|
367
|
+
[
|
|
368
|
+
"/oneuptime-assets/tailwind/tailwind-3.4.5.js",
|
|
369
|
+
"/oneuptime-assets/fonts/InterVariable.woff2",
|
|
370
|
+
],
|
|
371
|
+
],
|
|
372
|
+
[
|
|
373
|
+
path.join("Home", "Views", "head-basic.ejs"),
|
|
374
|
+
["/oneuptime-assets/tailwind/tailwind-3.4.5.js"],
|
|
375
|
+
],
|
|
376
|
+
[
|
|
377
|
+
path.join("Home", "Views", "Blog", "Post.ejs"),
|
|
378
|
+
[
|
|
379
|
+
"/oneuptime-assets/highlight/highlight.min.js",
|
|
380
|
+
"/oneuptime-assets/mermaid/mermaid.min.js",
|
|
381
|
+
],
|
|
382
|
+
],
|
|
383
|
+
];
|
|
384
|
+
|
|
385
|
+
for (const [viewName, expectedUrls] of expectations) {
|
|
386
|
+
const view: ViewFile | undefined = allViews.find(
|
|
387
|
+
(candidate: ViewFile): boolean => {
|
|
388
|
+
return candidate.name === viewName;
|
|
389
|
+
},
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
expect([viewName, Boolean(view)]).toEqual([viewName, true]);
|
|
393
|
+
|
|
394
|
+
for (const expectedUrl of expectedUrls) {
|
|
395
|
+
expect([
|
|
396
|
+
viewName,
|
|
397
|
+
expectedUrl,
|
|
398
|
+
view?.contents.includes(expectedUrl),
|
|
399
|
+
]).toEqual([viewName, expectedUrl, true]);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
describe("lazily-loaded highlight.js grammars", () => {
|
|
406
|
+
/*
|
|
407
|
+
* The docs and the blog build their script URL by concatenation:
|
|
408
|
+
*
|
|
409
|
+
* s.src = '/oneuptime-assets/highlight/languages/' + lang + '.min.js';
|
|
410
|
+
*
|
|
411
|
+
* so nothing in the URL scan above can tell whether the grammar exists.
|
|
412
|
+
* Adding a language to one of these maps without vendoring the file leaves
|
|
413
|
+
* that language silently unhighlighted on an offline install - the same
|
|
414
|
+
* class of failure, just quieter.
|
|
415
|
+
*/
|
|
416
|
+
const viewsWithLanguageMaps: Array<string> = [
|
|
417
|
+
path.join(
|
|
418
|
+
REPOSITORY_ROOT,
|
|
419
|
+
"App",
|
|
420
|
+
"FeatureSet",
|
|
421
|
+
"Docs",
|
|
422
|
+
"Views",
|
|
423
|
+
"Partials",
|
|
424
|
+
"Head.ejs",
|
|
425
|
+
),
|
|
426
|
+
path.join(REPOSITORY_ROOT, "Home", "Views", "Blog", "Post.ejs"),
|
|
427
|
+
];
|
|
428
|
+
|
|
429
|
+
function grammarsUsedBy(viewPath: string): Array<string> {
|
|
430
|
+
const contents: string = fs.readFileSync(viewPath, "utf8");
|
|
431
|
+
const map: RegExpMatchArray | null = contents.match(
|
|
432
|
+
/var langMap = \{([\s\S]*?)\};/,
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
if (!map || !map[1]) {
|
|
436
|
+
return [];
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const values: Array<string> = map[1].match(/:\s*'([a-z0-9]+)'/g) || [];
|
|
440
|
+
|
|
441
|
+
return Array.from(
|
|
442
|
+
new Set(
|
|
443
|
+
values.map((value: string): string => {
|
|
444
|
+
return value.replace(/^:\s*'|'$/g, "");
|
|
445
|
+
}),
|
|
446
|
+
),
|
|
447
|
+
).sort();
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
test.each(
|
|
451
|
+
viewsWithLanguageMaps.map((viewPath: string) => {
|
|
452
|
+
return [viewPath];
|
|
453
|
+
}),
|
|
454
|
+
)("%s only maps grammars that are vendored", (viewPath: string) => {
|
|
455
|
+
const grammars: Array<string> = grammarsUsedBy(viewPath);
|
|
456
|
+
|
|
457
|
+
expect(grammars.length).toBeGreaterThan(0);
|
|
458
|
+
|
|
459
|
+
const missing: Array<string> = grammars.filter(
|
|
460
|
+
(grammar: string): boolean => {
|
|
461
|
+
return !fs.existsSync(
|
|
462
|
+
path.join(
|
|
463
|
+
VendorAssetsPath,
|
|
464
|
+
"highlight",
|
|
465
|
+
"languages",
|
|
466
|
+
`${grammar}.min.js`,
|
|
467
|
+
),
|
|
468
|
+
);
|
|
469
|
+
},
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
expect(missing).toEqual([]);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
test("vendors no grammar no view asks for", () => {
|
|
476
|
+
/*
|
|
477
|
+
* Not a correctness rule - a maintenance one. Every file here has to be
|
|
478
|
+
* re-downloaded on a highlight.js bump, so the set should stay the set
|
|
479
|
+
* something actually loads.
|
|
480
|
+
*/
|
|
481
|
+
const requested: Set<string> = new Set<string>();
|
|
482
|
+
|
|
483
|
+
for (const viewPath of viewsWithLanguageMaps) {
|
|
484
|
+
for (const grammar of grammarsUsedBy(viewPath)) {
|
|
485
|
+
requested.add(grammar);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/* The API reference loads these with plain <script> tags. */
|
|
490
|
+
for (const eager of [
|
|
491
|
+
"python",
|
|
492
|
+
"go",
|
|
493
|
+
"java",
|
|
494
|
+
"csharp",
|
|
495
|
+
"php",
|
|
496
|
+
"ruby",
|
|
497
|
+
"rust",
|
|
498
|
+
"powershell",
|
|
499
|
+
"bash",
|
|
500
|
+
"json",
|
|
501
|
+
"javascript",
|
|
502
|
+
"typescript",
|
|
503
|
+
]) {
|
|
504
|
+
requested.add(eager);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const vendored: Array<string> = fs
|
|
508
|
+
.readdirSync(path.join(VendorAssetsPath, "highlight", "languages"))
|
|
509
|
+
.map((file: string): string => {
|
|
510
|
+
return file.replace(/\.min\.js$/, "");
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
const unused: Array<string> = vendored.filter(
|
|
514
|
+
(grammar: string): boolean => {
|
|
515
|
+
return !requested.has(grammar);
|
|
516
|
+
},
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
expect(unused).toEqual([]);
|
|
520
|
+
});
|
|
521
|
+
});
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterEach,
|
|
3
|
+
beforeEach,
|
|
4
|
+
describe,
|
|
5
|
+
expect,
|
|
6
|
+
jest,
|
|
7
|
+
test,
|
|
8
|
+
} from "@jest/globals";
|
|
9
|
+
import { ExpressRequest, ExpressResponse } from "../../../Server/Utils/Express";
|
|
10
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* Response.render is the only thing standing between a self-hosted install and
|
|
14
|
+
* a Google Tag Manager snippet.
|
|
15
|
+
*
|
|
16
|
+
* The views it renders - the on-call acknowledge page, the SSO message page -
|
|
17
|
+
* are rendered from a dozen call sites, none of which pass an analytics flag,
|
|
18
|
+
* and their <head> partial now guards the GTM block on one. Somebody has to
|
|
19
|
+
* supply it. Doing that per call site would have meant a dozen chances to
|
|
20
|
+
* forget; doing it here means the default is right and a caller has to opt in
|
|
21
|
+
* on purpose.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
interface RenderCall {
|
|
25
|
+
path: string;
|
|
26
|
+
variables: JSONObject;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe("Response.render", () => {
|
|
30
|
+
let rendered: Array<RenderCall>;
|
|
31
|
+
let response: ExpressResponse;
|
|
32
|
+
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
rendered = [];
|
|
35
|
+
|
|
36
|
+
response = {
|
|
37
|
+
render: (path: string, variables: JSONObject): void => {
|
|
38
|
+
rendered.push({ path, variables });
|
|
39
|
+
},
|
|
40
|
+
} as unknown as ExpressResponse;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
jest.resetModules();
|
|
45
|
+
delete process.env["BILLING_ENABLED"];
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
type LoadResponse = () => Promise<{
|
|
49
|
+
render: (
|
|
50
|
+
request: ExpressRequest,
|
|
51
|
+
response: ExpressResponse,
|
|
52
|
+
path: string,
|
|
53
|
+
variables: JSONObject,
|
|
54
|
+
) => void;
|
|
55
|
+
}>;
|
|
56
|
+
|
|
57
|
+
const loadResponse: LoadResponse = async () => {
|
|
58
|
+
const { default: ResponseUtil } = await import(
|
|
59
|
+
"../../../Server/Utils/Response"
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
return ResponseUtil as unknown as Awaited<ReturnType<LoadResponse>>;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
test("turns analytics off when billing is off", async () => {
|
|
66
|
+
process.env["BILLING_ENABLED"] = "false";
|
|
67
|
+
|
|
68
|
+
(await loadResponse()).render(
|
|
69
|
+
{} as ExpressRequest,
|
|
70
|
+
response,
|
|
71
|
+
"/views/ViewMessage.ejs",
|
|
72
|
+
{ title: "Acknowledged" },
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
expect(rendered[0]?.variables["enableGoogleTagManager"]).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("turns analytics off when billing is not configured at all", async () => {
|
|
79
|
+
/*
|
|
80
|
+
* The common self-hosted case: the variable is simply absent, not set to
|
|
81
|
+
* "false".
|
|
82
|
+
*/
|
|
83
|
+
delete process.env["BILLING_ENABLED"];
|
|
84
|
+
|
|
85
|
+
(await loadResponse()).render(
|
|
86
|
+
{} as ExpressRequest,
|
|
87
|
+
response,
|
|
88
|
+
"/views/ViewMessage.ejs",
|
|
89
|
+
{},
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
expect(rendered[0]?.variables["enableGoogleTagManager"]).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("leaves analytics on for the hosted product", async () => {
|
|
96
|
+
process.env["BILLING_ENABLED"] = "true";
|
|
97
|
+
|
|
98
|
+
(await loadResponse()).render(
|
|
99
|
+
{} as ExpressRequest,
|
|
100
|
+
response,
|
|
101
|
+
"/views/ViewMessage.ejs",
|
|
102
|
+
{},
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
expect(rendered[0]?.variables["enableGoogleTagManager"]).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("lets a caller override the default", async () => {
|
|
109
|
+
process.env["BILLING_ENABLED"] = "true";
|
|
110
|
+
|
|
111
|
+
(await loadResponse()).render(
|
|
112
|
+
{} as ExpressRequest,
|
|
113
|
+
response,
|
|
114
|
+
"/views/ViewMessage.ejs",
|
|
115
|
+
{ enableGoogleTagManager: false },
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
expect(rendered[0]?.variables["enableGoogleTagManager"]).toBe(false);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("passes the caller's own variables through untouched", async () => {
|
|
122
|
+
process.env["BILLING_ENABLED"] = "false";
|
|
123
|
+
|
|
124
|
+
(await loadResponse()).render(
|
|
125
|
+
{} as ExpressRequest,
|
|
126
|
+
response,
|
|
127
|
+
"/views/AcknowledgeUserOnCallNotification.ejs",
|
|
128
|
+
{
|
|
129
|
+
title: "Acknowledge Incident",
|
|
130
|
+
message: "Do you want to acknowledge this Incident?",
|
|
131
|
+
acknowledgeUrl: "https://oneuptime.example.com/api/ack/1",
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
expect(rendered[0]?.path).toBe(
|
|
136
|
+
"/views/AcknowledgeUserOnCallNotification.ejs",
|
|
137
|
+
);
|
|
138
|
+
expect(rendered[0]?.variables["title"]).toBe("Acknowledge Incident");
|
|
139
|
+
expect(rendered[0]?.variables["acknowledgeUrl"]).toBe(
|
|
140
|
+
"https://oneuptime.example.com/api/ack/1",
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
});
|