@oneuptime/common 13.0.1 → 13.0.4
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/RumSession.ts +34 -0
- package/Models/DatabaseModels/AlertEpisodeLabelRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodeOnCallRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodeOwnerRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodePrivacyRule.ts +2 -2
- package/Models/DatabaseModels/AlertGroupingRule.ts +2 -2
- package/Models/DatabaseModels/AlertLabelRule.ts +2 -2
- package/Models/DatabaseModels/AlertOnCallRule.ts +2 -2
- package/Models/DatabaseModels/AlertOwnerRule.ts +2 -2
- package/Models/DatabaseModels/AlertPrivacyRule.ts +2 -2
- package/Models/DatabaseModels/AlertReminderRule.ts +6 -4
- package/Models/DatabaseModels/AutoRemediationRule.ts +2 -2
- package/Models/DatabaseModels/CephClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/CephClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/CloudResourceLabelRule.ts +2 -2
- package/Models/DatabaseModels/CloudResourceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/DashboardLabelRule.ts +2 -2
- package/Models/DatabaseModels/DashboardOwnerRule.ts +2 -2
- package/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.ts +11 -0
- package/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.ts +44 -0
- package/Models/DatabaseModels/DockerHostLabelRule.ts +2 -2
- package/Models/DatabaseModels/DockerHostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/DockerSwarmClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/DockerSwarmClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/HostLabelRule.ts +2 -2
- package/Models/DatabaseModels/HostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodeLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodeOnCallRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodeOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodePrivacyRule.ts +2 -2
- package/Models/DatabaseModels/IncidentGroupingRule.ts +2 -2
- package/Models/DatabaseModels/IncidentLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncidentOnCallRule.ts +2 -2
- package/Models/DatabaseModels/IncidentOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncidentPrivacyRule.ts +2 -2
- package/Models/DatabaseModels/IncidentReminderRule.ts +6 -4
- package/Models/DatabaseModels/IncidentSlaRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicy.ts +3 -4
- package/Models/DatabaseModels/IncomingCallPolicyLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicyOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.ts +254 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/IoTFleetLabelRule.ts +2 -2
- package/Models/DatabaseModels/IoTFleetOwnerRule.ts +2 -2
- package/Models/DatabaseModels/KubernetesClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/KubernetesClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/MonitorLabelRule.ts +2 -2
- package/Models/DatabaseModels/MonitorOwnerRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceLabelRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyLabelRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.ts +2 -2
- package/Models/DatabaseModels/PodmanHostLabelRule.ts +2 -2
- package/Models/DatabaseModels/PodmanHostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ProxmoxClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/ProxmoxClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RumApplicationLabelRule.ts +2 -2
- package/Models/DatabaseModels/RumApplicationOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RunbookLabelRule.ts +2 -2
- package/Models/DatabaseModels/RunbookOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RunbookRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenanceLabelRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenanceReminderRule.ts +6 -4
- package/Models/DatabaseModels/ServerlessFunctionLabelRule.ts +2 -2
- package/Models/DatabaseModels/ServerlessFunctionOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ServiceLabelRule.ts +2 -2
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +283 -4
- package/Models/DatabaseModels/ServiceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageLabelRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageMonitorRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageOwnerRule.ts +2 -2
- package/Models/DatabaseModels/VMwareVCenterLabelRule.ts +2 -2
- package/Models/DatabaseModels/VMwareVCenterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/WorkflowLabelRule.ts +2 -2
- package/Models/DatabaseModels/WorkflowOwnerRule.ts +2 -2
- package/Server/API/TelemetryAPI.ts +323 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.ts +111 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.ts +644 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.ts +72 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/MultipartFormData.ts +46 -21
- package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodeOnCallRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +21 -0
- package/Server/Services/AlertGroupingEngineService.ts +27 -0
- package/Server/Services/AlertLabelRuleEngineService.ts +27 -0
- package/Server/Services/AlertOnCallRuleEngineService.ts +27 -0
- package/Server/Services/AlertOwnerRuleEngineService.ts +27 -0
- package/Server/Services/AlertPrivacyRuleEngineService.ts +27 -0
- package/Server/Services/AlertReminderRuleService.ts +65 -33
- package/Server/Services/AutoRemediationRuleEngineService.ts +90 -8
- package/Server/Services/CephClusterLabelRuleEngineService.ts +20 -0
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +20 -0
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +20 -0
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DashboardLabelRuleEngineService.ts +20 -0
- package/Server/Services/DashboardOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DatabaseService.ts +409 -6
- package/Server/Services/DockerHostLabelRuleEngineService.ts +20 -0
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +23 -0
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +23 -0
- package/Server/Services/HostLabelRuleEngineService.ts +13 -0
- package/Server/Services/HostOwnerRuleEngineService.ts +13 -0
- package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodeOnCallRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +21 -0
- package/Server/Services/IncidentGroupingEngineService.ts +64 -13
- package/Server/Services/IncidentLabelRuleEngineService.ts +64 -9
- package/Server/Services/IncidentOnCallRuleEngineService.ts +64 -10
- package/Server/Services/IncidentOwnerRuleEngineService.ts +64 -10
- package/Server/Services/IncidentPrivacyRuleEngineService.ts +64 -10
- package/Server/Services/IncidentReminderRuleService.ts +66 -34
- package/Server/Services/IncidentSlaRuleService.ts +55 -12
- package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +20 -0
- package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +20 -0
- package/Server/Services/IncomingCallPolicyPhoneNumberService.ts +184 -0
- package/Server/Services/IncomingCallPolicyService.ts +276 -5
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/IoTFleetLabelRuleEngineService.ts +20 -0
- package/Server/Services/IoTFleetOwnerRuleEngineService.ts +20 -0
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +23 -0
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +23 -0
- package/Server/Services/LabelService.ts +50 -7
- package/Server/Services/MonitorLabelRuleEngineService.ts +20 -0
- package/Server/Services/MonitorOwnerRuleEngineService.ts +20 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +2 -0
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +93 -1
- package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +26 -0
- package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +25 -0
- package/Server/Services/NetworkDeviceService.ts +2 -0
- package/Server/Services/NetworkSiteAssignmentRuleService.ts +90 -1
- package/Server/Services/NetworkSiteService.ts +242 -29
- package/Server/Services/NetworkSiteTypeService.ts +177 -77
- package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +20 -0
- package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +20 -0
- package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +22 -0
- package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +22 -0
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +20 -0
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +20 -0
- package/Server/Services/ProjectCallSMSConfigService.ts +156 -7
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +25 -0
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +25 -0
- package/Server/Services/RumApplicationLabelRuleEngineService.ts +22 -0
- package/Server/Services/RumApplicationOwnerRuleEngineService.ts +22 -0
- package/Server/Services/RunbookLabelRuleEngineService.ts +20 -0
- package/Server/Services/RunbookOwnerRuleEngineService.ts +20 -0
- package/Server/Services/RunbookRuleEngineService.ts +18 -1
- package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +62 -10
- package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +62 -11
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +48 -18
- package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +25 -0
- package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +25 -0
- package/Server/Services/ServiceLabelRuleEngineService.ts +20 -0
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +675 -12
- package/Server/Services/ServiceLevelObjectiveService.ts +55 -13
- package/Server/Services/ServiceOwnerRuleEngineService.ts +20 -0
- package/Server/Services/StatusPageLabelRuleEngineService.ts +20 -0
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +31 -2
- package/Server/Services/StatusPageMonitorRuleService.ts +34 -1
- package/Server/Services/StatusPageOwnerRuleEngineService.ts +20 -0
- package/Server/Services/UserService.ts +23 -50
- package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +25 -0
- package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +25 -0
- package/Server/Services/WorkflowLabelRuleEngineService.ts +20 -0
- package/Server/Services/WorkflowOwnerRuleEngineService.ts +20 -0
- package/Server/Static/Brand/README.md +10 -5
- package/Server/Static/Brand/favicons/oneuptime-up-v1.svg +8 -0
- package/Server/Types/Database/QueryHelper.ts +88 -0
- package/Server/Utils/AI/Toolbox/SloTools.ts +19 -2
- package/Server/Utils/IncomingCallPhoneNumber.ts +29 -16
- package/Server/Utils/Profiling.ts +13 -1
- package/Server/Utils/Rules/MonitorRuleCriteriaCache.ts +38 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +498 -0
- package/Server/Utils/Telemetry.ts +3 -1
- package/Server/Utils/VendorAssets.ts +3 -0
- package/Tests/App/Dashboard/AIInsightViewTriage.test.tsx +348 -0
- package/Tests/App/Dashboard/ArchiveResourceCard.test.tsx +476 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +25 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +449 -24
- package/Tests/App/Dashboard/DashboardPersistentSideMenuLayouts.test.tsx +702 -0
- package/Tests/App/Dashboard/ExceptionsLandingRedirect.test.tsx +63 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +150 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +279 -100
- package/Tests/App/Dashboard/InventoryItemSideMenu.test.tsx +155 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +11 -0
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +215 -71
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +347 -0
- package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +263 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +413 -17
- package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +138 -0
- package/Tests/App/Dashboard/SloDashboardTemplateWidgets.test.tsx +940 -0
- package/Tests/App/Dashboard/TelemetryIngestionKeyEdit.test.tsx +378 -0
- package/Tests/App/Dashboard/TelemetryIngestionKeyForm.test.tsx +735 -0
- package/Tests/App/Dashboard/TwoFactorStatus.test.tsx +275 -108
- package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +13 -3
- package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +127 -4
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +5 -4
- package/Tests/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.test.ts +362 -0
- package/Tests/Models/DatabaseModels/RuleBaseModel.test.ts +69 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +181 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +1303 -145
- package/Tests/Server/API/UserTwoFactorSelfService.test.ts +407 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +611 -0
- package/Tests/Server/Middleware/MultipartFormData.test.ts +61 -3
- package/Tests/Server/Middleware/TelemetryIngestionDisabled.test.ts +211 -0
- package/Tests/Server/Services/AlertIncidentRuleCriteriaEngineServices.test.ts +651 -0
- package/Tests/Server/Services/AutoRemediationRuleEngineService.test.ts +79 -0
- package/Tests/Server/Services/DatabaseServiceRelationOnlyRuleRollout.test.ts +330 -0
- package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +522 -0
- package/Tests/Server/Services/IncidentSlaRuleCriteriaCorrelation.test.ts +99 -0
- package/Tests/Server/Services/IncomingCallPolicyPhoneNumberService.test.ts +1540 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +179 -2
- package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +170 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +559 -53
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +122 -55
- package/Tests/Server/Services/ReminderRuleCriteria.test.ts +173 -0
- package/Tests/Server/Services/ResourceRuleCriteriaEngineServices.test.ts +170 -0
- package/Tests/Server/Services/ScheduledMaintenanceRuleCriteriaCorrelation.test.ts +154 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +2450 -470
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +464 -121
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +281 -0
- package/Tests/Server/Services/StatusPageMonitorRuleEngineService.test.ts +132 -0
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +159 -14
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +6 -8
- package/Tests/Server/Services/UserTwoFactorAuthAdmin.test.ts +203 -34
- package/Tests/Server/Types/Database/QueryHelperJsonArrayObjects.test.ts +128 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +190 -1
- package/Tests/Server/Utils/AI/Toolbox/AIToolbox.test.ts +461 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +25 -0
- package/Tests/Server/Utils/Billing/BillingFailureNoticeThrottle.test.ts +359 -0
- package/Tests/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.test.ts +318 -0
- package/Tests/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.test.ts +220 -0
- package/Tests/Server/Utils/Dashboard/SloTemplatePublicDashboard.test.ts +1043 -0
- package/Tests/Server/Utils/Execute.test.ts +302 -0
- package/Tests/Server/Utils/GracefulShutdown.test.ts +565 -0
- package/Tests/Server/Utils/IncomingCallPhoneNumber.test.ts +36 -20
- package/Tests/Server/Utils/LoggerCore.test.ts +597 -0
- package/Tests/Server/Utils/Monitor/MonitorTemplateUtil.test.ts +1109 -0
- package/Tests/Server/Utils/Monitor/SloTemplateMetricEmitterContract.test.ts +750 -0
- package/Tests/Server/Utils/ProductAnalytics.test.ts +404 -0
- package/Tests/Server/Utils/Profiling.test.ts +366 -0
- package/Tests/Server/Utils/Rules/MonitorRuleCriteriaCache.test.ts +99 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +558 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +711 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +522 -0
- package/Tests/Server/Utils/VendorAssets.test.ts +17 -0
- package/Tests/Types/Dashboard/DashboardTemplateEditorialInvariants.test.ts +659 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +97 -0
- package/Tests/Types/Dashboard/SloDashboardTemplate.test.ts +1179 -0
- package/Tests/Types/Database/AccessControl/OwnedThrough.test.ts +136 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilCorePaths.test.ts +1014 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveRotation.test.ts +9 -6
- package/Tests/Types/Rules/RuleCriteriaFieldRegistry.test.ts +276 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +180 -1
- package/Tests/Types/Telemetry/LlmConventions.test.ts +495 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +13 -6
- package/Tests/UI/Components/Alert.test.tsx +532 -93
- package/Tests/UI/Components/Feed.test.tsx +241 -0
- package/Tests/UI/Components/Forms/BasicFormStepNavigation.test.tsx +368 -0
- package/Tests/UI/Components/Forms/FormSummary.test.tsx +454 -0
- package/Tests/UI/Components/Forms/ModelFormJsonColumns.test.tsx +290 -0
- package/Tests/UI/Components/Forms/ModelFormRuleCriteria.test.tsx +331 -0
- package/Tests/UI/Components/IconOpticalSize.test.tsx +79 -31
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +6 -6
- package/Tests/UI/Components/NavBar.test.tsx +91 -2
- package/Tests/UI/Components/PencilButton.test.tsx +211 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaBuilder.test.tsx +510 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +350 -0
- package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +50 -0
- package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +329 -0
- package/Tests/UI/Components/useFeedItems.test.tsx +107 -0
- package/Tests/UI/Rum/ChunkLoader.test.ts +401 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +1 -1
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +7 -1
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +2 -0
- package/Tests/UI/Rum/ReplayEngine.test.ts +1069 -5
- package/Tests/UI/Rum/ReplayHeader.test.tsx +579 -2
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +23 -5
- package/Tests/UI/Rum/ReplayRail.test.tsx +143 -1
- package/Tests/UI/Rum/ReplayRenderBudget.test.tsx +338 -0
- package/Tests/UI/Rum/ReplaySignals.test.ts +179 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +210 -3
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +180 -1
- package/Tests/UI/Rum/ReplayUserSessionsMenu.test.tsx +405 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +13 -16
- package/Tests/UI/Rum/SessionReplayFacets.test.tsx +199 -0
- package/Tests/UI/Rum/SessionReplaySearchBar.test.tsx +58 -21
- package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +2 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +717 -4
- package/Tests/UI/Rum/SessionReplayUsersPage.test.tsx +435 -0
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +577 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +1 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +1 -1
- package/Tests/UI/Utils/LabelRuleImportExport.test.ts +192 -0
- package/Tests/UI/Utils/Navigation.test.ts +30 -0
- package/Tests/Utils/Dashboard/SloTemplateVariableScoping.test.ts +880 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +158 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +93 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +138 -0
- package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +174 -0
- package/Tests/Utils/Rules/RuleCriteriaMatcher.test.ts +1424 -0
- package/Tests/Utils/Rum/SessionIdentity.test.ts +72 -0
- package/Tests/Utils/Rum/SessionReplayHealth.test.ts +884 -0
- package/Tests/Utils/Slo/SloBurnRateRuleState.test.ts +374 -28
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +118 -0
- package/Types/Dashboard/DashboardTemplates.ts +465 -0
- package/Types/OnCallDutyPolicy/Layer.ts +12 -0
- package/Types/Rules/RuleCriteria.ts +51 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +449 -0
- package/Types/Rum/SessionReplay.ts +75 -0
- package/Types/Rum/SessionReplayApi.ts +93 -0
- package/UI/Components/Alerts/Alert.tsx +102 -72
- package/UI/Components/Button/Button.tsx +4 -1
- package/UI/Components/Dropdown/Dropdown.tsx +2 -0
- package/UI/Components/Feed/Feed.tsx +15 -0
- package/UI/Components/Feed/useFeedItems.ts +227 -0
- package/UI/Components/Forms/BasicForm.tsx +42 -21
- package/UI/Components/Forms/ModelForm.tsx +80 -1
- package/UI/Components/Icon/Icon.tsx +3 -35
- package/UI/Components/ModelTable/ModelTable.tsx +19 -0
- package/UI/Components/Navbar/NavBar.tsx +1 -0
- package/UI/Components/RuleCriteria/RuleCriteriaBuilder.tsx +735 -0
- package/UI/Components/RuleCriteria/RuleCriteriaModelForm.tsx +209 -0
- package/UI/Components/RuleCriteria/RuleCriteriaModelTable.tsx +205 -0
- package/UI/Components/RuleCriteria/RuleCriteriaSummary.tsx +123 -0
- package/UI/Components/Table/Table.tsx +3 -0
- package/UI/Components/Table/TableBody.tsx +3 -0
- package/UI/Components/Table/TableRow.tsx +8 -2
- package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +14 -2
- package/UI/Styles/Theme.css +1 -0
- package/UI/Utils/LabelRuleImportExport.ts +114 -6
- package/UI/Utils/Navigation.ts +1 -2
- package/UI/esbuild-config.js +46 -0
- package/Utils/Faker.ts +93 -6
- package/Utils/LabelRuleImportExport.ts +295 -2
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +108 -8
- package/Utils/NetworkSite/CidrMatchUtil.ts +102 -0
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +152 -2
- package/Utils/Rules/RuleCriteriaMatcher.ts +931 -0
- package/Utils/Rum/SessionIdentity.ts +16 -0
- package/Utils/Slo/SloBurnRateRuleState.ts +87 -33
- package/Utils/Telemetry/OriginAllowList.ts +74 -0
- package/build/dist/Models/AnalyticsModels/RumSession.js +32 -0
- package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodePrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodePrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertPrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertPrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/AlertReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AutoRemediationRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AutoRemediationRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResourceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CloudResourceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResourceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CloudResourceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DashboardLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DashboardLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DashboardOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DashboardOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.js +50 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DockerHostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerHostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerHostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/HostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/HostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/HostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/HostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodePrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentPrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/IncidentReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentSlaRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentSlaRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js +3 -4
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.js +277 -0
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.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/IoTFleetLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/KubernetesClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/MonitorLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/MonitorOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/PodmanHostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/PodmanHostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplicationLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RumApplicationLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplicationOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RumApplicationOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunctionLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServerlessFunctionLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServiceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +281 -4
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServiceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/WorkflowLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/WorkflowOwnerRule.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +211 -4
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.js +60 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.js +301 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.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/Middleware/MultipartFormData.js +38 -21
- package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js +21 -0
- package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOnCallRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +44 -26
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +54 -11
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +235 -10
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +12 -0
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +12 -0
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +39 -13
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +39 -9
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentReminderRuleService.js +44 -26
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSlaRuleService.js +33 -12
- package/build/dist/Server/Services/IncidentSlaRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyPhoneNumberService.js +127 -0
- package/build/dist/Server/Services/IncomingCallPolicyPhoneNumberService.js.map +1 -0
- package/build/dist/Server/Services/IncomingCallPolicyService.js +187 -4
- package/build/dist/Server/Services/IncomingCallPolicyService.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/IoTFleetLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +39 -7
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +2 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +57 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +2 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +56 -1
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +187 -22
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +126 -51
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js +115 -6
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookRuleEngineService.js +12 -0
- package/build/dist/Server/Services/RunbookRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +38 -9
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +38 -10
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +32 -14
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +554 -12
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +50 -14
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +25 -2
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js +19 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +14 -49
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +67 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +21 -4
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
- package/build/dist/Server/Utils/IncomingCallPhoneNumber.js +9 -3
- package/build/dist/Server/Utils/IncomingCallPhoneNumber.js.map +1 -1
- package/build/dist/Server/Utils/Profiling.js +10 -1
- package/build/dist/Server/Utils/Profiling.js.map +1 -1
- package/build/dist/Server/Utils/Rules/MonitorRuleCriteriaCache.js +30 -0
- package/build/dist/Server/Utils/Rules/MonitorRuleCriteriaCache.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +344 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +1 -1
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +2 -0
- package/build/dist/Server/Utils/VendorAssets.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +425 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +11 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteria.js +18 -0
- package/build/dist/Types/Rules/RuleCriteria.js.map +1 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +435 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplay.js +64 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/UI/Components/Alerts/Alert.js +63 -41
- package/build/dist/UI/Components/Alerts/Alert.js.map +1 -1
- package/build/dist/UI/Components/Button/Button.js +3 -1
- package/build/dist/UI/Components/Button/Button.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Feed/Feed.js +4 -1
- package/build/dist/UI/Components/Feed/Feed.js.map +1 -1
- package/build/dist/UI/Components/Feed/useFeedItems.js +137 -0
- package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -0
- package/build/dist/UI/Components/Forms/BasicForm.js +38 -19
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +65 -1
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +3 -35
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +12 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js +383 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelForm.js +124 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelForm.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelTable.js +126 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelTable.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaSummary.js +63 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaSummary.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +1 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +4 -2
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +3 -2
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +14 -2
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +1 -1
- package/build/dist/UI/Utils/LabelRuleImportExport.js +81 -5
- package/build/dist/UI/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/Utils/Faker.js +76 -6
- package/build/dist/Utils/Faker.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +157 -3
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +81 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +77 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +109 -2
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -1
- package/build/dist/Utils/Rules/RuleCriteriaMatcher.js +526 -0
- package/build/dist/Utils/Rules/RuleCriteriaMatcher.js.map +1 -0
- package/build/dist/Utils/Rum/SessionIdentity.js +13 -1
- package/build/dist/Utils/Rum/SessionIdentity.js.map +1 -1
- package/build/dist/Utils/Slo/SloBurnRateRuleState.js +28 -15
- package/build/dist/Utils/Slo/SloBurnRateRuleState.js.map +1 -1
- package/build/dist/Utils/Telemetry/OriginAllowList.js +61 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -1
- package/package.json +20 -20
|
@@ -0,0 +1,1043 @@
|
|
|
1
|
+
import PublicDashboardResourceListPolicy, {
|
|
2
|
+
PublicDashboardResourceListPolicyResult,
|
|
3
|
+
} from "../../../../Server/Utils/Dashboard/PublicDashboardResourceListPolicy";
|
|
4
|
+
import PublicDashboardSloWidget, {
|
|
5
|
+
PublicDashboardSloWidgetConfig,
|
|
6
|
+
} from "../../../../Server/Utils/Dashboard/PublicDashboardSloWidget";
|
|
7
|
+
import PublicDashboardViewConfig from "../../../../Server/Utils/Dashboard/PublicDashboardViewConfig";
|
|
8
|
+
import Alert from "../../../../Models/DatabaseModels/Alert";
|
|
9
|
+
import DatabaseBaseModel from "../../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
10
|
+
import Incident from "../../../../Models/DatabaseModels/Incident";
|
|
11
|
+
import Monitor from "../../../../Models/DatabaseModels/Monitor";
|
|
12
|
+
import ServiceLevelObjective from "../../../../Models/DatabaseModels/ServiceLevelObjective";
|
|
13
|
+
import SortOrder from "../../../../Types/BaseDatabase/SortOrder";
|
|
14
|
+
import { LIMIT_PER_PROJECT } from "../../../../Types/Database/LimitMax";
|
|
15
|
+
import DashboardBaseComponent from "../../../../Types/Dashboard/DashboardComponents/DashboardBaseComponent";
|
|
16
|
+
import {
|
|
17
|
+
SloWidgetDisplayType,
|
|
18
|
+
SloWidgetMetric,
|
|
19
|
+
} from "../../../../Types/Dashboard/DashboardComponents/DashboardSloComponent";
|
|
20
|
+
import DashboardComponentType from "../../../../Types/Dashboard/DashboardComponentType";
|
|
21
|
+
import {
|
|
22
|
+
DashboardTemplateType,
|
|
23
|
+
getTemplateConfig,
|
|
24
|
+
} from "../../../../Types/Dashboard/DashboardTemplates";
|
|
25
|
+
import DashboardVariable, {
|
|
26
|
+
DashboardVariableType,
|
|
27
|
+
} from "../../../../Types/Dashboard/DashboardVariable";
|
|
28
|
+
import DashboardViewConfig from "../../../../Types/Dashboard/DashboardViewConfig";
|
|
29
|
+
import BadDataException from "../../../../Types/Exception/BadDataException";
|
|
30
|
+
import { JSONObject } from "../../../../Types/JSON";
|
|
31
|
+
import ObjectID from "../../../../Types/ObjectID";
|
|
32
|
+
import { describe, expect, it } from "@jest/globals";
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* The SLO template's own stored config, driven through the server policy that
|
|
36
|
+
* stands between an ANONYMOUS public-dashboard viewer and the project's data.
|
|
37
|
+
*
|
|
38
|
+
* The editorial suite (Tests/Types/Dashboard/SloDashboardTemplate.test.ts)
|
|
39
|
+
* pins what the template SAYS. This one pins what it can be made to DO once a
|
|
40
|
+
* dashboard created from it is published: which rows the unauthenticated
|
|
41
|
+
* routes will read, which columns of those rows travel to the viewer, and
|
|
42
|
+
* which widgets fail closed instead of resolving to something broader than
|
|
43
|
+
* their author picked.
|
|
44
|
+
*
|
|
45
|
+
* Written against the template rather than against hand-built widgets on
|
|
46
|
+
* purpose: a widget the template ships is a widget that exists on real public
|
|
47
|
+
* dashboards, so the two files have to agree about the same JSON, and a
|
|
48
|
+
* change to either one that breaks that agreement fails here.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
// -- Fixtures --------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* The owning dashboard's project. DashboardAPI.servePublicResourceList stamps
|
|
55
|
+
* this over the policy query as the LAST word before the root read, so it is
|
|
56
|
+
* modelled here rather than assumed.
|
|
57
|
+
*/
|
|
58
|
+
const DASHBOARD_PROJECT_ID: ObjectID = ObjectID.generate();
|
|
59
|
+
|
|
60
|
+
// The objective an editor picks on a widget after creating the dashboard.
|
|
61
|
+
const PICKED_SLO_ID: ObjectID = ObjectID.generate();
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* Everything a caller of the public endpoint controls, all of it naming
|
|
65
|
+
* something this dashboard never published: another SLO, another project,
|
|
66
|
+
* another row set, an unbounded page. None of it may reach the query.
|
|
67
|
+
*/
|
|
68
|
+
const HOSTILE_QUERY: JSONObject = {
|
|
69
|
+
_id: ObjectID.generate().toString(),
|
|
70
|
+
projectId: ObjectID.generate().toString(),
|
|
71
|
+
name: "probe",
|
|
72
|
+
isEnabled: true,
|
|
73
|
+
isPrivate: false,
|
|
74
|
+
limit: 100000,
|
|
75
|
+
skip: 500,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
* The two refusal messages the policy can answer a template widget with. Both
|
|
80
|
+
* are pinned as literals: they are what an operator reads when a public page
|
|
81
|
+
* shows an error, and they say two DIFFERENT things — "nobody picked an
|
|
82
|
+
* objective yet" versus "this kind of widget has no public list at all".
|
|
83
|
+
*/
|
|
84
|
+
const NO_OBJECTIVE_MESSAGE: string =
|
|
85
|
+
"This dashboard widget has no Service Level Objective selected.";
|
|
86
|
+
|
|
87
|
+
/*
|
|
88
|
+
* The public list resource each template widget kind resolves to. Any widget
|
|
89
|
+
* kind NOT in this map must be refused; that is the whole point of the
|
|
90
|
+
* fall-through walk at the bottom of the file.
|
|
91
|
+
*/
|
|
92
|
+
const PUBLIC_LIST_RESOURCE_BY_COMPONENT_TYPE: Partial<
|
|
93
|
+
Record<DashboardComponentType, string>
|
|
94
|
+
> = {
|
|
95
|
+
[DashboardComponentType.IncidentList]: "incident",
|
|
96
|
+
[DashboardComponentType.AlertList]: "alert",
|
|
97
|
+
[DashboardComponentType.MonitorList]: "monitor",
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
type WidgetArguments = Record<string, unknown>;
|
|
101
|
+
|
|
102
|
+
// -- Helpers ---------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
/*
|
|
105
|
+
* The config exactly as the public route reads it back: sanitized for
|
|
106
|
+
* anonymous viewers, then through JSON, because it lives in a JSONB column.
|
|
107
|
+
* Anything the template puts in a widget argument that does not survive that
|
|
108
|
+
* round trip is not what the policy parses.
|
|
109
|
+
*/
|
|
110
|
+
function storedConfig(): DashboardViewConfig {
|
|
111
|
+
const sanitized: DashboardViewConfig | null =
|
|
112
|
+
PublicDashboardViewConfig.sanitize(
|
|
113
|
+
getTemplateConfig(DashboardTemplateType.Slo),
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
expect(sanitized).not.toBeNull();
|
|
117
|
+
|
|
118
|
+
return JSON.parse(JSON.stringify(sanitized)) as DashboardViewConfig;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function componentsOfType(
|
|
122
|
+
config: DashboardViewConfig,
|
|
123
|
+
componentType: DashboardComponentType,
|
|
124
|
+
): Array<DashboardBaseComponent> {
|
|
125
|
+
return config.components.filter(
|
|
126
|
+
(component: DashboardBaseComponent): boolean => {
|
|
127
|
+
return component.componentType === componentType;
|
|
128
|
+
},
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Fails loudly (rather than returning undefined) when the widget is gone.
|
|
133
|
+
function onlyComponentOfType(
|
|
134
|
+
config: DashboardViewConfig,
|
|
135
|
+
componentType: DashboardComponentType,
|
|
136
|
+
): DashboardBaseComponent {
|
|
137
|
+
const matches: Array<DashboardBaseComponent> = componentsOfType(
|
|
138
|
+
config,
|
|
139
|
+
componentType,
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
expect(matches).toHaveLength(1);
|
|
143
|
+
|
|
144
|
+
return matches[0] as DashboardBaseComponent;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function argumentsOf(component: DashboardBaseComponent): WidgetArguments {
|
|
148
|
+
return (component.arguments as WidgetArguments | undefined) || {};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/*
|
|
152
|
+
* Widget titles are the only stable handle on a template widget — component
|
|
153
|
+
* ids are regenerated on every getTemplateConfig() call and row positions
|
|
154
|
+
* move whenever a band is inserted. Each family stores its title under its
|
|
155
|
+
* own key; the Slo widget uses `widgetTitle`, which no other family does.
|
|
156
|
+
*/
|
|
157
|
+
function titleOf(component: DashboardBaseComponent): string {
|
|
158
|
+
const args: WidgetArguments = argumentsOf(component);
|
|
159
|
+
|
|
160
|
+
for (const key of ["widgetTitle", "title", "chartTitle", "text"]) {
|
|
161
|
+
const value: unknown = args[key];
|
|
162
|
+
|
|
163
|
+
if (typeof value === "string" && value.length > 0) {
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return "(untitled)";
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Every assertion below is labelled with this, so a failure names the widget.
|
|
172
|
+
function labelOf(component: DashboardBaseComponent): string {
|
|
173
|
+
return `${component.componentType} "${titleOf(component)}"`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/*
|
|
177
|
+
* A copy of a stored widget with its arguments overridden — used to model the
|
|
178
|
+
* editor picking an objective on a template widget, which is the only thing
|
|
179
|
+
* that turns one of them into a widget that resolves.
|
|
180
|
+
*/
|
|
181
|
+
function withArguments(
|
|
182
|
+
component: DashboardBaseComponent,
|
|
183
|
+
overrides: WidgetArguments,
|
|
184
|
+
): DashboardBaseComponent {
|
|
185
|
+
return {
|
|
186
|
+
...component,
|
|
187
|
+
arguments: { ...argumentsOf(component), ...overrides },
|
|
188
|
+
} as DashboardBaseComponent;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function buildPolicy(data: {
|
|
192
|
+
config: DashboardViewConfig;
|
|
193
|
+
component: DashboardBaseComponent;
|
|
194
|
+
requestedQuery?: JSONObject | undefined;
|
|
195
|
+
requestedVariables?: Array<JSONObject> | undefined;
|
|
196
|
+
}): PublicDashboardResourceListPolicyResult {
|
|
197
|
+
return PublicDashboardResourceListPolicy.build({
|
|
198
|
+
widget: data.component as unknown as JSONObject,
|
|
199
|
+
dashboardViewConfig: data.config,
|
|
200
|
+
requestedVariables: data.requestedVariables || [],
|
|
201
|
+
requestedQuery: data.requestedQuery || {},
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/*
|
|
206
|
+
* The query the route actually executes: the policy query, with the owning
|
|
207
|
+
* dashboard's project stamped over it. Asserting on THIS rather than on
|
|
208
|
+
* policy.query alone is what proves a requested projectId cannot survive.
|
|
209
|
+
*/
|
|
210
|
+
function routeQuery(policy: PublicDashboardResourceListPolicyResult): {
|
|
211
|
+
[key: string]: unknown;
|
|
212
|
+
} {
|
|
213
|
+
return { ...policy.query, projectId: DASHBOARD_PROJECT_ID };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/*
|
|
217
|
+
* What the policy did with one stored widget, as a single comparable string:
|
|
218
|
+
* either the resource it will list, or the refusal it answered with. A widget
|
|
219
|
+
* that resolves where it should be refused reads as a plain diff rather than
|
|
220
|
+
* as a missing throw.
|
|
221
|
+
*/
|
|
222
|
+
function outcomeOf(data: {
|
|
223
|
+
config: DashboardViewConfig;
|
|
224
|
+
component: DashboardBaseComponent;
|
|
225
|
+
}): string {
|
|
226
|
+
try {
|
|
227
|
+
const policy: PublicDashboardResourceListPolicyResult = buildPolicy(data);
|
|
228
|
+
|
|
229
|
+
return `lists ${policy.resourceType}`;
|
|
230
|
+
} catch (error) {
|
|
231
|
+
if (error instanceof BadDataException) {
|
|
232
|
+
return `refused: ${error.message}`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return `threw a non-BadDataException: ${String(error)}`;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function expectedOutcomeOf(component: DashboardBaseComponent): string {
|
|
240
|
+
const resourceType: string | undefined =
|
|
241
|
+
PUBLIC_LIST_RESOURCE_BY_COMPONENT_TYPE[component.componentType];
|
|
242
|
+
|
|
243
|
+
if (resourceType) {
|
|
244
|
+
return `lists ${resourceType}`;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/*
|
|
248
|
+
* Every Slo widget the template ships is unconfigured, so it refuses for
|
|
249
|
+
* the one reason that is not a bug.
|
|
250
|
+
*/
|
|
251
|
+
if (component.componentType === DashboardComponentType.Slo) {
|
|
252
|
+
return `refused: ${NO_OBJECTIVE_MESSAGE}`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/*
|
|
256
|
+
* Text, Value and Chart widgets read the metric store, not a Postgres list,
|
|
257
|
+
* so the public list endpoint has nothing to serve them — and says which
|
|
258
|
+
* widget kind it is turning away.
|
|
259
|
+
*/
|
|
260
|
+
return `refused: Unsupported public dashboard resource widget: ${component.componentType}`;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/*
|
|
264
|
+
* The columns the model declares that a widget's public select does NOT
|
|
265
|
+
* publish. Derived from the model itself so it cannot go stale as the model
|
|
266
|
+
* grows.
|
|
267
|
+
*/
|
|
268
|
+
function withheldColumnsOf(data: {
|
|
269
|
+
model: DatabaseBaseModel;
|
|
270
|
+
select: JSONObject;
|
|
271
|
+
}): Array<string> {
|
|
272
|
+
const published: Array<string> = Object.keys(data.select);
|
|
273
|
+
|
|
274
|
+
return data.model
|
|
275
|
+
.getTableColumns()
|
|
276
|
+
.columns.filter((column: string): boolean => {
|
|
277
|
+
return !published.includes(column);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/*
|
|
282
|
+
* Two directions, both needed:
|
|
283
|
+
*
|
|
284
|
+
* - every field the select DOES publish is a real column of the model, so a
|
|
285
|
+
* pinned select cannot quietly drift onto a field that no longer exists;
|
|
286
|
+
* - every column named as sensitive is a real column of the model AND is
|
|
287
|
+
* withheld. Checking that the name is real is what stops this list from
|
|
288
|
+
* rotting into a set of no-op assertions after a column rename.
|
|
289
|
+
*/
|
|
290
|
+
function expectSelectPublishesNothingSensitive(data: {
|
|
291
|
+
modelName: string;
|
|
292
|
+
model: DatabaseBaseModel;
|
|
293
|
+
select: JSONObject;
|
|
294
|
+
sensitiveColumns: Array<string>;
|
|
295
|
+
}): void {
|
|
296
|
+
const declared: Array<string> = data.model.getTableColumns().columns;
|
|
297
|
+
const withheld: Array<string> = withheldColumnsOf({
|
|
298
|
+
model: data.model,
|
|
299
|
+
select: data.select,
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
expect(declared.length).toBeGreaterThan(0);
|
|
303
|
+
expect(withheld.length).toBeGreaterThan(0);
|
|
304
|
+
expect(data.sensitiveColumns.length).toBeGreaterThan(0);
|
|
305
|
+
|
|
306
|
+
for (const column of Object.keys(data.select)) {
|
|
307
|
+
expect(
|
|
308
|
+
`${data.modelName}.${column} is ${
|
|
309
|
+
declared.includes(column) ? "a column" : "NOT A COLUMN"
|
|
310
|
+
}`,
|
|
311
|
+
).toBe(`${data.modelName}.${column} is a column`);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
for (const column of data.sensitiveColumns) {
|
|
315
|
+
expect(
|
|
316
|
+
`${data.modelName}.${column} is ${
|
|
317
|
+
declared.includes(column) ? "a column" : "NOT A COLUMN"
|
|
318
|
+
}`,
|
|
319
|
+
).toBe(`${data.modelName}.${column} is a column`);
|
|
320
|
+
|
|
321
|
+
expect(
|
|
322
|
+
`${data.modelName}.${column} is ${
|
|
323
|
+
withheld.includes(column) ? "withheld" : "PUBLISHED"
|
|
324
|
+
}`,
|
|
325
|
+
).toBe(`${data.modelName}.${column} is withheld`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function monitorVariableOf(config: DashboardViewConfig): DashboardVariable {
|
|
330
|
+
const telemetryVariables: Array<DashboardVariable> = (
|
|
331
|
+
config.variables || []
|
|
332
|
+
).filter((variable: DashboardVariable): boolean => {
|
|
333
|
+
return variable.type === DashboardVariableType.TelemetryAttribute;
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
expect(telemetryVariables).toHaveLength(1);
|
|
337
|
+
|
|
338
|
+
return telemetryVariables[0] as DashboardVariable;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/*
|
|
342
|
+
* A selection for the template's own Monitor variable, plus one for a
|
|
343
|
+
* variable this dashboard does not have. Neither may become a filter on the
|
|
344
|
+
* Postgres-backed lists, which read no telemetry attribute at all.
|
|
345
|
+
*/
|
|
346
|
+
function hostileVariableSelections(
|
|
347
|
+
config: DashboardViewConfig,
|
|
348
|
+
): Array<JSONObject> {
|
|
349
|
+
return [
|
|
350
|
+
{
|
|
351
|
+
id: monitorVariableOf(config).id,
|
|
352
|
+
selectedValues: ["' OR 1=1 --", "%"],
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
id: ObjectID.generate().toString(),
|
|
356
|
+
selectedValues: ["a variable this dashboard never stored"],
|
|
357
|
+
},
|
|
358
|
+
];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// -- Tests -----------------------------------------------------------------
|
|
362
|
+
|
|
363
|
+
describe("SLO dashboard template on a public dashboard", () => {
|
|
364
|
+
describe("the config an anonymous viewer is served", () => {
|
|
365
|
+
/*
|
|
366
|
+
* The sanitizer drops Data Source widgets outright, because their stored
|
|
367
|
+
* config IS a query against an internal system. This template ships none,
|
|
368
|
+
* so publishing it must cost it no widgets — if a later revision reaches
|
|
369
|
+
* for a Data Source widget, the public page would silently lose it.
|
|
370
|
+
*/
|
|
371
|
+
it("keeps every widget the template ships", () => {
|
|
372
|
+
const template: DashboardViewConfig = getTemplateConfig(
|
|
373
|
+
DashboardTemplateType.Slo,
|
|
374
|
+
) as DashboardViewConfig;
|
|
375
|
+
|
|
376
|
+
expect(template).not.toBeNull();
|
|
377
|
+
expect(template.components.length).toBeGreaterThan(0);
|
|
378
|
+
|
|
379
|
+
const published: DashboardViewConfig = storedConfig();
|
|
380
|
+
|
|
381
|
+
expect(
|
|
382
|
+
published.components.map(
|
|
383
|
+
(component: DashboardBaseComponent): string => {
|
|
384
|
+
return component.componentType;
|
|
385
|
+
},
|
|
386
|
+
),
|
|
387
|
+
).toEqual(
|
|
388
|
+
template.components.map((component: DashboardBaseComponent): string => {
|
|
389
|
+
return component.componentType;
|
|
390
|
+
}),
|
|
391
|
+
);
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
describe("SLO widgets while no objective is picked", () => {
|
|
396
|
+
/*
|
|
397
|
+
* The security property this template rests on. Every Slo widget ships
|
|
398
|
+
* without a serviceLevelObjectiveId because a template cannot know a
|
|
399
|
+
* project's SLO ids — and on a public dashboard the stored id IS the
|
|
400
|
+
* authorization decision. An unconfigured widget therefore has to fail
|
|
401
|
+
* closed: the one thing it must never do is resolve to "whichever SLO the
|
|
402
|
+
* query finds", which on a project-scoped read means any of them.
|
|
403
|
+
*/
|
|
404
|
+
it("refuses every SLO widget the template ships", () => {
|
|
405
|
+
const config: DashboardViewConfig = storedConfig();
|
|
406
|
+
const sloWidgets: Array<DashboardBaseComponent> = componentsOfType(
|
|
407
|
+
config,
|
|
408
|
+
DashboardComponentType.Slo,
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
expect(sloWidgets.length).toBeGreaterThan(0);
|
|
412
|
+
|
|
413
|
+
const outcomes: Array<string> = sloWidgets.map(
|
|
414
|
+
(component: DashboardBaseComponent): string => {
|
|
415
|
+
return `${labelOf(component)} -> ${outcomeOf({ config, component })}`;
|
|
416
|
+
},
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
expect(outcomes).toEqual(
|
|
420
|
+
sloWidgets.map((component: DashboardBaseComponent): string => {
|
|
421
|
+
return `${labelOf(component)} -> refused: ${NO_OBJECTIVE_MESSAGE}`;
|
|
422
|
+
}),
|
|
423
|
+
);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
/*
|
|
427
|
+
* The same stored widget also drives the SloHistory aggregation route,
|
|
428
|
+
* which is a second unauthenticated surface reading a different store.
|
|
429
|
+
* Both parse the id through PublicDashboardSloWidget, so both have to
|
|
430
|
+
* refuse the unconfigured widget — a template whose widgets failed closed
|
|
431
|
+
* on one route and open on the other would be worse than either.
|
|
432
|
+
*/
|
|
433
|
+
it("refuses the same widgets on the SLO history route too", () => {
|
|
434
|
+
const config: DashboardViewConfig = storedConfig();
|
|
435
|
+
const sloWidgets: Array<DashboardBaseComponent> = componentsOfType(
|
|
436
|
+
config,
|
|
437
|
+
DashboardComponentType.Slo,
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
expect(sloWidgets.length).toBeGreaterThan(0);
|
|
441
|
+
|
|
442
|
+
const outcomes: Array<string> = sloWidgets.map(
|
|
443
|
+
(component: DashboardBaseComponent): string => {
|
|
444
|
+
try {
|
|
445
|
+
const parsed: PublicDashboardSloWidgetConfig =
|
|
446
|
+
PublicDashboardSloWidget.readConfig(component);
|
|
447
|
+
|
|
448
|
+
return `${labelOf(component)} -> read ${parsed.serviceLevelObjectiveId.toString()}`;
|
|
449
|
+
} catch (error) {
|
|
450
|
+
if (error instanceof BadDataException) {
|
|
451
|
+
return `${labelOf(component)} -> refused: ${error.message}`;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return `${labelOf(component)} -> threw a non-BadDataException: ${String(
|
|
455
|
+
error,
|
|
456
|
+
)}`;
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
expect(outcomes).toEqual(
|
|
462
|
+
sloWidgets.map((component: DashboardBaseComponent): string => {
|
|
463
|
+
return `${labelOf(component)} -> refused: ${NO_OBJECTIVE_MESSAGE}`;
|
|
464
|
+
}),
|
|
465
|
+
);
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
describe("an SLO widget once an objective is picked", () => {
|
|
470
|
+
/*
|
|
471
|
+
* The id comes from stored config and from nowhere else. A caller that
|
|
472
|
+
* names a different SLO, a different project, or no filter at all gets
|
|
473
|
+
* the one row the widget's author published — which is why this endpoint
|
|
474
|
+
* cannot be walked across the project's other objectives.
|
|
475
|
+
*/
|
|
476
|
+
it("resolves to exactly the SLO stored on the widget, whatever the request asks for", () => {
|
|
477
|
+
const config: DashboardViewConfig = storedConfig();
|
|
478
|
+
const sloWidgets: Array<DashboardBaseComponent> = componentsOfType(
|
|
479
|
+
config,
|
|
480
|
+
DashboardComponentType.Slo,
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
expect(sloWidgets.length).toBeGreaterThan(0);
|
|
484
|
+
|
|
485
|
+
const resolved: Array<string> = sloWidgets.map(
|
|
486
|
+
(component: DashboardBaseComponent): string => {
|
|
487
|
+
const policy: PublicDashboardResourceListPolicyResult = buildPolicy({
|
|
488
|
+
config,
|
|
489
|
+
component: withArguments(component, {
|
|
490
|
+
serviceLevelObjectiveId: PICKED_SLO_ID.toString(),
|
|
491
|
+
}),
|
|
492
|
+
requestedQuery: HOSTILE_QUERY,
|
|
493
|
+
requestedVariables: hostileVariableSelections(config),
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
return `${labelOf(component)} -> ${policy.resourceType} ${JSON.stringify(
|
|
497
|
+
routeQuery(policy),
|
|
498
|
+
)}`;
|
|
499
|
+
},
|
|
500
|
+
);
|
|
501
|
+
|
|
502
|
+
expect(resolved).toEqual(
|
|
503
|
+
sloWidgets.map((component: DashboardBaseComponent): string => {
|
|
504
|
+
return `${labelOf(component)} -> slo ${JSON.stringify({
|
|
505
|
+
_id: PICKED_SLO_ID,
|
|
506
|
+
projectId: DASHBOARD_PROJECT_ID,
|
|
507
|
+
})}`;
|
|
508
|
+
}),
|
|
509
|
+
);
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
/*
|
|
513
|
+
* One row, no filter, and no caller-supplied page size. A widget that
|
|
514
|
+
* renders a single objective has no use for a second row, and a read that
|
|
515
|
+
* accepts no filter cannot be turned into an oracle that answers
|
|
516
|
+
* questions about the SLOs it was not pointed at.
|
|
517
|
+
*/
|
|
518
|
+
it("reads one row and accepts no filter of its own", () => {
|
|
519
|
+
const config: DashboardViewConfig = storedConfig();
|
|
520
|
+
const sloWidgets: Array<DashboardBaseComponent> = componentsOfType(
|
|
521
|
+
config,
|
|
522
|
+
DashboardComponentType.Slo,
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
expect(sloWidgets.length).toBeGreaterThan(0);
|
|
526
|
+
|
|
527
|
+
for (const component of sloWidgets) {
|
|
528
|
+
const policy: PublicDashboardResourceListPolicyResult = buildPolicy({
|
|
529
|
+
config,
|
|
530
|
+
component: withArguments(component, {
|
|
531
|
+
serviceLevelObjectiveId: PICKED_SLO_ID.toString(),
|
|
532
|
+
}),
|
|
533
|
+
requestedQuery: HOSTILE_QUERY,
|
|
534
|
+
requestedVariables: hostileVariableSelections(config),
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
expect(`${labelOf(component)} reads ${policy.limit} row(s)`).toBe(
|
|
538
|
+
`${labelOf(component)} reads 1 row(s)`,
|
|
539
|
+
);
|
|
540
|
+
expect(
|
|
541
|
+
`${labelOf(component)} filters on ${Object.keys(policy.query)
|
|
542
|
+
.sort()
|
|
543
|
+
.join(", ")}`,
|
|
544
|
+
).toBe(`${labelOf(component)} filters on _id`);
|
|
545
|
+
expect(policy.sort).toEqual({ name: SortOrder.Ascending });
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
/*
|
|
550
|
+
* The id is not the only thing the server parses out of these widgets:
|
|
551
|
+
* the series and the shape are stored under `sloMetric` and
|
|
552
|
+
* `displayType`, and the policy reads those same keys. Renaming either
|
|
553
|
+
* key in the template would leave the server silently defaulting to the
|
|
554
|
+
* SLI tile on six widgets that draw three different numbers.
|
|
555
|
+
*/
|
|
556
|
+
it("parses back the series and display the template stored on each widget", () => {
|
|
557
|
+
const config: DashboardViewConfig = storedConfig();
|
|
558
|
+
const sloWidgets: Array<DashboardBaseComponent> = componentsOfType(
|
|
559
|
+
config,
|
|
560
|
+
DashboardComponentType.Slo,
|
|
561
|
+
);
|
|
562
|
+
|
|
563
|
+
expect(sloWidgets.length).toBeGreaterThan(0);
|
|
564
|
+
|
|
565
|
+
const parsed: Array<string> = sloWidgets.map(
|
|
566
|
+
(component: DashboardBaseComponent): string => {
|
|
567
|
+
const config2: PublicDashboardSloWidgetConfig =
|
|
568
|
+
PublicDashboardSloWidget.readConfig(
|
|
569
|
+
withArguments(component, {
|
|
570
|
+
serviceLevelObjectiveId: PICKED_SLO_ID.toString(),
|
|
571
|
+
}),
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
return `${labelOf(component)} -> ${config2.sloMetric}/${config2.displayType}`;
|
|
575
|
+
},
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
expect(parsed).toEqual(
|
|
579
|
+
sloWidgets.map((component: DashboardBaseComponent): string => {
|
|
580
|
+
const args: WidgetArguments = argumentsOf(component);
|
|
581
|
+
|
|
582
|
+
return `${labelOf(component)} -> ${String(args["sloMetric"])}/${String(
|
|
583
|
+
args["displayType"],
|
|
584
|
+
)}`;
|
|
585
|
+
}),
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
// ...and what came back is a real member of each enum, not a free string.
|
|
589
|
+
for (const entry of parsed) {
|
|
590
|
+
const [metric, display] = (entry.split(" -> ")[1] as string).split("/");
|
|
591
|
+
|
|
592
|
+
expect(Object.values(SloWidgetMetric) as Array<string>).toContain(
|
|
593
|
+
metric as string,
|
|
594
|
+
);
|
|
595
|
+
expect(Object.values(SloWidgetDisplayType) as Array<string>).toContain(
|
|
596
|
+
display as string,
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
describe("what an SLO row may show in public", () => {
|
|
603
|
+
function sloSelect(): JSONObject {
|
|
604
|
+
const config: DashboardViewConfig = storedConfig();
|
|
605
|
+
const sloWidgets: Array<DashboardBaseComponent> = componentsOfType(
|
|
606
|
+
config,
|
|
607
|
+
DashboardComponentType.Slo,
|
|
608
|
+
);
|
|
609
|
+
|
|
610
|
+
expect(sloWidgets.length).toBeGreaterThan(0);
|
|
611
|
+
|
|
612
|
+
return buildPolicy({
|
|
613
|
+
config,
|
|
614
|
+
component: withArguments(sloWidgets[0] as DashboardBaseComponent, {
|
|
615
|
+
serviceLevelObjectiveId: PICKED_SLO_ID.toString(),
|
|
616
|
+
}),
|
|
617
|
+
requestedQuery: HOSTILE_QUERY,
|
|
618
|
+
}).select;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
it("publishes the row id and the seven display numbers, and nothing else", () => {
|
|
622
|
+
expect(sloSelect()).toEqual({
|
|
623
|
+
_id: true,
|
|
624
|
+
name: true,
|
|
625
|
+
targetPercentage: true,
|
|
626
|
+
currentSliPercentage: true,
|
|
627
|
+
errorBudgetRemainingPercentage: true,
|
|
628
|
+
errorBudgetRemainingSeconds: true,
|
|
629
|
+
currentBurnRate: true,
|
|
630
|
+
sloStatus: true,
|
|
631
|
+
});
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
/*
|
|
635
|
+
* An SLO's headline numbers are publishable; its DEFINITION is not. Which
|
|
636
|
+
* monitors it watches, how it is evaluated and on what schedule, the
|
|
637
|
+
* metric query behind it, and who created it are all things a reader of a
|
|
638
|
+
* public status page has no business reading out of it.
|
|
639
|
+
*
|
|
640
|
+
* Driven from ServiceLevelObjective's own column list so that each name
|
|
641
|
+
* below is checked to be a real column before it is checked to be
|
|
642
|
+
* withheld — a rename that made one of these assertions vacuous fails
|
|
643
|
+
* here instead of passing quietly.
|
|
644
|
+
*/
|
|
645
|
+
it("keeps every other ServiceLevelObjective column behind the session", () => {
|
|
646
|
+
expectSelectPublishesNothingSensitive({
|
|
647
|
+
modelName: "ServiceLevelObjective",
|
|
648
|
+
model: new ServiceLevelObjective(),
|
|
649
|
+
select: sloSelect(),
|
|
650
|
+
sensitiveColumns: [
|
|
651
|
+
"description",
|
|
652
|
+
"slug",
|
|
653
|
+
"labels",
|
|
654
|
+
"monitors",
|
|
655
|
+
"monitorLabels",
|
|
656
|
+
"autoAddedMonitors",
|
|
657
|
+
"downtimeMonitorStatuses",
|
|
658
|
+
"multiMonitorMode",
|
|
659
|
+
"metricQueryConfig",
|
|
660
|
+
"sliType",
|
|
661
|
+
"windowType",
|
|
662
|
+
"windowDays",
|
|
663
|
+
"timezone",
|
|
664
|
+
"lastEvaluatedAt",
|
|
665
|
+
"nextEvaluationAt",
|
|
666
|
+
"lastAccumulatedBucketEndAt",
|
|
667
|
+
"statusChangeNotificationSentAt",
|
|
668
|
+
"createdByUser",
|
|
669
|
+
"createdByUserId",
|
|
670
|
+
"projectId",
|
|
671
|
+
],
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
describe("the incident, alert and monitor lists the template ships", () => {
|
|
677
|
+
/*
|
|
678
|
+
* These three read Postgres and carry no stored filter at all — the
|
|
679
|
+
* template deliberately pre-filters none of them to a lifecycle state, a
|
|
680
|
+
* severity, or a monitor type. So the ONLY thing narrowing the read is
|
|
681
|
+
* the project the dashboard belongs to, and that has to hold even when
|
|
682
|
+
* the caller supplies a query naming another project.
|
|
683
|
+
*/
|
|
684
|
+
it("scopes each list to the dashboard's project and to nothing else", () => {
|
|
685
|
+
const config: DashboardViewConfig = storedConfig();
|
|
686
|
+
const listWidgets: Array<DashboardBaseComponent> = [
|
|
687
|
+
onlyComponentOfType(config, DashboardComponentType.IncidentList),
|
|
688
|
+
onlyComponentOfType(config, DashboardComponentType.AlertList),
|
|
689
|
+
onlyComponentOfType(config, DashboardComponentType.MonitorList),
|
|
690
|
+
];
|
|
691
|
+
|
|
692
|
+
expect(listWidgets.length).toBeGreaterThan(0);
|
|
693
|
+
|
|
694
|
+
for (const component of listWidgets) {
|
|
695
|
+
const policy: PublicDashboardResourceListPolicyResult = buildPolicy({
|
|
696
|
+
config,
|
|
697
|
+
component,
|
|
698
|
+
requestedQuery: HOSTILE_QUERY,
|
|
699
|
+
requestedVariables: hostileVariableSelections(config),
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
/*
|
|
703
|
+
* The policy names no project of its own: the route's stamp is the
|
|
704
|
+
* only source of project scope, and it must be the last word.
|
|
705
|
+
*/
|
|
706
|
+
expect(
|
|
707
|
+
`${labelOf(component)} filters on [${Object.keys(policy.query)
|
|
708
|
+
.sort()
|
|
709
|
+
.join(", ")}]`,
|
|
710
|
+
).toBe(`${labelOf(component)} filters on []`);
|
|
711
|
+
|
|
712
|
+
expect(routeQuery(policy)).toEqual({
|
|
713
|
+
projectId: DASHBOARD_PROJECT_ID,
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
/*
|
|
719
|
+
* The dashboard's Monitor variable is a TelemetryAttribute bound to the
|
|
720
|
+
* bare `monitorName` key, which these three widgets cannot read: they
|
|
721
|
+
* query Postgres, and MonitorList's only variable binding is a
|
|
722
|
+
* ProjectLabel one this template does not ship. A selection therefore has
|
|
723
|
+
* to leave the query untouched rather than become an IN-list on it.
|
|
724
|
+
*/
|
|
725
|
+
it("lets no variable selection become a filter on those lists", () => {
|
|
726
|
+
const config: DashboardViewConfig = storedConfig();
|
|
727
|
+
const variable: DashboardVariable = monitorVariableOf(config);
|
|
728
|
+
|
|
729
|
+
expect(variable.attributeKey).toBe("monitorName");
|
|
730
|
+
|
|
731
|
+
for (const componentType of [
|
|
732
|
+
DashboardComponentType.IncidentList,
|
|
733
|
+
DashboardComponentType.AlertList,
|
|
734
|
+
DashboardComponentType.MonitorList,
|
|
735
|
+
]) {
|
|
736
|
+
const component: DashboardBaseComponent = onlyComponentOfType(
|
|
737
|
+
config,
|
|
738
|
+
componentType,
|
|
739
|
+
);
|
|
740
|
+
const withSelection: PublicDashboardResourceListPolicyResult =
|
|
741
|
+
buildPolicy({
|
|
742
|
+
config,
|
|
743
|
+
component,
|
|
744
|
+
requestedVariables: [
|
|
745
|
+
{
|
|
746
|
+
id: variable.id,
|
|
747
|
+
selectedValues: ["api-monitor", "' OR 1=1 --"],
|
|
748
|
+
},
|
|
749
|
+
],
|
|
750
|
+
});
|
|
751
|
+
const withoutSelection: PublicDashboardResourceListPolicyResult =
|
|
752
|
+
buildPolicy({ config, component });
|
|
753
|
+
|
|
754
|
+
expect(
|
|
755
|
+
`${labelOf(component)} with a monitor picked: ${JSON.stringify(
|
|
756
|
+
withSelection.query,
|
|
757
|
+
)}`,
|
|
758
|
+
).toBe(
|
|
759
|
+
`${labelOf(component)} with a monitor picked: ${JSON.stringify(
|
|
760
|
+
withoutSelection.query,
|
|
761
|
+
)}`,
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
/*
|
|
767
|
+
* Resource type, order and page size, per widget. The resource type is
|
|
768
|
+
* checked against the URL the caller requested before any read happens,
|
|
769
|
+
* so a widget resolving to the wrong one would let a dashboard serve a
|
|
770
|
+
* resource it does not render; the limit comes from the widget's OWN
|
|
771
|
+
* stored maxRows, never from the request.
|
|
772
|
+
*/
|
|
773
|
+
it("maps each list to its own resource, order and stored row cap", () => {
|
|
774
|
+
const config: DashboardViewConfig = storedConfig();
|
|
775
|
+
|
|
776
|
+
const expectations: Array<{
|
|
777
|
+
componentType: DashboardComponentType;
|
|
778
|
+
resourceType: string;
|
|
779
|
+
sort: JSONObject;
|
|
780
|
+
}> = [
|
|
781
|
+
{
|
|
782
|
+
componentType: DashboardComponentType.IncidentList,
|
|
783
|
+
resourceType: "incident",
|
|
784
|
+
sort: { createdAt: SortOrder.Descending },
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
componentType: DashboardComponentType.AlertList,
|
|
788
|
+
resourceType: "alert",
|
|
789
|
+
sort: { createdAt: SortOrder.Descending },
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
componentType: DashboardComponentType.MonitorList,
|
|
793
|
+
resourceType: "monitor",
|
|
794
|
+
sort: { name: SortOrder.Ascending },
|
|
795
|
+
},
|
|
796
|
+
];
|
|
797
|
+
|
|
798
|
+
for (const expectation of expectations) {
|
|
799
|
+
const component: DashboardBaseComponent = onlyComponentOfType(
|
|
800
|
+
config,
|
|
801
|
+
expectation.componentType,
|
|
802
|
+
);
|
|
803
|
+
const policy: PublicDashboardResourceListPolicyResult = buildPolicy({
|
|
804
|
+
config,
|
|
805
|
+
component,
|
|
806
|
+
requestedQuery: HOSTILE_QUERY,
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
expect(`${labelOf(component)} lists ${policy.resourceType}`).toBe(
|
|
810
|
+
`${labelOf(component)} lists ${expectation.resourceType}`,
|
|
811
|
+
);
|
|
812
|
+
expect(policy.sort).toEqual(expectation.sort);
|
|
813
|
+
|
|
814
|
+
// The cap is the widget's own stored one, not the request's 100000.
|
|
815
|
+
expect(`${labelOf(component)} reads ${policy.limit} rows`).toBe(
|
|
816
|
+
`${labelOf(component)} reads ${String(
|
|
817
|
+
argumentsOf(component)["maxRows"],
|
|
818
|
+
)} rows`,
|
|
819
|
+
);
|
|
820
|
+
expect(policy.limit).toBeGreaterThan(0);
|
|
821
|
+
expect(policy.limit).toBeLessThanOrEqual(LIMIT_PER_PROJECT);
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
it("publishes only the columns the incident list renders", () => {
|
|
826
|
+
const config: DashboardViewConfig = storedConfig();
|
|
827
|
+
const select: JSONObject = buildPolicy({
|
|
828
|
+
config,
|
|
829
|
+
component: onlyComponentOfType(
|
|
830
|
+
config,
|
|
831
|
+
DashboardComponentType.IncidentList,
|
|
832
|
+
),
|
|
833
|
+
}).select;
|
|
834
|
+
|
|
835
|
+
expect(select).toEqual({
|
|
836
|
+
_id: true,
|
|
837
|
+
title: true,
|
|
838
|
+
createdAt: true,
|
|
839
|
+
currentIncidentState: { name: true, color: true },
|
|
840
|
+
incidentSeverity: { name: true, color: true },
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
/*
|
|
844
|
+
* An incident's title and state are what the widget draws. Its write-up
|
|
845
|
+
* is not: the description, the root cause, the remediation notes and
|
|
846
|
+
* the postmortem are internal narrative, and the telemetry query and
|
|
847
|
+
* monitor bindings describe the project's topology.
|
|
848
|
+
*/
|
|
849
|
+
expectSelectPublishesNothingSensitive({
|
|
850
|
+
modelName: "Incident",
|
|
851
|
+
model: new Incident(),
|
|
852
|
+
select,
|
|
853
|
+
sensitiveColumns: [
|
|
854
|
+
"description",
|
|
855
|
+
"rootCause",
|
|
856
|
+
"remediationNotes",
|
|
857
|
+
"postmortemNote",
|
|
858
|
+
"postmortemAttachments",
|
|
859
|
+
"telemetryQuery",
|
|
860
|
+
"customFields",
|
|
861
|
+
"monitors",
|
|
862
|
+
"monitorSummary",
|
|
863
|
+
"labels",
|
|
864
|
+
"onCallDutyPolicies",
|
|
865
|
+
"isPrivate",
|
|
866
|
+
"createdByUserId",
|
|
867
|
+
"seriesLabels",
|
|
868
|
+
],
|
|
869
|
+
});
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
it("publishes only the columns the alert list renders", () => {
|
|
873
|
+
const config: DashboardViewConfig = storedConfig();
|
|
874
|
+
const select: JSONObject = buildPolicy({
|
|
875
|
+
config,
|
|
876
|
+
component: onlyComponentOfType(
|
|
877
|
+
config,
|
|
878
|
+
DashboardComponentType.AlertList,
|
|
879
|
+
),
|
|
880
|
+
}).select;
|
|
881
|
+
|
|
882
|
+
expect(select).toEqual({
|
|
883
|
+
_id: true,
|
|
884
|
+
title: true,
|
|
885
|
+
createdAt: true,
|
|
886
|
+
currentAlertState: { name: true, color: true },
|
|
887
|
+
alertSeverity: { name: true, color: true },
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
expectSelectPublishesNothingSensitive({
|
|
891
|
+
modelName: "Alert",
|
|
892
|
+
model: new Alert(),
|
|
893
|
+
select,
|
|
894
|
+
sensitiveColumns: [
|
|
895
|
+
"description",
|
|
896
|
+
"rootCause",
|
|
897
|
+
"remediationNotes",
|
|
898
|
+
"telemetryQuery",
|
|
899
|
+
"customFields",
|
|
900
|
+
"monitor",
|
|
901
|
+
"monitorId",
|
|
902
|
+
"monitorSummary",
|
|
903
|
+
"labels",
|
|
904
|
+
"onCallDutyPolicies",
|
|
905
|
+
"isPrivate",
|
|
906
|
+
"createdByUserId",
|
|
907
|
+
"seriesLabels",
|
|
908
|
+
],
|
|
909
|
+
});
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
it("publishes only the columns the monitor list renders", () => {
|
|
913
|
+
const config: DashboardViewConfig = storedConfig();
|
|
914
|
+
const select: JSONObject = buildPolicy({
|
|
915
|
+
config,
|
|
916
|
+
component: onlyComponentOfType(
|
|
917
|
+
config,
|
|
918
|
+
DashboardComponentType.MonitorList,
|
|
919
|
+
),
|
|
920
|
+
}).select;
|
|
921
|
+
|
|
922
|
+
expect(select).toEqual({
|
|
923
|
+
_id: true,
|
|
924
|
+
name: true,
|
|
925
|
+
monitorType: true,
|
|
926
|
+
currentMonitorStatus: { name: true, color: true },
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
/*
|
|
930
|
+
* The monitor list is the one on this dashboard with credentials behind
|
|
931
|
+
* it. A monitor's steps carry the request it makes — URLs, headers,
|
|
932
|
+
* bodies — and three columns are literally secret keys that let a
|
|
933
|
+
* caller post as that monitor.
|
|
934
|
+
*/
|
|
935
|
+
expectSelectPublishesNothingSensitive({
|
|
936
|
+
modelName: "Monitor",
|
|
937
|
+
model: new Monitor(),
|
|
938
|
+
select,
|
|
939
|
+
sensitiveColumns: [
|
|
940
|
+
"monitorSteps",
|
|
941
|
+
"serverMonitorSecretKey",
|
|
942
|
+
"incomingRequestSecretKey",
|
|
943
|
+
"incomingEmailSecretKey",
|
|
944
|
+
"incomingMonitorRequest",
|
|
945
|
+
"incomingEmailMonitorRequest",
|
|
946
|
+
"serverMonitorResponse",
|
|
947
|
+
"customFields",
|
|
948
|
+
"description",
|
|
949
|
+
"labels",
|
|
950
|
+
"slug",
|
|
951
|
+
"dependsOnMonitors",
|
|
952
|
+
"monitoringInterval",
|
|
953
|
+
"createdByUserId",
|
|
954
|
+
],
|
|
955
|
+
});
|
|
956
|
+
});
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
describe("every component on the template", () => {
|
|
960
|
+
/*
|
|
961
|
+
* The fall-through guard. Walking the whole config — not just the widgets
|
|
962
|
+
* this file has an opinion about — is what proves that no widget kind the
|
|
963
|
+
* template ships reaches the public list endpoint by accident. A widget
|
|
964
|
+
* added to the template later either appears in the expected map above,
|
|
965
|
+
* or it must be refused; there is no third outcome, and "silently built a
|
|
966
|
+
* policy nobody reviewed" is exactly the one worth failing on.
|
|
967
|
+
*/
|
|
968
|
+
it("either lists a known resource or is refused, with nothing in between", () => {
|
|
969
|
+
const config: DashboardViewConfig = storedConfig();
|
|
970
|
+
const components: Array<DashboardBaseComponent> = config.components;
|
|
971
|
+
|
|
972
|
+
expect(components.length).toBeGreaterThan(0);
|
|
973
|
+
|
|
974
|
+
const outcomes: Array<string> = components.map(
|
|
975
|
+
(component: DashboardBaseComponent): string => {
|
|
976
|
+
return `${labelOf(component)} -> ${outcomeOf({ config, component })}`;
|
|
977
|
+
},
|
|
978
|
+
);
|
|
979
|
+
|
|
980
|
+
expect(outcomes).toEqual(
|
|
981
|
+
components.map((component: DashboardBaseComponent): string => {
|
|
982
|
+
return `${labelOf(component)} -> ${expectedOutcomeOf(component)}`;
|
|
983
|
+
}),
|
|
984
|
+
);
|
|
985
|
+
|
|
986
|
+
/*
|
|
987
|
+
* Guards: a template that listed everything, or nothing, would pass the
|
|
988
|
+
* comparison above only because the expectations were derived from it.
|
|
989
|
+
*/
|
|
990
|
+
const listed: Array<string> = outcomes.filter(
|
|
991
|
+
(outcome: string): boolean => {
|
|
992
|
+
return outcome.includes(" -> lists ");
|
|
993
|
+
},
|
|
994
|
+
);
|
|
995
|
+
const refused: Array<string> = outcomes.filter(
|
|
996
|
+
(outcome: string): boolean => {
|
|
997
|
+
return outcome.includes(" -> refused: ");
|
|
998
|
+
},
|
|
999
|
+
);
|
|
1000
|
+
|
|
1001
|
+
expect(listed.length).toBe(
|
|
1002
|
+
Object.keys(PUBLIC_LIST_RESOURCE_BY_COMPONENT_TYPE).length,
|
|
1003
|
+
);
|
|
1004
|
+
expect(refused.length).toBeGreaterThan(0);
|
|
1005
|
+
expect(listed.length + refused.length).toBe(components.length);
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
/*
|
|
1009
|
+
* Nothing that does resolve may resolve to an empty policy: a blank
|
|
1010
|
+
* resource type would fail the route's resource check for the wrong
|
|
1011
|
+
* reason, and a blank select would hand the serializer a whole row.
|
|
1012
|
+
*/
|
|
1013
|
+
it("gives every widget that does resolve a complete policy", () => {
|
|
1014
|
+
const config: DashboardViewConfig = storedConfig();
|
|
1015
|
+
const listWidgets: Array<DashboardBaseComponent> =
|
|
1016
|
+
config.components.filter(
|
|
1017
|
+
(component: DashboardBaseComponent): boolean => {
|
|
1018
|
+
return Boolean(
|
|
1019
|
+
PUBLIC_LIST_RESOURCE_BY_COMPONENT_TYPE[component.componentType],
|
|
1020
|
+
);
|
|
1021
|
+
},
|
|
1022
|
+
);
|
|
1023
|
+
|
|
1024
|
+
expect(listWidgets.length).toBeGreaterThan(0);
|
|
1025
|
+
|
|
1026
|
+
for (const component of listWidgets) {
|
|
1027
|
+
const policy: PublicDashboardResourceListPolicyResult = buildPolicy({
|
|
1028
|
+
config,
|
|
1029
|
+
component,
|
|
1030
|
+
});
|
|
1031
|
+
|
|
1032
|
+
expect(
|
|
1033
|
+
`${labelOf(component)} resource "${policy.resourceType}"`,
|
|
1034
|
+
).not.toBe(`${labelOf(component)} resource ""`);
|
|
1035
|
+
expect(
|
|
1036
|
+
`${labelOf(component)} selects ${Object.keys(policy.select).length} field(s)`,
|
|
1037
|
+
).not.toBe(`${labelOf(component)} selects 0 field(s)`);
|
|
1038
|
+
expect(Object.keys(policy.sort).length).toBeGreaterThan(0);
|
|
1039
|
+
expect(policy.limit).toBeGreaterThan(0);
|
|
1040
|
+
}
|
|
1041
|
+
});
|
|
1042
|
+
});
|
|
1043
|
+
});
|